summaryrefslogtreecommitdiffstats
path: root/ldap/xpcom/src/nsLDAPSyncQuery.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/xpcom/src/nsLDAPSyncQuery.cpp')
-rw-r--r--ldap/xpcom/src/nsLDAPSyncQuery.cpp386
1 files changed, 386 insertions, 0 deletions
diff --git a/ldap/xpcom/src/nsLDAPSyncQuery.cpp b/ldap/xpcom/src/nsLDAPSyncQuery.cpp
new file mode 100644
index 000000000..e1f70ee7f
--- /dev/null
+++ b/ldap/xpcom/src/nsLDAPSyncQuery.cpp
@@ -0,0 +1,386 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsLDAPSyncQuery.h"
+#include "nsIServiceManager.h"
+#include "nsILDAPErrors.h"
+#include "nsThreadUtils.h"
+#include "nsILDAPMessage.h"
+#include "nsComponentManagerUtils.h"
+#include "nsServiceManagerUtils.h"
+#include "nsMemory.h"
+
+// nsISupports Implementation
+
+NS_IMPL_ISUPPORTS(nsLDAPSyncQuery, nsILDAPSyncQuery, nsILDAPMessageListener)
+
+// Constructor
+//
+nsLDAPSyncQuery::nsLDAPSyncQuery() :
+ mFinished(false), // This is a control variable for event loop
+ mProtocolVersion(nsILDAPConnection::VERSION3)
+{
+}
+
+// Destructor
+//
+nsLDAPSyncQuery::~nsLDAPSyncQuery()
+{
+}
+
+
+// Messages received are passed back via this function.
+// void OnLDAPMessage (in nsILDAPMessage aMessage)
+//
+NS_IMETHODIMP
+nsLDAPSyncQuery::OnLDAPMessage(nsILDAPMessage *aMessage)
+{
+ int32_t messageType;
+
+ // just in case.
+ //
+ if (!aMessage) {
+ return NS_OK;
+ }
+
+ // figure out what sort of message was returned
+ //
+ nsresult rv = aMessage->GetType(&messageType);
+ if (NS_FAILED(rv)) {
+ NS_ERROR("nsLDAPSyncQuery::OnLDAPMessage(): unexpected "
+ "error in aMessage->GetType()");
+ FinishLDAPQuery();
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ switch (messageType) {
+
+ case nsILDAPMessage::RES_BIND:
+
+ // a bind has completed
+ //
+ return OnLDAPBind(aMessage);
+
+ case nsILDAPMessage::RES_SEARCH_ENTRY:
+
+ // a search entry has been returned
+ //
+ return OnLDAPSearchEntry(aMessage);
+
+ case nsILDAPMessage::RES_SEARCH_RESULT:
+
+ // the search is finished; we're all done
+ //
+ return OnLDAPSearchResult(aMessage);
+
+ default:
+
+ // Given the LDAP operations nsLDAPSyncQuery uses, we should
+ // never get here. If we do get here in a release build, it's
+ // probably a bug, but maybe it's the LDAP server doing something
+ // weird. Might as well try and continue anyway. The session should
+ // eventually get reaped by the timeout code, if necessary.
+ //
+ NS_ERROR("nsLDAPSyncQuery::OnLDAPMessage(): unexpected "
+ "LDAP message received");
+ return NS_OK;
+ }
+}
+
+// void onLDAPInit (in nsresult aStatus);
+//
+NS_IMETHODIMP
+nsLDAPSyncQuery::OnLDAPInit(nsILDAPConnection *aConn, nsresult aStatus)
+{
+ nsresult rv; // temp for xpcom return values
+ // create and initialize an LDAP operation (to be used for the bind)
+ //
+ mOperation = do_CreateInstance("@mozilla.org/network/ldap-operation;1",
+ &rv);
+ if (NS_FAILED(rv)) {
+ FinishLDAPQuery();
+ return NS_ERROR_FAILURE;
+ }
+
+ // our OnLDAPMessage accepts all result callbacks
+ //
+ rv = mOperation->Init(mConnection, this, nullptr);
+ if (NS_FAILED(rv)) {
+ FinishLDAPQuery();
+ return NS_ERROR_UNEXPECTED; // this should never happen
+ }
+
+ // kick off a bind operation
+ //
+ rv = mOperation->SimpleBind(EmptyCString());
+ if (NS_FAILED(rv)) {
+ FinishLDAPQuery();
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsLDAPSyncQuery::OnLDAPBind(nsILDAPMessage *aMessage)
+{
+
+ int32_t errCode;
+
+ mOperation = nullptr; // done with bind op; make nsCOMPtr release it
+
+ // get the status of the bind
+ //
+ nsresult rv = aMessage->GetErrorCode(&errCode);
+ if (NS_FAILED(rv)) {
+
+ NS_ERROR("nsLDAPSyncQuery::OnLDAPBind(): couldn't get "
+ "error code from aMessage");
+ FinishLDAPQuery();
+ return NS_ERROR_FAILURE;
+ }
+
+
+ // check to be sure the bind succeeded
+ //
+ if (errCode != nsILDAPErrors::SUCCESS) {
+ FinishLDAPQuery();
+ return NS_ERROR_FAILURE;
+ }
+
+ // ok, we're starting a search
+ //
+ return StartLDAPSearch();
+}
+
+nsresult
+nsLDAPSyncQuery::OnLDAPSearchEntry(nsILDAPMessage *aMessage)
+{
+ uint32_t attrCount;
+ char** attributes;
+ nsresult rv = aMessage->GetAttributes(&attrCount, &attributes);
+ if (NS_FAILED(rv))
+ {
+ NS_WARNING("nsLDAPSyncQuery:OnLDAPSearchEntry(): "
+ "aMessage->GetAttributes() failed");
+ FinishLDAPQuery();
+ return rv;
+ }
+
+ // Iterate through the attributes received in this message
+ for (uint32_t i = 0; i < attrCount; i++)
+ {
+ char16_t **vals;
+ uint32_t valueCount;
+
+ // Get the values of this attribute.
+ // XXX better failure handling
+ rv = aMessage->GetValues(attributes[i], &valueCount, &vals);
+ if (NS_FAILED(rv))
+ {
+ NS_WARNING("nsLDAPSyncQuery:OnLDAPSearchEntry(): "
+ "aMessage->GetValues() failed\n");
+ FinishLDAPQuery();
+ break;
+ }
+
+ // Store all values of this attribute in the mResults.
+ for (uint32_t j = 0; j < valueCount; j++) {
+ mResults.Append(char16_t('\n'));
+ mResults.AppendASCII(attributes[i]);
+ mResults.Append(char16_t('='));
+ mResults.Append(vals[j]);
+ }
+
+ NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(valueCount, vals);
+ }
+ NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(attrCount, attributes);
+
+ return rv;
+}
+
+
+nsresult
+nsLDAPSyncQuery::OnLDAPSearchResult(nsILDAPMessage *aMessage)
+{
+ // We are done with the LDAP search.
+ // Release the control variable for the eventloop and other members
+ //
+ FinishLDAPQuery();
+ return NS_OK;
+}
+
+nsresult
+nsLDAPSyncQuery::StartLDAPSearch()
+{
+ nsresult rv;
+ // create and initialize an LDAP operation (to be used for the search
+ //
+ mOperation =
+ do_CreateInstance("@mozilla.org/network/ldap-operation;1", &rv);
+
+ if (NS_FAILED(rv)) {
+ NS_ERROR("nsLDAPSyncQuery::StartLDAPSearch(): couldn't "
+ "create @mozilla.org/network/ldap-operation;1");
+ FinishLDAPQuery();
+ return NS_ERROR_FAILURE;
+ }
+
+ // initialize the LDAP operation object
+ //
+ rv = mOperation->Init(mConnection, this, nullptr);
+ if (NS_FAILED(rv)) {
+ NS_ERROR("nsLDAPSyncQuery::StartLDAPSearch(): couldn't "
+ "initialize LDAP operation");
+ FinishLDAPQuery();
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ // get the search filter associated with the directory server url;
+ //
+ nsAutoCString urlFilter;
+ rv = mServerURL->GetFilter(urlFilter);
+ if (NS_FAILED(rv)) {
+ FinishLDAPQuery();
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ // get the base dn to search
+ //
+ nsAutoCString dn;
+ rv = mServerURL->GetDn(dn);
+ if (NS_FAILED(rv)) {
+ FinishLDAPQuery();
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ // and the scope
+ //
+ int32_t scope;
+ rv = mServerURL->GetScope(&scope);
+ if (NS_FAILED(rv)) {
+ FinishLDAPQuery();
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsAutoCString attributes;
+ rv = mServerURL->GetAttributes(attributes);
+ if (NS_FAILED(rv)) {
+ FinishLDAPQuery();
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ // time to kick off the search.
+ rv = mOperation->SearchExt(dn, scope, urlFilter, attributes, 0, 0);
+
+ if (NS_FAILED(rv)) {
+ FinishLDAPQuery();
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+// void initConnection ();
+//
+nsresult nsLDAPSyncQuery::InitConnection()
+{
+ // Because mConnection->Init proxies back to the main thread, this
+ // better be the main thread.
+ NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_FAILURE);
+ nsresult rv; // temp for xpcom return values
+ // create an LDAP connection
+ //
+ mConnection = do_CreateInstance("@mozilla.org/network/ldap-connection;1",
+ &rv);
+ if (NS_FAILED(rv)) {
+ NS_ERROR("nsLDAPSyncQuery::InitConnection(): could "
+ "not create @mozilla.org/network/ldap-connection;1");
+ FinishLDAPQuery();
+ return NS_ERROR_FAILURE;
+ }
+
+ // have we been properly initialized?
+ //
+ if (!mServerURL) {
+ NS_ERROR("nsLDAPSyncQuery::InitConnection(): mServerURL "
+ "is NULL");
+ FinishLDAPQuery();
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ rv = mConnection->Init(mServerURL, EmptyCString(), this,
+ nullptr, mProtocolVersion);
+ if (NS_FAILED(rv)) {
+ FinishLDAPQuery();
+ return NS_ERROR_UNEXPECTED; // this should never happen
+ }
+
+ return NS_OK;
+}
+
+void
+nsLDAPSyncQuery::FinishLDAPQuery()
+{
+ // We are done with the LDAP operation.
+ // Release the Control variable for the eventloop
+ //
+ mFinished = true;
+
+ // Release member variables
+ //
+ mConnection = nullptr;
+ mOperation = nullptr;
+ mServerURL = nullptr;
+
+}
+
+/* wstring getQueryResults (in nsILDAPURL aServerURL, in unsigned long aVersion); */
+NS_IMETHODIMP nsLDAPSyncQuery::GetQueryResults(nsILDAPURL *aServerURL,
+ uint32_t aProtocolVersion,
+ char16_t **_retval)
+{
+ nsresult rv;
+
+ if (!aServerURL) {
+ NS_ERROR("nsLDAPSyncQuery::GetQueryResults() called without LDAP URL");
+ return NS_ERROR_FAILURE;
+ }
+ mServerURL = aServerURL;
+ mProtocolVersion = aProtocolVersion;
+
+ nsCOMPtr<nsIThread> currentThread = do_GetCurrentThread();
+
+ // Start an LDAP query.
+ // InitConnection will bind to the ldap server and post a OnLDAPMessage
+ // event. This event will trigger a search and the whole operation will
+ // be carried out by chain of events
+ //
+ rv = InitConnection();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // We want this LDAP query to be synchronous while the XPCOM LDAP is
+ // async in nature. So this eventQueue handling will wait for the
+ // LDAP operation to be finished.
+ // mFinished controls the state of the LDAP opertion.
+ // It will be released in any case (success/failure)
+
+
+ // Run the event loop,
+ // mFinished is a control variable
+ //
+ while (!mFinished)
+ NS_ENSURE_STATE(NS_ProcessNextEvent(currentThread));
+
+ // Return results
+ //
+ if (!mResults.IsEmpty()) {
+ *_retval = ToNewUnicode(mResults);
+ if (!_retval)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ return rv;
+
+}