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 = pos;
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] == '/' ) {
193 // no hostname and port
196 pos = m_urlString.find('/', startpos);
197 std::string hostport = m_urlString.substr(startpos,
199 DEBUG(LDAP_DEBUG_TRACE, " hostport: <" << hostport << ">"
201 std::string::size_type portstart = m_urlString.find(':', startpos);
202 if (portstart == std::string::npos || portstart > pos ) {
203 percentDecode(hostport, m_Host);
204 if ( m_Scheme == "ldap" || m_Scheme == "cldap" ) {
205 m_Port = LDAP_DEFAULT_PORT;
206 } else if ( m_Scheme == "ldaps" ) {
207 m_Port = LDAPS_DEFAULT_PORT;
210 std::string tmp = m_urlString.substr(startpos,
211 portstart - startpos);
212 percentDecode(tmp, m_Host);
213 DEBUG(LDAP_DEBUG_TRACE, "Host: <" << m_Host << ">" << std::endl);
214 std::string port = m_urlString.substr(portstart+1,
216 if ( port.length() > 0 ) {
217 std::istringstream i(port);
220 throw LDAPUrlException(LDAPUrlException::INVALID_PORT);
223 DEBUG(LDAP_DEBUG_TRACE, " Port: <" << m_Port << ">"
228 int parserMode = base;
229 while ( pos != std::string::npos ) {
230 pos = m_urlString.find('?', startpos);
231 std::string actComponent = m_urlString.substr(startpos,
233 DEBUG(LDAP_DEBUG_TRACE, " ParserMode:" << parserMode << std::endl);
234 DEBUG(LDAP_DEBUG_TRACE, " ActComponent: <" << actComponent << ">"
236 std::string s_scope = "";
237 std::string s_ext = "";
240 percentDecode(actComponent, m_DN);
241 DEBUG(LDAP_DEBUG_TRACE, " BaseDN:" << m_DN << std::endl);
244 DEBUG(LDAP_DEBUG_TRACE, " reading Attributes" << std::endl);
245 if (actComponent.length() != 0 ) {
246 string2list(actComponent,m_Attrs, true);
250 percentDecode(actComponent, s_scope);
251 if (s_scope == "base" || s_scope == "" ) {
253 } else if (s_scope == "one" ) {
255 } else if (s_scope == "sub" ) {
258 throw LDAPUrlException(LDAPUrlException::INVALID_SCOPE);
260 DEBUG(LDAP_DEBUG_TRACE, " Scope: <" << s_scope << ">"
264 percentDecode(actComponent, m_Filter);
265 DEBUG(LDAP_DEBUG_TRACE, " filter: <" << m_Filter << ">"
269 DEBUG(LDAP_DEBUG_TRACE, " reading Extensions" << std::endl);
270 string2list(actComponent, m_Extensions, true);
273 DEBUG(LDAP_DEBUG_TRACE, " unknown state" << std::endl);
281 void LDAPUrl::percentDecode(const std::string& src, std::string &out)
283 DEBUG(LDAP_DEBUG_TRACE, "LDAPUrl::percentDecode()" << std::endl);
284 std::string::size_type pos = 0;
285 std::string::size_type startpos = 0;
286 pos = src.find('%', startpos);
287 while ( pos != std::string::npos ) {
288 out += src.substr(startpos, pos - startpos);
289 std::string istr(src.substr(pos+1, 2));
290 std::istringstream i(istr);
291 i.setf(std::ios::hex, std::ios::basefield);
292 i.unsetf(std::ios::showbase);
296 throw LDAPUrlException(LDAPUrlException::URL_DECODING_ERROR,
297 "Invalid percent encoding");
302 pos = src.find('%', startpos);
304 out += src.substr(startpos, pos - startpos);
307 void LDAPUrl::string2list(const std::string &src, StringList& sl,
310 std::string::size_type comma_startpos = 0;
311 std::string::size_type comma_pos = 0;
313 while ( comma_pos != std::string::npos ) {
314 comma_pos = src.find(',', comma_startpos);
315 actItem = src.substr(comma_startpos, comma_pos - comma_startpos);
318 this->percentDecode(actItem,decoded);
322 comma_startpos = comma_pos + 1;
327 void LDAPUrl::components2Url() const
329 std::ostringstream url;
330 std::string encoded = "";
331 this->percentEncode(m_Host, encoded, PCT_ENCFLAG_SLASH);
332 url << m_Scheme << "://" << encoded;
334 url << ":" << m_Port;
340 this->percentEncode( m_DN, encoded );
344 if ( ! m_Attrs.empty() ){
347 for ( StringList::const_iterator i = m_Attrs.begin();
348 i != m_Attrs.end(); i++)
350 this->percentEncode( *i, encoded );
361 if ( m_Scope == 1 ) {
364 } else if ( m_Scope == 2 ) {
370 if (m_Filter != "" ){
371 this->percentEncode( m_Filter, encoded );
372 url << qm << "?" << encoded;
378 if ( ! m_Extensions.empty() ){
381 for ( StringList::const_iterator i = m_Extensions.begin();
382 i != m_Extensions.end(); i++)
384 this->percentEncode( *i, encoded, 1);
393 m_urlString=url.str();
397 void LDAPUrl::percentEncode( const std::string &src,
401 std::ostringstream o;
402 o.setf(std::ios::hex, std::ios::basefield);
403 o.setf(std::ios::uppercase);
404 o.unsetf(std::ios::showbase);
406 for ( std::string::const_iterator i = src.begin(); i != src.end(); i++ ){
413 if ( flags & PCT_ENCFLAG_COMMA ) {
421 if ( flags & PCT_ENCFLAG_SLASH ) {
449 if ( std::isalnum(*i) ) {
457 o << "%" << (int)(unsigned char)*i ;
465 const code2string_s LDAPUrlException::code2string[] = {
466 { INVALID_SCHEME, "Invalid URL Scheme" },
467 { INVALID_PORT, "Invalid Port in Url" },
468 { INVALID_SCOPE, "Invalid Search Scope in Url" },
469 { INVALID_URL, "Invalid LDAP Url" },
470 { URL_DECODING_ERROR, "Url-decoding Error" },
474 LDAPUrlException::LDAPUrlException( int code, const std::string &msg) :
475 m_code(code), m_addMsg(msg) {}
477 int LDAPUrlException::getCode() const
482 const std::string LDAPUrlException::getAdditionalInfo() const
487 const std::string LDAPUrlException::getErrorMessage() const
489 for ( int i = 0; code2string[i].string != 0; i++ ) {
490 if ( code2string[i].code == m_code ) {
491 return std::string(code2string[i].string);