diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/mailnews/addrbook/src/nsLDAPURL.cpp | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/mailnews/addrbook/src/nsLDAPURL.cpp')
-rw-r--r-- | comm/mailnews/addrbook/src/nsLDAPURL.cpp | 591 |
1 files changed, 591 insertions, 0 deletions
diff --git a/comm/mailnews/addrbook/src/nsLDAPURL.cpp b/comm/mailnews/addrbook/src/nsLDAPURL.cpp new file mode 100644 index 0000000000..90e4e370e4 --- /dev/null +++ b/comm/mailnews/addrbook/src/nsLDAPURL.cpp @@ -0,0 +1,591 @@ +/* -*- 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 "nsLDAPURL.h" +#include "netCore.h" +#include "plstr.h" +#include "nsCOMPtr.h" +#include "nsNetCID.h" +#include "nsComponentManagerUtils.h" +#include "nsIStandardURL.h" +#include "nsMsgUtils.h" +#include "nsUnicharUtils.h" +#include "mozilla/Encoding.h" + +// The two schemes we support, LDAP and LDAPS +// +constexpr auto LDAP_SCHEME = "ldap"_ns; +constexpr auto LDAP_SSL_SCHEME = "ldaps"_ns; + +NS_IMPL_ISUPPORTS(nsLDAPURL, nsILDAPURL, nsIURI) + +nsLDAPURL::nsLDAPURL() : mScope(SCOPE_BASE), mOptions(0) {} + +nsLDAPURL::~nsLDAPURL() {} + +nsresult nsLDAPURL::Init(uint32_t aUrlType, int32_t aDefaultPort, + const nsACString& aSpec, const char* aOriginCharset, + nsIURI* aBaseURI) { + nsresult rv; + nsCOMPtr<nsIURI> base(aBaseURI); + rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID) + .Apply(&nsIStandardURLMutator::Init, + nsIStandardURL::URLTYPE_STANDARD, aDefaultPort, + PromiseFlatCString(aSpec), aOriginCharset, aBaseURI, nullptr) + .Finalize(mBaseURL); + NS_ENSURE_SUCCESS(rv, rv); + + // Now get the spec from the mBaseURL in case it was a relative one + nsCString spec; + rv = mBaseURL->GetSpec(spec); + NS_ENSURE_SUCCESS(rv, rv); + + return SetSpecInternal(spec); +} + +void nsLDAPURL::GetPathInternal(nsCString& aPath) { + aPath.Assign('/'); + + if (!mDN.IsEmpty()) aPath.Append(mDN); + + if (!mAttributes.IsEmpty()) aPath.Append('?'); + + // If mAttributes isn't empty, cut off the internally stored commas at start + // and end, and append to the path. + if (!mAttributes.IsEmpty()) + aPath.Append(Substring(mAttributes, 1, mAttributes.Length() - 2)); + + if (mScope || !mFilter.IsEmpty()) { + aPath.Append((mAttributes.IsEmpty() ? "??" : "?")); + if (mScope) { + if (mScope == SCOPE_ONELEVEL) + aPath.Append("one"); + else if (mScope == SCOPE_SUBTREE) + aPath.Append("sub"); + } + if (!mFilter.IsEmpty()) { + aPath.Append('?'); + aPath.Append(mFilter); + } + } +} + +nsresult nsLDAPURL::SetPathInternal(const nsCString& aPath) { + nsCOMPtr<nsILDAPURLParser> parser = + do_CreateInstance("@mozilla.org/network/ldap-url-parser;1"); + nsCOMPtr<nsILDAPURLParserResult> parserResult; + nsresult rv = parser->Parse(aPath, getter_AddRefs(parserResult)); + NS_ENSURE_SUCCESS(rv, rv); + + parserResult->GetDn(mDN); + parserResult->GetScope(&mScope); + parserResult->GetFilter(mFilter); + parserResult->GetOptions(&mOptions); + + nsCString attributes; + parserResult->GetAttributes(attributes); + mAttributes.Truncate(); + if (!attributes.IsEmpty()) { + // Always start and end with a comma if not empty. + mAttributes.Append(','); + mAttributes.Append(attributes); + mAttributes.Append(','); + } + + return NS_OK; +} + +// A string representation of the URI. Setting the spec +// causes the new spec to be parsed, initializing the URI. Setting +// the spec (or any of the accessors) causes also any currently +// open streams on the URI's channel to be closed. + +NS_IMETHODIMP +nsLDAPURL::GetSpec(nsACString& _retval) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return mBaseURL->GetSpec(_retval); +} + +nsresult nsLDAPURL::SetSpecInternal(const nsACString& aSpec) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + // Cache the original spec in case we don't like what we've been passed and + // need to reset ourselves. + nsCString originalSpec; + nsresult rv = mBaseURL->GetSpec(originalSpec); + NS_ENSURE_SUCCESS(rv, rv); + + rv = NS_MutateURI(mBaseURL).SetSpec(aSpec).Finalize(mBaseURL); + NS_ENSURE_SUCCESS(rv, rv); + + rv = SetPathInternal(PromiseFlatCString(aSpec)); + if (NS_FAILED(rv)) { + nsresult rv2 = + NS_MutateURI(mBaseURL).SetSpec(originalSpec).Finalize(mBaseURL); + NS_ENSURE_SUCCESS(rv2, rv2); + } + + return rv; +} + +NS_IMETHODIMP nsLDAPURL::GetPrePath(nsACString& _retval) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return mBaseURL->GetPrePath(_retval); +} + +NS_IMETHODIMP nsLDAPURL::GetScheme(nsACString& _retval) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return mBaseURL->GetScheme(_retval); +} + +nsresult nsLDAPURL::SetScheme(const nsACString& aScheme) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + if (aScheme.Equals(LDAP_SCHEME, nsCaseInsensitiveCStringComparator)) + mOptions &= ~OPT_SECURE; + else if (aScheme.Equals(LDAP_SSL_SCHEME, nsCaseInsensitiveCStringComparator)) + mOptions |= OPT_SECURE; + else + return NS_ERROR_MALFORMED_URI; + + return NS_MutateURI(mBaseURL).SetScheme(aScheme).Finalize(mBaseURL); +} + +NS_IMETHODIMP +nsLDAPURL::GetUserPass(nsACString& _retval) { + _retval.Truncate(); + return NS_OK; +} + +nsresult nsLDAPURL::SetUserPass(const nsACString& aUserPass) { return NS_OK; } + +NS_IMETHODIMP +nsLDAPURL::GetUsername(nsACString& _retval) { + _retval.Truncate(); + return NS_OK; +} + +nsresult nsLDAPURL::SetUsername(const nsACString& aUsername) { return NS_OK; } + +NS_IMETHODIMP +nsLDAPURL::GetPassword(nsACString& _retval) { + _retval.Truncate(); + return NS_OK; +} + +nsresult nsLDAPURL::SetPassword(const nsACString& aPassword) { return NS_OK; } + +NS_IMETHODIMP +nsLDAPURL::GetHostPort(nsACString& _retval) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return mBaseURL->GetHostPort(_retval); +} + +nsresult nsLDAPURL::SetHostPort(const nsACString& aHostPort) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return NS_MutateURI(mBaseURL).SetHostPort(aHostPort).Finalize(mBaseURL); +} + +NS_IMETHODIMP +nsLDAPURL::GetHost(nsACString& _retval) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return mBaseURL->GetHost(_retval); +} + +nsresult nsLDAPURL::SetHost(const nsACString& aHost) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return NS_MutateURI(mBaseURL).SetHost(aHost).Finalize(mBaseURL); +} + +NS_IMETHODIMP +nsLDAPURL::GetPort(int32_t* _retval) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return mBaseURL->GetPort(_retval); +} + +nsresult nsLDAPURL::SetPort(int32_t aPort) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return NS_MutateURI(mBaseURL).SetPort(aPort).Finalize(mBaseURL); +} + +NS_IMETHODIMP nsLDAPURL::GetPathQueryRef(nsACString& _retval) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return mBaseURL->GetPathQueryRef(_retval); +} + +nsresult nsLDAPURL::SetPathQueryRef(const nsACString& aPath) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + nsresult rv = SetPathInternal(PromiseFlatCString(aPath)); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_MutateURI(mBaseURL).SetPathQueryRef(aPath).Finalize(mBaseURL); +} + +NS_IMETHODIMP nsLDAPURL::GetAsciiSpec(nsACString& _retval) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + // XXX handle extra items? + return mBaseURL->GetAsciiSpec(_retval); +} + +NS_IMETHODIMP nsLDAPURL::GetAsciiHost(nsACString& _retval) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return mBaseURL->GetAsciiHost(_retval); +} + +NS_IMETHODIMP +nsLDAPURL::GetAsciiHostPort(nsACString& _retval) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return mBaseURL->GetAsciiHostPort(_retval); +} + +// boolean equals (in nsIURI other) +// (based on nsSimpleURI::Equals) +NS_IMETHODIMP nsLDAPURL::Equals(nsIURI* other, bool* _retval) { + *_retval = false; + if (other) { + nsresult rv; + nsCOMPtr<nsILDAPURL> otherURL(do_QueryInterface(other, &rv)); + if (NS_SUCCEEDED(rv)) { + nsAutoCString thisSpec, otherSpec; + uint32_t otherOptions; + + rv = GetSpec(thisSpec); + NS_ENSURE_SUCCESS(rv, rv); + + rv = otherURL->GetSpec(otherSpec); + NS_ENSURE_SUCCESS(rv, rv); + + rv = otherURL->GetOptions(&otherOptions); + NS_ENSURE_SUCCESS(rv, rv); + + if (thisSpec == otherSpec && mOptions == otherOptions) *_retval = true; + } + } + return NS_OK; +} + +// boolean schemeIs(in const char * scheme); +// +NS_IMETHODIMP nsLDAPURL::SchemeIs(const char* aScheme, bool* aEquals) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + return mBaseURL->SchemeIs(aScheme, aEquals); +} + +// nsIURI clone (); +// +nsresult nsLDAPURL::Clone(nsIURI** aResult) { + NS_ENSURE_ARG_POINTER(aResult); + + RefPtr<nsLDAPURL> clone = new nsLDAPURL(); + + clone->mDN = mDN; + clone->mScope = mScope; + clone->mFilter = mFilter; + clone->mOptions = mOptions; + clone->mAttributes = mAttributes; + + nsresult rv = NS_MutateURI(mBaseURL).Finalize(clone->mBaseURL); + NS_ENSURE_SUCCESS(rv, rv); + + clone.forget(aResult); + return NS_OK; +} + +// string resolve (in string relativePath); +// +NS_IMETHODIMP nsLDAPURL::Resolve(const nsACString& relativePath, + nsACString& _retval) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +// The following attributes come from nsILDAPURL + +// attribute AUTF8String dn; +// +NS_IMETHODIMP nsLDAPURL::GetDn(nsACString& _retval) { + _retval.Assign(mDN); + return NS_OK; +} +NS_IMETHODIMP nsLDAPURL::SetDn(const nsACString& aDn) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + mDN.Assign(aDn); + + // Now get the current path + nsCString newPath; + GetPathInternal(newPath); + + // and update the base url + return NS_MutateURI(mBaseURL).SetPathQueryRef(newPath).Finalize(mBaseURL); +} + +NS_IMETHODIMP nsLDAPURL::GetAttributes(nsACString& aAttributes) { + if (mAttributes.IsEmpty()) { + aAttributes.Truncate(); + return NS_OK; + } + + NS_ASSERTION( + mAttributes[0] == ',' && mAttributes[mAttributes.Length() - 1] == ',', + "mAttributes does not begin and end with a comma"); + + // We store the string internally with comma before and after, so strip + // them off here. + aAttributes = Substring(mAttributes, 1, mAttributes.Length() - 2); + return NS_OK; +} + +NS_IMETHODIMP nsLDAPURL::SetAttributes(const nsACString& aAttributes) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + if (aAttributes.IsEmpty()) + mAttributes.Truncate(); + else { + // We need to make sure we start off the string with a comma. + if (aAttributes[0] != ',') mAttributes = ','; + + mAttributes.Append(aAttributes); + + // Also end with a comma if appropriate. + if (mAttributes[mAttributes.Length() - 1] != ',') mAttributes.Append(','); + } + + // Now get the current path + nsCString newPath; + GetPathInternal(newPath); + + // and update the base url + return NS_MutateURI(mBaseURL).SetPathQueryRef(newPath).Finalize(mBaseURL); +} + +NS_IMETHODIMP nsLDAPURL::AddAttribute(const nsACString& aAttribute) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + if (mAttributes.IsEmpty()) { + mAttributes = ','; + mAttributes.Append(aAttribute); + mAttributes.Append(','); + } else { + // Wrap the attribute in commas, so that we can do an exact match. + nsAutoCString findAttribute(","); + findAttribute.Append(aAttribute); + findAttribute.Append(','); + + // Check to see if the attribute is already stored. If it is, then also + // check to see if it is the last attribute in the string, or if the next + // character is a comma, this means we won't match substrings. + if (FindInReadable(findAttribute, mAttributes, + nsCaseInsensitiveCStringComparator)) { + return NS_OK; + } + + mAttributes.Append(Substring(findAttribute, 1)); + } + + // Now get the current path + nsCString newPath; + GetPathInternal(newPath); + + // and update the base url + return NS_MutateURI(mBaseURL).SetPathQueryRef(newPath).Finalize(mBaseURL); +} + +NS_IMETHODIMP nsLDAPURL::RemoveAttribute(const nsACString& aAttribute) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + if (mAttributes.IsEmpty()) return NS_OK; + + // We use comma as delimiter (even first attr has a leading comma). + nsAutoCString findAttribute(","); + findAttribute.Append(aAttribute); + findAttribute.Append(','); + + if (!FindInReadable(findAttribute, mAttributes, + nsCaseInsensitiveCStringComparator)) { + return NS_OK; + } + if (mAttributes.Equals(findAttribute, nsCaseInsensitiveCStringComparator)) { + mAttributes.Truncate(); + } else { + mAttributes.ReplaceSubstring(findAttribute, ","_ns); + } + + // Now get the current path + nsCString newPath; + GetPathInternal(newPath); + + // and update the base url + return NS_MutateURI(mBaseURL).SetPathQueryRef(newPath).Finalize(mBaseURL); +} + +NS_IMETHODIMP nsLDAPURL::HasAttribute(const nsACString& aAttribute, + bool* _retval) { + NS_ENSURE_ARG_POINTER(_retval); + + // We use comma as delimiter (even first attr has a leading comma). + nsAutoCString findAttribute(","); + findAttribute.Append(aAttribute); + findAttribute.Append(','); + + *_retval = FindInReadable(findAttribute, mAttributes, + nsCaseInsensitiveCStringComparator); + return NS_OK; +} + +NS_IMETHODIMP nsLDAPURL::GetScope(int32_t* _retval) { + NS_ENSURE_ARG_POINTER(_retval); + *_retval = mScope; + return NS_OK; +} + +NS_IMETHODIMP nsLDAPURL::SetScope(int32_t aScope) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + // Only allow scopes supported by the C-SDK + if ((aScope != SCOPE_BASE) && (aScope != SCOPE_ONELEVEL) && + (aScope != SCOPE_SUBTREE)) + return NS_ERROR_MALFORMED_URI; + + mScope = aScope; + + // Now get the current path + nsCString newPath; + GetPathInternal(newPath); + + // and update the base url + return NS_MutateURI(mBaseURL).SetPathQueryRef(newPath).Finalize(mBaseURL); +} + +NS_IMETHODIMP nsLDAPURL::GetFilter(nsACString& _retval) { + _retval.Assign(mFilter); + return NS_OK; +} +NS_IMETHODIMP nsLDAPURL::SetFilter(const nsACString& aFilter) { + if (!mBaseURL) return NS_ERROR_NOT_INITIALIZED; + + mFilter.Assign(aFilter); + + if (mFilter.IsEmpty()) mFilter.AssignLiteral("(objectclass=*)"); + + // Now get the current path + nsCString newPath; + GetPathInternal(newPath); + + // and update the base url + return NS_MutateURI(mBaseURL).SetPathQueryRef(newPath).Finalize(mBaseURL); +} + +NS_IMETHODIMP nsLDAPURL::GetOptions(uint32_t* _retval) { + NS_ENSURE_ARG_POINTER(_retval); + *_retval = mOptions; + return NS_OK; +} + +NS_IMETHODIMP nsLDAPURL::SetOptions(uint32_t aOptions) { + // Secure is the only option supported at the moment + if ((mOptions & OPT_SECURE) == (aOptions & OPT_SECURE)) return NS_OK; + + mOptions = aOptions; + + if ((aOptions & OPT_SECURE) == OPT_SECURE) return SetScheme(LDAP_SSL_SCHEME); + + return SetScheme(LDAP_SCHEME); +} + +nsresult nsLDAPURL::SetRef(const nsACString& aRef) { + return NS_MutateURI(mBaseURL).SetRef(aRef).Finalize(mBaseURL); +} + +NS_IMETHODIMP +nsLDAPURL::GetRef(nsACString& result) { return mBaseURL->GetRef(result); } + +NS_IMETHODIMP nsLDAPURL::EqualsExceptRef(nsIURI* other, bool* result) { + return mBaseURL->EqualsExceptRef(other, result); +} + +NS_IMETHODIMP +nsLDAPURL::GetSpecIgnoringRef(nsACString& result) { + return mBaseURL->GetSpecIgnoringRef(result); +} + +NS_IMETHODIMP +nsLDAPURL::GetDisplaySpec(nsACString& aUnicodeSpec) { + return mBaseURL->GetDisplaySpec(aUnicodeSpec); +} + +NS_IMETHODIMP +nsLDAPURL::GetDisplayHostPort(nsACString& aUnicodeHostPort) { + return mBaseURL->GetDisplayHostPort(aUnicodeHostPort); +} + +NS_IMETHODIMP +nsLDAPURL::GetDisplayHost(nsACString& aUnicodeHost) { + return mBaseURL->GetDisplayHost(aUnicodeHost); +} + +NS_IMETHODIMP +nsLDAPURL::GetDisplayPrePath(nsACString& aPrePath) { + return mBaseURL->GetDisplayPrePath(aPrePath); +} + +NS_IMETHODIMP +nsLDAPURL::GetHasRef(bool* result) { return mBaseURL->GetHasRef(result); } + +NS_IMETHODIMP +nsLDAPURL::GetFilePath(nsACString& aFilePath) { + return mBaseURL->GetFilePath(aFilePath); +} + +nsresult nsLDAPURL::SetFilePath(const nsACString& aFilePath) { + return NS_MutateURI(mBaseURL).SetFilePath(aFilePath).Finalize(mBaseURL); +} + +NS_IMETHODIMP +nsLDAPURL::GetQuery(nsACString& aQuery) { return mBaseURL->GetQuery(aQuery); } + +nsresult nsLDAPURL::SetQuery(const nsACString& aQuery) { + return NS_MutateURI(mBaseURL).SetQuery(aQuery).Finalize(mBaseURL); +} + +nsresult nsLDAPURL::SetQueryWithEncoding(const nsACString& aQuery, + const mozilla::Encoding* aEncoding) { + return NS_MutateURI(mBaseURL) + .SetQueryWithEncoding(aQuery, aEncoding) + .Finalize(mBaseURL); +} + +NS_IMETHODIMP_(void) +nsLDAPURL::Serialize(mozilla::ipc::URIParams& aParams) { + mBaseURL->Serialize(aParams); +} + +NS_IMPL_ISUPPORTS(nsLDAPURL::Mutator, nsIURISetters, nsIURIMutator) + +NS_IMETHODIMP +nsLDAPURL::Mutate(nsIURIMutator** aMutator) { + RefPtr<nsLDAPURL::Mutator> mutator = new nsLDAPURL::Mutator(); + nsresult rv = mutator->InitFromURI(this); + if (NS_FAILED(rv)) { + return rv; + } + mutator.forget(aMutator); + return NS_OK; +} |