LCOV - app.info - modules/libjar/nsJARChannel.cpp

LCOV - code coverage report
| Current view: | directory - modules/libjar - nsJARChannel.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 415 | 188 | 45.3 %
| Date: | 2012-04-21 | Functions: | 57 | 31 | 54.4 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  *
           3                 :  * ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is mozilla.org Code.
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is
          19                 :  * Netscape Communications Corporation.
          20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          21                 :  * the Initial Developer. All Rights Reserved.
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *   Jeff Walden <jwalden+code@mit.edu>
          25                 :  *
          26                 :  * Alternatively, the contents of this file may be used under the terms of
          27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          30                 :  * of those above. If you wish to allow use of your version of this file only
          31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          32                 :  * use your version of this file under the terms of the MPL, indicate your
          33                 :  * decision by deleting the provisions above and replace them with the notice
          34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          35                 :  * the provisions above, a recipient may use your version of this file under
          36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          37                 :  *
          38                 :  * ***** END LICENSE BLOCK ***** */
          39                 :
          40                 : #include "nsJAR.h"
          41                 : #include "nsJARChannel.h"
          42                 : #include "nsJARProtocolHandler.h"
          43                 : #include "nsMimeTypes.h"
          44                 : #include "nsNetUtil.h"
          45                 : #include "nsEscape.h"
          46                 : #include "nsIPrefService.h"
          47                 : #include "nsIPrefBranch.h"
          48                 : #include "nsIViewSourceChannel.h"
          49                 : #include "nsChannelProperties.h"
          50                 :
          51                 : #include "nsIScriptSecurityManager.h"
          52                 : #include "nsIPrincipal.h"
          53                 : #include "nsIFileURL.h"
          54                 :
          55                 : #include "mozilla/Preferences.h"
          56                 :
          57                 : using namespace mozilla;
          58                 :
          59                 : static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
          60                 :
          61                 : // the entry for a directory will either be empty (in the case of the
          62                 : // top-level directory) or will end with a slash
          63                 : #define ENTRY_IS_DIRECTORY(_entry) \
          64                 :   ((_entry).IsEmpty() || '/' == (_entry).Last())
          65                 :
          66                 : //-----------------------------------------------------------------------------
          67                 :
          68                 : #if defined(PR_LOGGING)
          69                 : //
          70                 : // set NSPR_LOG_MODULES=nsJarProtocol:5
          71                 : //
          72                 : static PRLogModuleInfo *gJarProtocolLog = nsnull;
          73                 : #endif
          74                 :
          75                 : #define LOG(args)     PR_LOG(gJarProtocolLog, PR_LOG_DEBUG, args)
          76                 : #define LOG_ENABLED() PR_LOG_TEST(gJarProtocolLog, 4)
          77                 :
          78                 : //-----------------------------------------------------------------------------
          79                 : // nsJARInputThunk
          80                 : //
          81                 : // this class allows us to do some extra work on the stream transport thread.
          82                 : //-----------------------------------------------------------------------------
          83                 :
          84                 : class nsJARInputThunk : public nsIInputStream
          85                 : {
          86                 : public:
          87                 :     NS_DECL_ISUPPORTS
          88                 :     NS_DECL_NSIINPUTSTREAM
          89                 :
          90             192 :     nsJARInputThunk(nsIZipReader *zipReader,
          91                 :                     nsIURI* fullJarURI,
          92                 :                     const nsACString &jarEntry,
          93                 :                     nsIZipReaderCache *jarCache)
          94                 :         : mJarCache(jarCache)
          95                 :         , mJarReader(zipReader)
          96                 :         , mJarEntry(jarEntry)
          97             192 :         , mContentLength(-1)
          98                 :     {
          99             192 :         if (fullJarURI) {
         100                 : #ifdef DEBUG
         101                 :             nsresult rv =
         102                 : #endif
         103             192 :                 fullJarURI->GetAsciiSpec(mJarDirSpec);
         104             192 :             NS_ASSERTION(NS_SUCCEEDED(rv), "this shouldn't fail");
         105                 :         }
         106             192 :     }
         107                 :
         108             384 :     virtual ~nsJARInputThunk()
         109             384 :     {
         110             192 :         if (!mJarCache && mJarReader)
         111               0 :             mJarReader->Close();
         112             768 :     }
         113                 :
         114               0 :     void GetJarReader(nsIZipReader **result)
         115                 :     {
         116               0 :         NS_IF_ADDREF(*result = mJarReader);
         117               0 :     }
         118                 :
         119              57 :     PRInt32 GetContentLength()
         120                 :     {
         121              57 :         return mContentLength;
         122                 :     }
         123                 :
         124                 :     nsresult EnsureJarStream();
         125                 :
         126                 : private:
         127                 :
         128                 :     nsCOMPtr<nsIZipReaderCache> mJarCache;
         129                 :     nsCOMPtr<nsIZipReader>      mJarReader;
         130                 :     nsCString                   mJarDirSpec;
         131                 :     nsCOMPtr<nsIInputStream>    mJarStream;
         132                 :     nsCString                   mJarEntry;
         133                 :     PRInt32                     mContentLength;
         134                 : };
         135                 :
         136            1548 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsJARInputThunk, nsIInputStream)
         137                 :
         138                 : nsresult
         139             354 : nsJARInputThunk::EnsureJarStream()
         140                 : {
         141             354 :     if (mJarStream)
         142             162 :         return NS_OK;
         143                 :
         144                 :     nsresult rv;
         145             192 :     if (ENTRY_IS_DIRECTORY(mJarEntry)) {
         146                 :         // A directory stream also needs the Spec of the FullJarURI
         147                 :         // because is included in the stream data itself.
         148                 :
         149               0 :         NS_ENSURE_STATE(!mJarDirSpec.IsEmpty());
         150                 :
         151               0 :         rv = mJarReader->GetInputStreamWithSpec(mJarDirSpec,
         152                 :                                                 mJarEntry,
         153               0 :                                                 getter_AddRefs(mJarStream));
         154                 :     }
         155                 :     else {
         156             192 :         rv = mJarReader->GetInputStream(mJarEntry,
         157             192 :                                         getter_AddRefs(mJarStream));
         158                 :     }
         159             192 :     if (NS_FAILED(rv)) {
         160                 :         // convert to the proper result if the entry wasn't found
         161                 :         // so that error pages work
         162              41 :         if (rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
         163              41 :             rv = NS_ERROR_FILE_NOT_FOUND;
         164              41 :         return rv;
         165                 :     }
         166                 :
         167                 :     // ask the JarStream for the content length
         168             151 :     rv = mJarStream->Available((PRUint32 *) &mContentLength);
         169             151 :     if (NS_FAILED(rv)) return rv;
         170                 :
         171             151 :     return NS_OK;
         172                 : }
         173                 :
         174                 : NS_IMETHODIMP
         175               0 : nsJARInputThunk::Close()
         176                 : {
         177               0 :     if (mJarStream)
         178               0 :         return mJarStream->Close();
         179                 :
         180               0 :     return NS_OK;
         181                 : }
         182                 :
         183                 : NS_IMETHODIMP
         184              53 : nsJARInputThunk::Available(PRUint32 *avail)
         185                 : {
         186              53 :     nsresult rv = EnsureJarStream();
         187              53 :     if (NS_FAILED(rv)) return rv;
         188                 :
         189              53 :     return mJarStream->Available(avail);
         190                 : }
         191                 :
         192                 : NS_IMETHODIMP
         193             109 : nsJARInputThunk::Read(char *buf, PRUint32 count, PRUint32 *countRead)
         194                 : {
         195             109 :     nsresult rv = EnsureJarStream();
         196             109 :     if (NS_FAILED(rv)) return rv;
         197                 :
         198             109 :     return mJarStream->Read(buf, count, countRead);
         199                 : }
         200                 :
         201                 : NS_IMETHODIMP
         202               1 : nsJARInputThunk::ReadSegments(nsWriteSegmentFun writer, void *closure,
         203                 :                               PRUint32 count, PRUint32 *countRead)
         204                 : {
         205                 :     // stream transport does only calls Read()
         206               1 :     return NS_ERROR_NOT_IMPLEMENTED;
         207                 : }
         208                 :
         209                 : NS_IMETHODIMP
         210               0 : nsJARInputThunk::IsNonBlocking(bool *nonBlocking)
         211                 : {
         212               0 :     *nonBlocking = false;
         213               0 :     return NS_OK;
         214                 : }
         215                 :
         216                 : //-----------------------------------------------------------------------------
         217                 : // nsJARChannel
         218                 : //-----------------------------------------------------------------------------
         219                 :
         220                 :
         221             398 : nsJARChannel::nsJARChannel()
         222                 :     : mContentLength(-1)
         223                 :     , mLoadFlags(LOAD_NORMAL)
         224                 :     , mStatus(NS_OK)
         225                 :     , mIsPending(false)
         226                 :     , mIsUnsafe(true)
         227             398 :     , mJarInput(nsnull)
         228                 : {
         229                 : #if defined(PR_LOGGING)
         230             398 :     if (!gJarProtocolLog)
         231              24 :         gJarProtocolLog = PR_NewLogModule("nsJarProtocol");
         232                 : #endif
         233                 :
         234                 :     // hold an owning reference to the jar handler
         235             398 :     NS_ADDREF(gJarHandler);
         236             398 : }
         237                 :
         238            1194 : nsJARChannel::~nsJARChannel()
         239                 : {
         240                 :     // with the exception of certain error cases mJarInput will already be null.
         241             398 :     NS_IF_RELEASE(mJarInput);
         242                 :
         243                 :     // release owning reference to the jar handler
         244             398 :     nsJARProtocolHandler *handler = gJarHandler;
         245             398 :     NS_RELEASE(handler); // NULL parameter
         246            1592 : }
         247                 :
         248            2757 : NS_IMPL_ISUPPORTS_INHERITED6(nsJARChannel,
         249                 :                              nsHashPropertyBag,
         250                 :                              nsIRequest,
         251                 :                              nsIChannel,
         252                 :                              nsIStreamListener,
         253                 :                              nsIRequestObserver,
         254                 :                              nsIDownloadObserver,
         255                 :                              nsIJARChannel)
         256                 :
         257                 : nsresult
         258             398 : nsJARChannel::Init(nsIURI *uri)
         259                 : {
         260                 :     nsresult rv;
         261             398 :     rv = nsHashPropertyBag::Init();
         262             398 :     if (NS_FAILED(rv))
         263               0 :         return rv;
         264                 :
         265             398 :     mJarURI = do_QueryInterface(uri, &rv);
         266             398 :     if (NS_FAILED(rv))
         267               0 :         return rv;
         268                 :
         269             398 :     mOriginalURI = mJarURI;
         270                 :
         271                 :     // Prevent loading jar:javascript URIs (see bug 290982).
         272             796 :     nsCOMPtr<nsIURI> innerURI;
         273             398 :     rv = mJarURI->GetJARFile(getter_AddRefs(innerURI));
         274             398 :     if (NS_FAILED(rv))
         275               0 :         return rv;
         276                 :     bool isJS;
         277             398 :     rv = innerURI->SchemeIs("javascript", &isJS);
         278             398 :     if (NS_FAILED(rv))
         279               0 :         return rv;
         280             398 :     if (isJS) {
         281               0 :         NS_WARNING("blocking jar:javascript:");
         282               0 :         return NS_ERROR_INVALID_ARG;
         283                 :     }
         284                 :
         285                 : #if defined(PR_LOGGING)
         286             398 :     mJarURI->GetSpec(mSpec);
         287                 : #endif
         288             398 :     return rv;
         289                 : }
         290                 :
         291                 : nsresult
         292             194 : nsJARChannel::CreateJarInput(nsIZipReaderCache *jarCache)
         293                 : {
         294                 :     // important to pass a clone of the file since the nsIFile impl is not
         295                 :     // necessarily MT-safe
         296             388 :     nsCOMPtr<nsIFile> clonedFile;
         297             194 :     nsresult rv = mJarFile->Clone(getter_AddRefs(clonedFile));
         298             194 :     if (NS_FAILED(rv))
         299               0 :         return rv;
         300                 :
         301             388 :     nsCOMPtr<nsIZipReader> reader;
         302             194 :     if (jarCache) {
         303             194 :         if (mInnerJarEntry.IsEmpty())
         304             150 :             rv = jarCache->GetZip(mJarFile, getter_AddRefs(reader));
         305                 :         else
         306                 :             rv = jarCache->GetInnerZip(mJarFile, mInnerJarEntry,
         307              44 :                                        getter_AddRefs(reader));
         308                 :     } else {
         309                 :         // create an uncached jar reader
         310               0 :         nsCOMPtr<nsIZipReader> outerReader = do_CreateInstance(kZipReaderCID, &rv);
         311               0 :         if (NS_FAILED(rv))
         312               0 :             return rv;
         313                 :
         314               0 :         rv = outerReader->Open(mJarFile);
         315               0 :         if (NS_FAILED(rv))
         316               0 :             return rv;
         317                 :
         318               0 :         if (mInnerJarEntry.IsEmpty())
         319               0 :             reader = outerReader;
         320                 :         else {
         321               0 :             reader = do_CreateInstance(kZipReaderCID, &rv);
         322               0 :             if (NS_FAILED(rv))
         323               0 :                 return rv;
         324                 :
         325               0 :             rv = reader->OpenInner(outerReader, mInnerJarEntry);
         326                 :         }
         327                 :     }
         328             194 :     if (NS_FAILED(rv))
         329               2 :         return rv;
         330                 :
         331             384 :     mJarInput = new nsJARInputThunk(reader, mJarURI, mJarEntry, jarCache);
         332             192 :     if (!mJarInput)
         333               0 :         return NS_ERROR_OUT_OF_MEMORY;
         334             192 :     NS_ADDREF(mJarInput);
         335             192 :     return NS_OK;
         336                 : }
         337                 :
         338                 : nsresult
         339             195 : nsJARChannel::EnsureJarInput(bool blocking)
         340                 : {
         341             195 :     LOG(("nsJARChannel::EnsureJarInput [this=%x %s]\n", this, mSpec.get()));
         342                 :
         343                 :     nsresult rv;
         344             390 :     nsCOMPtr<nsIURI> uri;
         345                 :
         346             195 :     rv = mJarURI->GetJARFile(getter_AddRefs(mJarBaseURI));
         347             195 :     if (NS_FAILED(rv)) return rv;
         348                 :
         349             195 :     rv = mJarURI->GetJAREntry(mJarEntry);
         350             195 :     if (NS_FAILED(rv)) return rv;
         351                 :
         352                 :     // The name of the JAR entry must not contain URL-escaped characters:
         353                 :     // we're moving from URL domain to a filename domain here. nsStandardURL
         354                 :     // does basic escaping by default, which breaks reading zipped files which
         355                 :     // have e.g. spaces in their filenames.
         356             195 :     NS_UnescapeURL(mJarEntry);
         357                 :
         358                 :     // try to get a nsIFile directly from the url, which will often succeed.
         359                 :     {
         360             390 :         nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mJarBaseURI);
         361             195 :         if (fileURL)
         362             150 :             fileURL->GetFile(getter_AddRefs(mJarFile));
         363                 :     }
         364                 :     // try to handle a nested jar
         365             195 :     if (!mJarFile) {
         366              90 :         nsCOMPtr<nsIJARURI> jarURI = do_QueryInterface(mJarBaseURI);
         367              45 :         if (jarURI) {
         368              88 :             nsCOMPtr<nsIFileURL> fileURL;
         369              88 :             nsCOMPtr<nsIURI> innerJarURI;
         370              44 :             rv = jarURI->GetJARFile(getter_AddRefs(innerJarURI));
         371              44 :             if (NS_SUCCEEDED(rv))
         372              44 :                 fileURL = do_QueryInterface(innerJarURI);
         373              44 :             if (fileURL) {
         374              44 :                 fileURL->GetFile(getter_AddRefs(mJarFile));
         375              44 :                 jarURI->GetJAREntry(mInnerJarEntry);
         376                 :             }
         377                 :         }
         378                 :     }
         379                 :
         380             195 :     if (mJarFile) {
         381             194 :         mIsUnsafe = false;
         382                 :
         383                 :         // NOTE: we do not need to deal with mSecurityInfo here,
         384                 :         // because we're loading from a local file
         385             194 :         rv = CreateJarInput(gJarHandler->JarCache());
         386                 :     }
         387               1 :     else if (blocking) {
         388               0 :         NS_NOTREACHED("need sync downloader");
         389               0 :         rv = NS_ERROR_NOT_IMPLEMENTED;
         390                 :     }
         391                 :     else {
         392                 :         // kick off an async download of the base URI...
         393               1 :         rv = NS_NewDownloader(getter_AddRefs(mDownloader), this);
         394               1 :         if (NS_SUCCEEDED(rv))
         395                 :             rv = NS_OpenURI(mDownloader, nsnull, mJarBaseURI, nsnull,
         396                 :                             mLoadGroup, mCallbacks,
         397               1 :                             mLoadFlags & ~(LOAD_DOCUMENT_URI | LOAD_CALL_CONTENT_SNIFFERS));
         398                 :     }
         399             195 :     return rv;
         400                 :
         401                 : }
         402                 :
         403                 : //-----------------------------------------------------------------------------
         404                 : // nsIRequest
         405                 : //-----------------------------------------------------------------------------
         406                 :
         407                 : NS_IMETHODIMP
         408               0 : nsJARChannel::GetName(nsACString &result)
         409                 : {
         410               0 :     return mJarURI->GetSpec(result);
         411                 : }
         412                 :
         413                 : NS_IMETHODIMP
         414               0 : nsJARChannel::IsPending(bool *result)
         415                 : {
         416               0 :     *result = mIsPending;
         417               0 :     return NS_OK;
         418                 : }
         419                 :
         420                 : NS_IMETHODIMP
         421               0 : nsJARChannel::GetStatus(nsresult *status)
         422                 : {
         423               0 :     if (mPump && NS_SUCCEEDED(mStatus))
         424               0 :         mPump->GetStatus(status);
         425                 :     else
         426               0 :         *status = mStatus;
         427               0 :     return NS_OK;
         428                 : }
         429                 :
         430                 : NS_IMETHODIMP
         431               0 : nsJARChannel::Cancel(nsresult status)
         432                 : {
         433               0 :     mStatus = status;
         434               0 :     if (mPump)
         435               0 :         return mPump->Cancel(status);
         436                 :
         437               0 :     NS_ASSERTION(!mIsPending, "need to implement cancel when downloading");
         438               0 :     return NS_OK;
         439                 : }
         440                 :
         441                 : NS_IMETHODIMP
         442               0 : nsJARChannel::Suspend()
         443                 : {
         444               0 :     if (mPump)
         445               0 :         return mPump->Suspend();
         446                 :
         447               0 :     NS_ASSERTION(!mIsPending, "need to implement suspend when downloading");
         448               0 :     return NS_OK;
         449                 : }
         450                 :
         451                 : NS_IMETHODIMP
         452               0 : nsJARChannel::Resume()
         453                 : {
         454               0 :     if (mPump)
         455               0 :         return mPump->Resume();
         456                 :
         457               0 :     NS_ASSERTION(!mIsPending, "need to implement resume when downloading");
         458               0 :     return NS_OK;
         459                 : }
         460                 :
         461                 : NS_IMETHODIMP
         462               0 : nsJARChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
         463                 : {
         464               0 :     *aLoadFlags = mLoadFlags;
         465               0 :     return NS_OK;
         466                 : }
         467                 :
         468                 : NS_IMETHODIMP
         469               0 : nsJARChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
         470                 : {
         471               0 :     mLoadFlags = aLoadFlags;
         472               0 :     return NS_OK;
         473                 : }
         474                 :
         475                 : NS_IMETHODIMP
         476               0 : nsJARChannel::GetLoadGroup(nsILoadGroup **aLoadGroup)
         477                 : {
         478               0 :     NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
         479               0 :     return NS_OK;
         480                 : }
         481                 :
         482                 : NS_IMETHODIMP
         483               0 : nsJARChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
         484                 : {
         485               0 :     mLoadGroup = aLoadGroup;
         486               0 :     return NS_OK;
         487                 : }
         488                 :
         489                 : //-----------------------------------------------------------------------------
         490                 : // nsIChannel
         491                 : //-----------------------------------------------------------------------------
         492                 :
         493                 : NS_IMETHODIMP
         494               0 : nsJARChannel::GetOriginalURI(nsIURI **aURI)
         495                 : {
         496               0 :     *aURI = mOriginalURI;
         497               0 :     NS_ADDREF(*aURI);
         498               0 :     return NS_OK;
         499                 : }
         500                 :
         501                 : NS_IMETHODIMP
         502               3 : nsJARChannel::SetOriginalURI(nsIURI *aURI)
         503                 : {
         504               3 :     NS_ENSURE_ARG_POINTER(aURI);
         505               3 :     mOriginalURI = aURI;
         506               3 :     return NS_OK;
         507                 : }
         508                 :
         509                 : NS_IMETHODIMP
         510             202 : nsJARChannel::GetURI(nsIURI **aURI)
         511                 : {
         512             202 :     NS_IF_ADDREF(*aURI = mJarURI);
         513             202 :     return NS_OK;
         514                 : }
         515                 :
         516                 : NS_IMETHODIMP
         517               0 : nsJARChannel::GetOwner(nsISupports **result)
         518                 : {
         519                 :     nsresult rv;
         520                 :
         521               0 :     if (mOwner) {
         522               0 :         NS_ADDREF(*result = mOwner);
         523               0 :         return NS_OK;
         524                 :     }
         525                 :
         526               0 :     if (!mJarInput) {
         527               0 :         *result = nsnull;
         528               0 :         return NS_OK;
         529                 :     }
         530                 :
         531                 :     //-- Verify signature, if one is present, and set owner accordingly
         532               0 :     nsCOMPtr<nsIZipReader> jarReader;
         533               0 :     mJarInput->GetJarReader(getter_AddRefs(jarReader));
         534               0 :     if (!jarReader)
         535               0 :         return NS_ERROR_NOT_INITIALIZED;
         536                 :
         537               0 :     nsCOMPtr<nsIPrincipal> cert;
         538               0 :     rv = jarReader->GetCertificatePrincipal(mJarEntry, getter_AddRefs(cert));
         539               0 :     if (NS_FAILED(rv)) return rv;
         540                 :
         541               0 :     if (cert) {
         542               0 :         nsCAutoString certFingerprint;
         543               0 :         rv = cert->GetFingerprint(certFingerprint);
         544               0 :         if (NS_FAILED(rv)) return rv;
         545                 :
         546               0 :         nsCAutoString subjectName;
         547               0 :         rv = cert->GetSubjectName(subjectName);
         548               0 :         if (NS_FAILED(rv)) return rv;
         549                 :
         550               0 :         nsCAutoString prettyName;
         551               0 :         rv = cert->GetPrettyName(prettyName);
         552               0 :         if (NS_FAILED(rv)) return rv;
         553                 :
         554               0 :         nsCOMPtr<nsISupports> certificate;
         555               0 :         rv = cert->GetCertificate(getter_AddRefs(certificate));
         556               0 :         if (NS_FAILED(rv)) return rv;
         557                 :
         558                 :         nsCOMPtr<nsIScriptSecurityManager> secMan =
         559               0 :                  do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
         560               0 :         if (NS_FAILED(rv)) return rv;
         561                 :
         562               0 :         rv = secMan->GetCertificatePrincipal(certFingerprint, subjectName,
         563                 :                                              prettyName, certificate,
         564                 :                                              mJarBaseURI,
         565               0 :                                              getter_AddRefs(cert));
         566               0 :         if (NS_FAILED(rv)) return rv;
         567                 :
         568               0 :         mOwner = do_QueryInterface(cert, &rv);
         569               0 :         if (NS_FAILED(rv)) return rv;
         570                 :
         571               0 :         NS_ADDREF(*result = mOwner);
         572                 :     }
         573               0 :     return NS_OK;
         574                 : }
         575                 :
         576                 : NS_IMETHODIMP
         577               1 : nsJARChannel::SetOwner(nsISupports *aOwner)
         578                 : {
         579               1 :     mOwner = aOwner;
         580               1 :     return NS_OK;
         581                 : }
         582                 :
         583                 : NS_IMETHODIMP
         584               0 : nsJARChannel::GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks)
         585                 : {
         586               0 :     NS_IF_ADDREF(*aCallbacks = mCallbacks);
         587               0 :     return NS_OK;
         588                 : }
         589                 :
         590                 : NS_IMETHODIMP
         591               0 : nsJARChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
         592                 : {
         593               0 :     mCallbacks = aCallbacks;
         594               0 :     return NS_OK;
         595                 : }
         596                 :
         597                 : NS_IMETHODIMP
         598               0 : nsJARChannel::GetSecurityInfo(nsISupports **aSecurityInfo)
         599                 : {
         600               0 :     NS_PRECONDITION(aSecurityInfo, "Null out param");
         601               0 :     NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
         602               0 :     return NS_OK;
         603                 : }
         604                 :
         605                 : NS_IMETHODIMP
         606               0 : nsJARChannel::GetContentType(nsACString &result)
         607                 : {
         608               0 :     if (mContentType.IsEmpty()) {
         609                 :         //
         610                 :         // generate content type and set it
         611                 :         //
         612               0 :         const char *ext = nsnull, *fileName = mJarEntry.get();
         613               0 :         PRInt32 len = mJarEntry.Length();
         614                 :
         615                 :         // check if we're displaying a directory
         616                 :         // mJarEntry will be empty if we're trying to display
         617                 :         // the topmost directory in a zip, e.g. jar:foo.zip!/
         618               0 :         if (ENTRY_IS_DIRECTORY(mJarEntry)) {
         619               0 :             mContentType.AssignLiteral(APPLICATION_HTTP_INDEX_FORMAT);
         620                 :         }
         621                 :         else {
         622                 :             // not a directory, take a guess by its extension
         623               0 :             for (PRInt32 i = len-1; i >= 0; i--) {
         624               0 :                 if (fileName[i] == '.') {
         625               0 :                     ext = &fileName[i + 1];
         626               0 :                     break;
         627                 :                 }
         628                 :             }
         629               0 :             if (ext) {
         630               0 :                 nsIMIMEService *mimeServ = gJarHandler->MimeService();
         631               0 :                 if (mimeServ)
         632               0 :                     mimeServ->GetTypeFromExtension(nsDependentCString(ext), mContentType);
         633                 :             }
         634               0 :             if (mContentType.IsEmpty())
         635               0 :                 mContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE);
         636                 :         }
         637                 :     }
         638               0 :     result = mContentType;
         639               0 :     return NS_OK;
         640                 : }
         641                 :
         642                 : NS_IMETHODIMP
         643              97 : nsJARChannel::SetContentType(const nsACString &aContentType)
         644                 : {
         645                 :     // If someone gives us a type hint we should just use that type instead of
         646                 :     // doing our guessing.  So we don't care when this is being called.
         647                 :
         648                 :     // mContentCharset is unchanged if not parsed
         649              97 :     NS_ParseContentType(aContentType, mContentType, mContentCharset);
         650              97 :     return NS_OK;
         651                 : }
         652                 :
         653                 : NS_IMETHODIMP
         654               0 : nsJARChannel::GetContentCharset(nsACString &aContentCharset)
         655                 : {
         656                 :     // If someone gives us a charset hint we should just use that charset.
         657                 :     // So we don't care when this is being called.
         658               0 :     aContentCharset = mContentCharset;
         659               0 :     return NS_OK;
         660                 : }
         661                 :
         662                 : NS_IMETHODIMP
         663               0 : nsJARChannel::SetContentCharset(const nsACString &aContentCharset)
         664                 : {
         665               0 :     mContentCharset = aContentCharset;
         666               0 :     return NS_OK;
         667                 : }
         668                 :
         669                 : NS_IMETHODIMP
         670               1 : nsJARChannel::GetContentDisposition(PRUint32 *aContentDisposition)
         671                 : {
         672               1 :     if (mContentDispositionHeader.IsEmpty())
         673               1 :         return NS_ERROR_NOT_AVAILABLE;
         674                 :
         675               0 :     *aContentDisposition = mContentDisposition;
         676               0 :     return NS_OK;
         677                 : }
         678                 :
         679                 : NS_IMETHODIMP
         680               0 : nsJARChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
         681                 : {
         682               0 :     return NS_ERROR_NOT_AVAILABLE;
         683                 : }
         684                 :
         685                 : NS_IMETHODIMP
         686               0 : nsJARChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
         687                 : {
         688               0 :     if (mContentDispositionHeader.IsEmpty())
         689               0 :         return NS_ERROR_NOT_AVAILABLE;
         690                 :
         691               0 :     aContentDispositionHeader = mContentDispositionHeader;
         692               0 :     return NS_OK;
         693                 : }
         694                 :
         695                 : NS_IMETHODIMP
         696              57 : nsJARChannel::GetContentLength(PRInt32 *result)
         697                 : {
         698                 :     // if content length is unknown, query mJarInput...
         699              57 :     if (mContentLength < 0 && mJarInput)
         700              57 :         mContentLength = mJarInput->GetContentLength();
         701                 :
         702              57 :     *result = mContentLength;
         703              57 :     return NS_OK;
         704                 : }
         705                 :
         706                 : NS_IMETHODIMP
         707               0 : nsJARChannel::SetContentLength(PRInt32 aContentLength)
         708                 : {
         709                 :     // XXX does this really make any sense at all?
         710               0 :     mContentLength = aContentLength;
         711               0 :     return NS_OK;
         712                 : }
         713                 :
         714                 : NS_IMETHODIMP
         715             194 : nsJARChannel::Open(nsIInputStream **stream)
         716                 : {
         717             194 :     LOG(("nsJARChannel::Open [this=%x]\n", this));
         718                 :
         719             194 :     NS_ENSURE_TRUE(!mJarInput, NS_ERROR_IN_PROGRESS);
         720             194 :     NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
         721                 :
         722             194 :     mJarFile = nsnull;
         723             194 :     mIsUnsafe = true;
         724                 :
         725             194 :     nsresult rv = EnsureJarInput(true);
         726             194 :     if (NS_FAILED(rv)) return rv;
         727                 :
         728             192 :     if (!mJarInput)
         729               0 :         return NS_ERROR_UNEXPECTED;
         730                 :
         731                 :     // force load the jar file now so GetContentLength will return a
         732                 :     // meaningful value once we return.
         733             192 :     rv = mJarInput->EnsureJarStream();
         734             192 :     if (NS_FAILED(rv)) return rv;
         735                 :
         736             151 :     NS_ADDREF(*stream = mJarInput);
         737             151 :     return NS_OK;
         738                 : }
         739                 :
         740                 : NS_IMETHODIMP
         741               2 : nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
         742                 : {
         743               2 :     LOG(("nsJARChannel::AsyncOpen [this=%x]\n", this));
         744                 :
         745               2 :     NS_ENSURE_ARG_POINTER(listener);
         746               1 :     NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
         747                 :
         748               1 :     mJarFile = nsnull;
         749               1 :     mIsUnsafe = true;
         750                 :
         751                 :     // Initialize mProgressSink
         752               1 :     NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
         753                 :
         754               1 :     nsresult rv = EnsureJarInput(false);
         755               1 :     if (NS_FAILED(rv)) return rv;
         756                 :
         757                 :     // These variables must only be set if we're going to trigger an
         758                 :     // OnStartRequest, either from AsyncRead or OnDownloadComplete.
         759               1 :     mListener = listener;
         760               1 :     mListenerContext = ctx;
         761               1 :     mIsPending = true;
         762               1 :     if (mJarInput) {
         763                 :         // create input stream pump and call AsyncRead as a block
         764               0 :         rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mJarInput);
         765               0 :         if (NS_SUCCEEDED(rv))
         766               0 :             rv = mPump->AsyncRead(this, nsnull);
         767                 :
         768                 :         // If we failed to create the pump or initiate the AsyncRead,
         769                 :         // then we need to clear these variables.
         770               0 :         if (NS_FAILED(rv)) {
         771               0 :             mIsPending = false;
         772               0 :             mListenerContext = nsnull;
         773               0 :             mListener = nsnull;
         774               0 :             return rv;
         775                 :         }
         776                 :     }
         777                 :
         778               1 :     if (mLoadGroup)
         779               0 :         mLoadGroup->AddRequest(this, nsnull);
         780                 :
         781               1 :     return NS_OK;
         782                 : }
         783                 :
         784                 : //-----------------------------------------------------------------------------
         785                 : // nsIJARChannel
         786                 : //-----------------------------------------------------------------------------
         787                 : NS_IMETHODIMP
         788               0 : nsJARChannel::GetIsUnsafe(bool *isUnsafe)
         789                 : {
         790               0 :     *isUnsafe = mIsUnsafe;
         791               0 :     return NS_OK;
         792                 : }
         793                 :
         794                 : //-----------------------------------------------------------------------------
         795                 : // nsIDownloadObserver
         796                 : //-----------------------------------------------------------------------------
         797                 :
         798                 : NS_IMETHODIMP
         799               1 : nsJARChannel::OnDownloadComplete(nsIDownloader *downloader,
         800                 :                                  nsIRequest    *request,
         801                 :                                  nsISupports   *context,
         802                 :                                  nsresult       status,
         803                 :                                  nsIFile       *file)
         804                 : {
         805                 :     nsresult rv;
         806                 :
         807               2 :     nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
         808               1 :     if (channel) {
         809                 :         PRUint32 loadFlags;
         810               1 :         channel->GetLoadFlags(&loadFlags);
         811               1 :         if (loadFlags & LOAD_REPLACE) {
         812               0 :             mLoadFlags |= LOAD_REPLACE;
         813                 :
         814               0 :             if (!mOriginalURI) {
         815               0 :                 SetOriginalURI(mJarURI);
         816                 :             }
         817                 :
         818               0 :             nsCOMPtr<nsIURI> innerURI;
         819               0 :             rv = channel->GetURI(getter_AddRefs(innerURI));
         820               0 :             if (NS_SUCCEEDED(rv)) {
         821               0 :                 nsCOMPtr<nsIJARURI> newURI;
         822               0 :                 rv = mJarURI->CloneWithJARFile(innerURI,
         823               0 :                                                getter_AddRefs(newURI));
         824               0 :                 if (NS_SUCCEEDED(rv)) {
         825               0 :                     mJarURI = newURI;
         826                 :                 }
         827                 :             }
         828               0 :             if (NS_SUCCEEDED(status)) {
         829               0 :                 status = rv;
         830                 :             }
         831                 :         }
         832                 :     }
         833                 :
         834               1 :     if (NS_SUCCEEDED(status) && channel) {
         835                 :         // Grab the security info from our base channel
         836               0 :         channel->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
         837                 :
         838               0 :         nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
         839               0 :         if (httpChannel) {
         840                 :             // We only want to run scripts if the server really intended to
         841                 :             // send us a JAR file.  Check the server-supplied content type for
         842                 :             // a JAR type.
         843               0 :             nsCAutoString header;
         844               0 :             httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Type"),
         845               0 :                                            header);
         846               0 :             nsCAutoString contentType;
         847               0 :             nsCAutoString charset;
         848               0 :             NS_ParseContentType(header, contentType, charset);
         849               0 :             nsCAutoString channelContentType;
         850               0 :             channel->GetContentType(channelContentType);
         851               0 :             mIsUnsafe = !(contentType.Equals(channelContentType) &&
         852               0 :                           (contentType.EqualsLiteral("application/java-archive") ||
         853               0 :                            contentType.EqualsLiteral("application/x-jar")));
         854                 :         } else {
         855               0 :             nsCOMPtr<nsIJARChannel> innerJARChannel(do_QueryInterface(channel));
         856               0 :             if (innerJARChannel) {
         857                 :                 bool unsafe;
         858               0 :                 innerJARChannel->GetIsUnsafe(&unsafe);
         859               0 :                 mIsUnsafe = unsafe;
         860                 :             }
         861                 :         }
         862                 :
         863               0 :         channel->GetContentDispositionHeader(mContentDispositionHeader);
         864               0 :         mContentDisposition = NS_GetContentDispositionFromHeader(mContentDispositionHeader, this);
         865                 :     }
         866                 :
         867               1 :     if (NS_SUCCEEDED(status) && mIsUnsafe &&
         868               0 :         !Preferences::GetBool("network.jar.open-unsafe-types", false)) {
         869               0 :         status = NS_ERROR_UNSAFE_CONTENT_TYPE;
         870                 :     }
         871                 :
         872               1 :     if (NS_SUCCEEDED(status)) {
         873                 :         // Refuse to unpack view-source: jars even if open-unsafe-types is set.
         874               0 :         nsCOMPtr<nsIViewSourceChannel> viewSource = do_QueryInterface(channel);
         875               0 :         if (viewSource) {
         876               0 :             status = NS_ERROR_UNSAFE_CONTENT_TYPE;
         877                 :         }
         878                 :     }
         879                 :
         880               1 :     if (NS_SUCCEEDED(status)) {
         881               0 :         mJarFile = file;
         882                 :
         883               0 :         rv = CreateJarInput(nsnull);
         884               0 :         if (NS_SUCCEEDED(rv)) {
         885                 :             // create input stream pump
         886               0 :             rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mJarInput);
         887               0 :             if (NS_SUCCEEDED(rv))
         888               0 :                 rv = mPump->AsyncRead(this, nsnull);
         889                 :         }
         890               0 :         status = rv;
         891                 :     }
         892                 :
         893               1 :     if (NS_FAILED(status)) {
         894               1 :         mStatus = status;
         895               1 :         OnStartRequest(nsnull, nsnull);
         896               1 :         OnStopRequest(nsnull, nsnull, status);
         897                 :     }
         898                 :
         899               1 :     return NS_OK;
         900                 : }
         901                 :
         902                 : //-----------------------------------------------------------------------------
         903                 : // nsIStreamListener
         904                 : //-----------------------------------------------------------------------------
         905                 :
         906                 : NS_IMETHODIMP
         907               1 : nsJARChannel::OnStartRequest(nsIRequest *req, nsISupports *ctx)
         908                 : {
         909               1 :     LOG(("nsJARChannel::OnStartRequest [this=%x %s]\n", this, mSpec.get()));
         910                 :
         911               1 :     return mListener->OnStartRequest(this, mListenerContext);
         912                 : }
         913                 :
         914                 : NS_IMETHODIMP
         915               1 : nsJARChannel::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status)
         916                 : {
         917               1 :     LOG(("nsJARChannel::OnStopRequest [this=%x %s status=%x]\n",
         918                 :         this, mSpec.get(), status));
         919                 :
         920               1 :     if (NS_SUCCEEDED(mStatus))
         921               0 :         mStatus = status;
         922                 :
         923               1 :     if (mListener) {
         924               1 :         mListener->OnStopRequest(this, mListenerContext, status);
         925               1 :         mListener = 0;
         926               1 :         mListenerContext = 0;
         927                 :     }
         928                 :
         929               1 :     if (mLoadGroup)
         930               0 :         mLoadGroup->RemoveRequest(this, nsnull, status);
         931                 :
         932               1 :     mPump = 0;
         933               1 :     NS_IF_RELEASE(mJarInput);
         934               1 :     mIsPending = false;
         935               1 :     mDownloader = 0; // this may delete the underlying jar file
         936                 :
         937                 :     // Drop notification callbacks to prevent cycles.
         938               1 :     mCallbacks = 0;
         939               1 :     mProgressSink = 0;
         940                 :
         941               1 :     return NS_OK;
         942                 : }
         943                 :
         944                 : NS_IMETHODIMP
         945               0 : nsJARChannel::OnDataAvailable(nsIRequest *req, nsISupports *ctx,
         946                 :                                nsIInputStream *stream,
         947                 :                                PRUint32 offset, PRUint32 count)
         948                 : {
         949                 : #if defined(PR_LOGGING)
         950               0 :     LOG(("nsJARChannel::OnDataAvailable [this=%x %s]\n", this, mSpec.get()));
         951                 : #endif
         952                 :
         953                 :     nsresult rv;
         954                 :
         955               0 :     rv = mListener->OnDataAvailable(this, mListenerContext, stream, offset, count);
         956                 :
         957                 :     // simply report progress here instead of hooking ourselves up as a
         958                 :     // nsITransportEventSink implementation.
         959                 :     // XXX do the 64-bit stuff for real
         960               0 :     if (mProgressSink && NS_SUCCEEDED(rv) && !(mLoadFlags & LOAD_BACKGROUND))
         961               0 :         mProgressSink->OnProgress(this, nsnull, PRUint64(offset + count),
         962               0 :                                   PRUint64(mContentLength));
         963                 :
         964               0 :     return rv; // let the pump cancel on failure
         965                 : }

Generated by: LCOV version 1.7