Back to index

lightning-sunbird  0.9+nobinonly
nsMsgMailNewsUrl.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "nsMsgMailNewsUrl.h"
00040 #include "nsMsgBaseCID.h"
00041 #include "nsIMsgMailSession.h"
00042 #include "nsIMsgAccountManager.h"
00043 #include "nsXPIDLString.h"
00044 #include "nsReadableUtils.h"
00045 #include "nsIDocumentLoader.h"
00046 #include "nsILoadGroup.h"
00047 #include "nsIDocShell.h"
00048 #include "nsIWebProgress.h"
00049 #include "nsIWebProgressListener.h"
00050 #include "nsIInterfaceRequestor.h"
00051 #include "nsIInterfaceRequestorUtils.h"
00052 #include "nsIIOService.h"
00053 #include "nsNetCID.h"
00054 #include "nsEscape.h"
00055 #include "nsIStreamListener.h"
00056 #include "nsIOutputStream.h"
00057 #include "nsIInputStream.h"
00058 #include "nsIFileSpec.h"
00059 #include <time.h>
00060 
00061 static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
00062 
00063 nsMsgMailNewsUrl::nsMsgMailNewsUrl()
00064 {
00065   // nsIURI specific state
00066   m_errorMessage = nsnull;
00067   m_runningUrl = PR_FALSE;
00068   m_updatingFolder = PR_FALSE;
00069   m_addContentToCache = PR_FALSE;
00070   m_msgIsInLocalCache = PR_FALSE;
00071   m_suppressErrorMsgs = PR_FALSE;
00072   
00073   m_urlListeners = do_CreateInstance(NS_URLLISTENERMANAGER_CONTRACTID);
00074   m_baseURL = do_CreateInstance(NS_STANDARDURL_CONTRACTID);
00075 }
00076 
00077 nsMsgMailNewsUrl::~nsMsgMailNewsUrl()
00078 {
00079   PR_FREEIF(m_errorMessage);
00080 }
00081   
00082 NS_IMPL_THREADSAFE_ADDREF(nsMsgMailNewsUrl)
00083 NS_IMPL_THREADSAFE_RELEASE(nsMsgMailNewsUrl)
00084 
00085 NS_INTERFACE_MAP_BEGIN(nsMsgMailNewsUrl)
00086    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMsgMailNewsUrl)
00087    NS_INTERFACE_MAP_ENTRY(nsIMsgMailNewsUrl)
00088    NS_INTERFACE_MAP_ENTRY(nsIURL)
00089    NS_INTERFACE_MAP_ENTRY(nsIURI)
00090 NS_INTERFACE_MAP_END_THREADSAFE
00091 
00093 // Begin nsIMsgMailNewsUrl specific support
00095 
00096 nsresult nsMsgMailNewsUrl::GetUrlState(PRBool * aRunningUrl)
00097 {
00098   if (aRunningUrl)
00099     *aRunningUrl = m_runningUrl;
00100 
00101   return NS_OK;
00102 }
00103 
00104 nsresult nsMsgMailNewsUrl::SetUrlState(PRBool aRunningUrl, nsresult aExitCode)
00105 {
00106   // if we already knew this running state, return, unless the url was aborted
00107   if (m_runningUrl == aRunningUrl && aExitCode != NS_MSG_ERROR_URL_ABORTED)
00108     return NS_OK;
00109   m_runningUrl = aRunningUrl;
00110   nsCOMPtr <nsIMsgStatusFeedback> statusFeedback;
00111   
00112   // put this back - we need it for urls that don't run through the doc loader
00113   if (NS_SUCCEEDED(GetStatusFeedback(getter_AddRefs(statusFeedback))) && statusFeedback)
00114   {
00115     if (m_runningUrl)
00116       statusFeedback->StartMeteors();
00117     else
00118     {
00119       statusFeedback->ShowProgress(0);
00120       statusFeedback->StopMeteors();
00121     }
00122   }
00123   if (m_urlListeners)
00124   {
00125     if (m_runningUrl)
00126     {
00127       m_urlListeners->OnStartRunningUrl(this);
00128     }
00129     else
00130     {
00131       m_urlListeners->OnStopRunningUrl(this, aExitCode);
00132       m_loadGroup = nsnull; // try to break circular refs.
00133     }
00134   }
00135   else
00136     printf("no listeners in set url state\n");
00137   
00138   return NS_OK;
00139 }
00140 
00141 nsresult nsMsgMailNewsUrl::RegisterListener (nsIUrlListener * aUrlListener)
00142 {
00143   if (m_urlListeners)
00144     m_urlListeners->RegisterListener(aUrlListener);
00145   return NS_OK;
00146 }
00147 
00148 nsresult nsMsgMailNewsUrl::UnRegisterListener (nsIUrlListener * aUrlListener)
00149 {
00150   if (m_urlListeners)
00151     m_urlListeners->UnRegisterListener(aUrlListener);
00152   return NS_OK;
00153 }
00154 
00155 nsresult nsMsgMailNewsUrl::SetErrorMessage (const char * errorMessage)
00156 {
00157   // functionality has been moved to nsIMsgStatusFeedback
00158   return NS_ERROR_NOT_IMPLEMENTED;
00159 }
00160 
00161 nsresult nsMsgMailNewsUrl::GetErrorMessage (char ** errorMessage)
00162 {
00163   // functionality has been moved to nsIMsgStatusFeedback
00164   return NS_ERROR_NOT_IMPLEMENTED;
00165 }
00166 
00167 NS_IMETHODIMP nsMsgMailNewsUrl::GetServer(nsIMsgIncomingServer ** aIncomingServer)
00168 {
00169   // mscott --> we could cache a copy of the server here....but if we did, we run
00170   // the risk of leaking the server if any single url gets leaked....of course that
00171   // shouldn't happen...but it could. so i'm going to look it up every time and
00172   // we can look at caching it later.
00173 
00174   nsresult rv;
00175   nsCAutoString urlstr;
00176   nsCAutoString scheme;
00177 
00178   nsCOMPtr<nsIURL> url = do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
00179   if (NS_FAILED(rv)) return rv;
00180 
00181   m_baseURL->GetSpec(urlstr);
00182   rv = url->SetSpec(urlstr);
00183   if (NS_FAILED(rv)) return rv;
00184   rv = GetScheme(scheme);
00185     if (NS_SUCCEEDED(rv))
00186     {
00187         if (scheme.EqualsLiteral("pop"))
00188           scheme.Assign("pop3");
00189         // we use "nntp" in the server list so translate it here.
00190         if (scheme.EqualsLiteral("news"))
00191           scheme.Assign("nntp");
00192         url->SetScheme(scheme);
00193         nsCOMPtr<nsIMsgAccountManager> accountManager = 
00194                  do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
00195         if (NS_FAILED(rv)) return rv;
00196         
00197         nsCOMPtr<nsIMsgIncomingServer> server;
00198         rv = accountManager->FindServerByURI(url, PR_FALSE,
00199                                         aIncomingServer);
00200         if (!*aIncomingServer && scheme.EqualsLiteral("imap"))
00201         {
00202           // look for any imap server with this host name so clicking on 
00203           // other users folder urls will work. We could override this method
00204           // for imap urls, or we could make caching of servers work and
00205           // just set the server in the imap code for this case.
00206           url->SetUserPass(EmptyCString());
00207           rv = accountManager->FindServerByURI(url, PR_FALSE,
00208                                           aIncomingServer);
00209         }
00210     }
00211 
00212     return rv;
00213 }
00214 
00215 NS_IMETHODIMP nsMsgMailNewsUrl::SetStatusFeedback(nsIMsgStatusFeedback *aMsgFeedback)
00216 {
00217   if (aMsgFeedback)
00218     m_statusFeedback = do_QueryInterface(aMsgFeedback);
00219   return NS_OK;
00220 }
00221 
00222 NS_IMETHODIMP nsMsgMailNewsUrl::GetMsgWindow(nsIMsgWindow **aMsgWindow)
00223 {
00224   NS_ENSURE_ARG_POINTER(aMsgWindow);
00225   
00226   // note: it is okay to return a null msg window and not return an error
00227   // it's possible the url really doesn't have msg window
00228 
00229   *aMsgWindow = m_msgWindow;
00230   NS_IF_ADDREF(*aMsgWindow);
00231 
00232   return NS_OK;
00233 }
00234 
00235 NS_IMETHODIMP nsMsgMailNewsUrl::SetMsgWindow(nsIMsgWindow *aMsgWindow)
00236 {
00237   if (aMsgWindow)
00238     m_msgWindow = do_QueryInterface(aMsgWindow);
00239   return NS_OK;
00240 }
00241 
00242 NS_IMETHODIMP nsMsgMailNewsUrl::GetStatusFeedback(nsIMsgStatusFeedback **aMsgFeedback)
00243 {
00244   nsresult rv = NS_OK;
00245   // note: it is okay to return a null status feedback and not return an error
00246   // it's possible the url really doesn't have status feedback
00247   if (!m_statusFeedback)
00248   {
00249 
00250     if(m_msgWindow)
00251     {
00252       m_msgWindow->GetStatusFeedback(getter_AddRefs(m_statusFeedback));
00253     }
00254   }
00255   if (aMsgFeedback)
00256   {
00257     *aMsgFeedback = m_statusFeedback;
00258     NS_IF_ADDREF(*aMsgFeedback);
00259   }
00260   else
00261     rv = NS_ERROR_NULL_POINTER;
00262   return rv;
00263 }
00264 
00265 NS_IMETHODIMP nsMsgMailNewsUrl::GetLoadGroup(nsILoadGroup **aLoadGroup)
00266 {
00267   nsresult rv = NS_OK;
00268   // note: it is okay to return a null load group and not return an error
00269   // it's possible the url really doesn't have load group
00270   if (!m_loadGroup)
00271   {
00272     if (m_msgWindow)
00273     {
00274             // XXXbz This is really weird... why are we getting some
00275             // random loadgroup we're not really a part of?
00276             nsCOMPtr<nsIDocShell> docShell;
00277             m_msgWindow->GetRootDocShell(getter_AddRefs(docShell));
00278 
00279 #if 0   // since we're not going through the doc loader for most mail/news urls,
00280        //, this code isn't useful
00281         // but I can imagine it could be useful at some point.
00282 
00283             // load group needs status feedback set, since it's
00284             // not the main window load group.
00285             nsCOMPtr<nsIMsgStatusFeedback> statusFeedback;
00286             m_msgWindow->GetStatusFeedback(getter_AddRefs(statusFeedback));
00287 
00288             if (statusFeedback)
00289             {
00290               nsCOMPtr<nsIWebProgress> webProgress(do_GetInterface(docShell));
00291               nsCOMPtr<nsIWebProgressListener> webProgressListener(do_QueryInterface(statusFeedback));
00292 
00293               // register our status feedback object
00294               if (statusFeedback && docShell)
00295               {
00296                 webProgressListener = do_QueryInterface(statusFeedback);
00297                 webProgress->AddProgressListener(webProgressListener,
00298                                                  nsIWebProgress::NOTIFY_ALL);
00299               }
00300             }
00301 #endif
00302             m_loadGroup = do_GetInterface(docShell);
00303     }
00304   }
00305 
00306   if (aLoadGroup)
00307   {
00308     *aLoadGroup = m_loadGroup;
00309     NS_IF_ADDREF(*aLoadGroup);
00310   }
00311   else
00312     rv = NS_ERROR_NULL_POINTER;
00313   return rv;
00314 
00315 }
00316 
00317 NS_IMETHODIMP nsMsgMailNewsUrl::GetUpdatingFolder(PRBool *aResult)
00318 {
00319   NS_ENSURE_ARG(aResult);
00320   *aResult = m_updatingFolder;
00321   return NS_OK;
00322 }
00323 
00324 NS_IMETHODIMP nsMsgMailNewsUrl::SetUpdatingFolder(PRBool updatingFolder)
00325 {
00326   m_updatingFolder = updatingFolder;
00327   return NS_OK;
00328 }
00329 
00330 NS_IMETHODIMP nsMsgMailNewsUrl::GetAddToMemoryCache(PRBool *aAddToCache)
00331 {
00332   NS_ENSURE_ARG(aAddToCache); 
00333   *aAddToCache = m_addContentToCache;
00334   return NS_OK;
00335 }
00336 
00337 NS_IMETHODIMP nsMsgMailNewsUrl::SetAddToMemoryCache(PRBool aAddToCache)
00338 {
00339   m_addContentToCache = aAddToCache;
00340   return NS_OK;
00341 }
00342 
00343 NS_IMETHODIMP nsMsgMailNewsUrl::GetMsgIsInLocalCache(PRBool *aMsgIsInLocalCache)
00344 {
00345   NS_ENSURE_ARG(aMsgIsInLocalCache); 
00346   *aMsgIsInLocalCache = m_msgIsInLocalCache;
00347   return NS_OK;
00348 }
00349 
00350 NS_IMETHODIMP nsMsgMailNewsUrl::SetMsgIsInLocalCache(PRBool aMsgIsInLocalCache)
00351 {
00352   m_msgIsInLocalCache = aMsgIsInLocalCache;
00353   return NS_OK;
00354 }
00355 
00356 NS_IMETHODIMP nsMsgMailNewsUrl::GetSuppressErrorMsgs(PRBool *aSuppressErrorMsgs)
00357 {
00358   NS_ENSURE_ARG(aSuppressErrorMsgs); 
00359   *aSuppressErrorMsgs = m_suppressErrorMsgs;
00360   return NS_OK;
00361 }
00362 
00363 NS_IMETHODIMP nsMsgMailNewsUrl::SetSuppressErrorMsgs(PRBool aSuppressErrorMsgs)
00364 {
00365   m_suppressErrorMsgs = aSuppressErrorMsgs;
00366   return NS_OK;
00367 }
00368 
00369 NS_IMETHODIMP nsMsgMailNewsUrl::IsUrlType(PRUint32 type, PRBool *isType)
00370 {
00371   //base class doesn't know about any specific types
00372   NS_ENSURE_ARG(isType);
00373   *isType = PR_FALSE;
00374   return NS_OK;
00375 
00376 }
00377 
00378 NS_IMETHODIMP nsMsgMailNewsUrl::SetSearchSession(nsIMsgSearchSession *aSearchSession)
00379 {
00380   if (aSearchSession)
00381     m_searchSession = do_QueryInterface(aSearchSession);
00382   return NS_OK;
00383 }
00384 
00385 NS_IMETHODIMP nsMsgMailNewsUrl::GetSearchSession(nsIMsgSearchSession **aSearchSession)
00386 {
00387   NS_ENSURE_ARG(aSearchSession);
00388   *aSearchSession = m_searchSession;
00389   NS_IF_ADDREF(*aSearchSession);
00390   return NS_OK;
00391 }
00392 
00394 // End nsIMsgMailNewsUrl specific support
00396 
00398 // Begin nsIURI support
00400 
00401 
00402 NS_IMETHODIMP nsMsgMailNewsUrl::GetSpec(nsACString &aSpec)
00403 {
00404   return m_baseURL->GetSpec(aSpec);
00405 }
00406 
00407 #define FILENAME_PART "&filename="
00408 #define FILENAME_PART_LEN 10
00409 
00410 NS_IMETHODIMP nsMsgMailNewsUrl::SetSpec(const nsACString &aSpec)
00411 {
00412   nsCAutoString spec(aSpec);
00413   // Parse out "filename" attribute if present.
00414   char *start, *end;
00415   start = PL_strcasestr(spec.BeginWriting(),FILENAME_PART);
00416   if (start)
00417   { // Make sure we only get our own value.
00418     end = PL_strcasestr((char*)(start+FILENAME_PART_LEN),"&");
00419     if (end)
00420     {
00421       *end = 0;
00422       mAttachmentFileName = start+FILENAME_PART_LEN;
00423       *end = '&';
00424     }
00425     else
00426       mAttachmentFileName = start+FILENAME_PART_LEN;
00427   }
00428   // Now, set the rest.
00429   return m_baseURL->SetSpec(aSpec);
00430 }
00431 
00432 NS_IMETHODIMP nsMsgMailNewsUrl::GetPrePath(nsACString &aPrePath)
00433 {
00434   return m_baseURL->GetPrePath(aPrePath);
00435 }
00436 
00437 NS_IMETHODIMP nsMsgMailNewsUrl::GetScheme(nsACString &aScheme)
00438 {
00439   return m_baseURL->GetScheme(aScheme);
00440 }
00441 
00442 NS_IMETHODIMP nsMsgMailNewsUrl::SetScheme(const nsACString &aScheme)
00443 {
00444   return m_baseURL->SetScheme(aScheme);
00445 }
00446 
00447 
00448 NS_IMETHODIMP nsMsgMailNewsUrl::GetUserPass(nsACString &aUserPass)
00449 {
00450   return m_baseURL->GetUserPass(aUserPass);
00451 }
00452 
00453 NS_IMETHODIMP nsMsgMailNewsUrl::SetUserPass(const nsACString &aUserPass)
00454 {
00455   return m_baseURL->SetUserPass(aUserPass);
00456 }
00457 
00458 NS_IMETHODIMP nsMsgMailNewsUrl::GetUsername(nsACString &aUsername)
00459 {
00460   /* note:  this will return an escaped string */
00461   return m_baseURL->GetUsername(aUsername);
00462 }
00463 
00464 NS_IMETHODIMP nsMsgMailNewsUrl::SetUsername(const nsACString &aUsername)
00465 {
00466   return m_baseURL->SetUsername(aUsername);
00467 }
00468 
00469 NS_IMETHODIMP nsMsgMailNewsUrl::GetPassword(nsACString &aPassword)
00470 {
00471   return m_baseURL->GetPassword(aPassword);
00472 }
00473 
00474 NS_IMETHODIMP nsMsgMailNewsUrl::SetPassword(const nsACString &aPassword)
00475 {
00476   return m_baseURL->SetPassword(aPassword);
00477 }
00478 
00479 NS_IMETHODIMP nsMsgMailNewsUrl::GetHostPort(nsACString &aHostPort)
00480 {
00481   return m_baseURL->GetHostPort(aHostPort);
00482 }
00483 
00484 NS_IMETHODIMP nsMsgMailNewsUrl::SetHostPort(const nsACString &aHostPort)
00485 {
00486   return m_baseURL->SetHostPort(aHostPort);
00487 }
00488 
00489 NS_IMETHODIMP nsMsgMailNewsUrl::GetHost(nsACString &aHost)
00490 {
00491   return m_baseURL->GetHost(aHost);
00492 }
00493 
00494 NS_IMETHODIMP nsMsgMailNewsUrl::SetHost(const nsACString &aHost)
00495 {
00496   return m_baseURL->SetHost(aHost);
00497 }
00498 
00499 NS_IMETHODIMP nsMsgMailNewsUrl::GetPort(PRInt32 *aPort)
00500 {
00501   return m_baseURL->GetPort(aPort);
00502 }
00503 
00504 NS_IMETHODIMP nsMsgMailNewsUrl::SetPort(PRInt32 aPort)
00505 {
00506   return m_baseURL->SetPort(aPort);
00507 }
00508 
00509 NS_IMETHODIMP nsMsgMailNewsUrl::GetPath(nsACString &aPath)
00510 {
00511   return m_baseURL->GetPath(aPath);
00512 }
00513 
00514 NS_IMETHODIMP nsMsgMailNewsUrl::SetPath(const nsACString &aPath)
00515 {
00516   return m_baseURL->SetPath(aPath);
00517 }
00518 
00519 NS_IMETHODIMP nsMsgMailNewsUrl::GetAsciiHost(nsACString &aHostA)
00520 {
00521     return m_baseURL->GetAsciiHost(aHostA);
00522 }
00523 
00524 NS_IMETHODIMP nsMsgMailNewsUrl::GetAsciiSpec(nsACString &aSpecA)
00525 {
00526     return m_baseURL->GetAsciiSpec(aSpecA);
00527 }
00528 
00529 NS_IMETHODIMP nsMsgMailNewsUrl::GetOriginCharset(nsACString &aOriginCharset)
00530 {
00531     return m_baseURL->GetOriginCharset(aOriginCharset);
00532 }
00533 
00534 NS_IMETHODIMP nsMsgMailNewsUrl::GetBaseURI(nsIURI **aBaseURI)
00535 {
00536   NS_ENSURE_ARG_POINTER(aBaseURI);
00537   return m_baseURL->QueryInterface(NS_GET_IID(nsIURI), (void**) aBaseURI);
00538 }
00539 
00540 NS_IMETHODIMP nsMsgMailNewsUrl::Equals(nsIURI *other, PRBool *_retval)
00541 {
00542   nsCOMPtr <nsIMsgMailNewsUrl> mailUrl = do_QueryInterface(other);
00543   // we really want to compare the base uris to each other, not our base URI
00544   // with the other's real URI.
00545   if (mailUrl)
00546   {
00547     nsCOMPtr <nsIURI> baseURI;
00548     mailUrl->GetBaseURI(getter_AddRefs(baseURI));
00549     if (baseURI)
00550       return m_baseURL->Equals(baseURI, _retval);
00551   }
00552   return m_baseURL->Equals(other, _retval);
00553 }
00554 
00555 NS_IMETHODIMP nsMsgMailNewsUrl::SchemeIs(const char *aScheme, PRBool *_retval)
00556 {
00557   nsCAutoString scheme;
00558   nsresult rv = m_baseURL->GetScheme(scheme);
00559   NS_ENSURE_SUCCESS(rv,rv);
00560 
00561   // fix #76200 crash on email with <img> with no src.
00562   //
00563   // make sure we have a scheme before calling SchemeIs()
00564   // we have to do this because url parsing can result in a null mScheme
00565   // this extra string copy should be removed when #73845 is fixed.
00566   if (!scheme.IsEmpty()) {
00567     return m_baseURL->SchemeIs(aScheme, _retval);
00568   }
00569   else {
00570     *_retval = PR_FALSE;
00571     return NS_OK;
00572   }
00573 }
00574 
00575 NS_IMETHODIMP nsMsgMailNewsUrl::Clone(nsIURI **_retval)
00576 {
00577   nsresult rv;
00578   nsCAutoString urlSpec;
00579   nsCOMPtr<nsIIOService> ioService = do_GetService(kIOServiceCID, &rv);
00580   if (NS_FAILED(rv)) return rv;
00581   rv = GetSpec(urlSpec);
00582   if (NS_FAILED(rv)) return rv;
00583   return ioService->NewURI(urlSpec, nsnull, nsnull, _retval);
00584 } 
00585 
00586 NS_IMETHODIMP nsMsgMailNewsUrl::Resolve(const nsACString &relativePath, nsACString &result) 
00587 {
00588   // only resolve anchor urls....i.e. urls which start with '#' against the mailnews url...
00589   // everything else shouldn't be resolved against mailnews urls.
00590   nsresult rv = NS_OK;
00591 
00592   if (relativePath.First() == '#') // an anchor
00593     return m_baseURL->Resolve(relativePath, result);
00594   else
00595   {
00596     // if relativePath is a complete url with it's own scheme then allow it...
00597     nsCOMPtr<nsIIOService> ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
00598     NS_ENSURE_SUCCESS(rv, rv);
00599     nsCAutoString scheme;
00600 
00601     rv = ioService->ExtractScheme(relativePath, scheme);
00602     // if we have a fully qualified scheme then pass the relative path back as the result
00603     if (NS_SUCCEEDED(rv) && !scheme.IsEmpty())
00604     {
00605       result = relativePath;
00606       rv = NS_OK;
00607     }
00608     else
00609     {
00610       result.Truncate();
00611       rv = NS_ERROR_FAILURE;
00612     }
00613   }
00614 
00615   return rv;
00616 }
00617 
00618 NS_IMETHODIMP nsMsgMailNewsUrl::GetDirectory(nsACString &aDirectory)
00619 {
00620   return m_baseURL->GetDirectory(aDirectory);
00621 }
00622 
00623 NS_IMETHODIMP nsMsgMailNewsUrl::SetDirectory(const nsACString &aDirectory)
00624 {
00625 
00626   return m_baseURL->SetDirectory(aDirectory);
00627 }
00628 
00629 NS_IMETHODIMP nsMsgMailNewsUrl::GetFileName(nsACString &aFileName)
00630 {
00631   if (!mAttachmentFileName.IsEmpty())
00632   {
00633     aFileName = mAttachmentFileName;
00634     return NS_OK;
00635   }
00636   return m_baseURL->GetFileName(aFileName);
00637 }
00638 
00639 NS_IMETHODIMP nsMsgMailNewsUrl::GetFileBaseName(nsACString &aFileBaseName)
00640 {
00641   return m_baseURL->GetFileBaseName(aFileBaseName);
00642 }
00643 
00644 NS_IMETHODIMP nsMsgMailNewsUrl::SetFileBaseName(const nsACString &aFileBaseName)
00645 {
00646   return m_baseURL->SetFileBaseName(aFileBaseName);
00647 }
00648 
00649 NS_IMETHODIMP nsMsgMailNewsUrl::GetFileExtension(nsACString &aFileExtension)
00650 {
00651   if (!mAttachmentFileName.IsEmpty())
00652   {
00653     nsCAutoString extension;
00654     PRInt32 pos = mAttachmentFileName.RFindChar(PRUnichar('.'));
00655     if (pos > 0)
00656       mAttachmentFileName.Right(extension,
00657                                 mAttachmentFileName.Length() -
00658                                 (pos + 1) /* skip the '.' */);
00659     aFileExtension = extension;
00660     return NS_OK;
00661   }
00662   return m_baseURL->GetFileExtension(aFileExtension);
00663 }
00664 
00665 NS_IMETHODIMP nsMsgMailNewsUrl::SetFileExtension(const nsACString &aFileExtension)
00666 {
00667   return m_baseURL->SetFileExtension(aFileExtension);
00668 }
00669 
00670 NS_IMETHODIMP nsMsgMailNewsUrl::SetFileName(const nsACString &aFileName)
00671 {
00672   mAttachmentFileName = aFileName;
00673   return NS_OK;
00674 }
00675 
00676 NS_IMETHODIMP nsMsgMailNewsUrl::GetParam(nsACString &aParam)
00677 {
00678   return m_baseURL->GetParam(aParam);
00679 }
00680 
00681 NS_IMETHODIMP nsMsgMailNewsUrl::SetParam(const nsACString &aParam)
00682 {
00683   return m_baseURL->SetParam(aParam);
00684 }
00685 
00686 NS_IMETHODIMP nsMsgMailNewsUrl::GetQuery(nsACString &aQuery)
00687 {
00688   return m_baseURL->GetQuery(aQuery);
00689 }
00690 
00691 NS_IMETHODIMP nsMsgMailNewsUrl::SetQuery(const nsACString &aQuery)
00692 {
00693   return m_baseURL->SetQuery(aQuery);
00694 }
00695 
00696 NS_IMETHODIMP nsMsgMailNewsUrl::GetRef(nsACString &aRef)
00697 {
00698   return m_baseURL->GetRef(aRef);
00699 }
00700 
00701 NS_IMETHODIMP nsMsgMailNewsUrl::SetRef(const nsACString &aRef)
00702 {
00703   return m_baseURL->SetRef(aRef);
00704 }
00705 
00706 NS_IMETHODIMP nsMsgMailNewsUrl::GetFilePath(nsACString &o_DirFile)
00707 {
00708   return m_baseURL->GetFilePath(o_DirFile);
00709 }
00710 
00711 NS_IMETHODIMP nsMsgMailNewsUrl::SetFilePath(const nsACString &i_DirFile)
00712 {
00713   return m_baseURL->SetFilePath(i_DirFile);
00714 }
00715 
00716 NS_IMETHODIMP nsMsgMailNewsUrl::GetCommonBaseSpec(nsIURI *uri2, nsACString &result)
00717 {
00718   return m_baseURL->GetCommonBaseSpec(uri2, result);
00719 }
00720 
00721 NS_IMETHODIMP nsMsgMailNewsUrl::GetRelativeSpec(nsIURI *uri2, nsACString &result)
00722 {
00723   return m_baseURL->GetRelativeSpec(uri2, result);
00724 }
00725 
00726 NS_IMETHODIMP nsMsgMailNewsUrl::SetMemCacheEntry(nsICacheEntryDescriptor *memCacheEntry)
00727 {
00728   m_memCacheEntry = memCacheEntry;
00729   return NS_OK;
00730 }
00731 
00732 NS_IMETHODIMP nsMsgMailNewsUrl:: GetMemCacheEntry(nsICacheEntryDescriptor **memCacheEntry)
00733 {
00734   NS_ENSURE_ARG(memCacheEntry);
00735   nsresult rv = NS_OK;
00736 
00737   if (m_memCacheEntry)
00738   {
00739     *memCacheEntry = m_memCacheEntry;
00740     NS_ADDREF(*memCacheEntry);
00741   }
00742   else
00743   {
00744     *memCacheEntry = nsnull;
00745     return NS_ERROR_NULL_POINTER;
00746   }
00747 
00748   return rv;
00749 }
00750 
00751 NS_IMETHODIMP nsMsgMailNewsUrl::SetImageCacheSession(nsICacheSession *imageCacheSession)
00752 {
00753   m_imageCacheSession = imageCacheSession;
00754   return NS_OK;
00755 }
00756 
00757 NS_IMETHODIMP nsMsgMailNewsUrl:: GetImageCacheSession(nsICacheSession **imageCacheSession)
00758 {
00759   NS_ENSURE_ARG(imageCacheSession);
00760 
00761   NS_IF_ADDREF(*imageCacheSession = m_imageCacheSession);
00762 
00763   return NS_OK;
00764 }
00765 
00766 NS_IMETHODIMP nsMsgMailNewsUrl:: CacheCacheEntry(nsICacheEntryDescriptor *cacheEntry)
00767 {
00768   if (!m_cachedMemCacheEntries)
00769     NS_NewISupportsArray(getter_AddRefs(m_cachedMemCacheEntries));
00770   if (m_cachedMemCacheEntries)
00771   {
00772     nsCOMPtr<nsISupports> cacheEntrySupports(do_QueryInterface(cacheEntry));
00773     if(cacheEntrySupports)
00774       m_cachedMemCacheEntries->AppendElement(cacheEntrySupports);
00775   }
00776 
00777   return NS_OK;
00778 }
00779 
00780 NS_IMETHODIMP nsMsgMailNewsUrl:: RemoveCacheEntry(nsICacheEntryDescriptor *cacheEntry)
00781 {
00782   if (m_cachedMemCacheEntries)
00783   {
00784     nsCOMPtr<nsISupports> cacheEntrySupports(do_QueryInterface(cacheEntry));
00785     if(cacheEntrySupports)
00786       m_cachedMemCacheEntries->RemoveElement(cacheEntrySupports);
00787   }
00788   return NS_OK;
00789 }
00790 
00791 NS_IMETHODIMP nsMsgMailNewsUrl::GetMimeHeaders(nsIMimeHeaders * *mimeHeaders)
00792 {
00793     NS_ENSURE_ARG_POINTER(mimeHeaders);
00794     NS_IF_ADDREF(*mimeHeaders = mMimeHeaders);
00795     return (mMimeHeaders) ? NS_OK : NS_ERROR_NULL_POINTER;
00796 }
00797 
00798 NS_IMETHODIMP nsMsgMailNewsUrl::SetMimeHeaders(nsIMimeHeaders *mimeHeaders)
00799 {
00800     mMimeHeaders = mimeHeaders;
00801     return NS_OK;
00802 }
00803 
00804 #define SAVE_BUF_SIZE 8192
00805 class nsMsgSaveAsListener : public nsIStreamListener
00806 {
00807 public:
00808   NS_DECL_ISUPPORTS
00809   NS_DECL_NSIREQUESTOBSERVER
00810   NS_DECL_NSISTREAMLISTENER
00811 
00812   nsMsgSaveAsListener(nsIFileSpec *aFileSpec, PRBool addDummyEnvelope);
00813   virtual ~nsMsgSaveAsListener();
00814   nsresult SetupMsgWriteStream(nsIFileSpec *aFileSpec, PRBool addDummyEnvelope);
00815 protected:
00816   nsCOMPtr<nsIOutputStream> m_outputStream;
00817   nsCOMPtr<nsIFileSpec> m_outputFile;
00818   PRBool m_addDummyEnvelope;
00819   PRBool m_writtenData;
00820   PRUint32 m_leftOver;
00821   char m_dataBuffer[SAVE_BUF_SIZE+1]; // temporary buffer for this save operation
00822 
00823 };
00824 
00825 NS_IMPL_ISUPPORTS1(nsMsgSaveAsListener, nsIStreamListener)
00826 
00827 nsMsgSaveAsListener::nsMsgSaveAsListener(nsIFileSpec *aFileSpec, PRBool addDummyEnvelope)
00828 {
00829   m_outputFile = aFileSpec;
00830   m_writtenData = PR_FALSE;
00831   m_addDummyEnvelope = addDummyEnvelope;
00832   m_leftOver = 0;
00833 }
00834 
00835 nsMsgSaveAsListener::~nsMsgSaveAsListener()
00836 {
00837 }
00838 
00839 NS_IMETHODIMP nsMsgSaveAsListener::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
00840 {
00841   return NS_OK;
00842 }
00843 
00844 NS_IMETHODIMP
00845 nsMsgSaveAsListener::OnStopRequest(nsIRequest *request, nsISupports * aCtxt, nsresult aStatus)
00846 {
00847   if (m_outputStream)
00848   {
00849     m_outputStream->Flush();
00850     m_outputStream->Close();
00851   }
00852   if (m_outputFile)
00853     m_outputFile->CloseStream();
00854   return NS_OK;
00855 } 
00856 
00857 NS_IMETHODIMP nsMsgSaveAsListener::OnDataAvailable(nsIRequest* request, 
00858                                   nsISupports* aSupport,
00859                                   nsIInputStream* inStream, 
00860                                   PRUint32 srcOffset,
00861                                   PRUint32 count)
00862 {
00863   nsresult rv;
00864   PRUint32 available;
00865   rv = inStream->Available(&available);
00866   if (!m_writtenData)
00867   {
00868     m_writtenData = PR_TRUE;
00869     rv = SetupMsgWriteStream(m_outputFile, m_addDummyEnvelope);
00870     NS_ENSURE_SUCCESS(rv, rv);
00871   }
00872 
00873   PRBool useCanonicalEnding = PR_FALSE;
00874   nsCOMPtr <nsIMsgMessageUrl> msgUrl = do_QueryInterface(aSupport);
00875   if (msgUrl)
00876     msgUrl->GetCanonicalLineEnding(&useCanonicalEnding);
00877   
00878   const char *lineEnding = (useCanonicalEnding) ? CRLF : MSG_LINEBREAK;
00879   PRUint32 lineEndingLength = (useCanonicalEnding) ? 2 : MSG_LINEBREAK_LEN;
00880 
00881   PRUint32 readCount, maxReadCount = SAVE_BUF_SIZE - m_leftOver;
00882   PRUint32 writeCount;
00883   char *start, *end;
00884   PRUint32 linebreak_len = 0;
00885 
00886   while (count > 0)
00887   {
00888       if (count < maxReadCount)
00889           maxReadCount = count;
00890       rv = inStream->Read(m_dataBuffer + m_leftOver,
00891                           maxReadCount,
00892                           &readCount);
00893       if (NS_FAILED(rv)) return rv;
00894 
00895       m_leftOver += readCount;
00896       m_dataBuffer[m_leftOver] = '\0';
00897 
00898       start = m_dataBuffer;
00899       end = PL_strchr(start, '\r');
00900       if (!end)
00901           end = PL_strchr(start, '\n');
00902       else if (*(end+1) == nsCRT::LF && linebreak_len == 0)
00903           linebreak_len = 2;
00904 
00905       if (linebreak_len == 0) // not initialize yet
00906           linebreak_len = 1;
00907 
00908       count -= readCount;
00909       maxReadCount = SAVE_BUF_SIZE - m_leftOver;
00910 
00911       if (!end && count > maxReadCount)
00912           // must be a very very long line; sorry cannot handle it
00913           return NS_ERROR_FAILURE;
00914 
00915       while (start && end)
00916       {
00917           if (PL_strncasecmp(start, "X-Mozilla-Status:", 17) &&
00918               PL_strncasecmp(start, "X-Mozilla-Status2:", 18) &&
00919               PL_strncmp(start, "From - ", 7))
00920           {
00921               rv = m_outputStream->Write(start, end-start, &writeCount);
00922               rv = m_outputStream->Write(lineEnding, lineEndingLength, &writeCount);
00923           }
00924           start = end+linebreak_len;
00925           if (start >= m_dataBuffer + m_leftOver)
00926           {
00927               maxReadCount = SAVE_BUF_SIZE;
00928               m_leftOver = 0;
00929               break;
00930           }
00931           end = PL_strchr(start, '\r');
00932           if (!end)
00933               end = PL_strchr(start, '\n');
00934           if (start && !end)
00935           {
00936               m_leftOver -= (start - m_dataBuffer);
00937               memcpy(m_dataBuffer, start,
00938                             m_leftOver+1); // including null
00939               maxReadCount = SAVE_BUF_SIZE - m_leftOver;
00940           }
00941       }
00942       if (NS_FAILED(rv)) return rv;
00943   }
00944   return rv;
00945   
00946   //  rv = m_outputStream->WriteFrom(inStream, PR_MIN(available, count), &bytesWritten);
00947 }
00948 
00949 nsresult nsMsgSaveAsListener::SetupMsgWriteStream(nsIFileSpec *aFileSpec, PRBool addDummyEnvelope)
00950 {
00951   nsresult rv = NS_ERROR_FAILURE;
00952 
00953   // If the file already exists, delete it, but do this before
00954   // getting the outputstream.
00955   // Due to bug 328027, the nsSaveMsgListener created in 
00956   // nsMessenger::SaveAs now opens the stream on the nsIFileSpec
00957   // object, thus creating an empty file. Actual save operations for
00958   // IMAP and NNTP use this nsMsgSaveAsListener here, though, so we
00959   // have to close the stream before deleting the file, else data
00960   // would still be written happily into a now non-existing file.
00961   // (Windows doesn't care, btw, just unixoids do...)
00962   nsFileSpec fileSpec;
00963   aFileSpec->CloseStream();
00964   aFileSpec->GetFileSpec(&fileSpec);
00965   fileSpec.Delete(PR_FALSE);
00966 
00967   rv = aFileSpec->GetOutputStream(getter_AddRefs(m_outputStream));
00968   NS_ENSURE_SUCCESS(rv,rv);
00969 
00970   if (m_outputStream && addDummyEnvelope)
00971   {
00972     nsCAutoString result;
00973     char *ct;
00974     PRUint32 writeCount;
00975     time_t now = time ((time_t*) 0);
00976     ct = ctime(&now);
00977     ct[24] = 0;
00978     result = "From - ";
00979     result += ct;
00980     result += MSG_LINEBREAK;
00981     
00982     m_outputStream->Write(result.get(), result.Length(),
00983                                &writeCount);
00984     result = "X-Mozilla-Status: 0001";
00985     result += MSG_LINEBREAK;
00986     m_outputStream->Write(result.get(), result.Length(),
00987                                &writeCount);
00988     result =  "X-Mozilla-Status2: 00000000";
00989     result += MSG_LINEBREAK;
00990     m_outputStream->Write(result.get(), result.Length(),
00991                                &writeCount);
00992   }
00993   return rv;
00994 }
00995 
00996 
00997 NS_IMETHODIMP nsMsgMailNewsUrl::GetSaveAsListener(PRBool addDummyEnvelope, 
00998                                                   nsIFileSpec *aFileSpec, nsIStreamListener **aSaveListener)
00999 {
01000   NS_ENSURE_ARG_POINTER(aSaveListener);
01001   nsMsgSaveAsListener *saveAsListener = new nsMsgSaveAsListener(aFileSpec, addDummyEnvelope);
01002   return saveAsListener->QueryInterface(NS_GET_IID(nsIStreamListener), (void **) aSaveListener);
01003 }
01004 
01005 
01006 NS_IMETHODIMP nsMsgMailNewsUrl::SetFolder(nsIMsgFolder * /* aFolder */)
01007 {
01008   return NS_ERROR_NOT_IMPLEMENTED;
01009 }
01010 
01011 NS_IMETHODIMP nsMsgMailNewsUrl::GetFolder(nsIMsgFolder ** /* aFolder */)
01012 {
01013   return NS_ERROR_NOT_IMPLEMENTED;
01014 }
01015 
01016 NS_IMETHODIMP nsMsgMailNewsUrl::GetMsgHeaderSink(nsIMsgHeaderSink * *aMsgHdrSink)
01017 {
01018     NS_ENSURE_ARG_POINTER(aMsgHdrSink);
01019     NS_IF_ADDREF(*aMsgHdrSink = mMsgHeaderSink);
01020     return NS_OK;
01021 }
01022 
01023 NS_IMETHODIMP nsMsgMailNewsUrl::SetMsgHeaderSink(nsIMsgHeaderSink * aMsgHdrSink)
01024 {
01025     mMsgHeaderSink = aMsgHdrSink;
01026     return NS_OK;
01027 }