Back to index

lightning-sunbird  0.9+nobinonly
nsLDAPURL.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  * 
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is the mozilla.org LDAP XPCOM SDK.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 2000
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Dan Mosedale <dmose@mozilla.org>
00025  *   Leif Hedstrom <leif@netscape.com>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #include "nsLDAPURL.h"
00042 #include "nsReadableUtils.h"
00043 #include "netCore.h"
00044 #include "plstr.h"
00045 
00046 // The two schemes we support, LDAP and LDAPS
00047 //
00048 static const char kLDAPScheme[] = "ldap";
00049 static const char kLDAPSSLScheme[] = "ldaps";
00050 
00051 
00052 // Constructor and destructor
00053 //
00054 NS_IMPL_THREADSAFE_ISUPPORTS2(nsLDAPURL, nsILDAPURL, nsIURI)
00055 
00056 nsLDAPURL::nsLDAPURL()
00057     : mPort(0),
00058       mScope(SCOPE_BASE),
00059       mOptions(0),
00060       mAttributes(0)
00061 {
00062 }
00063 
00064 nsLDAPURL::~nsLDAPURL()
00065 {
00066     // Delete the array of attributes
00067     delete mAttributes;
00068 }
00069 
00070 nsresult
00071 nsLDAPURL::Init()
00072 {
00073     if (!mAttributes) {
00074         mAttributes = new nsCStringArray();
00075         if (!mAttributes) {
00076             NS_ERROR("nsLDAPURL::Init: out of memory ");
00077             return NS_ERROR_OUT_OF_MEMORY;
00078         }
00079     }
00080 
00081     return NS_OK;
00082 }
00083 
00084 // A string representation of the URI. Setting the spec 
00085 // causes the new spec to be parsed, initializing the URI. Setting
00086 // the spec (or any of the accessors) causes also any currently
00087 // open streams on the URI's channel to be closed.
00088 //
00089 // attribute string spec;
00090 //
00091 NS_IMETHODIMP 
00092 nsLDAPURL::GetSpec(nsACString &_retval)
00093 {
00094     nsCAutoString spec;
00095     PRUint32 count;
00096     
00097     spec = ((mOptions & OPT_SECURE) ? kLDAPSSLScheme : kLDAPScheme);
00098     spec.Append("://");
00099     if (!mHost.IsEmpty()) {
00100         spec.Append(mHost);
00101     }
00102     if (mPort > 0) {
00103         spec.Append(':');
00104         spec.AppendInt(mPort);
00105     }
00106     spec.Append('/');
00107     if (!mDN.IsEmpty()) {
00108         spec.Append(mDN);
00109     }
00110 
00111     if ((count = mAttributes->Count())) {
00112         PRUint32 index = 0;
00113 
00114         spec.Append('?');
00115         while (index < count) {
00116             spec.Append(*(mAttributes->CStringAt(index++)));
00117             if (index < count) {
00118                 spec.Append(',');
00119             }
00120         }
00121     }
00122 
00123     if (mScope || !mFilter.IsEmpty()) {
00124         spec.Append((count ? "?" : "??"));
00125         if (mScope) {
00126             if (mScope == SCOPE_ONELEVEL) {
00127                 spec.Append("one");
00128             } else if (mScope == SCOPE_SUBTREE) {
00129                 spec.Append("sub");
00130             }
00131         }
00132         if (!mFilter.IsEmpty()) {
00133             spec.Append('?');
00134             spec.Append(mFilter);
00135         }
00136     }
00137 
00138     _retval = spec;
00139     return NS_OK;
00140 }
00141 NS_IMETHODIMP 
00142 nsLDAPURL::SetSpec(const nsACString &aSpec)
00143 {
00144     PRUint32 rv, count;
00145     LDAPURLDesc *desc;
00146     nsCString str;
00147     char **attributes;
00148 
00149     // This is from the LDAP C-SDK, which currently doesn't
00150     // support everything from RFC 2255... :(
00151     //
00152     rv = ldap_url_parse(PromiseFlatCString(aSpec).get(), &desc);
00153     switch (rv) {
00154     case LDAP_SUCCESS:
00155         mHost = desc->lud_host;
00156         mPort = desc->lud_port;
00157         mDN = desc->lud_dn;
00158         mScope = desc->lud_scope;
00159         mFilter = desc->lud_filter;
00160         mOptions = desc->lud_options;
00161 
00162         // Set the attributes array, need to count it first.
00163         //
00164         count = 0;
00165         attributes = desc->lud_attrs;
00166         while (attributes && *attributes++) {
00167             count++;
00168         }
00169         if (count) {
00170             rv = SetAttributes(count,
00171                                NS_CONST_CAST(const char **, desc->lud_attrs));
00172             // This error could only be out-of-memory, so pass it up
00173             //
00174             if (NS_FAILED(rv)) {
00175                 return rv;
00176             }
00177         } else {
00178             mAttributes->Clear();
00179         }
00180 
00181         ldap_free_urldesc(desc);
00182         return NS_OK;
00183 
00184     case LDAP_URL_ERR_NOTLDAP:
00185     case LDAP_URL_ERR_NODN:
00186     case LDAP_URL_ERR_BADSCOPE:
00187         return NS_ERROR_MALFORMED_URI;
00188 
00189     case LDAP_URL_ERR_MEM:
00190         NS_ERROR("nsLDAPURL::SetSpec: out of memory ");
00191         return NS_ERROR_OUT_OF_MEMORY;
00192 
00193     case LDAP_URL_ERR_PARAM: 
00194         return NS_ERROR_INVALID_POINTER;
00195     }
00196 
00197     // This shouldn't happen...
00198     return NS_ERROR_UNEXPECTED;
00199 }
00200 
00201 // attribute string prePath;
00202 //
00203 NS_IMETHODIMP nsLDAPURL::GetPrePath(nsACString &_retval)
00204 {
00205     _retval.Truncate();
00206     return NS_OK;
00207 }
00208 
00209 // attribute string scheme;
00210 //
00211 NS_IMETHODIMP nsLDAPURL::GetScheme(nsACString &_retval)
00212 {
00213     _retval = (mOptions & OPT_SECURE) ? kLDAPSSLScheme : kLDAPScheme;
00214     return NS_OK;
00215 }
00216 NS_IMETHODIMP nsLDAPURL::SetScheme(const nsACString &aScheme)
00217 {
00218     if (aScheme.Equals(kLDAPScheme, nsCaseInsensitiveCStringComparator())) {
00219         mOptions ^= OPT_SECURE;
00220     } else if (aScheme.Equals(kLDAPSSLScheme, nsCaseInsensitiveCStringComparator())) {
00221         mOptions |= OPT_SECURE;
00222     } else {
00223         return NS_ERROR_MALFORMED_URI;
00224     }
00225 
00226     return NS_OK;
00227 }
00228 
00229 // attribute string userPass;
00230 //
00231 NS_IMETHODIMP 
00232 nsLDAPURL::GetUserPass(nsACString &_retval)
00233 {
00234     _retval.Truncate();
00235     return NS_OK;
00236 }
00237 NS_IMETHODIMP
00238 nsLDAPURL::SetUserPass(const nsACString &aPreHost)
00239 {
00240     return NS_ERROR_NOT_IMPLEMENTED;
00241 }
00242 
00243 // attribute string username
00244 //
00245 NS_IMETHODIMP
00246 nsLDAPURL::GetUsername(nsACString &_retval)
00247 {
00248     _retval.Truncate();
00249     return NS_OK;
00250 }
00251 NS_IMETHODIMP
00252 nsLDAPURL::SetUsername(const nsACString &aUsername)
00253 {
00254     return NS_ERROR_NOT_IMPLEMENTED;
00255 }
00256 
00257 // attribute string password;
00258 //
00259 NS_IMETHODIMP 
00260 nsLDAPURL::GetPassword(nsACString &_retval)
00261 {
00262     _retval.Truncate();
00263     return NS_OK;
00264 }
00265 NS_IMETHODIMP 
00266 nsLDAPURL::SetPassword(const nsACString &aPassword)
00267 {
00268     return NS_ERROR_NOT_IMPLEMENTED;
00269 }
00270 
00271 // attribute string hostPort;
00272 //
00273 NS_IMETHODIMP 
00274 nsLDAPURL::GetHostPort(nsACString &_retval)
00275 {
00276     _retval.Truncate();
00277     return NS_OK;
00278 }
00279 NS_IMETHODIMP 
00280 nsLDAPURL::SetHostPort(const nsACString &aHostPort)
00281 {
00282     return NS_ERROR_NOT_IMPLEMENTED;
00283 }
00284 
00285 // attribute string host;
00286 //
00287 NS_IMETHODIMP 
00288 nsLDAPURL::GetHost(nsACString &_retval)
00289 {
00290     _retval = mHost;
00291     return NS_OK;
00292 }
00293 NS_IMETHODIMP 
00294 nsLDAPURL::SetHost(const nsACString &aHost)
00295 {
00296     mHost = aHost;
00297     return NS_OK;
00298 }
00299 
00300 // C-SDK URL parser defaults port 389 as "0", while nsIURI
00301 // specifies the default to be "-1", hence the translations.
00302 //
00303 // attribute long port;
00304 //
00305 NS_IMETHODIMP 
00306 nsLDAPURL::GetPort(PRInt32 *_retval)
00307 {
00308     if (!_retval) {
00309         NS_ERROR("nsLDAPURL::GetPort: null pointer ");
00310         return NS_ERROR_NULL_POINTER;
00311     }
00312 
00313     if (!mPort) {
00314         *_retval = -1;
00315     } else {
00316         *_retval = mPort;
00317     }
00318         
00319     return NS_OK;
00320 }
00321 NS_IMETHODIMP 
00322 nsLDAPURL::SetPort(PRInt32 aPort)
00323 {
00324     if (aPort == -1) {
00325         mPort = 0;
00326     } else if (aPort >= 0) {
00327         mPort = aPort;
00328     } else {
00329         return NS_ERROR_MALFORMED_URI;
00330     }
00331     
00332     return NS_OK;
00333 }
00334 
00335 // attribute string path;
00336 // XXXleif: For now, these are identical to SetDn()/GetDn().
00337 NS_IMETHODIMP nsLDAPURL::GetPath(nsACString &_retval)
00338 {
00339     _retval = mDN;
00340     return NS_OK;
00341 }
00342 NS_IMETHODIMP nsLDAPURL::SetPath(const nsACString &aPath)
00343 {
00344     mDN = aPath;
00345     return NS_OK;
00346 }
00347 
00348 // attribute string specA
00349 NS_IMETHODIMP nsLDAPURL::GetAsciiSpec(nsACString &_retval)
00350 {
00351     return GetSpec(_retval);
00352 }
00353 // attribute string hostA
00354 NS_IMETHODIMP nsLDAPURL::GetAsciiHost(nsACString &_retval)
00355 {
00356     return GetHost(_retval);
00357 }
00358 
00359 NS_IMETHODIMP nsLDAPURL::GetOriginCharset(nsACString &result)
00360 {
00361     result.Truncate();
00362     return NS_OK;
00363 }
00364 
00365 // boolean equals (in nsIURI other)
00366 //
00367 NS_IMETHODIMP nsLDAPURL::Equals(nsIURI *other, PRBool *_retval)
00368 {
00369     return NS_ERROR_NOT_IMPLEMENTED;
00370 }
00371 
00372 // boolean schemeIs(in const char * scheme);
00373 //
00374 NS_IMETHODIMP nsLDAPURL::SchemeIs(const char *i_Scheme, PRBool *o_Equals)
00375 {
00376     if (!i_Scheme) return NS_ERROR_INVALID_ARG;
00377     if (*i_Scheme == 'l' || *i_Scheme == 'L') {
00378         *o_Equals = PL_strcasecmp("ldap", i_Scheme) ? PR_FALSE : PR_TRUE;
00379     } else {
00380         *o_Equals = PR_FALSE;
00381     }
00382 
00383     return NS_OK;
00384 }
00385 
00386 // nsIURI clone ();
00387 //
00388 NS_IMETHODIMP nsLDAPURL::Clone(nsIURI **_retval)
00389 {
00390     return NS_ERROR_NOT_IMPLEMENTED;
00391 }
00392 
00393 // string resolve (in string relativePath);
00394 //
00395 NS_IMETHODIMP nsLDAPURL::Resolve(const nsACString &relativePath,
00396                                  nsACString &_retval)
00397 {
00398     return NS_ERROR_NOT_IMPLEMENTED;
00399 }
00400 
00401 // The following attributes come from nsILDAPURL
00402 
00403 // attribute AUTF8String dn;
00404 //
00405 NS_IMETHODIMP nsLDAPURL::GetDn(nsACString& _retval)
00406 {
00407     _retval.Assign(mDN);
00408     return NS_OK;
00409 }
00410 NS_IMETHODIMP nsLDAPURL::SetDn(const nsACString& aDn)
00411 {
00412     mDN.Assign(aDn);
00413     return NS_OK;
00414 }
00415 
00416 // void getAttributes (out unsigned long aCount, 
00417 //                     [array, size_is (aCount), retval] out string aAttrs);
00418 //
00419 NS_IMETHODIMP nsLDAPURL::GetAttributes(PRUint32 *aCount, char ***_retval)
00420 {
00421     PRUint32 index = 0;
00422     PRUint32 count;
00423     char **cArray = nsnull;
00424 
00425     if (!_retval) {
00426         NS_ERROR("nsLDAPURL::GetAttributes: null pointer ");
00427         return NS_ERROR_NULL_POINTER;
00428     }
00429 
00430     count = mAttributes->Count();
00431     if (count > 0) {
00432         cArray = NS_STATIC_CAST(char **, nsMemory::Alloc(count * sizeof(char *)));
00433         if (!cArray) {
00434             NS_ERROR("nsLDAPURL::GetAttributes: out of memory ");
00435             return NS_ERROR_OUT_OF_MEMORY;
00436         }
00437 
00438         // Loop through the string array, and build up the C-array.
00439         //
00440         while (index < count) {
00441             if (!(cArray[index] = ToNewCString(*(mAttributes->CStringAt(index))))) {
00442                 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(index, cArray);
00443                 NS_ERROR("nsLDAPURL::GetAttributes: out of memory ");
00444                 return NS_ERROR_OUT_OF_MEMORY;
00445             }
00446             index++;
00447         }
00448     }
00449     *aCount = count;
00450     *_retval = cArray;
00451 
00452     return NS_OK;
00453 }
00454 // void setAttributes (in unsigned long aCount,
00455 //                     [array, size_is (aCount)] in string aAttrs); */
00456 NS_IMETHODIMP nsLDAPURL::SetAttributes(PRUint32 count, const char **aAttrs)
00457 {
00458     PRUint32 index = 0;
00459     nsCString str;
00460     
00461     mAttributes->Clear();
00462     while (index < count) {
00463         // Have to assign the str into this temporary nsCString, to make
00464         // the compilers happy...
00465         //
00466         str = nsDependentCString(aAttrs[index]);
00467         if (!mAttributes->InsertCStringAt(str, index++)) {
00468             NS_ERROR("nsLDAPURL::SetAttributes: out of memory ");
00469             return NS_ERROR_OUT_OF_MEMORY;
00470         }
00471     }
00472 
00473     return NS_OK;
00474 }
00475 // void addAttribute (in string aAttribute);
00476 //
00477 NS_IMETHODIMP nsLDAPURL::AddAttribute(const char *aAttribute)
00478 {
00479     nsCString str;
00480 
00481     str = nsDependentCString(aAttribute);
00482     if (mAttributes->IndexOfIgnoreCase(str) >= 0) {
00483         return NS_OK;
00484     }
00485 
00486     if (!mAttributes->InsertCStringAt(str, mAttributes->Count())) {
00487         NS_ERROR("nsLDAPURL::AddAttribute: out of memory ");
00488         return NS_ERROR_OUT_OF_MEMORY;
00489     }
00490 
00491     return NS_OK;
00492 }
00493 // void removeAttribute (in string aAttribute);
00494 //
00495 NS_IMETHODIMP nsLDAPURL::RemoveAttribute(const char *aAttribute)
00496 {
00497     nsCString str;
00498 
00499     str = nsDependentCString(aAttribute);
00500     mAttributes->RemoveCString(str);
00501 
00502     return NS_OK;
00503 }
00504 // boolean hasAttribute (in string aAttribute);
00505 //
00506 NS_IMETHODIMP nsLDAPURL::HasAttribute(const char *aAttribute, PRBool *_retval)
00507 {
00508     nsCString str;
00509 
00510     if (!_retval) {
00511         NS_ERROR("nsLDAPURL::HasAttribute: null pointer ");
00512         return NS_ERROR_NULL_POINTER;
00513     }
00514 
00515     str = nsDependentCString(aAttribute);
00516     if (mAttributes->IndexOfIgnoreCase(str) >= 0) {
00517         *_retval = PR_TRUE;
00518     } else {
00519         *_retval = PR_FALSE;
00520     }
00521     
00522     return NS_OK;
00523 }
00524 
00525 // attribute long scope;
00526 //
00527 NS_IMETHODIMP nsLDAPURL::GetScope(PRInt32 *_retval)
00528 {
00529     if (!_retval) {
00530         NS_ERROR("nsLDAPURL::GetScope: null pointer ");
00531         return NS_ERROR_NULL_POINTER;
00532     }
00533 
00534     *_retval = mScope;
00535     return NS_OK;
00536 }
00537 NS_IMETHODIMP nsLDAPURL::SetScope(PRInt32 aScope)
00538 {
00539     // Only allow scopes supported by the C-SDK
00540     if ((aScope != SCOPE_BASE) &&
00541         (aScope != SCOPE_ONELEVEL) &&
00542         (aScope != SCOPE_SUBTREE)) {
00543         return NS_ERROR_MALFORMED_URI;
00544     }
00545 
00546     mScope = aScope;
00547 
00548     return NS_OK;
00549 }
00550 
00551 // attribute string filter;
00552 //
00553 NS_IMETHODIMP nsLDAPURL::GetFilter(nsACString& _retval)
00554 {
00555     _retval.Assign(mFilter);
00556     return NS_OK;
00557 }
00558 NS_IMETHODIMP nsLDAPURL::SetFilter(const nsACString& aFilter)
00559 {
00560     mFilter.Assign(aFilter);
00561     return NS_OK;
00562 }
00563 
00564 // attribute unsigned long options;
00565 //
00566 NS_IMETHODIMP nsLDAPURL::GetOptions(PRUint32 *_retval)
00567 {
00568     if (!_retval) {
00569         NS_ERROR("nsLDAPURL::GetOptions: null pointer ");
00570         return NS_ERROR_NULL_POINTER;
00571     }
00572 
00573     *_retval = mOptions;
00574     return NS_OK;
00575 }
00576 NS_IMETHODIMP nsLDAPURL::SetOptions(PRUint32 aOptions)
00577 {
00578     mOptions = aOptions;
00579     return NS_OK;
00580 }