~ttx/openldap/lucid-gssapi-495418

« back to all changes in this revision

Viewing changes to contrib/ldapc++/src/LDAPUrl.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2008-07-10 14:45:49 UTC
  • Revision ID: james.westby@ubuntu.com-20080710144549-wck73med0e72gfyo
Tags: upstream-2.4.10
ImportĀ upstreamĀ versionĀ 2.4.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// $OpenLDAP: pkg/ldap/contrib/ldapc++/src/LDAPUrl.cpp,v 1.3.10.5 2008/04/14 23:09:26 quanah Exp $
 
2
/*
 
3
 * Copyright 2000-2006, OpenLDAP Foundation, All Rights Reserved.
 
4
 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
 
5
 */
 
6
 
 
7
 
 
8
#include "LDAPUrl.h"
 
9
#include <sstream>
 
10
#include <iomanip>
 
11
#include "debug.h"
 
12
 
 
13
using namespace std;
 
14
 
 
15
#define PCT_ENCFLAG_NONE 0x0000U
 
16
#define PCT_ENCFLAG_COMMA 0x0001U
 
17
#define PCT_ENCFLAG_SLASH 0x0002U
 
18
 
 
19
#define LDAP_DEFAULT_PORT 389
 
20
#define LDAPS_DEFAULT_PORT 636
 
21
 
 
22
LDAPUrl::LDAPUrl(const std::string &url)
 
23
{
 
24
    DEBUG(LDAP_DEBUG_CONSTRUCT, "LDAPUrl::LDAPUrl()" << endl);
 
25
    DEBUG(LDAP_DEBUG_CONSTRUCT | LDAP_DEBUG_PARAMETER,
 
26
            "   url:" << url << endl);
 
27
    m_urlString = url;
 
28
    m_Filter = "";
 
29
    m_Scheme = "ldap";
 
30
    m_Scope = 0;
 
31
    m_Port = 0;
 
32
    regenerate = false;
 
33
    if (url != "") {
 
34
        this->parseUrl();
 
35
    }
 
36
}
 
37
 
 
38
LDAPUrl::~LDAPUrl()
 
39
{
 
40
    DEBUG(LDAP_DEBUG_DESTROY, "LDAPUrl::~LDAPUrl()" << endl);
 
41
    m_Attrs.clear();
 
42
}
 
43
 
 
44
int LDAPUrl::getPort() const 
 
45
{
 
46
    return m_Port;
 
47
}
 
48
 
 
49
void LDAPUrl::setPort(int port)
 
50
{
 
51
    m_Port = port;
 
52
    regenerate = true;
 
53
}
 
54
 
 
55
int LDAPUrl::getScope() const 
 
56
{
 
57
    return m_Scope;
 
58
}
 
59
 
 
60
void LDAPUrl::setScope( const std::string &scope )
 
61
{
 
62
    if (scope == "base" || scope == "" ) {
 
63
        m_Scope = 0;
 
64
    } else if (scope == "one" ) {
 
65
        m_Scope = 1;
 
66
    } else if (scope == "sub" ) {
 
67
        m_Scope = 2;
 
68
    } else {
 
69
        throw LDAPUrlException(LDAPUrlException::INVALID_SCOPE, 
 
70
                "Scope was:" + scope); 
 
71
    }
 
72
    regenerate = true;
 
73
}
 
74
 
 
75
const string& LDAPUrl::getURLString() const
 
76
{
 
77
    if (regenerate){
 
78
        this->components2Url();
 
79
        regenerate=false;
 
80
    }
 
81
    return m_urlString;
 
82
}
 
83
 
 
84
void LDAPUrl::setURLString( const std::string &url )
 
85
{
 
86
    m_urlString = url;
 
87
    if (url != "") {
 
88
        this->parseUrl();
 
89
    }
 
90
    regenerate = false;
 
91
}
 
92
 
 
93
const string& LDAPUrl::getHost() const 
 
94
{
 
95
    return m_Host;
 
96
}
 
97
 
 
98
void LDAPUrl::setHost( const std::string &host )
 
99
{
 
100
    m_Host = host;
 
101
    regenerate = true;
 
102
}
 
103
 
 
104
const string& LDAPUrl::getDN() const 
 
105
{
 
106
    return m_DN;
 
107
}
 
108
void LDAPUrl::setDN( const std::string &dn )
 
109
{
 
110
    m_DN = dn;
 
111
    regenerate = true;
 
112
}
 
113
 
 
114
const string& LDAPUrl::getFilter() const 
 
115
{
 
116
    return m_Filter;
 
117
}
 
118
void LDAPUrl::setFilter( const std::string &filter )
 
119
{
 
120
    m_Filter = filter;
 
121
    regenerate = true;
 
122
}
 
123
 
 
124
const StringList& LDAPUrl::getAttrs() const 
 
125
{
 
126
    return m_Attrs;
 
127
}
 
128
void LDAPUrl::setAttrs( const StringList &attrs )
 
129
{
 
130
    m_Attrs = attrs;
 
131
    regenerate = true;
 
132
}
 
133
 
 
134
const StringList& LDAPUrl::getExtensions() const 
 
135
{
 
136
    return m_Extensions;
 
137
}
 
138
 
 
139
void LDAPUrl::setExtensions( const StringList &ext )
 
140
{
 
141
    m_Extensions = ext;
 
142
    regenerate = true;
 
143
}
 
144
 
 
145
const std::string& LDAPUrl::getScheme() const
 
146
{
 
147
    return m_Scheme;
 
148
}
 
149
 
 
150
void LDAPUrl::setScheme( const std::string &scheme )
 
151
{
 
152
    if (scheme == "ldap" || scheme == "ldaps" || 
 
153
            scheme == "ldapi" || scheme == "cldap" ) 
 
154
    {
 
155
        m_Scheme = scheme;
 
156
        regenerate = true;
 
157
    } else {
 
158
        throw LDAPUrlException(LDAPUrlException::INVALID_SCHEME,
 
159
                "Unknown URL scheme: \"" + scheme + "\"");
 
160
    }
 
161
}
 
162
 
 
163
void LDAPUrl::parseUrl() 
 
164
{
 
165
    DEBUG(LDAP_DEBUG_TRACE, "LDAPUrl::parseUrl()" << std::endl);
 
166
    // reading Scheme
 
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");
 
172
    }
 
173
    std::string scheme = m_urlString.substr(0, pos);
 
174
    DEBUG(LDAP_DEBUG_TRACE, "    scheme is <" << scheme << ">" << std::endl);
 
175
 
 
176
    if ( scheme == "ldap" ) {
 
177
        m_Scheme = scheme;
 
178
    } else if ( scheme == "ldaps" ) {
 
179
        m_Scheme = scheme;
 
180
    } else if ( scheme == "ldapi" ) {
 
181
        m_Scheme = scheme;
 
182
    } else if ( scheme == "cldap" ) {
 
183
        m_Scheme = scheme;
 
184
    } else {
 
185
        throw LDAPUrlException(LDAPUrlException::INVALID_SCHEME,
 
186
                "Unknown URL Scheme: \"" + scheme + "\"");
 
187
    }
 
188
 
 
189
    if ( m_urlString[pos+1] != '/' || m_urlString[pos+2] != '/' ) {
 
190
        throw LDAPUrlException(LDAPUrlException::INVALID_URL);
 
191
    } else {
 
192
        startpos = pos + 3;
 
193
    }
 
194
    if ( m_urlString[startpos] == '/' ) {
 
195
        // no hostname and port
 
196
        startpos++;
 
197
    } else {
 
198
        std::string::size_type hostend;
 
199
        std::string::size_type portstart;
 
200
        pos = m_urlString.find('/', startpos);
 
201
 
 
202
        // IPv6 Address?
 
203
        if ( m_urlString[startpos] == '[' ) {
 
204
            // skip
 
205
            startpos++;
 
206
            hostend =  m_urlString.find(']', startpos);
 
207
            if ( hostend == std::string::npos ){
 
208
                throw LDAPUrlException(LDAPUrlException::INVALID_URL);
 
209
            }
 
210
            portstart = hostend + 1;
 
211
        } else {
 
212
            hostend = m_urlString.find(':', startpos);
 
213
            if ( hostend == std::string::npos || portstart > pos ) {
 
214
                hostend = pos;
 
215
            }
 
216
            portstart = hostend;
 
217
        }
 
218
        std::string host = m_urlString.substr(startpos, hostend - startpos);
 
219
        DEBUG(LDAP_DEBUG_TRACE, "    host: <" << host << ">" << std::endl);
 
220
        percentDecode(host, m_Host);
 
221
 
 
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;
 
227
            }
 
228
        } else {
 
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);
 
233
                i >> m_Port;
 
234
                if ( i.fail() ){
 
235
                    throw LDAPUrlException(LDAPUrlException::INVALID_PORT);
 
236
                }
 
237
            }
 
238
            DEBUG(LDAP_DEBUG_TRACE, "    Port: <" << m_Port << ">" 
 
239
                    << std::endl);
 
240
        }
 
241
        startpos = pos + 1;
 
242
    }
 
243
    int parserMode = base;
 
244
    while ( pos != std::string::npos ) {
 
245
        pos = m_urlString.find('?', startpos);
 
246
        std::string actComponent = m_urlString.substr(startpos, 
 
247
                pos - startpos);
 
248
        DEBUG(LDAP_DEBUG_TRACE, "    ParserMode:" << parserMode << std::endl);
 
249
        DEBUG(LDAP_DEBUG_TRACE, "    ActComponent: <" << actComponent << ">" 
 
250
                << std::endl);
 
251
        std::string s_scope = "";
 
252
        std::string s_ext = "";
 
253
        switch(parserMode) {
 
254
            case base :
 
255
                percentDecode(actComponent, m_DN);
 
256
                DEBUG(LDAP_DEBUG_TRACE, "    BaseDN:" << m_DN << std::endl); 
 
257
                break;
 
258
            case attrs :
 
259
                DEBUG(LDAP_DEBUG_TRACE, "    reading Attributes" << std::endl);
 
260
                if (actComponent.length() != 0 ) {
 
261
                    string2list(actComponent,m_Attrs, true);
 
262
                }
 
263
                break;
 
264
            case scope :
 
265
                percentDecode(actComponent, s_scope);
 
266
                if (s_scope == "base" || s_scope == "" ) {
 
267
                    m_Scope = 0;
 
268
                } else if (s_scope == "one" ) {
 
269
                    m_Scope = 1;
 
270
                } else if (s_scope == "sub" ) {
 
271
                    m_Scope = 2;
 
272
                } else {
 
273
                    throw LDAPUrlException(LDAPUrlException::INVALID_SCOPE);
 
274
                }
 
275
                DEBUG(LDAP_DEBUG_TRACE, "    Scope: <" << s_scope << ">"
 
276
                        << std::endl);
 
277
                break;
 
278
            case filter :
 
279
                percentDecode(actComponent, m_Filter);
 
280
                DEBUG(LDAP_DEBUG_TRACE, "    filter: <" << m_Filter << ">"
 
281
                        << std::endl);
 
282
                break;
 
283
            case extensions :
 
284
                DEBUG(LDAP_DEBUG_TRACE, "    reading Extensions" << std::endl); 
 
285
                string2list(actComponent, m_Extensions, true);
 
286
                break;
 
287
            default : 
 
288
                DEBUG(LDAP_DEBUG_TRACE, "    unknown state" << std::endl); 
 
289
                break;
 
290
        }
 
291
        startpos = pos + 1;
 
292
        parserMode++;
 
293
    }
 
294
}
 
295
 
 
296
void LDAPUrl::percentDecode(const std::string& src, std::string &out)
 
297
{
 
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);
 
308
        int hex;
 
309
        i >> hex;
 
310
        if ( i.fail() ){
 
311
            throw LDAPUrlException(LDAPUrlException::URL_DECODING_ERROR, 
 
312
                    "Invalid percent encoding");
 
313
        }
 
314
        char j = hex;
 
315
        out.push_back(j);
 
316
        startpos = pos+3;
 
317
        pos = src.find('%', startpos);
 
318
    } 
 
319
    out += src.substr(startpos, pos - startpos);
 
320
}
 
321
 
 
322
void LDAPUrl::string2list(const std::string &src, StringList& sl, 
 
323
            bool percentDecode)
 
324
{
 
325
    std::string::size_type comma_startpos = 0;
 
326
    std::string::size_type comma_pos = 0;
 
327
    std::string actItem;
 
328
    while ( comma_pos != std::string::npos ) {
 
329
        comma_pos = src.find(',', comma_startpos);
 
330
        actItem = src.substr(comma_startpos, comma_pos - comma_startpos);
 
331
        if (percentDecode){
 
332
            std::string decoded;
 
333
            this->percentDecode(actItem,decoded);
 
334
            actItem = decoded;
 
335
        }
 
336
        sl.add(actItem);
 
337
        comma_startpos = comma_pos + 1;
 
338
    }
 
339
}
 
340
 
 
341
 
 
342
void LDAPUrl::components2Url() const
 
343
{
 
344
    std::ostringstream url; 
 
345
    std::string encoded = "";
 
346
    
 
347
    url << m_Scheme << "://";
 
348
    // IPv6 ?
 
349
    if ( m_Host.find( ':', 0 ) != std::string::npos ) {
 
350
        url <<  "[" << this->percentEncode(m_Host, encoded) <<  "]";
 
351
    } else {
 
352
        url << this->percentEncode(m_Host, encoded, PCT_ENCFLAG_SLASH);
 
353
    }
 
354
 
 
355
    if ( m_Port != 0 ) {
 
356
        url << ":" << m_Port;
 
357
    }
 
358
 
 
359
    url << "/";
 
360
    encoded = "";
 
361
    if ( m_DN != "" ) {
 
362
        this->percentEncode( m_DN, encoded );
 
363
        url << encoded;
 
364
    }
 
365
    string qm = "";
 
366
    if ( ! m_Attrs.empty() ){
 
367
        url << "?";
 
368
        bool first = true;
 
369
        for ( StringList::const_iterator i = m_Attrs.begin();
 
370
                i != m_Attrs.end(); i++) 
 
371
        {
 
372
            this->percentEncode( *i, encoded );
 
373
            if ( ! first ) {
 
374
                url << ",";
 
375
            } else {
 
376
                first = false;
 
377
            }
 
378
            url << encoded;
 
379
        }
 
380
    } else {
 
381
        qm.append("?");
 
382
    }
 
383
    if ( m_Scope == 1 ) {
 
384
        url << qm << "?one";
 
385
        qm = "";
 
386
    } else if ( m_Scope == 2 ) {
 
387
        url << qm << "?sub";
 
388
        qm = "";
 
389
    } else {
 
390
        qm.append("?");
 
391
    }
 
392
    if (m_Filter != "" ){
 
393
        this->percentEncode( m_Filter, encoded );
 
394
        url << qm << "?" << encoded;
 
395
        qm = "";
 
396
    } else {
 
397
        qm.append("?");
 
398
    }
 
399
 
 
400
    if ( ! m_Extensions.empty() ){
 
401
        url << qm << "?";
 
402
        bool first = true;
 
403
        for ( StringList::const_iterator i = m_Extensions.begin();
 
404
                i != m_Extensions.end(); i++) 
 
405
        {
 
406
            this->percentEncode( *i, encoded, 1);
 
407
            if ( ! first ) {
 
408
                url << ",";
 
409
            } else {
 
410
                first = false;
 
411
            }
 
412
            url << encoded;
 
413
        }
 
414
    }
 
415
    m_urlString=url.str();  
 
416
}
 
417
 
 
418
 
 
419
std::string& LDAPUrl::percentEncode( const std::string &src, 
 
420
        std::string &dest, 
 
421
        int flags) const
 
422
{
 
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);
 
427
    bool escape=false;
 
428
    for ( std::string::const_iterator i = src.begin(); i != src.end(); i++ ){
 
429
        switch(*i){
 
430
            /* reserved */
 
431
            case '?' :
 
432
                escape = true;
 
433
            break;
 
434
            case ',' :
 
435
                if ( flags & PCT_ENCFLAG_COMMA ) {
 
436
                    escape = true;
 
437
                } else {
 
438
                    escape = false;
 
439
                }
 
440
            break;
 
441
            case ':' :
 
442
            case '/' :
 
443
                if ( flags & PCT_ENCFLAG_SLASH ) {
 
444
                    escape = true;
 
445
                } else {
 
446
                    escape = false;
 
447
                }
 
448
            break;
 
449
            case '#' :
 
450
            case '[' :
 
451
            case ']' :
 
452
            case '@' :
 
453
            case '!' :
 
454
            case '$' :
 
455
            case '&' :
 
456
            case '\'' :
 
457
            case '(' :
 
458
            case ')' :
 
459
            case '*' :
 
460
            case '+' :
 
461
            case ';' :
 
462
            case '=' :
 
463
            /* unreserved */
 
464
            case '-' :
 
465
            case '.' :
 
466
            case '_' :
 
467
            case '~' :
 
468
                escape = false;
 
469
            break;
 
470
            default :
 
471
                if (  std::isalnum(*i) ) {
 
472
                    escape = false;
 
473
                } else {
 
474
                    escape = true;
 
475
                }
 
476
            break;
 
477
        }
 
478
        if ( escape ) {
 
479
            o << "%" << std::setw(2) << std::setfill('0') << (int)(unsigned char)*i ;
 
480
        } else {
 
481
            o.put(*i);
 
482
        }
 
483
    }
 
484
    dest = o.str();
 
485
    return dest;
 
486
}
 
487
 
 
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" },
 
494
   { 0, 0 }
 
495
};
 
496
 
 
497
LDAPUrlException::LDAPUrlException( int code, const std::string &msg) :
 
498
    m_code(code), m_addMsg(msg) {}
 
499
 
 
500
int LDAPUrlException::getCode() const
 
501
{
 
502
    return m_code;
 
503
}
 
504
 
 
505
const std::string LDAPUrlException::getAdditionalInfo() const
 
506
{
 
507
    return m_addMsg;
 
508
}
 
509
 
 
510
const std::string LDAPUrlException::getErrorMessage() const
 
511
{
 
512
    for ( int i = 0; code2string[i].string != 0; i++ ) {
 
513
        if ( code2string[i].code == m_code ) {
 
514
            return std::string(code2string[i].string);
 
515
        }
 
516
    }
 
517
    return "";
 
518
 
 
519
}