Back to index

lightning-sunbird  0.9+nobinonly
nsMsgCopy.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) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Pierre Phaneuf <pp@ludusdesign.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 #include "nsMsgCopy.h"
00039 
00040 #include "nsXPIDLString.h"
00041 #include "nsCOMPtr.h"
00042 #include "nsMsgBaseCID.h"
00043 #include "nsMsgFolderFlags.h"
00044 #include "nsIMsgFolder.h"
00045 #include "nsIMsgAccountManager.h"
00046 #include "nsIMsgFolder.h"
00047 #include "nsISupportsArray.h"
00048 #include "nsIMsgIncomingServer.h"
00049 #include "nsISupports.h"
00050 #include "nsIRDFService.h"
00051 #include "nsIRDFResource.h"
00052 #include "nsRDFCID.h"
00053 #include "nsIURL.h"
00054 #include "nsNetCID.h"
00055 #include "nsMsgComposeStringBundle.h"
00056 #include "nsMsgCompUtils.h"
00057 #include "prcmon.h"
00058 #include "nsIMsgImapMailFolder.h"
00059 #include "nsIEventQueueService.h"
00060 #include "nsMsgSimulateError.h"
00061 #include "nsIMsgWindow.h"
00062 #include "nsIMsgProgress.h"
00063 
00064 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
00065 static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
00066 
00068 // This is the listener class for the copy operation. We have to create this class 
00069 // to listen for message copy completion and eventually notify the caller
00071 NS_IMPL_THREADSAFE_ADDREF(CopyListener)
00072 NS_IMPL_THREADSAFE_RELEASE(CopyListener)
00073 
00074 NS_INTERFACE_MAP_BEGIN(CopyListener)
00075    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMsgCopyServiceListener)
00076    NS_INTERFACE_MAP_ENTRY(nsIMsgCopyServiceListener)
00077 NS_INTERFACE_MAP_END_THREADSAFE
00078 
00079 CopyListener::CopyListener(void) 
00080 { 
00081   mCopyObject = nsnull;
00082   mCopyInProgress = PR_FALSE;
00083 }
00084 
00085 CopyListener::~CopyListener(void) 
00086 {
00087 }
00088 
00089 nsresult
00090 CopyListener::OnStartCopy()
00091 {
00092 #ifdef NS_DEBUG
00093   printf("CopyListener::OnStartCopy()\n");
00094 #endif
00095 
00096   if (mComposeAndSend)
00097     mComposeAndSend->NotifyListenerOnStartCopy();
00098   return NS_OK;
00099 }
00100   
00101 nsresult
00102 CopyListener::OnProgress(PRUint32 aProgress, PRUint32 aProgressMax)
00103 {
00104 #ifdef NS_DEBUG
00105   printf("CopyListener::OnProgress() %d of %d\n", aProgress, aProgressMax);
00106 #endif
00107 
00108   if (mComposeAndSend)
00109     mComposeAndSend->NotifyListenerOnProgressCopy(aProgress, aProgressMax);
00110 
00111   return NS_OK;
00112 }
00113 
00114 nsresult
00115 CopyListener::SetMessageKey(PRUint32 aMessageKey)
00116 {
00117   if (mComposeAndSend)
00118       mComposeAndSend->SetMessageKey(aMessageKey);
00119   return NS_OK;
00120 }
00121 
00122 nsresult
00123 CopyListener::GetMessageId(nsCString *aMessageId)
00124 {
00125   if (mComposeAndSend)
00126       mComposeAndSend->GetMessageId(aMessageId);
00127   return NS_OK;
00128 }
00129 
00130 nsresult
00131 CopyListener::OnStopCopy(nsresult aStatus)
00132 {
00133   if (NS_SUCCEEDED(aStatus))
00134   {
00135 #ifdef NS_DEBUG
00136     printf("CopyListener: SUCCESSFUL ON THE COPY OPERATION!\n");
00137 #endif
00138   }
00139   else
00140   {
00141 #ifdef NS_DEBUG
00142     printf("CopyListener: COPY OPERATION FAILED!\n");
00143 #endif
00144   }
00145 
00146   if (mCopyObject)
00147   {
00148       PR_CEnterMonitor(mCopyObject);
00149       PR_CNotifyAll(mCopyObject);
00150       mCopyInProgress = PR_FALSE;
00151       PR_CExitMonitor(mCopyObject);
00152   }
00153   if (mComposeAndSend)
00154     mComposeAndSend->NotifyListenerOnStopCopy(aStatus);
00155 
00156   return NS_OK;
00157 }
00158 
00159 nsresult
00160 CopyListener::SetMsgComposeAndSendObject(nsIMsgSend *obj)
00161 {
00162   if (obj)
00163     mComposeAndSend = obj;
00164 
00165   return NS_OK;
00166 }
00167 
00169 // END  END  END  END  END  END  END  END  END  END  END  END  END  END  END 
00170 // This is the listener class for the copy operation. We have to create this class 
00171 // to listen for message copy completion and eventually notify the caller
00173 
00174 NS_IMPL_ISUPPORTS1(nsMsgCopy, nsIUrlListener)
00175 
00176 nsMsgCopy::nsMsgCopy()
00177 {
00178   mCopyListener = nsnull;
00179   mFileSpec = nsnull;
00180   mMode = nsIMsgSend::nsMsgDeliverNow;
00181   mSavePref = nsnull;
00182 }
00183 
00184 nsMsgCopy::~nsMsgCopy()
00185 {
00186   PR_Free(mSavePref);
00187 }
00188 
00189 nsresult
00190 nsMsgCopy::StartCopyOperation(nsIMsgIdentity       *aUserIdentity,
00191                               nsIFileSpec          *aFileSpec, 
00192                               nsMsgDeliverMode     aMode,
00193                               nsIMsgSend           *aMsgSendObj,
00194                               const char           *aSavePref,
00195                               nsIMsgDBHdr            *aMsgToReplace)
00196 {
00197   nsCOMPtr<nsIMsgFolder>  dstFolder;
00198   PRBool                  isDraft = PR_FALSE;
00199   PRBool                  waitForUrl = PR_FALSE;
00200   nsresult                rv;
00201 
00202   if (!aMsgSendObj)
00203     return NS_ERROR_INVALID_ARG;
00204 
00205   // Store away the server location...
00206   if (aSavePref)
00207     mSavePref = PL_strdup(aSavePref);
00208 
00209   //
00210   // Vars for implementation...
00211   //
00212   if (aMode == nsIMsgSend::nsMsgQueueForLater)       // QueueForLater (Outbox)
00213   {
00214     rv = GetUnsentMessagesFolder(aUserIdentity, getter_AddRefs(dstFolder), &waitForUrl);
00215     isDraft = PR_FALSE;
00216     if (!dstFolder || NS_FAILED(rv)) {
00217       return NS_MSG_UNABLE_TO_SEND_LATER;
00218     } 
00219   }
00220   else if (aMode == nsIMsgSend::nsMsgSaveAsDraft)    // SaveAsDraft (Drafts)
00221   {
00222     rv = GetDraftsFolder(aUserIdentity, getter_AddRefs(dstFolder), &waitForUrl);
00223     isDraft = PR_TRUE;
00224     if (!dstFolder || NS_FAILED(rv))
00225       return NS_MSG_UNABLE_TO_SAVE_DRAFT;
00226   }
00227   else if (aMode == nsIMsgSend::nsMsgSaveAsTemplate) // SaveAsTemplate (Templates)
00228   {
00229     rv = GetTemplatesFolder(aUserIdentity, getter_AddRefs(dstFolder), &waitForUrl);
00230     isDraft = PR_FALSE;
00231     if (!dstFolder || NS_FAILED(rv) || CHECK_SIMULATED_ERROR(SIMULATED_SEND_ERROR_5))
00232            return NS_MSG_UNABLE_TO_SAVE_TEMPLATE;
00233   }
00234   else // SaveInSentFolder (Sent) -  nsMsgDeliverNow or nsMsgSendUnsent
00235   {
00236     rv = GetSentFolder(aUserIdentity, getter_AddRefs(dstFolder), &waitForUrl);
00237     isDraft = PR_FALSE;
00238     if (!dstFolder || NS_FAILED(rv)) 
00239       return NS_MSG_COULDNT_OPEN_FCC_FOLDER;
00240   }
00241 
00242   nsCOMPtr <nsIMsgWindow> msgWindow;
00243 
00244   if (aMsgSendObj)
00245   {
00246     nsCOMPtr <nsIMsgProgress> progress;
00247     aMsgSendObj->GetProgress(getter_AddRefs(progress));
00248     if (progress)
00249       progress->GetMsgWindow(getter_AddRefs(msgWindow));
00250   }
00251 
00252   mMode = aMode;
00253   mFileSpec = aFileSpec;
00254   mDstFolder = dstFolder;
00255   mMsgToReplace = aMsgToReplace;
00256   mIsDraft = isDraft;
00257   mMsgSendObj = aMsgSendObj;
00258   if (!waitForUrl)
00259   {
00260     // cache info needed for DoCopy and call DoCopy when OnStopUrl is called.
00261     rv = DoCopy(aFileSpec, dstFolder, aMsgToReplace, isDraft, msgWindow, aMsgSendObj);
00262     // N.B. "this" may be deleted when this call returns.
00263   }
00264   return rv;
00265 }
00266 
00267 nsresult 
00268 nsMsgCopy::DoCopy(nsIFileSpec *aDiskFile, nsIMsgFolder *dstFolder,
00269                   nsIMsgDBHdr *aMsgToReplace, PRBool aIsDraft,
00270                   nsIMsgWindow *msgWindow,
00271                   nsIMsgSend   *aMsgSendObj)
00272 {
00273   nsresult rv = NS_OK;
00274 
00275   // Check sanity
00276   if ((!aDiskFile) || (!dstFolder))
00277     return NS_ERROR_INVALID_ARG;
00278 
00279   //Call copyservice with dstFolder, disk file, and txnManager
00280   if(NS_SUCCEEDED(rv))
00281   {
00282     CopyListener    *tPtr = new CopyListener();
00283     if (!tPtr)
00284       return NS_ERROR_OUT_OF_MEMORY;
00285 
00286     mCopyListener = do_QueryInterface(tPtr, &rv);
00287     if (NS_FAILED(rv) || !mCopyListener)
00288       return NS_ERROR_OUT_OF_MEMORY;
00289 
00290     mCopyListener->SetMsgComposeAndSendObject(aMsgSendObj);
00291     nsCOMPtr<nsIEventQueue> eventQueue;
00292 
00293     if (aIsDraft)
00294     {
00295         nsCOMPtr<nsIMsgImapMailFolder> imapFolder =
00296             do_QueryInterface(dstFolder);
00297         nsCOMPtr<nsIMsgAccountManager> accountManager = 
00298                  do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
00299         if (NS_FAILED(rv)) return rv;
00300         PRBool shutdownInProgress = PR_FALSE;
00301         rv = accountManager->GetShutdownInProgress(&shutdownInProgress);
00302         
00303         if (NS_SUCCEEDED(rv) && shutdownInProgress && imapFolder)
00304         { 
00305           // set the following only when we were in the middle of shutdown
00306           // process
00307             mCopyListener->mCopyObject = do_QueryInterface(tPtr);
00308             mCopyListener->mCopyInProgress = PR_TRUE;
00309             nsCOMPtr<nsIEventQueueService> pEventQService = 
00310                      do_GetService(kEventQueueServiceCID, &rv);
00311             if (NS_FAILED(rv)) return rv;
00312             pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
00313                                                 getter_AddRefs(eventQueue)); 
00314         }
00315     }
00316     // ** make sure we have a valid copy listener while waiting for copy
00317     // server to finish
00318     nsCOMPtr<CopyListener> aCopyListener = do_QueryInterface(tPtr);
00319     nsCOMPtr<nsIMsgCopyService> copyService = do_GetService(NS_MSGCOPYSERVICE_CONTRACTID, &rv);
00320     NS_ENSURE_SUCCESS(rv, rv);
00321 
00322     rv = copyService->CopyFileMessage(aDiskFile, dstFolder, aMsgToReplace, 
00323                                       aIsDraft, MSG_FLAG_READ, mCopyListener, msgWindow);
00324     // aCopyListener->mCopyInProgress can only be set when we are in the
00325     // middle of the shutdown process
00326     while (aCopyListener->mCopyInProgress)
00327     {
00328         PR_CEnterMonitor(aCopyListener);
00329         PR_CWait(aCopyListener, PR_MicrosecondsToInterval(1000UL));
00330         PR_CExitMonitor(aCopyListener);
00331         if (eventQueue)
00332             eventQueue->ProcessPendingEvents();
00333     }
00334   }
00335 
00336   return rv;
00337 }
00338 
00339 // nsIUrlListener methods
00340 NS_IMETHODIMP
00341 nsMsgCopy::OnStartRunningUrl(nsIURI * aUrl)
00342 {
00343     return NS_OK;
00344 }
00345 
00346 NS_IMETHODIMP
00347 nsMsgCopy::OnStopRunningUrl(nsIURI * aUrl, nsresult aExitCode)
00348 {
00349   nsresult rv = aExitCode;
00350   if (NS_SUCCEEDED(aExitCode))
00351   {
00352     rv = DoCopy(mFileSpec, mDstFolder, mMsgToReplace, mIsDraft, nsnull, mMsgSendObj);
00353   }
00354   return rv;
00355 }
00356 
00357 nsresult
00358 nsMsgCopy::GetUnsentMessagesFolder(nsIMsgIdentity   *userIdentity, nsIMsgFolder **folder, PRBool *waitForUrl)
00359 {
00360   nsresult ret = LocateMessageFolder(userIdentity, nsIMsgSend::nsMsgQueueForLater, mSavePref, folder);
00361   CreateIfMissing(folder, waitForUrl);
00362   return ret;
00363 }
00364  
00365 nsresult 
00366 nsMsgCopy::GetDraftsFolder(nsIMsgIdentity *userIdentity, nsIMsgFolder **folder, PRBool *waitForUrl)
00367 {
00368   nsresult ret = LocateMessageFolder(userIdentity, nsIMsgSend::nsMsgSaveAsDraft, mSavePref, folder);
00369   CreateIfMissing(folder, waitForUrl);
00370   return ret;
00371 }
00372 
00373 nsresult 
00374 nsMsgCopy::GetTemplatesFolder(nsIMsgIdentity *userIdentity, nsIMsgFolder **folder, PRBool *waitForUrl)
00375 {
00376   nsresult ret = LocateMessageFolder(userIdentity, nsIMsgSend::nsMsgSaveAsTemplate, mSavePref, folder);
00377   CreateIfMissing(folder, waitForUrl);
00378   return ret;
00379 }
00380 
00381 nsresult 
00382 nsMsgCopy::GetSentFolder(nsIMsgIdentity *userIdentity, nsIMsgFolder **folder, PRBool *waitForUrl)
00383 {
00384   nsresult ret = LocateMessageFolder(userIdentity, nsIMsgSend::nsMsgDeliverNow, mSavePref, folder);
00385   CreateIfMissing(folder, waitForUrl);
00386   return ret;
00387 }
00388 
00389 nsresult 
00390 nsMsgCopy::CreateIfMissing(nsIMsgFolder **folder, PRBool *waitForUrl)
00391 {
00392   nsresult ret = NS_OK;
00393   if (folder && *folder)
00394   {
00395     nsCOMPtr <nsIMsgFolder> parent;
00396     (*folder)->GetParent(getter_AddRefs(parent));
00397     if (!parent)
00398     {
00399       nsCOMPtr <nsIFileSpec> folderPath;
00400       // for local folders, path is to the berkeley mailbox. 
00401       // for imap folders, path needs to have .msf appended to the name
00402       (*folder)->GetPath(getter_AddRefs(folderPath));
00403         PRBool isImapFolder = !nsCRT::strncasecmp(mSavePref, "imap:", 5);
00404       // if we can't get the path from the folder, then try to create the storage.
00405       // for imap, it doesn't matter if the .msf file exists - it still might not
00406       // exist on the server, so we should try to create it
00407       PRBool exists = PR_FALSE;
00408       if (!isImapFolder && folderPath)
00409         folderPath->Exists(&exists);
00410         if (!exists)
00411         {
00412           (*folder)->CreateStorageIfMissing(this);
00413           if (isImapFolder)
00414             *waitForUrl = PR_TRUE;
00415  
00416           ret = NS_OK;
00417         }
00418       }
00419     }
00420   return ret;
00421 }
00423 // Utility Functions for MsgFolders
00425 nsresult
00426 LocateMessageFolder(nsIMsgIdentity   *userIdentity, 
00427                     nsMsgDeliverMode aFolderType,
00428                     const char       *aFolderURI,
00429                     nsIMsgFolder     **msgFolder)
00430 {
00431   nsresult                  rv = NS_OK;
00432 
00433   RETURN_SIMULATED_ERROR(SIMULATED_SEND_ERROR_5, NS_ERROR_FAILURE)
00434   
00435   if (!msgFolder) return NS_ERROR_NULL_POINTER;
00436   *msgFolder = nsnull;
00437 
00438   if (!aFolderURI || !*aFolderURI)
00439     return NS_ERROR_INVALID_ARG;
00440 
00441   // as long as it doesn't start with anyfolder://
00442   if (PL_strncasecmp(ANY_SERVER, aFolderURI, strlen(aFolderURI)) != 0)
00443   {
00444     nsCOMPtr<nsIRDFService> rdf(do_GetService(kRDFServiceCID, &rv));
00445     if (NS_FAILED(rv)) return rv;
00446 
00447     // get the corresponding RDF resource
00448     // RDF will create the folder resource if it doesn't already exist
00449     nsCOMPtr<nsIRDFResource> resource;
00450     rv = rdf->GetResource(nsDependentCString(aFolderURI), getter_AddRefs(resource));
00451     if (NS_FAILED(rv)) return rv;
00452 
00453     nsCOMPtr <nsIMsgFolder> folderResource;
00454     folderResource = do_QueryInterface(resource, &rv);
00455     if (NS_SUCCEEDED(rv) && folderResource) 
00456     {
00457       // don't check validity of folder - caller will handle creating it
00458       nsCOMPtr<nsIMsgIncomingServer> server; 
00459       //make sure that folder hierarchy is built so that legitimate parent-child relationship is established
00460       rv = folderResource->GetServer(getter_AddRefs(server));
00461       NS_ENSURE_SUCCESS(rv,rv);
00462       return server->GetMsgFolderFromURI(folderResource, aFolderURI, msgFolder);
00463     }
00464     else 
00465     {
00466       return NS_ERROR_FAILURE;
00467     }
00468   }
00469   else 
00470   {
00471     PRUint32                  cnt = 0;
00472     PRUint32                  i;
00473 
00474     if (!userIdentity)
00475       return NS_ERROR_INVALID_ARG;
00476 
00477     // get the account manager
00478     nsCOMPtr<nsIMsgAccountManager> accountManager = 
00479              do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
00480     if (NS_FAILED(rv)) return rv;
00481 
00482     // if anyfolder will do, go look for one.
00483     nsCOMPtr<nsISupportsArray> retval; 
00484     accountManager->GetServersForIdentity(userIdentity, getter_AddRefs(retval)); 
00485     if (!retval) return NS_ERROR_FAILURE;
00486     
00487     // Ok, we have to look through the servers and try to find the server that
00488     // has a valid folder of the type that interests us...
00489     rv = retval->Count(&cnt);
00490     if (NS_FAILED(rv)) return rv;
00491     
00492     for (i=0; i<cnt; i++) {
00493       // Now that we have the server...we need to get the named message folder
00494       nsCOMPtr<nsIMsgIncomingServer> inServer; 
00495       
00496       inServer = do_QueryElementAt(retval, i, &rv);
00497       if(NS_FAILED(rv) || (!inServer))
00498         continue;
00499       
00500       //
00501       // If aFolderURI is passed in, then the user has chosen a specific
00502       // mail folder to save the message, but if it is null, just find the
00503       // first one and make that work. The folder is specified as a URI, like
00504       // the following:
00505       //
00506       //               mailbox://nobody@Local Folders/Sent
00507       //                  imap://rhp@nsmail-2/Drafts
00508       //                  newsgroup://news.mozilla.org/netscape.test
00509       //
00510       char *serverURI = nsnull;
00511       rv = inServer->GetServerURI(&serverURI);
00512       if ( NS_FAILED(rv) || (!serverURI) || !(*serverURI) )
00513         continue;
00514       
00515       nsCOMPtr<nsIMsgFolder> rootFolder;
00516       rv = inServer->GetRootFolder(getter_AddRefs(rootFolder));
00517       
00518       if(NS_FAILED(rv) || (!rootFolder))
00519         continue;
00520       
00521       PRUint32 numFolders = 0;
00522       
00523       // use the defaults by getting the folder by flags
00524       if (aFolderType == nsIMsgSend::nsMsgQueueForLater)       // QueueForLater (Outbox)
00525         {
00526           rv = rootFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_QUEUE, 1, &numFolders, msgFolder);
00527         }
00528       else if (aFolderType == nsIMsgSend::nsMsgSaveAsDraft)    // SaveAsDraft (Drafts)
00529         {
00530           rv = rootFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_DRAFTS, 1, &numFolders, msgFolder);
00531         }
00532       else if (aFolderType == nsIMsgSend::nsMsgSaveAsTemplate) // SaveAsTemplate (Templates)
00533         {
00534           rv = rootFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_TEMPLATES, 1, &numFolders, msgFolder);
00535         }
00536       else // SaveInSentFolder (Sent) -  nsMsgDeliverNow or nsMsgSendUnsent
00537         {
00538           rv = rootFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_SENTMAIL, 1, &numFolders, msgFolder);
00539         }
00540 
00541       if (NS_SUCCEEDED(rv) && *msgFolder) {
00542        return NS_OK;
00543       }
00544     }
00545   }
00546   
00547   return NS_ERROR_FAILURE;
00548 }
00549 
00550 //
00551 // Figure out if a folder is local or not and return a boolean to 
00552 // say so.
00553 //
00554 nsresult
00555 MessageFolderIsLocal(nsIMsgIdentity   *userIdentity, 
00556                      nsMsgDeliverMode aFolderType,
00557                      const char       *aFolderURI,
00558                    PRBool         *aResult)
00559 {
00560   nsresult rv;
00561 
00562   if (!aFolderURI) return NS_ERROR_NULL_POINTER;
00563 
00564   nsCOMPtr <nsIURL> url = do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
00565   if (NS_FAILED(rv)) return rv;
00566 
00567   rv = url->SetSpec(nsDependentCString(aFolderURI));
00568   if (NS_FAILED(rv)) return rv;
00569  
00570   /* mailbox:/ means its local (on disk) */
00571   rv = url->SchemeIs("mailbox", aResult);
00572   if (NS_FAILED(rv)) return rv;
00573   return NS_OK;
00574 }
00575