Back to index

lightning-sunbird  0.9+nobinonly
HeaderSniffer.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; 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  *   Adrian Mardare <amardare@qnx.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * 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 "nsILocalFile.h"
00040 #include "nsIChannel.h"
00041 #include "nsIHttpChannel.h"
00042 #include "nsIURL.h"
00043 #include "necko/nsNetUtil.h"
00044 #include "HeaderSniffer.h"
00045 #include "EmbedDownload.h"
00046 
00047 const char* const kPersistContractID = "@mozilla.org/embedding/browser/nsWebBrowserPersist;1";
00048 
00049 HeaderSniffer::HeaderSniffer( nsIWebBrowserPersist* aPersist, PtMozillaWidget_t *aMoz, nsIURI* aURL, nsIFile* aFile )
00050 : mPersist(aPersist)
00051 , mTmpFile(aFile)
00052 , mURL(aURL)
00053 {
00054        mMozillaWidget = aMoz;
00055 }
00056 
00057 HeaderSniffer::~HeaderSniffer( )
00058 {
00059 }
00060 
00061 NS_IMPL_ISUPPORTS1(HeaderSniffer, nsIWebProgressListener)
00062 
00063 
00064 /* nsIWebProgressListener interface */
00065 
00066 NS_IMETHODIMP HeaderSniffer::OnProgressChange(nsIWebProgress *aProgress, nsIRequest *aRequest, PRInt32 curSelfProgress, PRInt32 maxSelfProgress, PRInt32 curTotalProgress, PRInt32 maxTotalProgress) {
00067        return NS_OK;
00068        }
00069 
00070 NS_IMETHODIMP HeaderSniffer::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus) {
00071 
00072   if( aStateFlags & nsIWebProgressListener::STATE_START ) {
00073 
00074               nsCOMPtr<nsIWebBrowserPersist> kungFuDeathGrip(mPersist);   // be sure to keep it alive while we save
00075                                                                           // since it owns us as a listener
00076               nsCOMPtr<nsIWebProgressListener> kungFuSuicideGrip(this);   // and keep ourselves alive
00077 
00078     nsresult rv;
00079     nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest, &rv);
00080     if (!channel) return rv;
00081 
00082               nsCAutoString contentType, suggested_filename;
00083     channel->GetContentType(contentType);
00084 
00085     // Get the content-disposition if we're an HTTP channel.
00086     nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
00087     if (httpChannel) {
00088                      nsCAutoString contentDisposition;
00089       nsresult rv = httpChannel->GetResponseHeader(nsCAutoString("content-disposition"), contentDisposition);
00090                      if( NS_SUCCEEDED(rv) && !contentDisposition.IsEmpty() ) {
00091               PRInt32 index = contentDisposition.Find("filename=");
00092               if( index >= 0 ) {
00093                 // Take the substring following the prefix.
00094                 index += 9;
00095                 contentDisposition.Right(suggested_filename, contentDisposition.Length() - index);
00096                                    }
00097                             }
00098                      }
00099 
00100               /* make the client display a file selection dialog */
00101               PtCallbackInfo_t cbinfo;
00102               PtWebUnknownWithNameCallback_t cb;
00103 
00104               memset( &cbinfo, 0, sizeof( cbinfo ) );
00105               cbinfo.reason = Pt_CB_MOZ_UNKNOWN;
00106               cbinfo.cbdata = &cb;
00107               cb.action = Pt_WEB_ACTION_OK;
00108               cb.content_type = (char*)contentType.get();
00109               nsCAutoString spec; mURL->GetSpec( spec );
00110               cb.url = (char*)spec.get();
00111               cb.content_length = strlen( cb.url );
00112               cb.suggested_filename = (char*)suggested_filename.get();
00113               PtInvokeCallbackList( mMozillaWidget->web_unknown_cb, (PtWidget_t *)mMozillaWidget, &cbinfo );
00114               /* this will modal wait for a Pt_ARG_WEB_UNKNOWN_RESP, in mozserver */       
00115        
00116 
00117               /* cancel the initial save - we used it only to sniff the header */
00118               mPersist->CancelSave();
00119               
00120               /* remove the tmp file */
00121               PRBool exists;
00122               mTmpFile->Exists(&exists);
00123               if(exists)
00124                   mTmpFile->Remove(PR_FALSE);
00125 
00126               /* we have the result in mMozillaWidget->moz_unknown_ctrl */
00127               if( mMozillaWidget->moz_unknown_ctrl->response == Pt_WEB_RESPONSE_OK ) {
00128                      /* start the actual save */
00129                      
00130                      /* the user chosen filename is mMozillaWidget->moz_unknown_ctrl->filename */
00131                      nsCOMPtr<nsILocalFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
00132                      NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
00133 
00134                      nsCString s ( mMozillaWidget->moz_unknown_ctrl->filename );
00135                      file->InitWithNativePath( s );
00136                      if( !file ) return NS_ERROR_FAILURE;
00137 
00138                      /* add this download to our list */
00139                      nsCAutoString spec;
00140                      mURL->GetSpec( spec );
00141 
00142                      nsCOMPtr<nsIWebBrowserPersist> webPersist(do_CreateInstance(kPersistContractID, &rv));
00143                      EmbedDownload *download = new EmbedDownload( mMozillaWidget, mMozillaWidget->moz_unknown_ctrl->download_ticket, spec.get() );
00144                      if( webPersist ) {
00145                             download->mPersist = webPersist;
00146                             webPersist->SetProgressListener( download );
00147                             webPersist->SaveURI( mURL, nsnull, nsnull, nsnull, nsnull, file );
00148                             }
00149                      }
00150        }
00151        return NS_OK;
00152        }
00153 
00154 NS_IMETHODIMP HeaderSniffer::OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, nsIURI *location) {
00155        return NS_OK;
00156        }
00157 NS_IMETHODIMP HeaderSniffer::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, nsresult aStatus, const PRUnichar* aMessage) {
00158        return NS_OK;
00159        }
00160 NS_IMETHODIMP HeaderSniffer::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state) {
00161        return NS_OK;
00162        }
00163