Back to index

lightning-sunbird  0.9+nobinonly
nsLDAPMessage.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  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsLDAPInternal.h"
00041 #include "nsLDAPMessage.h"
00042 #include "nspr.h"
00043 #include "nsDebug.h"
00044 #include "nsCRT.h"
00045 #include "nsLDAPConnection.h"
00046 #include "nsReadableUtils.h"
00047 #include "nsISupportsUtils.h"
00048 #include "nsLDAPBERValue.h"
00049 
00050 
00051 NS_IMPL_THREADSAFE_ADDREF(nsLDAPMessage)
00052 NS_IMPL_THREADSAFE_RELEASE(nsLDAPMessage)
00053 NS_INTERFACE_MAP_BEGIN(nsLDAPMessage)
00054   NS_INTERFACE_MAP_ENTRY(nsILDAPMessage)
00055   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsILDAPMessage)
00056   NS_IMPL_QUERY_CLASSINFO(nsLDAPMessage)
00057 NS_INTERFACE_MAP_END_THREADSAFE
00058 NS_IMPL_CI_INTERFACE_GETTER1(nsLDAPMessage, nsILDAPMessage)
00059 
00060 
00061 // constructor
00062 //
00063 nsLDAPMessage::nsLDAPMessage() 
00064     : mMsgHandle(0),
00065       mErrorCode(LDAP_SUCCESS),
00066       mMatchedDn(0),
00067       mErrorMessage(0),
00068       mReferrals(0),
00069       mServerControls(0)
00070 {
00071 }
00072 
00073 // destructor
00074 //
00075 nsLDAPMessage::~nsLDAPMessage(void)
00076 {
00077     if (mMsgHandle) {
00078         int rc = ldap_msgfree(mMsgHandle);
00079 
00080 // If you are having problems compiling the following code on a Solaris
00081 // machine with the Forte 6 Update 1 compilers, then you need to make 
00082 // sure you have applied all the required patches. See:
00083 // http://www.mozilla.org/unix/solaris-build.html for more details.
00084 
00085         switch(rc) {
00086         case LDAP_RES_BIND:
00087         case LDAP_RES_SEARCH_ENTRY:
00088         case LDAP_RES_SEARCH_RESULT:
00089         case LDAP_RES_MODIFY:
00090         case LDAP_RES_ADD:
00091         case LDAP_RES_DELETE:
00092         case LDAP_RES_MODRDN:
00093         case LDAP_RES_COMPARE:
00094         case LDAP_RES_SEARCH_REFERENCE:
00095         case LDAP_RES_EXTENDED:
00096         case LDAP_RES_ANY:
00097             // success
00098             break;
00099 
00100         case LDAP_SUCCESS:
00101             // timed out (dunno why LDAP_SUCCESS is used to indicate this) 
00102             PR_LOG(gLDAPLogModule, PR_LOG_WARNING, 
00103                    ("nsLDAPMessage::~nsLDAPMessage: ldap_msgfree() "
00104                     "timed out\n"));
00105             break;
00106 
00107         default:
00108             // other failure
00109             PR_LOG(gLDAPLogModule, PR_LOG_WARNING, 
00110                    ("nsLDAPMessage::~nsLDAPMessage: ldap_msgfree() "
00111                     "failed: %s\n", ldap_err2string(rc)));
00112             break;
00113         }
00114     }
00115 
00116     if (mMatchedDn) {
00117         ldap_memfree(mMatchedDn);
00118     }
00119 
00120     if (mErrorMessage) {
00121         ldap_memfree(mErrorMessage);
00122     }
00123 
00124     if (mReferrals) {
00125         ldap_value_free(mReferrals);
00126     }
00127 
00128     if (mServerControls) {
00129         ldap_controls_free(mServerControls);
00130     }
00131 
00132 }
00133 
00145 nsresult 
00146 nsLDAPMessage::Init(nsILDAPConnection *aConnection, LDAPMessage *aMsgHandle)
00147 {
00148     int parseResult; 
00149 
00150     if (!aConnection || !aMsgHandle) {
00151         NS_WARNING("Null pointer passed in to nsLDAPMessage::Init()");
00152         return NS_ERROR_ILLEGAL_VALUE;
00153     }
00154 
00155     // initialize the appropriate member vars
00156     //
00157     mConnection = aConnection;
00158     mMsgHandle = aMsgHandle;
00159 
00160     // cache the connection handle.  we're violating the XPCOM type-system
00161     // here since we're a friend of the connection class and in the 
00162     // same module.
00163     //
00164     mConnectionHandle = NS_STATIC_CAST(nsLDAPConnection *, 
00165                                             aConnection)->mConnectionHandle;
00166 
00167     // do any useful message parsing
00168     //
00169     const int msgType = ldap_msgtype(mMsgHandle);
00170     if ( msgType == -1) {
00171         NS_ERROR("nsLDAPMessage::Init(): ldap_msgtype() failed");
00172         return NS_ERROR_UNEXPECTED;
00173     }
00174 
00175     switch (msgType) {
00176 
00177     case LDAP_RES_SEARCH_REFERENCE:
00178         // XXX should do something here?
00179         break;
00180 
00181     case LDAP_RES_SEARCH_ENTRY:
00182         // nothing to do here
00183         break;
00184 
00185     case LDAP_RES_EXTENDED:
00186         // XXX should do something here?
00187         break;
00188 
00189     case LDAP_RES_BIND:
00190     case LDAP_RES_SEARCH_RESULT:
00191     case LDAP_RES_MODIFY:
00192     case LDAP_RES_ADD:
00193     case LDAP_RES_DELETE:
00194     case LDAP_RES_MODRDN:
00195     case LDAP_RES_COMPARE:
00196         parseResult = ldap_parse_result(mConnectionHandle, 
00197                                         mMsgHandle, &mErrorCode, &mMatchedDn,
00198                                         &mErrorMessage,&mReferrals, 
00199                                         &mServerControls, 0);
00200         switch (parseResult) {
00201         case LDAP_SUCCESS: 
00202             // we're good
00203             break;
00204 
00205         case LDAP_DECODING_ERROR:
00206             NS_WARNING("nsLDAPMessage::Init(): ldap_parse_result() hit a "
00207                        "decoding error");
00208             return NS_ERROR_LDAP_DECODING_ERROR;
00209 
00210         case LDAP_NO_MEMORY:
00211             NS_WARNING("nsLDAPMessage::Init(): ldap_parse_result() ran out " 
00212                        "of memory");
00213             return NS_ERROR_OUT_OF_MEMORY;
00214 
00215         case LDAP_PARAM_ERROR:
00216         case LDAP_MORE_RESULTS_TO_RETURN:
00217         case LDAP_NO_RESULTS_RETURNED:
00218         default:
00219             NS_ERROR("nsLDAPMessage::Init(): ldap_parse_result returned "
00220                      "unexpected return code");
00221             return NS_ERROR_UNEXPECTED;
00222         }
00223 
00224         break;
00225 
00226     default:
00227         NS_ERROR("nsLDAPMessage::Init(): unexpected message type");
00228         return NS_ERROR_UNEXPECTED;
00229     }
00230 
00231     return NS_OK;
00232 }
00233 
00241 NS_IMETHODIMP
00242 nsLDAPMessage::GetErrorCode(PRInt32 *aErrorCode)
00243 {
00244     if (!aErrorCode) {
00245         return NS_ERROR_ILLEGAL_VALUE;
00246     }
00247 
00248     *aErrorCode = mErrorCode;
00249     return NS_OK;
00250 }
00251 
00252 NS_IMETHODIMP
00253 nsLDAPMessage::GetType(PRInt32 *aType)
00254 {
00255     if (!aType) {
00256         return NS_ERROR_ILLEGAL_VALUE;
00257     }
00258 
00259     *aType = ldap_msgtype(mMsgHandle);
00260     if (*aType == -1) {
00261         return NS_ERROR_UNEXPECTED;
00262     };
00263 
00264     return NS_OK;
00265 }
00266 
00267 // we don't get to use exceptions, so we'll fake it.  this is an error
00268 // handler for IterateAttributes().  
00269 //
00270 nsresult
00271 nsLDAPMessage::IterateAttrErrHandler(PRInt32 aLderrno, PRUint32 *aAttrCount, 
00272                                      char** *aAttributes, BerElement *position)
00273 {
00274 
00275     // if necessary, free the position holder used by 
00276     // ldap_{first,next}_attribute()  
00277     //
00278     if (position) {
00279         ldap_ber_free(position, 0);
00280     }
00281 
00282     // deallocate any entries in the array that have been allocated, then
00283     // the array itself
00284     //
00285     if (*aAttributes) {
00286         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(*aAttrCount, *aAttributes);
00287     }
00288 
00289     // possibly spit out a debugging message, then return an appropriate
00290     // error code
00291     //
00292     switch (aLderrno) {
00293 
00294     case LDAP_PARAM_ERROR:
00295         NS_WARNING("nsLDAPMessage::IterateAttributes() failure; probable bug "
00296                    "or memory corruption encountered");
00297         return NS_ERROR_UNEXPECTED;
00298         break;
00299 
00300     case LDAP_DECODING_ERROR:
00301         NS_WARNING("nsLDAPMessage::IterateAttributes(): decoding error");
00302         return NS_ERROR_LDAP_DECODING_ERROR;
00303         break;
00304 
00305     case LDAP_NO_MEMORY:
00306         return NS_ERROR_OUT_OF_MEMORY;
00307         break;
00308 
00309     }
00310 
00311     NS_WARNING("nsLDAPMessage::IterateAttributes(): LDAP C SDK returned "
00312                "unexpected value; possible bug or memory corruption");
00313     return NS_ERROR_UNEXPECTED;
00314 }
00315 
00316 
00317 // wrapper for ldap_first_attribute 
00318 //
00319 NS_IMETHODIMP
00320 nsLDAPMessage::GetAttributes(PRUint32 *aAttrCount, char** *aAttributes)
00321 {
00322     return IterateAttributes(aAttrCount, aAttributes, PR_TRUE);
00323 }
00324 
00325 // if getP is PR_TRUE, we get the attributes by recursing once
00326 // (without getP set) in order to fill in *attrCount, then allocate
00327 // and fill in the *aAttributes.  
00328 // 
00329 // if getP is PR_FALSE, just fill in *attrCount and return
00330 // 
00331 nsresult
00332 nsLDAPMessage::IterateAttributes(PRUint32 *aAttrCount, char** *aAttributes, 
00333                  PRBool getP)
00334 {
00335     BerElement *position;
00336     nsresult rv;
00337 
00338     if (!aAttrCount || !aAttributes ) {
00339         return NS_ERROR_INVALID_POINTER;
00340     }
00341 
00342     // if we've been called from GetAttributes, recurse once in order to
00343     // count the elements in this message.
00344     //
00345     if (getP) {
00346         *aAttributes = 0;
00347         *aAttrCount = 0;
00348 
00349         rv = IterateAttributes(aAttrCount, aAttributes, PR_FALSE);
00350         if (NS_FAILED(rv))
00351             return rv;
00352 
00353         // create an array of the appropriate size
00354         //
00355         *aAttributes = NS_STATIC_CAST(char **, 
00356                                       nsMemory::Alloc(*aAttrCount *
00357                                                       sizeof(char *)));
00358         if (!*aAttributes) {
00359             return NS_ERROR_OUT_OF_MEMORY;
00360         }
00361     } 
00362 
00363     // get the first attribute
00364     //
00365     char *attr = ldap_first_attribute(mConnectionHandle, 
00366                                       mMsgHandle, 
00367                                       &position);
00368     if (!attr) {
00369         return IterateAttrErrHandler(ldap_get_lderrno(mConnectionHandle, 0, 0),
00370                                      aAttrCount, aAttributes, position);
00371     }
00372 
00373     // if we're getting attributes, try and fill in the first field
00374     //
00375     if (getP) {
00376         (*aAttributes)[0] = nsCRT::strdup(attr);
00377         if (!(*aAttributes)[0]) {
00378             ldap_memfree(attr);
00379             nsMemory::Free(*aAttributes);
00380             return NS_ERROR_OUT_OF_MEMORY;
00381         }
00382 
00383         // note that we start counting again, in order to keep our place in 
00384         // the array so that we can unwind gracefully and avoid leakage if
00385         // we hit an error as we're filling in the array
00386         //
00387         *aAttrCount = 1;
00388     } else {
00389 
00390         // otherwise just update the count
00391         //
00392         *aAttrCount = 1;
00393     }
00394     ldap_memfree(attr);
00395 
00396     while (1) {
00397     
00398         // get the next attribute
00399         //
00400         attr = ldap_next_attribute(mConnectionHandle, mMsgHandle, position);
00401 
00402         // check to see if there is an error, or if we're just done iterating
00403         //
00404         if (!attr) {
00405             
00406             // bail out if there's an error
00407             //
00408             PRInt32 lderrno = ldap_get_lderrno(mConnectionHandle, 0, 0);
00409             if (lderrno != LDAP_SUCCESS) {
00410                 return IterateAttrErrHandler(lderrno, aAttrCount, aAttributes, 
00411                                              position);
00412             }
00413 
00414             // otherwise, there are no more attributes; we're done with
00415             // the while loop
00416             //
00417             break;
00418 
00419         } else if (getP) {
00420 
00421             // if ldap_next_attribute did return successfully, and 
00422             // we're supposed to fill in a value, do so.
00423             //
00424             (*aAttributes)[*aAttrCount] = nsCRT::strdup(attr);
00425             if (!(*aAttributes)[*aAttrCount]) {
00426                 ldap_memfree(attr);
00427                 return IterateAttrErrHandler(LDAP_NO_MEMORY, aAttrCount, 
00428                                              aAttributes, position);
00429             }
00430        
00431         }
00432         ldap_memfree(attr);
00433 
00434         // we're done using *aAttrCount as a c-style array index (ie starting
00435         // at 0).  update it to reflect the number of elements now in the array
00436         //
00437         *aAttrCount += 1;
00438     }
00439 
00440     // free the position pointer, if necessary
00441     //
00442     if (position) {
00443         ldap_ber_free(position, 0);
00444     }
00445 
00446     return NS_OK;
00447 }
00448 
00449 // readonly attribute wstring dn;
00450 NS_IMETHODIMP nsLDAPMessage::GetDn(nsACString& aDn)
00451 {
00452     char *rawDn = ldap_get_dn(mConnectionHandle, mMsgHandle);
00453 
00454     if (!rawDn) {
00455         PRInt32 lderrno = ldap_get_lderrno(mConnectionHandle, 0, 0);
00456 
00457         switch (lderrno) {
00458 
00459         case LDAP_DECODING_ERROR:
00460             NS_WARNING("nsLDAPMessage::GetDn(): ldap decoding error");
00461             return NS_ERROR_LDAP_DECODING_ERROR;
00462 
00463         case LDAP_PARAM_ERROR:
00464         default:
00465             NS_ERROR("nsLDAPMessage::GetDn(): internal error");
00466             return NS_ERROR_UNEXPECTED;
00467         }
00468     }
00469 
00470     PR_LOG(gLDAPLogModule, PR_LOG_DEBUG,
00471            ("nsLDAPMessage::GetDn(): dn = '%s'", rawDn));
00472 
00473     aDn.Assign(rawDn);
00474     ldap_memfree(rawDn);
00475 
00476     return NS_OK;
00477 }
00478 
00479 // wrapper for ldap_get_values()
00480 //
00481 NS_IMETHODIMP
00482 nsLDAPMessage::GetValues(const char *aAttr, PRUint32 *aCount, 
00483                          PRUnichar ***aValues)
00484 {
00485     char **values;
00486     
00487 #if defined(DEBUG)
00488     // We only want this being logged for debug builds so as not to affect performance too much.
00489     PR_LOG(gLDAPLogModule, PR_LOG_DEBUG,
00490            ("nsLDAPMessage::GetValues(): called with aAttr = '%s'", aAttr));
00491 #endif
00492 
00493     values = ldap_get_values(mConnectionHandle, mMsgHandle, aAttr);
00494 
00495     // bail out if there was a problem
00496     //
00497     if (!values) {
00498         PRInt32 lderrno = ldap_get_lderrno(mConnectionHandle, 0, 0);
00499 
00500         if ( lderrno == LDAP_DECODING_ERROR ) {
00501             // this may not be an error; it could just be that the 
00502             // caller has asked for an attribute that doesn't exist.
00503             //
00504             PR_LOG(gLDAPLogModule, PR_LOG_WARNING, 
00505                    ("nsLDAPMessage::GetValues(): ldap_get_values returned "
00506                     "LDAP_DECODING_ERROR"));
00507             return NS_ERROR_LDAP_DECODING_ERROR;
00508 
00509         } else if ( lderrno == LDAP_PARAM_ERROR ) {
00510             NS_ERROR("nsLDAPMessage::GetValues(): internal error: 1");
00511             return NS_ERROR_UNEXPECTED;
00512 
00513         } else {
00514             NS_ERROR("nsLDAPMessage::GetValues(): internal error: 2");
00515             return NS_ERROR_UNEXPECTED;
00516         }
00517     }
00518 
00519     // count the values
00520     //
00521     PRUint32 numVals = ldap_count_values(values);
00522 
00523     // create an array of the appropriate size
00524     //
00525     *aValues = NS_STATIC_CAST(PRUnichar **, 
00526                               nsMemory::Alloc(numVals * sizeof(PRUnichar *)));
00527     if (!*aValues) {
00528         ldap_value_free(values);
00529         return NS_ERROR_OUT_OF_MEMORY;
00530     }
00531 
00532     // clone the array (except for the trailing NULL entry) using the 
00533     // shared allocator for XPCOM correctness
00534     //
00535     PRUint32 i;
00536     for ( i = 0 ; i < numVals ; i++ ) {
00537         nsDependentCString sValue(values[i]);
00538         if (IsUTF8(sValue))
00539             (*aValues)[i] = UTF8ToNewUnicode(sValue);
00540         else
00541             (*aValues)[i] = ToNewUnicode(sValue);
00542         if ( ! (*aValues)[i] ) {
00543             NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, aValues);
00544             ldap_value_free(values);
00545             return NS_ERROR_OUT_OF_MEMORY;
00546         }
00547     }
00548 
00549     // now free our value array since we already cloned the values array 
00550     // to the 'aValues' results array.
00551     ldap_value_free(values);
00552 
00553     *aCount = numVals;
00554     return NS_OK;
00555 }
00556 
00557 // wrapper for get_values_len
00558 //
00559 NS_IMETHODIMP 
00560 nsLDAPMessage::GetBinaryValues(const char *aAttr, PRUint32 *aCount,
00561                                nsILDAPBERValue ***aValues)
00562 {
00563     struct berval **values;
00564 
00565 #if defined(DEBUG)
00566     // We only want this being logged for debug builds so as not to affect performance too much.
00567     PR_LOG(gLDAPLogModule, PR_LOG_DEBUG,
00568            ("nsLDAPMessage::GetBinaryValues(): called with aAttr = '%s'", 
00569             aAttr));
00570 #endif
00571 
00572     values = ldap_get_values_len(mConnectionHandle, mMsgHandle, aAttr);
00573 
00574     // bail out if there was a problem
00575     //
00576     if (!values) {
00577         PRInt32 lderrno = ldap_get_lderrno(mConnectionHandle, 0, 0);
00578 
00579         if ( lderrno == LDAP_DECODING_ERROR ) {
00580             // this may not be an error; it could just be that the 
00581             // caller has asked for an attribute that doesn't exist.
00582             //
00583             PR_LOG(gLDAPLogModule, PR_LOG_WARNING, 
00584                    ("nsLDAPMessage::GetBinaryValues(): ldap_get_values "
00585                     "returned LDAP_DECODING_ERROR"));
00586             return NS_ERROR_LDAP_DECODING_ERROR;
00587 
00588         } else if ( lderrno == LDAP_PARAM_ERROR ) {
00589             NS_ERROR("nsLDAPMessage::GetBinaryValues(): internal error: 1");
00590             return NS_ERROR_UNEXPECTED;
00591 
00592         } else {
00593             NS_ERROR("nsLDAPMessage::GetBinaryValues(): internal error: 2");
00594             return NS_ERROR_UNEXPECTED;
00595         }
00596     }
00597 
00598     // count the values
00599     //
00600     PRUint32 numVals = ldap_count_values_len(values);
00601 
00602     // create the out array
00603     //
00604     *aValues = 
00605         NS_STATIC_CAST(nsILDAPBERValue **, 
00606                        nsMemory::Alloc(numVals * sizeof(nsILDAPBERValue)));
00607     if (!aValues) {
00608         ldap_value_free_len(values);
00609         return NS_ERROR_OUT_OF_MEMORY;
00610     }
00611 
00612     // clone the array (except for the trailing NULL entry) using the 
00613     // shared allocator for XPCOM correctness
00614     //
00615     PRUint32 i;
00616     nsresult rv;
00617     nsCOMPtr<nsILDAPBERValue> berValue;
00618     for ( i = 0 ; i < numVals ; i++ ) {
00619 
00620         // create an nsBERValue object
00621         //
00622         NS_NEWXPCOM(berValue, nsLDAPBERValue);
00623         if (!berValue) {
00624             NS_ERROR("nsLDAPMessage::GetBinaryValues(): out of memory"
00625                      " creating nsLDAPBERValue object");
00626             NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, aValues);
00627             ldap_value_free_len(values);
00628             return NS_ERROR_OUT_OF_MEMORY;
00629         }
00630 
00631         // copy the value from the struct into the nsBERValue
00632         //
00633         rv = berValue->Set(values[i]->bv_len, 
00634                            NS_REINTERPRET_CAST(PRUint8 *, values[i]->bv_val));
00635         if (NS_FAILED(rv)) {
00636             NS_ERROR("nsLDAPMessage::GetBinaryValues(): error setting"
00637                      " nsBERValue");
00638             ldap_value_free_len(values);
00639             return rv == NS_ERROR_OUT_OF_MEMORY ? rv : NS_ERROR_UNEXPECTED;
00640         }
00641 
00642         // put the nsIBERValue object into the out array
00643         //
00644         NS_ADDREF( (*aValues)[i] = berValue.get() );
00645     }
00646 
00647     *aCount = numVals;
00648     ldap_value_free_len(values);
00649     return NS_OK;
00650 }
00651 
00652 // readonly attribute nsILDAPOperation operation;
00653 NS_IMETHODIMP nsLDAPMessage::GetOperation(nsILDAPOperation **_retval)
00654 {
00655     if (!_retval) {
00656         NS_ERROR("nsLDAPMessage::GetOperation: null pointer ");
00657         return NS_ERROR_NULL_POINTER;
00658     }
00659 
00660     NS_IF_ADDREF(*_retval = mOperation);
00661     return NS_OK;
00662 }
00663 
00664 NS_IMETHODIMP
00665 nsLDAPMessage::ToUnicode(PRUnichar* *aString)
00666 {
00667     return NS_ERROR_NOT_IMPLEMENTED;
00668 }
00669 
00670 NS_IMETHODIMP
00671 nsLDAPMessage::GetErrorMessage(nsACString & aErrorMessage)
00672 {
00673     aErrorMessage.Assign(mErrorMessage);
00674     return NS_OK;
00675 }
00676 
00677 NS_IMETHODIMP
00678 nsLDAPMessage::GetMatchedDn(nsACString & aMatchedDn)
00679 {
00680     aMatchedDn.Assign(mMatchedDn);
00681     return NS_OK;
00682 }
00683