Back to index

lightning-sunbird  0.9+nobinonly
nsNntpUrl.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  *   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 
00039 #include "msgCore.h"    // precompiled header...
00040 #include "prlog.h"
00041 #include "nsISupportsObsolete.h"
00042 
00043 #include "nsIURL.h"
00044 #include "nsNntpUrl.h"
00045 
00046 #include "nsString.h"
00047 #include "nsReadableUtils.h"
00048 #include "prmem.h"
00049 #include "plstr.h"
00050 #include "prprf.h"
00051 #include "nsCRT.h"
00052 #include "nsNewsUtils.h"
00053 #include "nsISupportsObsolete.h"
00054 
00055 #include "nntpCore.h"
00056 
00057 #include "nsCOMPtr.h"
00058 #include "nsXPIDLString.h"
00059 #include "nsIMsgDatabase.h"
00060 #include "nsMsgDBCID.h"
00061 #include "nsMsgNewsCID.h"
00062 #include "nsIRDFService.h"
00063 #include "rdf.h"
00064 #include "nsIMsgFolder.h"
00065 #include "nsINntpService.h"
00066 #include "nsIMsgMessageService.h"
00067 
00068     
00069 nsNntpUrl::nsNntpUrl()
00070 {
00071   m_newsgroupPost = nsnull;
00072   m_newsAction = nsINntpUrl::ActionUnknown;
00073   m_addDummyEnvelope = PR_FALSE;
00074   m_canonicalLineEnding = PR_FALSE;
00075   m_filePath = nsnull;
00076   m_getOldMessages = PR_FALSE;
00077 }
00078          
00079 nsNntpUrl::~nsNntpUrl()
00080 {
00081   NS_IF_RELEASE(m_newsgroupPost);
00082 }
00083   
00084 NS_IMPL_ADDREF_INHERITED(nsNntpUrl, nsMsgMailNewsUrl)
00085 NS_IMPL_RELEASE_INHERITED(nsNntpUrl, nsMsgMailNewsUrl)
00086 
00087 NS_INTERFACE_MAP_BEGIN(nsNntpUrl)
00088    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsINntpUrl)
00089    NS_INTERFACE_MAP_ENTRY(nsINntpUrl)
00090    NS_INTERFACE_MAP_ENTRY(nsIMsgMessageUrl)
00091    NS_INTERFACE_MAP_ENTRY(nsIMsgI18NUrl)
00092 NS_INTERFACE_MAP_END_INHERITING(nsMsgMailNewsUrl)
00093 
00095 // Begin nsINntpUrl specific support
00097 NS_IMETHODIMP nsNntpUrl::SetSpec(const nsACString &aSpec)
00098 {
00099        nsresult rv = nsMsgMailNewsUrl::SetSpec(aSpec);
00100   NS_ENSURE_SUCCESS(rv,rv);
00101 
00102        rv = DetermineNewsAction();
00103   NS_ENSURE_SUCCESS(rv,rv);
00104        return rv;
00105 }
00106 
00107 nsresult nsNntpUrl::DetermineNewsAction()
00108 {
00109   nsCAutoString path;
00110   nsresult rv = nsMsgMailNewsUrl::GetPath(path);
00111   NS_ENSURE_SUCCESS(rv,rv);
00112 
00113   if (!strcmp(path.get(),"/*")) {
00114     // news://news.mozilla.org/* 
00115     // get all newsgroups on the server, for subscribe
00116     m_newsAction = nsINntpUrl::ActionListGroups;
00117     return NS_OK;
00118   }
00119 
00120   if (!strcmp(path.get(),"/")) {
00121     // could be news:netscape.public.mozilla.mail-news or news://news.mozilla.org
00122     // news:netscape.public.mozilla.mail-news gets turned into news://netscape.public.mozilla.mail-news/ by nsStandardURL
00123     // news://news.mozilla.org gets turned in to news://news.mozilla.org/ by nsStandardURL
00124     // news://news.mozilla.org is nsINntpUrl::ActionUpdateCounts
00125     // (which is "update the unread counts for all groups that we're subscribed to on news.mozilla.org)
00126     // news:netscape.public.mozilla.mail-news is nsINntpUrl::AutoSubscribe
00127     //
00128     // also in here for, news:3B98D201.3020100@cs.com
00129     // and when posting, and during message display GetCodeBasePrinciple() and nsMimeNewURI()
00130     //
00131     // set it as unknown (so we won't try to check the cache for it
00132     // we'll figure out the action later, or it will be set on the url by the caller.
00133     m_newsAction = nsINntpUrl::ActionUnknown;
00134     return NS_OK;
00135   }
00136     
00137   if (PL_strcasestr(path.get(), "?part=") || PL_strcasestr(path.get(), "&part=")) {
00138     // news://news.mozilla.org:119/3B98D201.3020100%40cs.com?part=1
00139     // news://news.mozilla.org:119/b58dme%24aia2%40ripley.netscape.com?header=print&part=1.2&type=image/jpeg&filename=Pole.jpg
00140     m_newsAction = nsINntpUrl::ActionFetchPart;
00141     return NS_OK;
00142   }
00143 
00144   if (PL_strcasestr(path.get(), "?cancel")) {
00145     // news://news.mozilla.org/3C06C0E8.5090107@sspitzer.org?cancel
00146     m_newsAction = nsINntpUrl::ActionCancelArticle;
00147     return NS_OK;
00148   }
00149 
00150   if (PL_strcasestr(path.get(), "?list-ids")) {
00151     // news://news.mozilla.org/netscape.test?list-ids
00152     // remove all cancelled articles from netscape.test
00153     m_newsAction = nsINntpUrl::ActionListIds;
00154     return NS_OK;
00155   }
00156    
00157   if (strchr(path.get(), '@') || strstr(path.get(),"%40")) {
00158     // news://news.mozilla.org/3B98D201.3020100@cs.com
00159     // news://news.mozilla.org/3B98D201.3020100%40cs.com
00160     m_newsAction = nsINntpUrl::ActionFetchArticle;
00161     return NS_OK;
00162   }
00163 
00164   // news://news.mozilla.org/netscape.test could be 
00165   // get new news for netscape.test (nsINntpUrl::ActionGetNewNews)
00166   // or subscribe to netscape.test (nsINntpUrl::AutoSubscribe)
00167   // set it as unknown (so we won't try to check the cache for it
00168   // we'll figure out the action later, or it will be set on the url by the caller.
00169   m_newsAction = nsINntpUrl::ActionUnknown;
00170   return NS_OK;
00171 }
00172 
00173 NS_IMETHODIMP nsNntpUrl::SetGetOldMessages(PRBool aGetOldMessages)
00174 {
00175        m_getOldMessages = aGetOldMessages;
00176        return NS_OK;
00177 }
00178 
00179 NS_IMETHODIMP nsNntpUrl::GetGetOldMessages(PRBool * aGetOldMessages)
00180 {
00181        NS_ENSURE_ARG(aGetOldMessages);
00182        *aGetOldMessages = m_getOldMessages;
00183        return NS_OK;
00184 }
00185 
00186 NS_IMETHODIMP nsNntpUrl::GetNewsAction(nsNewsAction *aNewsAction)
00187 {
00188        if (aNewsAction)
00189               *aNewsAction = m_newsAction;
00190        return NS_OK;
00191 }
00192 
00193 
00194 NS_IMETHODIMP nsNntpUrl::SetNewsAction(nsNewsAction aNewsAction)
00195 {
00196        m_newsAction = aNewsAction;
00197        return NS_OK;
00198 }
00199 
00200 NS_IMETHODIMP nsNntpUrl::SetUri(const char * aURI)
00201 {
00202   mURI = aURI;
00203   return NS_OK;
00204 }
00205 
00206 // from nsIMsgMessageUrl
00207 NS_IMETHODIMP nsNntpUrl::GetUri(char ** aURI)
00208 {
00209   nsresult rv = NS_OK;
00210 
00211   // if we have been given a uri to associate with this url, then use it
00212   // otherwise try to reconstruct a URI on the fly....
00213   if (mURI.IsEmpty()) {
00214     nsCAutoString spec;
00215     rv = GetSpec(spec);
00216     NS_ENSURE_SUCCESS(rv,rv);
00217     mURI = spec;
00218   }
00219   
00220   *aURI = ToNewCString(mURI);
00221   if (!*aURI) return NS_ERROR_OUT_OF_MEMORY; 
00222   return rv;
00223 }
00224 
00225 
00226 NS_IMPL_GETSET(nsNntpUrl, AddDummyEnvelope, PRBool, m_addDummyEnvelope)
00227 NS_IMPL_GETSET(nsNntpUrl, CanonicalLineEnding, PRBool, m_canonicalLineEnding)
00228 
00229 NS_IMETHODIMP nsNntpUrl::SetMessageFile(nsIFileSpec * aFileSpec)
00230 {
00231        m_messageFileSpec = aFileSpec;
00232        return NS_OK;
00233 }
00234 
00235 NS_IMETHODIMP nsNntpUrl::GetMessageFile(nsIFileSpec ** aFileSpec)
00236 {
00237        if (aFileSpec)
00238        {
00239               *aFileSpec = m_messageFileSpec;
00240               NS_IF_ADDREF(*aFileSpec);
00241        }
00242        return NS_OK;
00243 }
00244 
00246 // End nsINntpUrl specific support
00248 
00249 nsresult nsNntpUrl::SetMessageToPost(nsINNTPNewsgroupPost *post)
00250 {
00251     NS_LOCK_INSTANCE();
00252     NS_IF_RELEASE(m_newsgroupPost);
00253     m_newsgroupPost=post;
00254     if (m_newsgroupPost) NS_ADDREF(m_newsgroupPost);
00255     NS_UNLOCK_INSTANCE();
00256     return NS_OK;
00257 }
00258 
00259 nsresult nsNntpUrl::GetMessageToPost(nsINNTPNewsgroupPost **aPost)
00260 {
00261     NS_LOCK_INSTANCE();
00262     if (!aPost) return NS_ERROR_NULL_POINTER;
00263     *aPost = m_newsgroupPost;
00264     if (*aPost) NS_ADDREF(*aPost);
00265     NS_UNLOCK_INSTANCE();
00266     return NS_OK;
00267 }
00268 
00269 NS_IMETHODIMP nsNntpUrl::GetMessageHeader(nsIMsgDBHdr ** aMsgHdr)
00270 {
00271   nsresult rv;
00272   
00273   nsCOMPtr <nsINntpService> nntpService = do_GetService(NS_NNTPSERVICE_CONTRACTID, &rv);
00274   NS_ENSURE_SUCCESS(rv,rv);
00275 
00276   nsCOMPtr <nsIMsgMessageService> msgService = do_QueryInterface(nntpService, &rv);
00277   NS_ENSURE_SUCCESS(rv,rv);
00278 
00279   if (mOriginalSpec.IsEmpty()) {
00280     // this can happen when viewing a news://host/message-id url
00281     return NS_ERROR_FAILURE;
00282   }
00283 
00284   rv = msgService->MessageURIToMsgHdr(mOriginalSpec.get(), aMsgHdr);
00285   NS_ENSURE_SUCCESS(rv,rv);
00286   
00287   return NS_OK;
00288 }
00289 
00290 NS_IMETHODIMP nsNntpUrl::IsUrlType(PRUint32 type, PRBool *isType)
00291 {
00292        NS_ENSURE_ARG(isType);
00293 
00294        switch(type)
00295        {
00296               case nsIMsgMailNewsUrl::eDisplay:
00297                      *isType = (m_newsAction == nsINntpUrl::ActionFetchArticle);
00298                      break;
00299               default:
00300                      *isType = PR_FALSE;
00301        };                          
00302 
00303        return NS_OK;
00304 
00305 }
00306 
00307 NS_IMETHODIMP
00308 nsNntpUrl::GetOriginalSpec(char **aSpec)
00309 {
00310     NS_ENSURE_ARG_POINTER(aSpec);
00311     *aSpec = ToNewCString(mOriginalSpec);
00312     if (!*aSpec) return NS_ERROR_OUT_OF_MEMORY;
00313     return NS_OK;
00314 }
00315 
00316 NS_IMETHODIMP
00317 nsNntpUrl::SetOriginalSpec(const char *aSpec)
00318 {
00319     mOriginalSpec = aSpec;
00320     return NS_OK;
00321 }
00322 
00323 NS_IMETHODIMP nsNntpUrl::GetFolder(nsIMsgFolder **msgFolder)
00324 {
00325    nsresult rv;
00326 
00327    if (mOriginalSpec.IsEmpty()) {
00328     // this could be a autosubscribe url (news://host/group)
00329     // or a message id url (news://host/message-id)
00330     // either way, we won't have a msgFolder for you
00331     return NS_ERROR_FAILURE;
00332    }
00333 
00334    nsCOMPtr <nsINntpService> nntpService = do_GetService(NS_NNTPSERVICE_CONTRACTID, &rv);
00335    NS_ENSURE_SUCCESS(rv,rv);
00336 
00337    nsMsgKey msgKey;
00338    // XXX should we find the first "?" in the mOriginalSpec, cut there, and pass that in?
00339    rv = nntpService->DecomposeNewsURI(mOriginalSpec.get(), msgFolder, &msgKey);
00340    NS_ENSURE_SUCCESS(rv,rv);
00341    return NS_OK;
00342 }
00343 
00344 NS_IMETHODIMP 
00345 nsNntpUrl::GetFolderCharset(char **aCharacterSet)
00346 {
00347   nsCOMPtr<nsIMsgFolder> folder;
00348   nsresult rv = GetFolder(getter_AddRefs(folder));
00349   // don't assert here.  this can happen if there is no message folder
00350   // like when we display a news://host/message-id url
00351   if (NS_FAILED(rv)) return rv;
00352 
00353   NS_ENSURE_TRUE(folder, NS_ERROR_FAILURE);
00354   rv = folder->GetCharset(aCharacterSet);
00355   NS_ENSURE_SUCCESS(rv,rv);
00356   return rv;
00357 }
00358 
00359 NS_IMETHODIMP nsNntpUrl::GetFolderCharsetOverride(PRBool * aCharacterSetOverride)
00360 {
00361   nsCOMPtr<nsIMsgFolder> folder;
00362   nsresult rv = GetFolder(getter_AddRefs(folder));
00363   NS_ENSURE_SUCCESS(rv,rv);
00364   NS_ENSURE_TRUE(folder, NS_ERROR_FAILURE);
00365   rv = folder->GetCharsetOverride(aCharacterSetOverride);
00366   NS_ENSURE_SUCCESS(rv,rv);
00367   return rv;
00368 }
00369 
00370 NS_IMETHODIMP nsNntpUrl::GetCharsetOverRide(char ** aCharacterSet)
00371 {
00372   if (!mCharsetOverride.IsEmpty())
00373     *aCharacterSet = ToNewCString(mCharsetOverride); 
00374   else
00375     *aCharacterSet = nsnull;
00376   return NS_OK;
00377 }
00378 
00379 NS_IMETHODIMP nsNntpUrl::SetCharsetOverRide(const char * aCharacterSet)
00380 {
00381   mCharsetOverride = aCharacterSet;
00382   return NS_OK;
00383 }
00384 
00385 NS_IMETHODIMP nsNntpUrl::Clone(nsIURI **_retval)
00386 {
00387   nsresult rv;
00388   rv = nsMsgMailNewsUrl::Clone(_retval);
00389   NS_ENSURE_SUCCESS(rv, rv);
00390 
00391   nsCOMPtr<nsIMsgMessageUrl> newsurl = do_QueryInterface(*_retval, &rv);
00392   NS_ENSURE_SUCCESS(rv, rv);
00393 
00394   return newsurl->SetUri(mURI.get());
00395 }
00396