/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Adrian Mardare * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsILocalFile.h" #include "nsIChannel.h" #include "nsIHttpChannel.h" #include "nsIURL.h" #include "necko/nsNetUtil.h" #include "HeaderSniffer.h" #include "EmbedDownload.h" const char* const kPersistContractID = "@mozilla.org/embedding/browser/nsWebBrowserPersist;1"; HeaderSniffer::HeaderSniffer( nsIWebBrowserPersist* aPersist, PtMozillaWidget_t *aMoz, nsIURI* aURL, nsIFile* aFile ) : mPersist(aPersist) , mTmpFile(aFile) , mURL(aURL) { mMozillaWidget = aMoz; } HeaderSniffer::~HeaderSniffer( ) { } NS_IMPL_ISUPPORTS1(HeaderSniffer, nsIWebProgressListener) /* nsIWebProgressListener interface */ NS_IMETHODIMP HeaderSniffer::OnProgressChange(nsIWebProgress *aProgress, nsIRequest *aRequest, PRInt32 curSelfProgress, PRInt32 maxSelfProgress, PRInt32 curTotalProgress, PRInt32 maxTotalProgress) { return NS_OK; } NS_IMETHODIMP HeaderSniffer::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus) { if( aStateFlags & nsIWebProgressListener::STATE_START ) { nsCOMPtr kungFuDeathGrip(mPersist); // be sure to keep it alive while we save // since it owns us as a listener nsCOMPtr kungFuSuicideGrip(this); // and keep ourselves alive nsresult rv; nsCOMPtr channel = do_QueryInterface(aRequest, &rv); if (!channel) return rv; nsCAutoString contentType, suggested_filename; channel->GetContentType(contentType); // Get the content-disposition if we're an HTTP channel. nsCOMPtr httpChannel(do_QueryInterface(channel)); if (httpChannel) { nsCAutoString contentDisposition; nsresult rv = httpChannel->GetResponseHeader(nsCAutoString("content-disposition"), contentDisposition); if( NS_SUCCEEDED(rv) && !contentDisposition.IsEmpty() ) { PRInt32 index = contentDisposition.Find("filename="); if( index >= 0 ) { // Take the substring following the prefix. index += 9; contentDisposition.Right(suggested_filename, contentDisposition.Length() - index); } } } /* make the client display a file selection dialog */ PtCallbackInfo_t cbinfo; PtWebUnknownWithNameCallback_t cb; memset( &cbinfo, 0, sizeof( cbinfo ) ); cbinfo.reason = Pt_CB_MOZ_UNKNOWN; cbinfo.cbdata = &cb; cb.action = Pt_WEB_ACTION_OK; cb.content_type = (char*)contentType.get(); nsCAutoString spec; mURL->GetSpec( spec ); cb.url = (char*)spec.get(); cb.content_length = strlen( cb.url ); cb.suggested_filename = (char*)suggested_filename.get(); PtInvokeCallbackList( mMozillaWidget->web_unknown_cb, (PtWidget_t *)mMozillaWidget, &cbinfo ); /* this will modal wait for a Pt_ARG_WEB_UNKNOWN_RESP, in mozserver */ /* cancel the initial save - we used it only to sniff the header */ mPersist->CancelSave(); /* remove the tmp file */ PRBool exists; mTmpFile->Exists(&exists); if(exists) mTmpFile->Remove(PR_FALSE); /* we have the result in mMozillaWidget->moz_unknown_ctrl */ if( mMozillaWidget->moz_unknown_ctrl->response == Pt_WEB_RESPONSE_OK ) { /* start the actual save */ /* the user chosen filename is mMozillaWidget->moz_unknown_ctrl->filename */ nsCOMPtr file(do_CreateInstance("@mozilla.org/file/local;1")); NS_ENSURE_TRUE(file, NS_ERROR_FAILURE); nsCString s ( mMozillaWidget->moz_unknown_ctrl->filename ); file->InitWithNativePath( s ); if( !file ) return NS_ERROR_FAILURE; /* add this download to our list */ nsCAutoString spec; mURL->GetSpec( spec ); nsCOMPtr webPersist(do_CreateInstance(kPersistContractID, &rv)); EmbedDownload *download = new EmbedDownload( mMozillaWidget, mMozillaWidget->moz_unknown_ctrl->download_ticket, spec.get() ); if( webPersist ) { download->mPersist = webPersist; webPersist->SetProgressListener( download ); webPersist->SaveURI( mURL, nsnull, nsnull, nsnull, nsnull, file ); } } } return NS_OK; } NS_IMETHODIMP HeaderSniffer::OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, nsIURI *location) { return NS_OK; } NS_IMETHODIMP HeaderSniffer::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, nsresult aStatus, const PRUnichar* aMessage) { return NS_OK; } NS_IMETHODIMP HeaderSniffer::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state) { return NS_OK; }