3 * Copyright 2000-2006, OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
15 #define PCT_ENCFLAG_NONE 0x0000U
16 #define PCT_ENCFLAG_COMMA 0x0001U
17 #define PCT_ENCFLAG_SLASH 0x0002U
19 #define LDAP_DEFAULT_PORT 389
20 #define LDAPS_DEFAULT_PORT 636
22 LDAPUrl::LDAPUrl(const std::string &url)
24 DEBUG(LDAP_DEBUG_CONSTRUCT, "LDAPUrl::LDAPUrl()" << endl);
25 DEBUG(LDAP_DEBUG_CONSTRUCT | LDAP_DEBUG_PARAMETER,
26 " url:" << url << endl);
40 DEBUG(LDAP_DEBUG_DESTROY, "LDAPUrl::~LDAPUrl()" << endl);
44 int LDAPUrl::getPort() const
49 void LDAPUrl::setPort(int port)
55 int LDAPUrl::getScope() const
60 void LDAPUrl::setScope( const std::string &scope )
62 if (scope == "base" || scope == "" ) {
64 } else if (scope == "one" ) {
66 } else if (scope == "sub" ) {
69 throw LDAPUrlException(LDAPUrlException::INVALID_SCOPE,
70 "Scope was:" + scope);
75 const string& LDAPUrl::getURLString() const
78 this->components2Url();
84 void LDAPUrl::setURLString( const std::string &url )
93 const string& LDAPUrl::getHost() const
98 void LDAPUrl::setHost( const std::string &host )
104 const string& LDAPUrl::getDN() const
108 void LDAPUrl::setDN( const std::string &dn )
114 const string& LDAPUrl::getFilter() const
118 void LDAPUrl::setFilter( const std::string &filter )
124 const StringList& LDAPUrl::getAttrs() const
128 void LDAPUrl::setAttrs( const StringList &attrs )
134 const StringList& LDAPUrl::getExtensions() const
139 void LDAPUrl::setExtensions( const StringList &ext )
145 const std::string& LDAPUrl::getScheme() const
150 void LDAPUrl::setScheme( const std::string &scheme )
152 if (scheme == "ldap" || scheme == "ldaps" ||
153 scheme == "ldapi" || scheme == "cldap" )
158 throw LDAPUrlException(LDAPUrlException::INVALID_SCHEME,
159 "Unknown URL scheme: \"" + scheme + "\"");
163 void LDAPUrl::parseUrl()
165 DEBUG(LDAP_DEBUG_TRACE, "LDAPUrl::parseUrl()" << std::endl);
167 std::string::size_type pos = m_urlString.find(':');
168 std::string::size_type startpos = pos;
169 if (pos == std::string::npos) {
170 throw LDAPUrlException(LDAPUrlException::INVALID_URL,
171 "No colon found in URL");
173 std::string scheme = m_urlString.substr(0, pos);
174 DEBUG(LDAP_DEBUG_TRACE, " scheme is <" << scheme << ">" << std::endl);
176 if ( scheme == "ldap" ) {
178 } else if ( scheme == "ldaps" ) {
180 } else if ( scheme == "ldapi" ) {
182 } else if ( scheme == "cldap" ) {
185 throw LDAPUrlException(LDAPUrlException::INVALID_SCHEME,
186 "Unknown URL Scheme: \"" + scheme + "\"");
189 if ( m_urlString[pos+1] != '/' || m_urlString[pos+2] != '/' ) {
190 throw LDAPUrlException(LDAPUrlException::INVALID_URL);
194 if ( m_urlString[startpos] == '/' ) {
195 // no hostname and port
198 std::string::size_type hostend, portstart=0;
199 pos = m_urlString.find('/', startpos);
202 if ( m_urlString[startpos] == '[' ) {
205 hostend = m_urlString.find(']', startpos);
206 if ( hostend == std::string::npos ){
207 throw LDAPUrlException(LDAPUrlException::INVALID_URL);
209 portstart = hostend + 1;
211 hostend = m_urlString.find(':', startpos);
212 if ( hostend == std::string::npos || portstart > pos ) {
217 std::string host = m_urlString.substr(startpos, hostend - startpos);
218 DEBUG(LDAP_DEBUG_TRACE, " host: <" << host << ">" << std::endl);
219 percentDecode(host, m_Host);
221 if (portstart >= m_urlString.length() || portstart >= pos ) {
222 if ( m_Scheme == "ldap" || m_Scheme == "cldap" ) {
223 m_Port = LDAP_DEFAULT_PORT;
224 } else if ( m_Scheme == "ldaps" ) {
225 m_Port = LDAPS_DEFAULT_PORT;
228 std::string port = m_urlString.substr(portstart+1,
229 (pos == std::string::npos ? pos : pos-portstart-1) );
230 if ( port.length() > 0 ) {
231 std::istringstream i(port);
234 throw LDAPUrlException(LDAPUrlException::INVALID_PORT);
237 DEBUG(LDAP_DEBUG_TRACE, " Port: <" << m_Port << ">"
242 int parserMode = base;
243 while ( pos != std::string::npos ) {
244 pos = m_urlString.find('?', startpos);
245 std::string actComponent = m_urlString.substr(startpos,
247 DEBUG(LDAP_DEBUG_TRACE, " ParserMode:" << parserMode << std::endl);
248 DEBUG(LDAP_DEBUG_TRACE, " ActComponent: <" << actComponent << ">"
250 std::string s_scope = "";
251 std::string s_ext = "";
254 percentDecode(actComponent, m_DN);
255 DEBUG(LDAP_DEBUG_TRACE, " BaseDN:" << m_DN << std::endl);
258 DEBUG(LDAP_DEBUG_TRACE, " reading Attributes" << std::endl);
259 if (actComponent.length() != 0 ) {
260 string2list(actComponent,m_Attrs, true);
264 percentDecode(actComponent, s_scope);
265 if (s_scope == "base" || s_scope == "" ) {
267 } else if (s_scope == "one" ) {
269 } else if (s_scope == "sub" ) {
272 throw LDAPUrlException(LDAPUrlException::INVALID_SCOPE);
274 DEBUG(LDAP_DEBUG_TRACE, " Scope: <" << s_scope << ">"
278 percentDecode(actComponent, m_Filter);
279 DEBUG(LDAP_DEBUG_TRACE, " filter: <" << m_Filter << ">"
283 DEBUG(LDAP_DEBUG_TRACE, " reading Extensions" << std::endl);
284 string2list(actComponent, m_Extensions, true);
287 DEBUG(LDAP_DEBUG_TRACE, " unknown state" << std::endl);
295 void LDAPUrl::percentDecode(const std::string& src, std::string &out)
297 DEBUG(LDAP_DEBUG_TRACE, "LDAPUrl::percentDecode()" << std::endl);
298 std::string::size_type pos = 0;
299 std::string::size_type startpos = 0;
300 pos = src.find('%', startpos);
301 while ( pos != std::string::npos ) {
302 out += src.substr(startpos, pos - startpos);
303 std::string istr(src.substr(pos+1, 2));
304 std::istringstream i(istr);
305 i.setf(std::ios::hex, std::ios::basefield);
306 i.unsetf(std::ios::showbase);
310 throw LDAPUrlException(LDAPUrlException::URL_DECODING_ERROR,
311 "Invalid percent encoding");
316 pos = src.find('%', startpos);
318 out += src.substr(startpos, pos - startpos);
321 void LDAPUrl::string2list(const std::string &src, StringList& sl,
324 std::string::size_type comma_startpos = 0;
325 std::string::size_type comma_pos = 0;
327 while ( comma_pos != std::string::npos ) {
328 comma_pos = src.find(',', comma_startpos);
329 actItem = src.substr(comma_startpos, comma_pos - comma_startpos);
332 this->percentDecode(actItem,decoded);
336 comma_startpos = comma_pos + 1;
341 void LDAPUrl::components2Url() const
343 std::ostringstream url;
344 std::string encoded = "";
346 url << m_Scheme << "://";
348 if ( m_Host.find( ':', 0 ) != std::string::npos ) {
349 url << "[" << this->percentEncode(m_Host, encoded) << "]";
351 url << this->percentEncode(m_Host, encoded, PCT_ENCFLAG_SLASH);
355 url << ":" << m_Port;
361 this->percentEncode( m_DN, encoded );
365 if ( ! m_Attrs.empty() ){
368 for ( StringList::const_iterator i = m_Attrs.begin();
369 i != m_Attrs.end(); i++)
371 this->percentEncode( *i, encoded );
382 if ( m_Scope == 1 ) {
385 } else if ( m_Scope == 2 ) {
391 if (m_Filter != "" ){
392 this->percentEncode( m_Filter, encoded );
393 url << qm << "?" << encoded;
399 if ( ! m_Extensions.empty() ){
402 for ( StringList::const_iterator i = m_Extensions.begin();
403 i != m_Extensions.end(); i++)
405 this->percentEncode( *i, encoded, 1);
414 m_urlString=url.str();
418 std::string& LDAPUrl::percentEncode( const std::string &src,
422 std::ostringstream o;
423 o.setf(std::ios::hex, std::ios::basefield);
424 o.setf(std::ios::uppercase);
425 o.unsetf(std::ios::showbase);
427 for ( std::string::const_iterator i = src.begin(); i != src.end(); i++ ){
434 if ( flags & PCT_ENCFLAG_COMMA ) {
442 if ( flags & PCT_ENCFLAG_SLASH ) {
470 if ( std::isalnum(*i) ) {
478 o << "%" << std::setw(2) << std::setfill('0') << (int)(unsigned char)*i ;
487 const code2string_s LDAPUrlException::code2string[] = {
488 { INVALID_SCHEME, "Invalid URL Scheme" },
489 { INVALID_PORT, "Invalid Port in Url" },
490 { INVALID_SCOPE, "Invalid Search Scope in Url" },
491 { INVALID_URL, "Invalid LDAP Url" },
492 { URL_DECODING_ERROR, "Url-decoding Error" },
496 LDAPUrlException::LDAPUrlException( int code, const std::string &msg) :
497 m_code(code), m_addMsg(msg) {}
499 int LDAPUrlException::getCode() const
504 const std::string LDAPUrlException::getAdditionalInfo() const
509 const std::string LDAPUrlException::getErrorMessage() const
511 for ( int i = 0; code2string[i].string != 0; i++ ) {
512 if ( code2string[i].code == m_code ) {
513 return std::string(code2string[i].string);