summaryrefslogtreecommitdiffstats
path: root/mailnews/imap/src/nsIMAPNamespace.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2019-11-03 00:17:46 -0400
committerMatt A. Tobin <email@mattatobin.com>2019-11-03 00:17:46 -0400
commit302bf1b523012e11b60425d6eee1221ebc2724eb (patch)
treeb191a895f8716efcbe42f454f37597a545a6f421 /mailnews/imap/src/nsIMAPNamespace.cpp
parent21b3f6247403c06f85e1f45d219f87549862198f (diff)
downloadUXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.gz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.lz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.xz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.zip
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
Diffstat (limited to 'mailnews/imap/src/nsIMAPNamespace.cpp')
-rw-r--r--mailnews/imap/src/nsIMAPNamespace.cpp650
1 files changed, 650 insertions, 0 deletions
diff --git a/mailnews/imap/src/nsIMAPNamespace.cpp b/mailnews/imap/src/nsIMAPNamespace.cpp
new file mode 100644
index 000000000..d46352373
--- /dev/null
+++ b/mailnews/imap/src/nsIMAPNamespace.cpp
@@ -0,0 +1,650 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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 "msgCore.h" // for pre-compiled headers
+
+#include "nsImapCore.h"
+#include "nsIMAPNamespace.h"
+#include "nsImapProtocol.h"
+#include "nsMsgImapCID.h"
+#include "nsImapUrl.h"
+#include "nsStringGlue.h"
+#include "nsServiceManagerUtils.h"
+
+//////////////////// nsIMAPNamespace /////////////////////////////////////////////////////////////
+
+static NS_DEFINE_CID(kCImapHostSessionListCID, NS_IIMAPHOSTSESSIONLIST_CID);
+
+nsIMAPNamespace::nsIMAPNamespace(EIMAPNamespaceType type, const char *prefix, char delimiter, bool from_prefs)
+{
+ m_namespaceType = type;
+ m_prefix = PL_strdup(prefix);
+ m_fromPrefs = from_prefs;
+
+ m_delimiter = delimiter;
+ m_delimiterFilledIn = !m_fromPrefs; // if it's from the prefs, we can't be sure about the delimiter until we list it.
+}
+
+nsIMAPNamespace::~nsIMAPNamespace()
+{
+ PR_FREEIF(m_prefix);
+}
+
+void nsIMAPNamespace::SetDelimiter(char delimiter, bool delimiterFilledIn)
+{
+ m_delimiter = delimiter;
+ m_delimiterFilledIn = delimiterFilledIn;
+}
+
+// returns -1 if this box is not part of this namespace,
+// or the length of the prefix if it is part of this namespace
+int nsIMAPNamespace::MailboxMatchesNamespace(const char *boxname)
+{
+ if (!boxname) return -1;
+
+ // If the namespace is part of the boxname
+ if (!m_prefix || !*m_prefix)
+ return 0;
+
+ if (PL_strstr(boxname, m_prefix) == boxname)
+ return PL_strlen(m_prefix);
+
+ // If the boxname is part of the prefix
+ // (Used for matching Personal mailbox with Personal/ namespace, etc.)
+ if (PL_strstr(m_prefix, boxname) == m_prefix)
+ return PL_strlen(boxname);
+ return -1;
+}
+
+
+nsIMAPNamespaceList *nsIMAPNamespaceList::CreatensIMAPNamespaceList()
+{
+ nsIMAPNamespaceList *rv = new nsIMAPNamespaceList();
+ return rv;
+}
+
+nsIMAPNamespaceList::nsIMAPNamespaceList()
+{
+}
+
+int nsIMAPNamespaceList::GetNumberOfNamespaces()
+{
+ return m_NamespaceList.Length();
+}
+
+
+nsresult nsIMAPNamespaceList::InitFromString(const char *nameSpaceString, EIMAPNamespaceType nstype)
+{
+ nsresult rv = NS_OK;
+ if (nameSpaceString)
+ {
+ int numNamespaces = UnserializeNamespaces(nameSpaceString, nullptr, 0);
+ char **prefixes = (char**) PR_CALLOC(numNamespaces * sizeof(char*));
+ if (prefixes)
+ {
+ int len = UnserializeNamespaces(nameSpaceString, prefixes, numNamespaces);
+ for (int i = 0; i < len; i++)
+ {
+ char *thisns = prefixes[i];
+ char delimiter = '/'; // a guess
+ if (PL_strlen(thisns) >= 1)
+ delimiter = thisns[PL_strlen(thisns)-1];
+ nsIMAPNamespace *ns = new nsIMAPNamespace(nstype, thisns, delimiter, true);
+ if (ns)
+ AddNewNamespace(ns);
+ PR_FREEIF(thisns);
+ }
+ PR_Free(prefixes);
+ }
+ }
+
+ return rv;
+}
+
+nsresult nsIMAPNamespaceList::OutputToString(nsCString &string)
+{
+ nsresult rv = NS_OK;
+
+ return rv;
+}
+
+
+int nsIMAPNamespaceList::GetNumberOfNamespaces(EIMAPNamespaceType type)
+{
+ int nodeIndex = 0, count = 0;
+ for (nodeIndex = m_NamespaceList.Length() - 1; nodeIndex >= 0; nodeIndex--)
+ {
+ nsIMAPNamespace *nspace = m_NamespaceList.ElementAt(nodeIndex);
+ if (nspace->GetType() == type)
+ {
+ count++;
+ }
+ }
+ return count;
+}
+
+int nsIMAPNamespaceList::AddNewNamespace(nsIMAPNamespace *ns)
+{
+ // If the namespace is from the NAMESPACE response, then we should see if there
+ // are any namespaces previously set by the preferences, or the default namespace. If so, remove these.
+
+ if (!ns->GetIsNamespaceFromPrefs())
+ {
+ int nodeIndex;
+ // iterate backwards because we delete elements
+ for (nodeIndex = m_NamespaceList.Length() - 1; nodeIndex >= 0; nodeIndex--)
+ {
+ nsIMAPNamespace *nspace = m_NamespaceList.ElementAt(nodeIndex);
+ // if we find existing namespace(s) that matches the
+ // new one, we'll just remove the old ones and let the
+ // new one get added when we've finished checking for
+ // matching namespaces or namespaces that came from prefs.
+ if (nspace &&
+ (nspace->GetIsNamespaceFromPrefs() ||
+ (!PL_strcmp(ns->GetPrefix(), nspace->GetPrefix()) &&
+ ns->GetType() == nspace->GetType() &&
+ ns->GetDelimiter() == nspace->GetDelimiter())))
+ {
+ m_NamespaceList.RemoveElementAt(nodeIndex);
+ delete nspace;
+ }
+ }
+ }
+
+ // Add the new namespace to the list. This must come after the removing code,
+ // or else we could never add the initial kDefaultNamespace type to the list.
+ m_NamespaceList.AppendElement(ns);
+
+ return 0;
+}
+
+
+// chrisf - later, fix this to know the real concept of "default" namespace of a given type
+nsIMAPNamespace *nsIMAPNamespaceList::GetDefaultNamespaceOfType(EIMAPNamespaceType type)
+{
+ nsIMAPNamespace *rv = 0, *firstOfType = 0;
+
+ int nodeIndex, count = m_NamespaceList.Length();
+ for (nodeIndex= 0; nodeIndex < count && !rv; nodeIndex++)
+ {
+ nsIMAPNamespace *ns = m_NamespaceList.ElementAt(nodeIndex);
+ if (ns->GetType() == type)
+ {
+ if (!firstOfType)
+ firstOfType = ns;
+ if (!(*(ns->GetPrefix())))
+ {
+ // This namespace's prefix is ""
+ // Therefore it is the default
+ rv = ns;
+ }
+ }
+ }
+ if (!rv)
+ rv = firstOfType;
+ return rv;
+}
+
+nsIMAPNamespaceList::~nsIMAPNamespaceList()
+{
+ ClearNamespaces(true, true, true);
+}
+
+// ClearNamespaces removes and deletes the namespaces specified, and if there are no namespaces left,
+void nsIMAPNamespaceList::ClearNamespaces(bool deleteFromPrefsNamespaces, bool deleteServerAdvertisedNamespaces, bool reallyDelete)
+{
+ int nodeIndex;
+
+ // iterate backwards because we delete elements
+ for (nodeIndex = m_NamespaceList.Length() - 1; nodeIndex >= 0; nodeIndex--)
+ {
+ nsIMAPNamespace *ns = m_NamespaceList.ElementAt(nodeIndex);
+ if (ns->GetIsNamespaceFromPrefs())
+ {
+ if (deleteFromPrefsNamespaces)
+ {
+ m_NamespaceList.RemoveElementAt(nodeIndex);
+ if (reallyDelete)
+ delete ns;
+ }
+ }
+ else if (deleteServerAdvertisedNamespaces)
+ {
+ m_NamespaceList.RemoveElementAt(nodeIndex);
+ if (reallyDelete)
+ delete ns;
+ }
+ }
+}
+
+nsIMAPNamespace *nsIMAPNamespaceList::GetNamespaceNumber(int nodeIndex)
+{
+ NS_ASSERTION(nodeIndex >= 0 && nodeIndex < GetNumberOfNamespaces(), "invalid IMAP namespace node index");
+ if (nodeIndex < 0) nodeIndex = 0;
+
+ // XXX really could be just ElementAt; that's why we have the assertion
+ return m_NamespaceList.SafeElementAt(nodeIndex);
+}
+
+nsIMAPNamespace *nsIMAPNamespaceList::GetNamespaceNumber(int nodeIndex, EIMAPNamespaceType type)
+{
+ int nodeCount, count = 0;
+ for (nodeCount = m_NamespaceList.Length() - 1; nodeCount >= 0; nodeCount--)
+ {
+ nsIMAPNamespace *nspace = m_NamespaceList.ElementAt(nodeCount);
+ if (nspace->GetType() == type)
+ {
+ count++;
+ if (count == nodeIndex)
+ return nspace;
+ }
+ }
+ return nullptr;
+}
+
+nsIMAPNamespace *nsIMAPNamespaceList::GetNamespaceForMailbox(const char *boxname)
+{
+ // We want to find the LONGEST substring that matches the beginning of this mailbox's path.
+ // This accounts for nested namespaces (i.e. "Public/" and "Public/Users/")
+
+ // Also, we want to match the namespace's mailbox to that namespace also:
+ // The Personal box will match the Personal/ namespace, etc.
+
+ // these lists shouldn't be too long (99% chance there won't be more than 3 or 4)
+ // so just do a linear search
+
+ int lengthMatched = -1;
+ int currentMatchedLength = -1;
+ nsIMAPNamespace *rv = nullptr;
+ int nodeIndex = 0;
+
+ if (!PL_strcasecmp(boxname, "INBOX"))
+ return GetDefaultNamespaceOfType(kPersonalNamespace);
+
+ for (nodeIndex = m_NamespaceList.Length() - 1; nodeIndex >= 0; nodeIndex--)
+ {
+ nsIMAPNamespace *nspace = m_NamespaceList.ElementAt(nodeIndex);
+ currentMatchedLength = nspace->MailboxMatchesNamespace(boxname);
+ if (currentMatchedLength > lengthMatched)
+ {
+ rv = nspace;
+ lengthMatched = currentMatchedLength;
+ }
+ }
+
+ return rv;
+}
+
+#define SERIALIZER_SEPARATORS ","
+
+/**
+ * If len is one, copies the first element of prefixes into serializedNamespaces.
+ * If len > 1, copies len strings from prefixes into serializedNamespaces
+ * as a comma-separated list of quoted strings.
+ */
+nsresult nsIMAPNamespaceList::SerializeNamespaces(char **prefixes, int len,
+ nsCString &serializedNamespaces)
+{
+ if (len <= 0)
+ return NS_OK;
+
+ if (len == 1)
+ {
+ serializedNamespaces.Assign(prefixes[0]);
+ return NS_OK;
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ if (i > 0)
+ serializedNamespaces.AppendLiteral(",");
+
+ serializedNamespaces.AppendLiteral("\"");
+ serializedNamespaces.Append(prefixes[i]);
+ serializedNamespaces.AppendLiteral("\"");
+ }
+ return NS_OK;
+}
+
+/* str is the string which needs to be unserialized.
+ If prefixes is NULL, simply returns the number of namespaces in str. (len is ignored)
+ If prefixes is not NULL, it should be an array of length len which is to be filled in
+ with newly-allocated string. Returns the number of strings filled in.
+*/
+int nsIMAPNamespaceList::UnserializeNamespaces(const char *str, char **prefixes, int len)
+{
+ if (!str)
+ return 0;
+ if (!prefixes)
+ {
+ if (str[0] != '"')
+ return 1;
+ else
+ {
+ int count = 0;
+ char *ourstr = PL_strdup(str);
+ char *origOurStr = ourstr;
+ if (ourstr)
+ {
+ char *token = NS_strtok(SERIALIZER_SEPARATORS, &ourstr );
+ while (token != nullptr)
+ {
+ token = NS_strtok(SERIALIZER_SEPARATORS, &ourstr );
+ count++;
+ }
+ PR_Free(origOurStr);
+ }
+ return count;
+ }
+ }
+ else
+ {
+ if ((str[0] != '"') && (len >= 1))
+ {
+ prefixes[0] = PL_strdup(str);
+ return 1;
+ }
+ else
+ {
+ int count = 0;
+ char *ourstr = PL_strdup(str);
+ char *origOurStr = ourstr;
+ if (ourstr)
+ {
+ char *token = NS_strtok(SERIALIZER_SEPARATORS, &ourstr );
+ while ((count < len) && (token != nullptr))
+ {
+
+ char *current = PL_strdup(token), *where = current;
+ if (where[0] == '"')
+ where++;
+ if (where[PL_strlen(where)-1] == '"')
+ where[PL_strlen(where)-1] = 0;
+ prefixes[count] = PL_strdup(where);
+ PR_FREEIF(current);
+ token = NS_strtok(SERIALIZER_SEPARATORS, &ourstr );
+ count++;
+ }
+ PR_Free(origOurStr);
+ }
+ return count;
+ }
+ }
+}
+
+
+
+
+char *nsIMAPNamespaceList::AllocateCanonicalFolderName(const char *onlineFolderName, char delimiter)
+{
+ char *canonicalPath = nullptr;
+ if (delimiter)
+ canonicalPath = nsImapUrl::ReplaceCharsInCopiedString(onlineFolderName, delimiter , '/');
+ else
+ canonicalPath = PL_strdup(onlineFolderName);
+
+ // eat any escape characters for escaped dir separators
+ if (canonicalPath)
+ {
+ char *currentEscapeSequence = strstr(canonicalPath, "\\/");
+ while (currentEscapeSequence)
+ {
+ strcpy(currentEscapeSequence, currentEscapeSequence+1);
+ currentEscapeSequence = strstr(currentEscapeSequence+1, "\\/");
+ }
+ }
+
+ return canonicalPath;
+}
+
+
+
+/*
+ GetFolderNameWithoutNamespace takes as input a folder name
+ in canonical form, and the namespace for the given folder. It returns an allocated
+ string of the folder's path with the namespace string stripped out. For instance,
+ when passed the folder Folders/a/b where the namespace is "Folders/", it will return
+ "a/b". Similarly, if the folder name is "#news/comp/mail/imap" in canonical form,
+ with a real delimiter of "." and a namespace of "#news.", it will return "comp/mail/imap".
+ The return value is always in canonical form.
+*/
+char* nsIMAPNamespaceList::GetFolderNameWithoutNamespace(nsIMAPNamespace *namespaceForFolder, const char *canonicalFolderName)
+{
+ NS_ASSERTION(canonicalFolderName, "null folder name");
+#ifdef DEBUG
+ NS_ASSERTION(namespaceForFolder || !PL_strcasecmp(canonicalFolderName, "INBOX"), "need namespace or INBOX");
+#endif
+
+ char *retFolderName = nullptr;
+
+ if (!PL_strcasecmp(canonicalFolderName, "INBOX"))
+ return PL_strdup(canonicalFolderName);
+
+ // convert the canonical path to the online path
+ char *convertedFolderName = nsIMAPNamespaceList::AllocateServerFolderName(canonicalFolderName, namespaceForFolder->GetDelimiter());
+ if (convertedFolderName)
+ {
+ char *beginFolderPath = nullptr;
+ if (strlen(convertedFolderName) <= strlen(namespaceForFolder->GetPrefix()))
+ beginFolderPath = convertedFolderName;
+ else
+ beginFolderPath = convertedFolderName + strlen(namespaceForFolder->GetPrefix());
+ NS_ASSERTION(beginFolderPath, "empty folder path");
+ retFolderName = nsIMAPNamespaceList::AllocateCanonicalFolderName(beginFolderPath, namespaceForFolder->GetDelimiter());
+ PR_Free(convertedFolderName);
+ }
+
+ NS_ASSERTION(retFolderName, "returning null folder name");
+ return retFolderName;
+}
+
+
+nsIMAPNamespace* nsIMAPNamespaceList::GetNamespaceForFolder(const char *hostName,
+ const char *canonicalFolderName,
+ char delimiter)
+{
+ if (!hostName || !canonicalFolderName)
+ return nullptr;
+
+ nsIMAPNamespace *resultNamespace = nullptr;
+ nsresult rv;
+ char *convertedFolderName = nsIMAPNamespaceList::AllocateServerFolderName(canonicalFolderName, delimiter);
+
+ if (convertedFolderName)
+ {
+
+ nsCOMPtr<nsIImapHostSessionList> hostSessionList =
+ do_GetService(kCImapHostSessionListCID, &rv);
+ if (NS_FAILED(rv))
+ return nullptr;
+ hostSessionList->GetNamespaceForMailboxForHost(hostName, convertedFolderName, resultNamespace);
+ PR_Free(convertedFolderName);
+ }
+ else
+ {
+ NS_ASSERTION(false, "couldn't get converted folder name");
+ }
+
+ return resultNamespace;
+}
+
+/* static */
+char *nsIMAPNamespaceList::AllocateServerFolderName(const char *canonicalFolderName, char delimiter)
+{
+ if (delimiter)
+ return nsImapUrl::ReplaceCharsInCopiedString(canonicalFolderName, '/', delimiter);
+ else
+ return NS_strdup(canonicalFolderName);
+}
+
+/*
+ GetFolderOwnerNameFromPath takes as inputs a folder name
+ in canonical form, and a namespace for that folder.
+ The namespace MUST be of type kOtherUsersNamespace, hence the folder MUST be
+ owned by another user. This function extracts the folder owner's name from the
+ canonical name of the folder, and returns an allocated copy of that owner's name
+*/
+/* static */
+char *nsIMAPNamespaceList::GetFolderOwnerNameFromPath(nsIMAPNamespace *namespaceForFolder, const char *canonicalFolderName)
+{
+ if (!namespaceForFolder || !canonicalFolderName)
+ {
+ NS_ASSERTION(false,"null namespace or canonical folder name");
+ return nullptr;
+ }
+
+ char *rv = nullptr;
+
+ // convert the canonical path to the online path
+ char *convertedFolderName = AllocateServerFolderName(canonicalFolderName, namespaceForFolder->GetDelimiter());
+ if (convertedFolderName)
+ {
+#ifdef DEBUG
+ NS_ASSERTION(strlen(convertedFolderName) > strlen(namespaceForFolder->GetPrefix()), "server folder name invalid");
+#endif
+ if (strlen(convertedFolderName) > strlen(namespaceForFolder->GetPrefix()))
+ {
+ char *owner = convertedFolderName + strlen(namespaceForFolder->GetPrefix());
+ NS_ASSERTION(owner, "couldn't find folder owner");
+ char *nextDelimiter = strchr(owner, namespaceForFolder->GetDelimiter());
+ // if !nextDelimiter, then the path is of the form Shared/Users/chrisf (no subfolder)
+ if (nextDelimiter)
+ {
+ *nextDelimiter = 0;
+ }
+ rv = PL_strdup(owner);
+ }
+ PR_Free(convertedFolderName);
+ }
+ else
+ {
+ NS_ASSERTION(false, "couldn't allocate server folder name");
+ }
+
+ return rv;
+}
+
+/*
+GetFolderIsNamespace returns TRUE if the given folder is the folder representing
+a namespace.
+*/
+
+bool nsIMAPNamespaceList::GetFolderIsNamespace(const char *hostName,
+ const char *canonicalFolderName,
+ char delimiter,nsIMAPNamespace *namespaceForFolder)
+{
+ NS_ASSERTION(namespaceForFolder, "null namespace");
+
+ bool rv = false;
+
+ const char *prefix = namespaceForFolder->GetPrefix();
+ NS_ASSERTION(prefix, "namespace has no prefix");
+ if (!prefix || !*prefix) // empty namespace prefix
+ return false;
+
+ char *convertedFolderName = AllocateServerFolderName(canonicalFolderName, delimiter);
+ if (convertedFolderName)
+ {
+ bool lastCharIsDelimiter = (prefix[strlen(prefix) - 1] == delimiter);
+
+ if (lastCharIsDelimiter)
+ {
+ rv = ((strncmp(convertedFolderName, prefix, strlen(convertedFolderName)) == 0) &&
+ (strlen(convertedFolderName) == strlen(prefix) - 1));
+ }
+ else
+ {
+ rv = (strcmp(convertedFolderName, prefix) == 0);
+ }
+
+ PR_Free(convertedFolderName);
+ }
+ else
+ {
+ NS_ASSERTION(false, "couldn't allocate server folder name");
+ }
+
+ return rv;
+}
+
+/*
+ SuggestHierarchySeparatorForNamespace takes a namespace from libmsg
+ and a hierarchy delimiter. If the namespace has not been filled in from
+ online NAMESPACE command yet, it fills in the suggested delimiter to be
+ used from then on (until it is overridden by an online response).
+*/
+
+void nsIMAPNamespaceList::SuggestHierarchySeparatorForNamespace(nsIMAPNamespace *namespaceForFolder, char delimiterFromFolder)
+{
+ NS_ASSERTION(namespaceForFolder, "need namespace");
+ if (namespaceForFolder && !namespaceForFolder->GetIsDelimiterFilledIn())
+ namespaceForFolder->SetDelimiter(delimiterFromFolder, false);
+}
+
+
+/*
+ GenerateFullFolderNameWithDefaultNamespace takes a folder name in canonical form,
+ converts it to online form, allocates a string to contain the full online server name
+ including the namespace prefix of the default namespace of the given type, in the form:
+ PR_smprintf("%s%s", prefix, onlineServerName) if there is a NULL owner
+ PR_smprintf("%s%s%c%s", prefix, owner, delimiter, onlineServerName) if there is an owner
+ It then converts this back to canonical form and returns it (allocated) to libmsg.
+ It returns NULL if there is no namespace of the given type.
+ If nsUsed is not passed in as NULL, then *nsUsed is filled in and returned; it is the
+ namespace used for generating the folder name.
+*/
+char *nsIMAPNamespaceList::GenerateFullFolderNameWithDefaultNamespace(const char *hostName,
+ const char *canonicalFolderName,
+ const char *owner,
+ EIMAPNamespaceType nsType,
+ nsIMAPNamespace **nsUsed)
+{
+ nsresult rv = NS_OK;
+
+ nsCOMPtr<nsIImapHostSessionList> hostSession =
+ do_GetService(kCImapHostSessionListCID, &rv);
+ NS_ENSURE_SUCCESS(rv, nullptr);
+ nsIMAPNamespace *ns;
+ char *fullFolderName = nullptr;
+ rv = hostSession->GetDefaultNamespaceOfTypeForHost(hostName, nsType, ns);
+ NS_ENSURE_SUCCESS(rv, nullptr);
+ if (ns)
+ {
+ if (nsUsed)
+ *nsUsed = ns;
+ const char *prefix = ns->GetPrefix();
+ char *convertedFolderName = AllocateServerFolderName(canonicalFolderName, ns->GetDelimiter());
+ if (convertedFolderName)
+ {
+ char *convertedReturnName = nullptr;
+ if (owner)
+ {
+ convertedReturnName = PR_smprintf("%s%s%c%s", prefix, owner, ns->GetDelimiter(), convertedFolderName);
+ }
+ else
+ {
+ convertedReturnName = PR_smprintf("%s%s", prefix, convertedFolderName);
+ }
+
+ if (convertedReturnName)
+ {
+ fullFolderName = AllocateCanonicalFolderName(convertedReturnName, ns->GetDelimiter());
+ PR_Free(convertedReturnName);
+ }
+ PR_Free(convertedFolderName);
+ }
+ else
+ {
+ NS_ASSERTION(false, "couldn't allocate server folder name");
+ }
+ }
+ else
+ {
+ // Could not find other users namespace on the given host
+ NS_WARNING("couldn't find namespace for given host");
+ }
+ return (fullFolderName);
+}
+