1
// $OpenLDAP: pkg/ldap/contrib/ldapc++/src/LDAPUrl.cpp,v 1.3.10.5 2008/04/14 23:09:26 quanah Exp $
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;
199
std::string::size_type portstart;
200
pos = m_urlString.find('/', startpos);
203
if ( m_urlString[startpos] == '[' ) {
206
hostend = m_urlString.find(']', startpos);
207
if ( hostend == std::string::npos ){
208
throw LDAPUrlException(LDAPUrlException::INVALID_URL);
210
portstart = hostend + 1;
212
hostend = m_urlString.find(':', startpos);
213
if ( hostend == std::string::npos || portstart > pos ) {
218
std::string host = m_urlString.substr(startpos, hostend - startpos);
219
DEBUG(LDAP_DEBUG_TRACE, " host: <" << host << ">" << std::endl);
220
percentDecode(host, m_Host);
222
if (portstart >= m_urlString.length() || portstart >= pos ) {
223
if ( m_Scheme == "ldap" || m_Scheme == "cldap" ) {
224
m_Port = LDAP_DEFAULT_PORT;
225
} else if ( m_Scheme == "ldaps" ) {
226
m_Port = LDAPS_DEFAULT_PORT;
229
std::string port = m_urlString.substr(portstart+1,
230
(pos == std::string::npos ? pos : pos-portstart-1) );
231
if ( port.length() > 0 ) {
232
std::istringstream i(port);
235
throw LDAPUrlException(LDAPUrlException::INVALID_PORT);
238
DEBUG(LDAP_DEBUG_TRACE, " Port: <" << m_Port << ">"
243
int parserMode = base;
244
while ( pos != std::string::npos ) {
245
pos = m_urlString.find('?', startpos);
246
std::string actComponent = m_urlString.substr(startpos,
248
DEBUG(LDAP_DEBUG_TRACE, " ParserMode:" << parserMode << std::endl);
249
DEBUG(LDAP_DEBUG_TRACE, " ActComponent: <" << actComponent << ">"
251
std::string s_scope = "";
252
std::string s_ext = "";
255
percentDecode(actComponent, m_DN);
256
DEBUG(LDAP_DEBUG_TRACE, " BaseDN:" << m_DN << std::endl);
259
DEBUG(LDAP_DEBUG_TRACE, " reading Attributes" << std::endl);
260
if (actComponent.length() != 0 ) {
261
string2list(actComponent,m_Attrs, true);
265
percentDecode(actComponent, s_scope);
266
if (s_scope == "base" || s_scope == "" ) {
268
} else if (s_scope == "one" ) {
270
} else if (s_scope == "sub" ) {
273
throw LDAPUrlException(LDAPUrlException::INVALID_SCOPE);
275
DEBUG(LDAP_DEBUG_TRACE, " Scope: <" << s_scope << ">"
279
percentDecode(actComponent, m_Filter);
280
DEBUG(LDAP_DEBUG_TRACE, " filter: <" << m_Filter << ">"
284
DEBUG(LDAP_DEBUG_TRACE, " reading Extensions" << std::endl);
285
string2list(actComponent, m_Extensions, true);
288
DEBUG(LDAP_DEBUG_TRACE, " unknown state" << std::endl);
296
void LDAPUrl::percentDecode(const std::string& src, std::string &out)
298
DEBUG(LDAP_DEBUG_TRACE, "LDAPUrl::percentDecode()" << std::endl);
299
std::string::size_type pos = 0;
300
std::string::size_type startpos = 0;
301
pos = src.find('%', startpos);
302
while ( pos != std::string::npos ) {
303
out += src.substr(startpos, pos - startpos);
304
std::string istr(src.substr(pos+1, 2));
305
std::istringstream i(istr);
306
i.setf(std::ios::hex, std::ios::basefield);
307
i.unsetf(std::ios::showbase);
311
throw LDAPUrlException(LDAPUrlException::URL_DECODING_ERROR,
312
"Invalid percent encoding");
317
pos = src.find('%', startpos);
319
out += src.substr(startpos, pos - startpos);
322
void LDAPUrl::string2list(const std::string &src, StringList& sl,
325
std::string::size_type comma_startpos = 0;
326
std::string::size_type comma_pos = 0;
328
while ( comma_pos != std::string::npos ) {
329
comma_pos = src.find(',', comma_startpos);
330
actItem = src.substr(comma_startpos, comma_pos - comma_startpos);
333
this->percentDecode(actItem,decoded);
337
comma_startpos = comma_pos + 1;
342
void LDAPUrl::components2Url() const
344
std::ostringstream url;
345
std::string encoded = "";
347
url << m_Scheme << "://";
349
if ( m_Host.find( ':', 0 ) != std::string::npos ) {
350
url << "[" << this->percentEncode(m_Host, encoded) << "]";
352
url << this->percentEncode(m_Host, encoded, PCT_ENCFLAG_SLASH);
356
url << ":" << m_Port;
362
this->percentEncode( m_DN, encoded );
366
if ( ! m_Attrs.empty() ){
369
for ( StringList::const_iterator i = m_Attrs.begin();
370
i != m_Attrs.end(); i++)
372
this->percentEncode( *i, encoded );
383
if ( m_Scope == 1 ) {
386
} else if ( m_Scope == 2 ) {
392
if (m_Filter != "" ){
393
this->percentEncode( m_Filter, encoded );
394
url << qm << "?" << encoded;
400
if ( ! m_Extensions.empty() ){
403
for ( StringList::const_iterator i = m_Extensions.begin();
404
i != m_Extensions.end(); i++)
406
this->percentEncode( *i, encoded, 1);
415
m_urlString=url.str();
419
std::string& LDAPUrl::percentEncode( const std::string &src,
423
std::ostringstream o;
424
o.setf(std::ios::hex, std::ios::basefield);
425
o.setf(std::ios::uppercase);
426
o.unsetf(std::ios::showbase);
428
for ( std::string::const_iterator i = src.begin(); i != src.end(); i++ ){
435
if ( flags & PCT_ENCFLAG_COMMA ) {
443
if ( flags & PCT_ENCFLAG_SLASH ) {
471
if ( std::isalnum(*i) ) {
479
o << "%" << std::setw(2) << std::setfill('0') << (int)(unsigned char)*i ;
488
const code2string_s LDAPUrlException::code2string[] = {
489
{ INVALID_SCHEME, "Invalid URL Scheme" },
490
{ INVALID_PORT, "Invalid Port in Url" },
491
{ INVALID_SCOPE, "Invalid Search Scope in Url" },
492
{ INVALID_URL, "Invalid LDAP Url" },
493
{ URL_DECODING_ERROR, "Url-decoding Error" },
497
LDAPUrlException::LDAPUrlException( int code, const std::string &msg) :
498
m_code(code), m_addMsg(msg) {}
500
int LDAPUrlException::getCode() const
505
const std::string LDAPUrlException::getAdditionalInfo() const
510
const std::string LDAPUrlException::getErrorMessage() const
512
for ( int i = 0; code2string[i].string != 0; i++ ) {
513
if ( code2string[i].code == m_code ) {
514
return std::string(code2string[i].string);