2 * Copyright 2000-2006, OpenLDAP Foundation, All Rights Reserved.
3 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
13 #define PCT_ENCFLAG_NONE 0x0000U
14 #define PCT_ENCFLAG_COMMA 0x0001U
15 #define PCT_ENCFLAG_SLASH 0x0002U
17 #define LDAP_DEFAULT_PORT 389
18 #define LDAPS_DEFAULT_PORT 636
20 LDAPUrl::LDAPUrl(const std::string &url)
22 DEBUG(LDAP_DEBUG_CONSTRUCT, "LDAPUrl::LDAPUrl()" << endl);
23 DEBUG(LDAP_DEBUG_CONSTRUCT | LDAP_DEBUG_PARAMETER,
24 " url:" << url << endl);
38 DEBUG(LDAP_DEBUG_DESTROY, "LDAPUrl::~LDAPUrl()" << endl);
42 int LDAPUrl::getPort() const
47 void LDAPUrl::setPort(int port)
53 int LDAPUrl::getScope() const
58 void LDAPUrl::setScope( const std::string &scope )
60 if (scope == "base" || scope == "" ) {
62 } else if (scope == "one" ) {
64 } else if (scope == "sub" ) {
67 throw LDAPUrlException(LDAPUrlException::INVALID_SCOPE,
68 "Scope was:" + scope);
73 const string& LDAPUrl::getURLString() const
76 this->components2Url();
82 void LDAPUrl::setURLString( const std::string &url )
91 const string& LDAPUrl::getHost() const
96 void LDAPUrl::setHost( const std::string &host )
102 const string& LDAPUrl::getDN() const
106 void LDAPUrl::setDN( const std::string &dn )
112 const string& LDAPUrl::getFilter() const
116 void LDAPUrl::setFilter( const std::string &filter )
122 const StringList& LDAPUrl::getAttrs() const
126 void LDAPUrl::setAttrs( const StringList &attrs )
132 const StringList& LDAPUrl::getExtensions() const
137 void LDAPUrl::setExtensions( const StringList &ext )
143 const std::string& LDAPUrl::getScheme() const
148 void LDAPUrl::setScheme( const std::string &scheme )
150 if (scheme == "ldap" || scheme == "ldaps" ||
151 scheme == "ldapi" || scheme == "cldap" )
156 throw LDAPUrlException(LDAPUrlException::INVALID_SCHEME,
157 "Unknown URL scheme: \"" + scheme + "\"");
161 void LDAPUrl::parseUrl()
163 DEBUG(LDAP_DEBUG_TRACE, "LDAPUrl::parseUrl()" << std::endl);
165 std::string::size_type pos = m_urlString.find(':');
166 std::string::size_type startpos = m_urlString.find(':');
167 if (pos == std::string::npos) {
168 throw LDAPUrlException(LDAPUrlException::INVALID_URL,
169 "No colon found in URL");
171 std::string scheme = m_urlString.substr(0, pos);
172 DEBUG(LDAP_DEBUG_TRACE, " scheme is <" << scheme << ">" << std::endl);
174 if ( scheme == "ldap" ) {
176 } else if ( scheme == "ldaps" ) {
178 } else if ( scheme == "ldapi" ) {
180 } else if ( scheme == "cldap" ) {
183 throw LDAPUrlException(LDAPUrlException::INVALID_SCHEME,
184 "Unknown URL Scheme: \"" + scheme + "\"");
187 if ( m_urlString[pos+1] != '/' || m_urlString[pos+2] != '/' ) {
188 throw LDAPUrlException(LDAPUrlException::INVALID_URL);
192 if ( m_urlString[startpos] == '/' ) {
195 pos = m_urlString.find('/', startpos);
196 std::string hostport = m_urlString.substr(startpos,
198 DEBUG(LDAP_DEBUG_TRACE, " hostport: <" << hostport << ">"
200 std::string::size_type portstart = m_urlString.find(':', startpos);
201 if (portstart == std::string::npos || portstart > pos ) {
202 percentDecode(hostport, m_Host);
203 if ( m_Scheme == "ldap" || m_Scheme == "cldap" ) {
204 m_Port = LDAP_DEFAULT_PORT;
205 } else if ( m_Scheme == "ldaps" ) {
206 m_Port = LDAPS_DEFAULT_PORT;
209 std::string tmp = m_urlString.substr(startpos,
210 portstart - startpos);
211 percentDecode(tmp, m_Host);
212 DEBUG(LDAP_DEBUG_TRACE, "Host: <" << m_Host << ">" << std::endl);
213 std::string port = m_urlString.substr(portstart+1,
215 if ( port.length() > 0 ) {
216 std::istringstream i(port);
219 throw LDAPUrlException(LDAPUrlException::INVALID_PORT);
222 DEBUG(LDAP_DEBUG_TRACE, " Port: <" << m_Port << ">"
227 int parserMode = base;
228 while ( pos != std::string::npos ) {
229 pos = m_urlString.find('?', startpos);
230 std::string actComponent = m_urlString.substr(startpos,
232 DEBUG(LDAP_DEBUG_TRACE, " ParserMode:" << parserMode << std::endl);
233 DEBUG(LDAP_DEBUG_TRACE, " ActComponent: <" << actComponent << ">"
235 std::string s_scope = "";
236 std::string s_ext = "";
239 percentDecode(actComponent, m_DN);
240 DEBUG(LDAP_DEBUG_TRACE, " BaseDN:" << m_DN << std::endl);
243 DEBUG(LDAP_DEBUG_TRACE, " reading Attributes" << std::endl);
244 if (actComponent.length() != 0 ) {
245 string2list(actComponent,m_Attrs, true);
249 percentDecode(actComponent, s_scope);
250 if (s_scope == "base" || s_scope == "" ) {
252 } else if (s_scope == "one" ) {
254 } else if (s_scope == "sub" ) {
257 throw LDAPUrlException(LDAPUrlException::INVALID_SCOPE);
259 DEBUG(LDAP_DEBUG_TRACE, " Scope: <" << s_scope << ">"
263 percentDecode(actComponent, m_Filter);
264 DEBUG(LDAP_DEBUG_TRACE, " filter: <" << m_Filter << ">"
268 DEBUG(LDAP_DEBUG_TRACE, " reading Extensions" << std::endl);
269 string2list(actComponent, m_Extensions, true);
272 DEBUG(LDAP_DEBUG_TRACE, " unknown state" << std::endl);
280 void LDAPUrl::percentDecode(const std::string& src, std::string &out)
282 DEBUG(LDAP_DEBUG_TRACE, "LDAPUrl::percentDecode()" << std::endl);
283 std::string::size_type pos = 0;
284 std::string::size_type startpos = 0;
285 pos = src.find('%', startpos);
286 while ( pos != std::string::npos ) {
287 out += src.substr(startpos, pos - startpos);
288 std::string istr(src.substr(pos+1, 2));
289 std::istringstream i(istr);
290 i.setf(std::ios::hex, std::ios::basefield);
291 i.unsetf(std::ios::showbase);
295 throw LDAPUrlException(LDAPUrlException::URL_DECODING_ERROR,
296 "Invalid percent encoding");
301 pos = src.find('%', startpos);
303 out += src.substr(startpos, pos - startpos);
306 void LDAPUrl::string2list(const std::string &src, StringList& sl,
309 std::string::size_type comma_startpos = 0;
310 std::string::size_type comma_pos = 0;
312 while ( comma_pos != std::string::npos ) {
313 comma_pos = src.find(',', comma_startpos);
314 actItem = src.substr(comma_startpos, comma_pos - comma_startpos);
317 this->percentDecode(actItem,decoded);
321 comma_startpos = comma_pos + 1;
326 void LDAPUrl::components2Url() const
328 std::ostringstream url;
329 std::string encoded = "";
330 this->percentEncode(m_Host, encoded, PCT_ENCFLAG_SLASH);
331 url << m_Scheme << "://" << encoded;
333 url << ":" << m_Port;
339 this->percentEncode( m_DN, encoded );
343 if ( ! m_Attrs.empty() ){
346 for ( StringList::const_iterator i = m_Attrs.begin();
347 i != m_Attrs.end(); i++)
349 this->percentEncode( *i, encoded );
360 if ( m_Scope == 1 ) {
363 } else if ( m_Scope == 2 ) {
369 if (m_Filter != "" ){
370 this->percentEncode( m_Filter, encoded );
371 url << qm << "?" << encoded;
377 if ( ! m_Extensions.empty() ){
380 for ( StringList::const_iterator i = m_Extensions.begin();
381 i != m_Extensions.end(); i++)
383 this->percentEncode( *i, encoded, 1);
392 m_urlString=url.str();
396 void LDAPUrl::percentEncode( const std::string &src,
400 std::ostringstream o;
401 o.setf(std::ios::hex, std::ios::basefield);
402 o.setf(std::ios::uppercase);
403 o.unsetf(std::ios::showbase);
405 for ( std::string::const_iterator i = src.begin(); i != src.end(); i++ ){
412 if ( flags & PCT_ENCFLAG_COMMA ) {
420 if ( flags & PCT_ENCFLAG_SLASH ) {
448 if ( std::isalnum(*i) ) {
456 o << "%" << (int)(unsigned char)*i ;
464 const code2string_s LDAPUrlException::code2string[] = {
465 { INVALID_SCHEME, "Invalid URL Scheme" },
466 { INVALID_PORT, "Invalid Port in Url" },
467 { INVALID_SCOPE, "Invalid Search Scope in Url" },
468 { INVALID_URL, "Invalid LDAP Url" },
469 { URL_DECODING_ERROR, "Url-decoding Error" },
473 LDAPUrlException::LDAPUrlException( int code, const std::string &msg) :
474 m_code(code), m_addMsg(msg) {}
476 int LDAPUrlException::getCode() const
481 const std::string LDAPUrlException::getAdditionalInfo() const
486 const std::string LDAPUrlException::getErrorMessage() const
488 for ( int i = 0; code2string[i].string != 0; i++ ) {
489 if ( code2string[i].code == m_code ) {
490 return std::string(code2string[i].string);