Back to index

lightning-sunbird  0.9+nobinonly
nsLocalUtils.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "msgCore.h"
00039 #include "nsLocalUtils.h"
00040 #include "nsIServiceManager.h"
00041 #include "prsystem.h"
00042 #include "nsCOMPtr.h"
00043 #include "nsReadableUtils.h"
00044 #include "nsEscape.h"
00045 #include "nsIFileSpec.h"
00046 
00047 // stuff for temporary root folder hack
00048 #include "nsIMsgAccountManager.h"
00049 #include "nsIMsgIncomingServer.h"
00050 #include "nsIPop3IncomingServer.h"
00051 #include "nsINoIncomingServer.h"
00052 #include "nsMsgBaseCID.h"
00053 
00054 #include "nsMsgUtils.h"
00055 #include "nsNetCID.h"
00056 
00057 // it would be really cool to:
00058 // - cache the last hostname->path match
00059 // - if no such server exists, behave like an old-style mailbox URL
00060 // (i.e. return the mail.directory preference or something)
00061 static nsresult
00062 nsGetMailboxServer(const char *uriStr, nsIMsgIncomingServer** aResult)
00063 {
00064   nsresult rv = NS_OK;
00065 
00066   nsCOMPtr<nsIURL> aUrl = do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
00067   if (NS_FAILED(rv)) return rv;
00068 
00069   rv = aUrl->SetSpec(nsDependentCString(uriStr));  
00070   if (NS_FAILED(rv)) return rv;
00071 
00072   // retrieve the AccountManager
00073   nsCOMPtr<nsIMsgAccountManager> accountManager = 
00074     do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
00075   if (NS_FAILED(rv)) return rv;
00076   
00077   // find all local mail "no servers" matching the given hostname
00078   nsCOMPtr<nsIMsgIncomingServer> none_server;
00079   aUrl->SetScheme(NS_LITERAL_CSTRING("none"));
00080   // No unescaping of username or hostname done here.
00081   // The unescaping is done inside of FindServerByURI
00082   rv = accountManager->FindServerByURI(aUrl, PR_FALSE,
00083                                   getter_AddRefs(none_server));
00084   if (NS_SUCCEEDED(rv)) {
00085     NS_ADDREF(*aResult = none_server);
00086     return rv;
00087   }
00088   
00089   // if that fails, look for the rss hosts matching the given hostname
00090   nsCOMPtr<nsIMsgIncomingServer> rss_server;
00091   aUrl->SetScheme(NS_LITERAL_CSTRING("rss"));
00092   rv = accountManager->FindServerByURI(aUrl, PR_FALSE,
00093                                   getter_AddRefs(rss_server));
00094   if (NS_SUCCEEDED(rv))
00095   {
00096      NS_ADDREF(*aResult = rss_server);
00097      return rv;
00098   }
00099 #ifdef HAVE_MOVEMAIL
00100   // find all movemail "servers" matching the given hostname
00101   nsCOMPtr<nsIMsgIncomingServer> movemail_server;
00102   aUrl->SetScheme(NS_LITERAL_CSTRING("movemail"));
00103   rv = accountManager->FindServerByURI(aUrl, PR_FALSE,
00104                                   getter_AddRefs(movemail_server));
00105   if (NS_SUCCEEDED(rv)) {
00106     NS_ADDREF(*aResult = movemail_server);
00107     return rv;
00108   }
00109 #endif /* HAVE_MOVEMAIL */
00110 
00111   // if that fails, look for the pop hosts matching the given hostname
00112   nsCOMPtr<nsIMsgIncomingServer> server;
00113   if (NS_FAILED(rv)) 
00114   {
00115     aUrl->SetScheme(NS_LITERAL_CSTRING("pop3"));
00116     rv = accountManager->FindServerByURI(aUrl, PR_FALSE,
00117                                     getter_AddRefs(server));
00118 
00119     // if we can't find a pop server, maybe it's a local message 
00120     // in an imap hierarchy. look for an imap server.
00121     if (NS_FAILED(rv)) 
00122     {
00123       aUrl->SetScheme(NS_LITERAL_CSTRING("imap"));
00124       rv = accountManager->FindServerByURI(aUrl, PR_FALSE,
00125                                     getter_AddRefs(server));
00126     }
00127   }
00128   if (NS_SUCCEEDED(rv)) 
00129   {
00130     NS_ADDREF(*aResult = server);
00131     return rv;
00132   }
00133 
00134 // if you fail after looking at all "pop3", "movemail" and "none" servers, you fail.
00135 return rv;
00136 }
00137 
00138 static nsresult
00139 nsLocalURI2Server(const char* uriStr,
00140                   nsIMsgIncomingServer ** aResult)
00141 {
00142   nsresult rv;
00143 
00144 
00145   nsCOMPtr<nsIMsgIncomingServer> server;
00146   rv = nsGetMailboxServer(uriStr, getter_AddRefs(server));
00147 
00148   NS_IF_ADDREF(*aResult = server);
00149 
00150   return rv;
00151 }
00152 
00153 // given rootURI and rootURI##folder, return on-disk path of folder
00154 nsresult
00155 nsLocalURI2Path(const char* rootURI, const char* uriStr,
00156                 nsFileSpec& pathResult)
00157 {
00158   nsresult rv;
00159   
00160   // verify that rootURI starts with "mailbox:/" or "mailbox-message:/"
00161   if ((PL_strcmp(rootURI, kMailboxRootURI) != 0) && 
00162       (PL_strcmp(rootURI, kMailboxMessageRootURI) != 0)) {
00163     pathResult = nsnull;
00164     return NS_ERROR_FAILURE;
00165   }
00166 
00167   // verify that uristr starts with rooturi
00168   nsCAutoString uri(uriStr);
00169   if (uri.Find(rootURI) != 0)
00170     return NS_ERROR_FAILURE;
00171 
00172 
00173   nsCOMPtr<nsIMsgIncomingServer> server;
00174   rv = nsLocalURI2Server(uriStr, getter_AddRefs(server));
00175 
00176   if (NS_FAILED(rv))
00177     return rv;
00178   
00179   // now ask the server what it's root is
00180   // and begin pathResult with the mailbox root
00181   nsCOMPtr<nsIFileSpec> localPath;
00182   rv = server->GetLocalPath(getter_AddRefs(localPath));
00183   if (NS_SUCCEEDED(rv)) 
00184     localPath->GetFileSpec(&pathResult);
00185 
00186   const char *curPos = uriStr + PL_strlen(rootURI);
00187   if (curPos) {
00188     
00189     // advance past hostname
00190     while ((*curPos)=='/') curPos++;
00191     while (*curPos && (*curPos)!='/') curPos++;
00192 
00193     // get the separator
00194     nsAutoString sbdSep;
00195     rv = nsGetMailFolderSeparator(sbdSep);
00196     
00197        
00198     nsCAutoString newPath("");
00199     char *unescaped = nsCRT::strdup(curPos);  
00200     // Unescape folder name
00201     if (unescaped) {
00202       nsUnescape(unescaped);
00203       NS_MsgCreatePathStringFromFolderURI(unescaped, newPath);
00204       PR_Free(unescaped);
00205     }
00206     else
00207       NS_MsgCreatePathStringFromFolderURI(curPos, newPath);
00208 
00209     pathResult+=newPath.get();
00210   }
00211 
00212   return NS_OK;
00213 }
00214 
00215 /* parses LocalMessageURI
00216  * mailbox-message://folder1/folder2#123?header=none or
00217  * mailbox-message://folder1/folder2#1234&part=1.2
00218  *
00219  * puts folder URI in folderURI (mailbox://folder1/folder2)
00220  * message key number in key
00221  */
00222 nsresult nsParseLocalMessageURI(const char* uri,
00223                                 nsCString& folderURI,
00224                                 PRUint32 *key)
00225 {
00226   if(!key)
00227     return NS_ERROR_NULL_POINTER;
00228 
00229   nsCAutoString uriStr(uri);
00230   PRInt32 keySeparator = uriStr.FindChar('#');
00231   if(keySeparator != -1)
00232   {
00233     PRInt32 keyEndSeparator = uriStr.FindCharInSet("?&", 
00234                                                    keySeparator); 
00235     nsAutoString folderPath;
00236     uriStr.Left(folderURI, keySeparator);
00237         folderURI.Cut(7, 8);    // cut out the -message part of mailbox-message:
00238 
00239     nsCAutoString keyStr;
00240     if (keyEndSeparator != -1)
00241         uriStr.Mid(keyStr, keySeparator+1, 
00242                    keyEndSeparator-(keySeparator+1));
00243     else
00244         uriStr.Right(keyStr, uriStr.Length() - (keySeparator + 1));
00245     PRInt32 errorCode;
00246     *key = keyStr.ToInteger(&errorCode);
00247 
00248     return errorCode;
00249   }
00250   return NS_ERROR_FAILURE;
00251 
00252 }
00253 
00254 nsresult nsBuildLocalMessageURI(const char *baseURI, PRUint32 key, nsCString& uri)
00255 {
00256   
00257   // need to convert mailbox://hostname/.. to mailbox-message://hostname/..
00258 
00259   uri.Append(baseURI);
00260   uri.Append('#');
00261   uri.AppendInt(key);
00262   return NS_OK;
00263 }
00264 
00265 nsresult nsCreateLocalBaseMessageURI(const char *baseURI, char **baseMessageURI)
00266 {
00267   if(!baseMessageURI)
00268     return NS_ERROR_NULL_POINTER;
00269 
00270   nsCAutoString tailURI(baseURI);
00271 
00272   // chop off mailbox:/
00273   if (tailURI.Find(kMailboxRootURI) == 0)
00274     tailURI.Cut(0, PL_strlen(kMailboxRootURI));
00275   
00276   nsCAutoString baseURIStr(kMailboxMessageRootURI);
00277   baseURIStr += tailURI;
00278 
00279   *baseMessageURI = ToNewCString(baseURIStr);
00280   if(!*baseMessageURI)
00281     return NS_ERROR_OUT_OF_MEMORY;
00282 
00283   return NS_OK;
00284 }