00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef MORE_NET_LDAP_H
00030 #define MORE_NET_LDAP_H
00031
00032 #include <more/gen/utility.h>
00033 #include <more/bits/experimental.h>
00034 #include <more/io/fwd.h>
00035 #include <map>
00036
00037 namespace more {
00038 namespace net {
00039
00040 class ldap_connection;
00041
00042 enum ldap_dn_syntax {
00043 ldap_dn_syntax_none,
00044 ldap_dn_syntax_rfc,
00045 ldap_dn_syntax_osf
00046 };
00047
00048 struct ldap_dn
00049 {
00050 private:
00051 struct content : gen::handle_data
00052 {
00053 ~content()
00054 {
00055 if (m_cxt && m_cxt->unref() == 0)
00056 delete m_cxt;
00057 }
00058
00059 std::string m_rdn;
00060 content const* m_cxt;
00061 };
00062
00063 explicit ldap_dn(content const* cxt)
00064 : m_data(cxt) {}
00065
00066 public:
00067 ldap_dn(std::string dn,
00068 ldap_dn_syntax stx = ldap_dn_syntax_none)
00069 {
00070 m_data.set_data(init(0, dn, stx));
00071 }
00072
00073 ldap_dn(ldap_dn const& cxt, std::string const& rdn,
00074 ldap_dn_syntax stx = ldap_dn_syntax_none)
00075 {
00076 m_data.set_data(init(cxt.m_data.data_ref(), rdn, stx));
00077 }
00078
00079 ~ldap_dn();
00080
00081 std::string const& rdn() const { return m_data.data()->m_rdn; }
00082
00083 bool is_single_rdn() const { return m_data.data()->m_cxt == 0; }
00084
00085 ldap_dn context() const
00086 {
00087 #ifndef MORE_NDEBUG
00088 if (m_data.data()->m_cxt == 0)
00089 throw std::logic_error("more::net::ldap_dn::context: "
00090 "Toplevel DN has no context.");
00091 #endif
00092 return ldap_dn(m_data.data()->m_cxt);
00093 }
00094
00095 bool operator==(ldap_dn const& rhs) const
00096 {
00097 return m_data.data() == rhs.m_data.data();
00098 }
00099
00100 private:
00101 static content*
00102 init(content const* cxt,
00103 std::string const& rdn, ldap_dn_syntax stx);
00104
00105 gen::handle<content> m_data;
00106 };
00107
00108 std::ostream& operator<<(std::ostream& os, ldap_dn const& dn);
00109
00110 struct ldap_entry_ref
00111 {
00112 private:
00113 typedef std::multimap<std::string, std::string> multimap_type;
00114
00115 struct content : gen::handle_data
00116 {
00117 ldap_connection* m_connection;
00118 ldap_dn m_current_dn;
00119 multimap_type m_current_attrs;
00120 ldap_dn m_update_dn;
00121 multimap_type m_update_attrs;
00122 };
00123
00124 ldap_entry_ref(content* c)
00125 : m_data(c) {}
00126
00127 public:
00128 ldap_entry_ref() {}
00129
00130 ldap_dn const& dn() const { return m_data.datachk()->m_current_dn; }
00131
00132 bool is_changed() const
00133 {
00134 return m_data.datachk()->m_current_dn == m_data.data()->m_update_dn
00135 && m_data.data()->m_current_attrs
00136 == m_data.data()->m_update_attrs;
00137 }
00138
00139 void commit() const;
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 private:
00150 gen::handle<content> m_data;
00151 friend class ldap_connection;
00152 };
00153
00154
00155
00156
00157 struct ldap_connection : gen::noncopyable
00158 {
00159 enum search_scope_type
00160 {
00161 search_scope_base,
00162 search_scope_one,
00163 search_scope_sub
00164 };
00165
00166 ldap_connection();
00167
00168
00169
00170 void declare_options(io::cmdline& cl);
00171
00172 void bind();
00173
00174 ldap_entry_ref const& checkout(ldap_dn const& dn);
00175
00176 template<typename OutputIterator>
00177 void search(std::string const& base, search_scope_type scope,
00178 std::string const& filter, OutputIterator it_out);
00179
00180
00181 private:
00182 gen::degenerate_set<ldap_entry_ref> m_cache;
00183 };
00184
00185 }}
00186
00187 #endif