modules/libjar/nsJARURI.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  *
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "base/basictypes.h"
     9 #include "nsJARURI.h"
    10 #include "nsNetUtil.h"
    11 #include "nsIIOService.h"
    12 #include "nsIStandardURL.h"
    13 #include "nsCRT.h"
    14 #include "nsIComponentManager.h"
    15 #include "nsIServiceManager.h"
    16 #include "nsIZipReader.h"
    17 #include "nsReadableUtils.h"
    18 #include "nsAutoPtr.h"
    19 #include "nsNetCID.h"
    20 #include "nsIObjectInputStream.h"
    21 #include "nsIObjectOutputStream.h"
    22 #include "nsIProgrammingLanguage.h"
    23 #include "mozilla/ipc/URIUtils.h"
    25 using namespace mozilla::ipc;
    27 static NS_DEFINE_CID(kJARURICID, NS_JARURI_CID);
    29 ////////////////////////////////////////////////////////////////////////////////
    31 nsJARURI::nsJARURI()
    32 {
    33 }
    35 nsJARURI::~nsJARURI()
    36 {
    37 }
    39 // XXX Why is this threadsafe?
    40 NS_IMPL_ADDREF(nsJARURI)
    41 NS_IMPL_RELEASE(nsJARURI)
    42 NS_INTERFACE_MAP_BEGIN(nsJARURI)
    43   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJARURI)
    44   NS_INTERFACE_MAP_ENTRY(nsIURI)
    45   NS_INTERFACE_MAP_ENTRY(nsIURL)
    46   NS_INTERFACE_MAP_ENTRY(nsIJARURI)
    47   NS_INTERFACE_MAP_ENTRY(nsISerializable)
    48   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
    49   NS_INTERFACE_MAP_ENTRY(nsINestedURI)
    50   NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableURI)
    51   // see nsJARURI::Equals
    52   if (aIID.Equals(NS_GET_IID(nsJARURI)))
    53       foundInterface = reinterpret_cast<nsISupports*>(this);
    54   else
    55 NS_INTERFACE_MAP_END
    57 nsresult
    58 nsJARURI::Init(const char *charsetHint)
    59 {
    60     mCharsetHint = charsetHint;
    61     return NS_OK;
    62 }
    64 #define NS_JAR_SCHEME           NS_LITERAL_CSTRING("jar:")
    65 #define NS_JAR_DELIMITER        NS_LITERAL_CSTRING("!/")
    66 #define NS_BOGUS_ENTRY_SCHEME   NS_LITERAL_CSTRING("x:///")
    68 // FormatSpec takes the entry spec (including the "x:///" at the
    69 // beginning) and gives us a full JAR spec.
    70 nsresult
    71 nsJARURI::FormatSpec(const nsACString &entrySpec, nsACString &result,
    72                      bool aIncludeScheme)
    73 {
    74     // The entrySpec MUST start with "x:///"
    75     NS_ASSERTION(StringBeginsWith(entrySpec, NS_BOGUS_ENTRY_SCHEME),
    76                  "bogus entry spec");
    78     nsAutoCString fileSpec;
    79     nsresult rv = mJARFile->GetSpec(fileSpec);
    80     if (NS_FAILED(rv)) return rv;
    82     if (aIncludeScheme)
    83         result = NS_JAR_SCHEME;
    84     else
    85         result.Truncate();
    87     result.Append(fileSpec + NS_JAR_DELIMITER +
    88                   Substring(entrySpec, 5, entrySpec.Length() - 5));
    89     return NS_OK;
    90 }
    92 nsresult
    93 nsJARURI::CreateEntryURL(const nsACString& entryFilename,
    94                          const char* charset,
    95                          nsIURL** url)
    96 {
    97     *url = nullptr;
    99     nsCOMPtr<nsIStandardURL> stdURL(do_CreateInstance(NS_STANDARDURL_CONTRACTID));
   100     if (!stdURL) {
   101         return NS_ERROR_OUT_OF_MEMORY;
   102     }
   104     // Flatten the concatenation, just in case.  See bug 128288
   105     nsAutoCString spec(NS_BOGUS_ENTRY_SCHEME + entryFilename);
   106     nsresult rv = stdURL->Init(nsIStandardURL::URLTYPE_NO_AUTHORITY, -1,
   107                                spec, charset, nullptr);
   108     if (NS_FAILED(rv)) {
   109         return rv;
   110     }
   112     return CallQueryInterface(stdURL, url);
   113 }
   115 ////////////////////////////////////////////////////////////////////////////////
   116 // nsISerializable methods:
   118 NS_IMETHODIMP
   119 nsJARURI::Read(nsIObjectInputStream* aInputStream)
   120 {
   121     nsresult rv;
   123     nsCOMPtr<nsISupports> supports;
   124     rv = aInputStream->ReadObject(true, getter_AddRefs(supports));
   125     NS_ENSURE_SUCCESS(rv, rv);
   127     mJARFile = do_QueryInterface(supports, &rv);
   128     NS_ENSURE_SUCCESS(rv, rv);
   130     rv = aInputStream->ReadObject(true, getter_AddRefs(supports));
   131     NS_ENSURE_SUCCESS(rv, rv);
   133     mJAREntry = do_QueryInterface(supports);
   134     NS_ENSURE_SUCCESS(rv, rv);
   136     rv = aInputStream->ReadCString(mCharsetHint);
   137     return rv;
   138 }
   140 NS_IMETHODIMP
   141 nsJARURI::Write(nsIObjectOutputStream* aOutputStream)
   142 {
   143     nsresult rv;
   145     rv = aOutputStream->WriteCompoundObject(mJARFile, NS_GET_IID(nsIURI),
   146                                             true);
   147     NS_ENSURE_SUCCESS(rv, rv);
   149     rv = aOutputStream->WriteCompoundObject(mJAREntry, NS_GET_IID(nsIURL),
   150                                             true);
   151     NS_ENSURE_SUCCESS(rv, rv);
   153     rv = aOutputStream->WriteStringZ(mCharsetHint.get());
   154     return rv;
   155 }
   157 ////////////////////////////////////////////////////////////////////////////////
   158 // nsIClassInfo methods:
   160 NS_IMETHODIMP 
   161 nsJARURI::GetInterfaces(uint32_t *count, nsIID * **array)
   162 {
   163     *count = 0;
   164     *array = nullptr;
   165     return NS_OK;
   166 }
   168 NS_IMETHODIMP 
   169 nsJARURI::GetHelperForLanguage(uint32_t language, nsISupports **_retval)
   170 {
   171     *_retval = nullptr;
   172     return NS_OK;
   173 }
   175 NS_IMETHODIMP 
   176 nsJARURI::GetContractID(char * *aContractID)
   177 {
   178     *aContractID = nullptr;
   179     return NS_OK;
   180 }
   182 NS_IMETHODIMP 
   183 nsJARURI::GetClassDescription(char * *aClassDescription)
   184 {
   185     *aClassDescription = nullptr;
   186     return NS_OK;
   187 }
   189 NS_IMETHODIMP 
   190 nsJARURI::GetClassID(nsCID * *aClassID)
   191 {
   192     *aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
   193     if (!*aClassID)
   194         return NS_ERROR_OUT_OF_MEMORY;
   195     return GetClassIDNoAlloc(*aClassID);
   196 }
   198 NS_IMETHODIMP 
   199 nsJARURI::GetImplementationLanguage(uint32_t *aImplementationLanguage)
   200 {
   201     *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
   202     return NS_OK;
   203 }
   205 NS_IMETHODIMP 
   206 nsJARURI::GetFlags(uint32_t *aFlags)
   207 {
   208     // XXX We implement THREADSAFE addref/release, but probably shouldn't.
   209     *aFlags = nsIClassInfo::MAIN_THREAD_ONLY;
   210     return NS_OK;
   211 }
   213 NS_IMETHODIMP 
   214 nsJARURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
   215 {
   216     *aClassIDNoAlloc = kJARURICID;
   217     return NS_OK;
   218 }
   220 ////////////////////////////////////////////////////////////////////////////////
   221 // nsIURI methods:
   223 NS_IMETHODIMP
   224 nsJARURI::GetSpec(nsACString &aSpec)
   225 {
   226     nsAutoCString entrySpec;
   227     mJAREntry->GetSpec(entrySpec);
   228     return FormatSpec(entrySpec, aSpec);
   229 }
   231 NS_IMETHODIMP
   232 nsJARURI::GetSpecIgnoringRef(nsACString &aSpec)
   233 {
   234     nsAutoCString entrySpec;
   235     mJAREntry->GetSpecIgnoringRef(entrySpec);
   236     return FormatSpec(entrySpec, aSpec);
   237 }
   239 NS_IMETHODIMP
   240 nsJARURI::GetHasRef(bool *result)
   241 {
   242     return mJAREntry->GetHasRef(result);
   243 }
   245 NS_IMETHODIMP
   246 nsJARURI::SetSpec(const nsACString& aSpec)
   247 {
   248     return SetSpecWithBase(aSpec, nullptr);
   249 }
   251 nsresult
   252 nsJARURI::SetSpecWithBase(const nsACString &aSpec, nsIURI* aBaseURL)
   253 {
   254     nsresult rv;
   256     nsCOMPtr<nsIIOService> ioServ(do_GetIOService(&rv));
   257     NS_ENSURE_SUCCESS(rv, rv);
   259     nsAutoCString scheme;
   260     rv = ioServ->ExtractScheme(aSpec, scheme);
   261     if (NS_FAILED(rv)) {
   262         // not an absolute URI
   263         if (!aBaseURL)
   264             return NS_ERROR_MALFORMED_URI;
   266         nsRefPtr<nsJARURI> otherJAR;
   267         aBaseURL->QueryInterface(NS_GET_IID(nsJARURI), getter_AddRefs(otherJAR));
   268         NS_ENSURE_TRUE(otherJAR, NS_NOINTERFACE);
   270         mJARFile = otherJAR->mJARFile;
   272         nsCOMPtr<nsIStandardURL> entry(do_CreateInstance(NS_STANDARDURL_CONTRACTID));
   273         if (!entry)
   274             return NS_ERROR_OUT_OF_MEMORY;
   276         rv = entry->Init(nsIStandardURL::URLTYPE_NO_AUTHORITY, -1,
   277                          aSpec, mCharsetHint.get(), otherJAR->mJAREntry);
   278         if (NS_FAILED(rv))
   279             return rv;
   281         mJAREntry = do_QueryInterface(entry);
   282         if (!mJAREntry)
   283             return NS_NOINTERFACE;
   285         return NS_OK;
   286     }
   288     NS_ENSURE_TRUE(scheme.EqualsLiteral("jar"), NS_ERROR_MALFORMED_URI);
   290     nsACString::const_iterator begin, end;
   291     aSpec.BeginReading(begin);
   292     aSpec.EndReading(end);
   294     while (begin != end && *begin != ':')
   295         ++begin;
   297     ++begin; // now we're past the "jar:"
   299     // Search backward from the end for the "!/" delimiter. Remember, jar URLs
   300     // can nest, e.g.:
   301     //    jar:jar:http://www.foo.com/bar.jar!/a.jar!/b.html
   302     // This gets the b.html document from out of the a.jar file, that's 
   303     // contained within the bar.jar file.
   304     // Also, the outermost "inner" URI may be a relative URI:
   305     //   jar:../relative.jar!/a.html
   307     nsACString::const_iterator delim_begin (begin),
   308                                delim_end   (end);
   310     if (!RFindInReadable(NS_JAR_DELIMITER, delim_begin, delim_end))
   311         return NS_ERROR_MALFORMED_URI;
   313     rv = ioServ->NewURI(Substring(begin, delim_begin), mCharsetHint.get(),
   314                         aBaseURL, getter_AddRefs(mJARFile));
   315     if (NS_FAILED(rv)) return rv;
   317     NS_TryToSetImmutable(mJARFile);
   319     // skip over any extra '/' chars
   320     while (*delim_end == '/')
   321         ++delim_end;
   323     return SetJAREntry(Substring(delim_end, end));
   324 }
   326 NS_IMETHODIMP
   327 nsJARURI::GetPrePath(nsACString &prePath)
   328 {
   329     prePath = NS_JAR_SCHEME;
   330     return NS_OK;
   331 }
   333 NS_IMETHODIMP
   334 nsJARURI::GetScheme(nsACString &aScheme)
   335 {
   336     aScheme = "jar";
   337     return NS_OK;
   338 }
   340 NS_IMETHODIMP
   341 nsJARURI::SetScheme(const nsACString &aScheme)
   342 {
   343     // doesn't make sense to set the scheme of a jar: URL
   344     return NS_ERROR_FAILURE;
   345 }
   347 NS_IMETHODIMP
   348 nsJARURI::GetUserPass(nsACString &aUserPass)
   349 {
   350     return NS_ERROR_FAILURE;
   351 }
   353 NS_IMETHODIMP
   354 nsJARURI::SetUserPass(const nsACString &aUserPass)
   355 {
   356     return NS_ERROR_FAILURE;
   357 }
   359 NS_IMETHODIMP
   360 nsJARURI::GetUsername(nsACString &aUsername)
   361 {
   362     return NS_ERROR_FAILURE;
   363 }
   365 NS_IMETHODIMP
   366 nsJARURI::SetUsername(const nsACString &aUsername)
   367 {
   368     return NS_ERROR_FAILURE;
   369 }
   371 NS_IMETHODIMP
   372 nsJARURI::GetPassword(nsACString &aPassword)
   373 {
   374     return NS_ERROR_FAILURE;
   375 }
   377 NS_IMETHODIMP
   378 nsJARURI::SetPassword(const nsACString &aPassword)
   379 {
   380     return NS_ERROR_FAILURE;
   381 }
   383 NS_IMETHODIMP
   384 nsJARURI::GetHostPort(nsACString &aHostPort)
   385 {
   386     return NS_ERROR_FAILURE;
   387 }
   389 NS_IMETHODIMP
   390 nsJARURI::SetHostPort(const nsACString &aHostPort)
   391 {
   392     return NS_ERROR_FAILURE;
   393 }
   395 NS_IMETHODIMP
   396 nsJARURI::GetHost(nsACString &aHost)
   397 {
   398     return NS_ERROR_FAILURE;
   399 }
   401 NS_IMETHODIMP
   402 nsJARURI::SetHost(const nsACString &aHost)
   403 {
   404     return NS_ERROR_FAILURE;
   405 }
   407 NS_IMETHODIMP
   408 nsJARURI::GetPort(int32_t *aPort)
   409 {
   410     return NS_ERROR_FAILURE;
   411 }
   413 NS_IMETHODIMP
   414 nsJARURI::SetPort(int32_t aPort)
   415 {
   416     return NS_ERROR_FAILURE;
   417 }
   419 NS_IMETHODIMP
   420 nsJARURI::GetPath(nsACString &aPath)
   421 {
   422     nsAutoCString entrySpec;
   423     mJAREntry->GetSpec(entrySpec);
   424     return FormatSpec(entrySpec, aPath, false);
   425 }
   427 NS_IMETHODIMP
   428 nsJARURI::SetPath(const nsACString &aPath)
   429 {
   430     return NS_ERROR_FAILURE;
   431 }
   433 NS_IMETHODIMP
   434 nsJARURI::GetAsciiSpec(nsACString &aSpec)
   435 {
   436     // XXX Shouldn't this like... make sure it returns ASCII or something?
   437     return GetSpec(aSpec);
   438 }
   440 NS_IMETHODIMP
   441 nsJARURI::GetAsciiHost(nsACString &aHost)
   442 {
   443     return NS_ERROR_FAILURE;
   444 }
   446 NS_IMETHODIMP
   447 nsJARURI::GetOriginCharset(nsACString &aOriginCharset)
   448 {
   449     aOriginCharset = mCharsetHint;
   450     return NS_OK;
   451 }
   453 NS_IMETHODIMP
   454 nsJARURI::Equals(nsIURI *other, bool *result)
   455 {
   456     return EqualsInternal(other, eHonorRef, result);
   457 }
   459 NS_IMETHODIMP
   460 nsJARURI::EqualsExceptRef(nsIURI *other, bool *result)
   461 {
   462     return EqualsInternal(other, eIgnoreRef, result);
   463 }
   465 // Helper method:
   466 /* virtual */ nsresult
   467 nsJARURI::EqualsInternal(nsIURI *other,
   468                          nsJARURI::RefHandlingEnum refHandlingMode,
   469                          bool *result)
   470 {
   471     *result = false;
   473     if (!other)
   474         return NS_OK;	// not equal
   476     nsRefPtr<nsJARURI> otherJAR;
   477     other->QueryInterface(NS_GET_IID(nsJARURI), getter_AddRefs(otherJAR));
   478     if (!otherJAR)
   479         return NS_OK;   // not equal
   481     bool equal;
   482     nsresult rv = mJARFile->Equals(otherJAR->mJARFile, &equal);
   483     if (NS_FAILED(rv) || !equal) {
   484         return rv;   // not equal
   485     }
   487     return refHandlingMode == eHonorRef ?
   488         mJAREntry->Equals(otherJAR->mJAREntry, result) :
   489         mJAREntry->EqualsExceptRef(otherJAR->mJAREntry, result);
   490 }
   492 NS_IMETHODIMP
   493 nsJARURI::SchemeIs(const char *i_Scheme, bool *o_Equals)
   494 {
   495     NS_ENSURE_ARG_POINTER(o_Equals);
   496     if (!i_Scheme) return NS_ERROR_INVALID_ARG;
   498     if (*i_Scheme == 'j' || *i_Scheme == 'J') {
   499         *o_Equals = PL_strcasecmp("jar", i_Scheme) ? false : true;
   500     } else {
   501         *o_Equals = false;
   502     }
   503     return NS_OK;
   504 }
   506 NS_IMETHODIMP
   507 nsJARURI::Clone(nsIURI **result)
   508 {
   509     nsresult rv;
   511     nsCOMPtr<nsIJARURI> uri;
   512     rv = CloneWithJARFileInternal(mJARFile, eHonorRef, getter_AddRefs(uri));
   513     if (NS_FAILED(rv)) return rv;
   515     return CallQueryInterface(uri, result);
   516 }
   518 NS_IMETHODIMP
   519 nsJARURI::CloneIgnoringRef(nsIURI **result)
   520 {
   521     nsresult rv;
   523     nsCOMPtr<nsIJARURI> uri;
   524     rv = CloneWithJARFileInternal(mJARFile, eIgnoreRef, getter_AddRefs(uri));
   525     if (NS_FAILED(rv)) return rv;
   527     return CallQueryInterface(uri, result);
   528 }
   530 NS_IMETHODIMP
   531 nsJARURI::Resolve(const nsACString &relativePath, nsACString &result)
   532 {
   533     nsresult rv;
   535     nsCOMPtr<nsIIOService> ioServ(do_GetIOService(&rv));
   536     if (NS_FAILED(rv))
   537       return rv;
   539     nsAutoCString scheme;
   540     rv = ioServ->ExtractScheme(relativePath, scheme);
   541     if (NS_SUCCEEDED(rv)) {
   542         // then aSpec is absolute
   543         result = relativePath;
   544         return NS_OK;
   545     }
   547     nsAutoCString resolvedPath;
   548     mJAREntry->Resolve(relativePath, resolvedPath);
   550     return FormatSpec(resolvedPath, result);
   551 }
   553 ////////////////////////////////////////////////////////////////////////////////
   554 // nsIURL methods:
   556 NS_IMETHODIMP
   557 nsJARURI::GetFilePath(nsACString& filePath)
   558 {
   559     return mJAREntry->GetFilePath(filePath);
   560 }
   562 NS_IMETHODIMP
   563 nsJARURI::SetFilePath(const nsACString& filePath)
   564 {
   565     return mJAREntry->SetFilePath(filePath);
   566 }
   568 NS_IMETHODIMP
   569 nsJARURI::GetQuery(nsACString& query)
   570 {
   571     return mJAREntry->GetQuery(query);
   572 }
   574 NS_IMETHODIMP
   575 nsJARURI::SetQuery(const nsACString& query)
   576 {
   577     return mJAREntry->SetQuery(query);
   578 }
   580 NS_IMETHODIMP
   581 nsJARURI::GetRef(nsACString& ref)
   582 {
   583     return mJAREntry->GetRef(ref);
   584 }
   586 NS_IMETHODIMP
   587 nsJARURI::SetRef(const nsACString& ref)
   588 {
   589     return mJAREntry->SetRef(ref);
   590 }
   592 NS_IMETHODIMP
   593 nsJARURI::GetDirectory(nsACString& directory)
   594 {
   595     return mJAREntry->GetDirectory(directory);
   596 }
   598 NS_IMETHODIMP
   599 nsJARURI::SetDirectory(const nsACString& directory)
   600 {
   601     return mJAREntry->SetDirectory(directory);
   602 }
   604 NS_IMETHODIMP
   605 nsJARURI::GetFileName(nsACString& fileName)
   606 {
   607     return mJAREntry->GetFileName(fileName);
   608 }
   610 NS_IMETHODIMP
   611 nsJARURI::SetFileName(const nsACString& fileName)
   612 {
   613     return mJAREntry->SetFileName(fileName);
   614 }
   616 NS_IMETHODIMP
   617 nsJARURI::GetFileBaseName(nsACString& fileBaseName)
   618 {
   619     return mJAREntry->GetFileBaseName(fileBaseName);
   620 }
   622 NS_IMETHODIMP
   623 nsJARURI::SetFileBaseName(const nsACString& fileBaseName)
   624 {
   625     return mJAREntry->SetFileBaseName(fileBaseName);
   626 }
   628 NS_IMETHODIMP
   629 nsJARURI::GetFileExtension(nsACString& fileExtension)
   630 {
   631     return mJAREntry->GetFileExtension(fileExtension);
   632 }
   634 NS_IMETHODIMP
   635 nsJARURI::SetFileExtension(const nsACString& fileExtension)
   636 {
   637     return mJAREntry->SetFileExtension(fileExtension);
   638 }
   640 NS_IMETHODIMP
   641 nsJARURI::GetCommonBaseSpec(nsIURI* uriToCompare, nsACString& commonSpec)
   642 {
   643     commonSpec.Truncate();
   645     NS_ENSURE_ARG_POINTER(uriToCompare);
   647     commonSpec.Truncate();
   648     nsCOMPtr<nsIJARURI> otherJARURI(do_QueryInterface(uriToCompare));
   649     if (!otherJARURI) {
   650         // Nothing in common
   651         return NS_OK;
   652     }
   654     nsCOMPtr<nsIURI> otherJARFile;
   655     nsresult rv = otherJARURI->GetJARFile(getter_AddRefs(otherJARFile));
   656     if (NS_FAILED(rv)) return rv;
   658     bool equal;
   659     rv = mJARFile->Equals(otherJARFile, &equal);
   660     if (NS_FAILED(rv)) return rv;
   662     if (!equal) {
   663         // See what the JAR file URIs have in common
   664         nsCOMPtr<nsIURL> ourJARFileURL(do_QueryInterface(mJARFile));
   665         if (!ourJARFileURL) {
   666             // Not a URL, so nothing in common
   667             return NS_OK;
   668         }
   669         nsAutoCString common;
   670         rv = ourJARFileURL->GetCommonBaseSpec(otherJARFile, common);
   671         if (NS_FAILED(rv)) return rv;
   673         commonSpec = NS_JAR_SCHEME + common;
   674         return NS_OK;
   676     }
   678     // At this point we have the same JAR file.  Compare the JAREntrys
   679     nsAutoCString otherEntry;
   680     rv = otherJARURI->GetJAREntry(otherEntry);
   681     if (NS_FAILED(rv)) return rv;
   683     nsAutoCString otherCharset;
   684     rv = uriToCompare->GetOriginCharset(otherCharset);
   685     if (NS_FAILED(rv)) return rv;
   687     nsCOMPtr<nsIURL> url;
   688     rv = CreateEntryURL(otherEntry, otherCharset.get(), getter_AddRefs(url));
   689     if (NS_FAILED(rv)) return rv;
   691     nsAutoCString common;
   692     rv = mJAREntry->GetCommonBaseSpec(url, common);
   693     if (NS_FAILED(rv)) return rv;
   695     rv = FormatSpec(common, commonSpec);
   696     return rv;
   697 }
   699 NS_IMETHODIMP
   700 nsJARURI::GetRelativeSpec(nsIURI* uriToCompare, nsACString& relativeSpec)
   701 {
   702     GetSpec(relativeSpec);
   704     NS_ENSURE_ARG_POINTER(uriToCompare);
   706     nsCOMPtr<nsIJARURI> otherJARURI(do_QueryInterface(uriToCompare));
   707     if (!otherJARURI) {
   708         // Nothing in common
   709         return NS_OK;
   710     }
   712     nsCOMPtr<nsIURI> otherJARFile;
   713     nsresult rv = otherJARURI->GetJARFile(getter_AddRefs(otherJARFile));
   714     if (NS_FAILED(rv)) return rv;
   716     bool equal;
   717     rv = mJARFile->Equals(otherJARFile, &equal);
   718     if (NS_FAILED(rv)) return rv;
   720     if (!equal) {
   721         // We live in different JAR files.  Nothing in common.
   722         return rv;
   723     }
   725     // Same JAR file.  Compare the JAREntrys
   726     nsAutoCString otherEntry;
   727     rv = otherJARURI->GetJAREntry(otherEntry);
   728     if (NS_FAILED(rv)) return rv;
   730     nsAutoCString otherCharset;
   731     rv = uriToCompare->GetOriginCharset(otherCharset);
   732     if (NS_FAILED(rv)) return rv;
   734     nsCOMPtr<nsIURL> url;
   735     rv = CreateEntryURL(otherEntry, otherCharset.get(), getter_AddRefs(url));
   736     if (NS_FAILED(rv)) return rv;
   738     nsAutoCString relativeEntrySpec;
   739     rv = mJAREntry->GetRelativeSpec(url, relativeEntrySpec);
   740     if (NS_FAILED(rv)) return rv;
   742     if (!StringBeginsWith(relativeEntrySpec, NS_BOGUS_ENTRY_SCHEME)) {
   743         // An actual relative spec!
   744         relativeSpec = relativeEntrySpec;
   745     }
   746     return rv;
   747 }
   749 ////////////////////////////////////////////////////////////////////////////////
   750 // nsIJARURI methods:
   752 NS_IMETHODIMP
   753 nsJARURI::GetJARFile(nsIURI* *jarFile)
   754 {
   755     return GetInnerURI(jarFile);
   756 }
   758 NS_IMETHODIMP
   759 nsJARURI::GetJAREntry(nsACString &entryPath)
   760 {
   761     nsAutoCString filePath;
   762     mJAREntry->GetFilePath(filePath);
   763     NS_ASSERTION(filePath.Length() > 0, "path should never be empty!");
   764     // Trim off the leading '/'
   765     entryPath = Substring(filePath, 1, filePath.Length() - 1);
   766     return NS_OK;
   767 }
   769 NS_IMETHODIMP
   770 nsJARURI::SetJAREntry(const nsACString &entryPath)
   771 {
   772     return CreateEntryURL(entryPath, mCharsetHint.get(),
   773                           getter_AddRefs(mJAREntry));
   774 }
   776 NS_IMETHODIMP
   777 nsJARURI::CloneWithJARFile(nsIURI *jarFile, nsIJARURI **result)
   778 {
   779     return CloneWithJARFileInternal(jarFile, eHonorRef, result);
   780 }
   782 nsresult
   783 nsJARURI::CloneWithJARFileInternal(nsIURI *jarFile,
   784                                    nsJARURI::RefHandlingEnum refHandlingMode,
   785                                    nsIJARURI **result)
   786 {
   787     if (!jarFile) {
   788         return NS_ERROR_INVALID_ARG;
   789     }
   791     nsresult rv;
   793     nsCOMPtr<nsIURI> newJARFile;
   794     rv = jarFile->Clone(getter_AddRefs(newJARFile));
   795     if (NS_FAILED(rv)) return rv;
   797     NS_TryToSetImmutable(newJARFile);
   799     nsCOMPtr<nsIURI> newJAREntryURI;
   800     rv = refHandlingMode == eHonorRef ?
   801         mJAREntry->Clone(getter_AddRefs(newJAREntryURI)) :
   802         mJAREntry->CloneIgnoringRef(getter_AddRefs(newJAREntryURI));
   804     if (NS_FAILED(rv)) return rv;
   806     nsCOMPtr<nsIURL> newJAREntry(do_QueryInterface(newJAREntryURI));
   807     NS_ASSERTION(newJAREntry, "This had better QI to nsIURL!");
   809     nsJARURI* uri = new nsJARURI();
   810     NS_ADDREF(uri);
   811     uri->mJARFile = newJARFile;
   812     uri->mJAREntry = newJAREntry;
   813     *result = uri;
   815     return NS_OK;
   816 }
   818 ////////////////////////////////////////////////////////////////////////////////
   820 NS_IMETHODIMP
   821 nsJARURI::GetInnerURI(nsIURI **uri)
   822 {
   823     return NS_EnsureSafeToReturn(mJARFile, uri);
   824 }
   826 NS_IMETHODIMP
   827 nsJARURI::GetInnermostURI(nsIURI** uri)
   828 {
   829     return NS_ImplGetInnermostURI(this, uri);
   830 }
   832 ////////////////////////////////////////////////////////////////////////////////
   833 // nsIIPCSerializableURI methods:
   835 void
   836 nsJARURI::Serialize(URIParams& aParams)
   837 {
   838     JARURIParams params;
   840     SerializeURI(mJARFile, params.jarFile());
   841     SerializeURI(mJAREntry, params.jarEntry());
   842     params.charset() = mCharsetHint;
   844     aParams = params;
   845 }
   847 bool
   848 nsJARURI::Deserialize(const URIParams& aParams)
   849 {
   850     if (aParams.type() != URIParams::TJARURIParams) {
   851         NS_ERROR("Received unknown parameters from the other process!");
   852         return false;
   853     }
   855     const JARURIParams& params = aParams.get_JARURIParams();
   857     nsCOMPtr<nsIURI> file = DeserializeURI(params.jarFile());
   858     if (!file) {
   859         NS_ERROR("Couldn't deserialize jar file URI!");
   860         return false;
   861     }
   863     nsCOMPtr<nsIURI> entry = DeserializeURI(params.jarEntry());
   864     if (!entry) {
   865         NS_ERROR("Couldn't deserialize jar entry URI!");
   866         return false;
   867     }
   869     nsCOMPtr<nsIURL> entryURL = do_QueryInterface(entry);
   870     if (!entryURL) {
   871         NS_ERROR("Couldn't QI jar entry URI to nsIURL!");
   872         return false;
   873     }
   875     mJARFile.swap(file);
   876     mJAREntry.swap(entryURL);
   877     mCharsetHint = params.charset();
   879     return true;
   880 }

mercurial