modules/libjar/nsJARURI.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/modules/libjar/nsJARURI.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,880 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + *
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "base/basictypes.h"
    1.11 +
    1.12 +#include "nsJARURI.h"
    1.13 +#include "nsNetUtil.h"
    1.14 +#include "nsIIOService.h"
    1.15 +#include "nsIStandardURL.h"
    1.16 +#include "nsCRT.h"
    1.17 +#include "nsIComponentManager.h"
    1.18 +#include "nsIServiceManager.h"
    1.19 +#include "nsIZipReader.h"
    1.20 +#include "nsReadableUtils.h"
    1.21 +#include "nsAutoPtr.h"
    1.22 +#include "nsNetCID.h"
    1.23 +#include "nsIObjectInputStream.h"
    1.24 +#include "nsIObjectOutputStream.h"
    1.25 +#include "nsIProgrammingLanguage.h"
    1.26 +#include "mozilla/ipc/URIUtils.h"
    1.27 +
    1.28 +using namespace mozilla::ipc;
    1.29 +
    1.30 +static NS_DEFINE_CID(kJARURICID, NS_JARURI_CID);
    1.31 +
    1.32 +////////////////////////////////////////////////////////////////////////////////
    1.33 + 
    1.34 +nsJARURI::nsJARURI()
    1.35 +{
    1.36 +}
    1.37 + 
    1.38 +nsJARURI::~nsJARURI()
    1.39 +{
    1.40 +}
    1.41 +
    1.42 +// XXX Why is this threadsafe?
    1.43 +NS_IMPL_ADDREF(nsJARURI)
    1.44 +NS_IMPL_RELEASE(nsJARURI)
    1.45 +NS_INTERFACE_MAP_BEGIN(nsJARURI)
    1.46 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJARURI)
    1.47 +  NS_INTERFACE_MAP_ENTRY(nsIURI)
    1.48 +  NS_INTERFACE_MAP_ENTRY(nsIURL)
    1.49 +  NS_INTERFACE_MAP_ENTRY(nsIJARURI)
    1.50 +  NS_INTERFACE_MAP_ENTRY(nsISerializable)
    1.51 +  NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
    1.52 +  NS_INTERFACE_MAP_ENTRY(nsINestedURI)
    1.53 +  NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableURI)
    1.54 +  // see nsJARURI::Equals
    1.55 +  if (aIID.Equals(NS_GET_IID(nsJARURI)))
    1.56 +      foundInterface = reinterpret_cast<nsISupports*>(this);
    1.57 +  else
    1.58 +NS_INTERFACE_MAP_END
    1.59 +
    1.60 +nsresult
    1.61 +nsJARURI::Init(const char *charsetHint)
    1.62 +{
    1.63 +    mCharsetHint = charsetHint;
    1.64 +    return NS_OK;
    1.65 +}
    1.66 +
    1.67 +#define NS_JAR_SCHEME           NS_LITERAL_CSTRING("jar:")
    1.68 +#define NS_JAR_DELIMITER        NS_LITERAL_CSTRING("!/")
    1.69 +#define NS_BOGUS_ENTRY_SCHEME   NS_LITERAL_CSTRING("x:///")
    1.70 +
    1.71 +// FormatSpec takes the entry spec (including the "x:///" at the
    1.72 +// beginning) and gives us a full JAR spec.
    1.73 +nsresult
    1.74 +nsJARURI::FormatSpec(const nsACString &entrySpec, nsACString &result,
    1.75 +                     bool aIncludeScheme)
    1.76 +{
    1.77 +    // The entrySpec MUST start with "x:///"
    1.78 +    NS_ASSERTION(StringBeginsWith(entrySpec, NS_BOGUS_ENTRY_SCHEME),
    1.79 +                 "bogus entry spec");
    1.80 +
    1.81 +    nsAutoCString fileSpec;
    1.82 +    nsresult rv = mJARFile->GetSpec(fileSpec);
    1.83 +    if (NS_FAILED(rv)) return rv;
    1.84 +
    1.85 +    if (aIncludeScheme)
    1.86 +        result = NS_JAR_SCHEME;
    1.87 +    else
    1.88 +        result.Truncate();
    1.89 +
    1.90 +    result.Append(fileSpec + NS_JAR_DELIMITER +
    1.91 +                  Substring(entrySpec, 5, entrySpec.Length() - 5));
    1.92 +    return NS_OK;
    1.93 +}
    1.94 +
    1.95 +nsresult
    1.96 +nsJARURI::CreateEntryURL(const nsACString& entryFilename,
    1.97 +                         const char* charset,
    1.98 +                         nsIURL** url)
    1.99 +{
   1.100 +    *url = nullptr;
   1.101 +
   1.102 +    nsCOMPtr<nsIStandardURL> stdURL(do_CreateInstance(NS_STANDARDURL_CONTRACTID));
   1.103 +    if (!stdURL) {
   1.104 +        return NS_ERROR_OUT_OF_MEMORY;
   1.105 +    }
   1.106 +
   1.107 +    // Flatten the concatenation, just in case.  See bug 128288
   1.108 +    nsAutoCString spec(NS_BOGUS_ENTRY_SCHEME + entryFilename);
   1.109 +    nsresult rv = stdURL->Init(nsIStandardURL::URLTYPE_NO_AUTHORITY, -1,
   1.110 +                               spec, charset, nullptr);
   1.111 +    if (NS_FAILED(rv)) {
   1.112 +        return rv;
   1.113 +    }
   1.114 +
   1.115 +    return CallQueryInterface(stdURL, url);
   1.116 +}
   1.117 +    
   1.118 +////////////////////////////////////////////////////////////////////////////////
   1.119 +// nsISerializable methods:
   1.120 +
   1.121 +NS_IMETHODIMP
   1.122 +nsJARURI::Read(nsIObjectInputStream* aInputStream)
   1.123 +{
   1.124 +    nsresult rv;
   1.125 +
   1.126 +    nsCOMPtr<nsISupports> supports;
   1.127 +    rv = aInputStream->ReadObject(true, getter_AddRefs(supports));
   1.128 +    NS_ENSURE_SUCCESS(rv, rv);
   1.129 +
   1.130 +    mJARFile = do_QueryInterface(supports, &rv);
   1.131 +    NS_ENSURE_SUCCESS(rv, rv);
   1.132 +
   1.133 +    rv = aInputStream->ReadObject(true, getter_AddRefs(supports));
   1.134 +    NS_ENSURE_SUCCESS(rv, rv);
   1.135 +
   1.136 +    mJAREntry = do_QueryInterface(supports);
   1.137 +    NS_ENSURE_SUCCESS(rv, rv);
   1.138 +
   1.139 +    rv = aInputStream->ReadCString(mCharsetHint);
   1.140 +    return rv;
   1.141 +}
   1.142 +
   1.143 +NS_IMETHODIMP
   1.144 +nsJARURI::Write(nsIObjectOutputStream* aOutputStream)
   1.145 +{
   1.146 +    nsresult rv;
   1.147 +    
   1.148 +    rv = aOutputStream->WriteCompoundObject(mJARFile, NS_GET_IID(nsIURI),
   1.149 +                                            true);
   1.150 +    NS_ENSURE_SUCCESS(rv, rv);
   1.151 +
   1.152 +    rv = aOutputStream->WriteCompoundObject(mJAREntry, NS_GET_IID(nsIURL),
   1.153 +                                            true);
   1.154 +    NS_ENSURE_SUCCESS(rv, rv);
   1.155 +
   1.156 +    rv = aOutputStream->WriteStringZ(mCharsetHint.get());
   1.157 +    return rv;
   1.158 +}
   1.159 +
   1.160 +////////////////////////////////////////////////////////////////////////////////
   1.161 +// nsIClassInfo methods:
   1.162 +
   1.163 +NS_IMETHODIMP 
   1.164 +nsJARURI::GetInterfaces(uint32_t *count, nsIID * **array)
   1.165 +{
   1.166 +    *count = 0;
   1.167 +    *array = nullptr;
   1.168 +    return NS_OK;
   1.169 +}
   1.170 +
   1.171 +NS_IMETHODIMP 
   1.172 +nsJARURI::GetHelperForLanguage(uint32_t language, nsISupports **_retval)
   1.173 +{
   1.174 +    *_retval = nullptr;
   1.175 +    return NS_OK;
   1.176 +}
   1.177 +
   1.178 +NS_IMETHODIMP 
   1.179 +nsJARURI::GetContractID(char * *aContractID)
   1.180 +{
   1.181 +    *aContractID = nullptr;
   1.182 +    return NS_OK;
   1.183 +}
   1.184 +
   1.185 +NS_IMETHODIMP 
   1.186 +nsJARURI::GetClassDescription(char * *aClassDescription)
   1.187 +{
   1.188 +    *aClassDescription = nullptr;
   1.189 +    return NS_OK;
   1.190 +}
   1.191 +
   1.192 +NS_IMETHODIMP 
   1.193 +nsJARURI::GetClassID(nsCID * *aClassID)
   1.194 +{
   1.195 +    *aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
   1.196 +    if (!*aClassID)
   1.197 +        return NS_ERROR_OUT_OF_MEMORY;
   1.198 +    return GetClassIDNoAlloc(*aClassID);
   1.199 +}
   1.200 +
   1.201 +NS_IMETHODIMP 
   1.202 +nsJARURI::GetImplementationLanguage(uint32_t *aImplementationLanguage)
   1.203 +{
   1.204 +    *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
   1.205 +    return NS_OK;
   1.206 +}
   1.207 +
   1.208 +NS_IMETHODIMP 
   1.209 +nsJARURI::GetFlags(uint32_t *aFlags)
   1.210 +{
   1.211 +    // XXX We implement THREADSAFE addref/release, but probably shouldn't.
   1.212 +    *aFlags = nsIClassInfo::MAIN_THREAD_ONLY;
   1.213 +    return NS_OK;
   1.214 +}
   1.215 +
   1.216 +NS_IMETHODIMP 
   1.217 +nsJARURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
   1.218 +{
   1.219 +    *aClassIDNoAlloc = kJARURICID;
   1.220 +    return NS_OK;
   1.221 +}
   1.222 +
   1.223 +////////////////////////////////////////////////////////////////////////////////
   1.224 +// nsIURI methods:
   1.225 +
   1.226 +NS_IMETHODIMP
   1.227 +nsJARURI::GetSpec(nsACString &aSpec)
   1.228 +{
   1.229 +    nsAutoCString entrySpec;
   1.230 +    mJAREntry->GetSpec(entrySpec);
   1.231 +    return FormatSpec(entrySpec, aSpec);
   1.232 +}
   1.233 +
   1.234 +NS_IMETHODIMP
   1.235 +nsJARURI::GetSpecIgnoringRef(nsACString &aSpec)
   1.236 +{
   1.237 +    nsAutoCString entrySpec;
   1.238 +    mJAREntry->GetSpecIgnoringRef(entrySpec);
   1.239 +    return FormatSpec(entrySpec, aSpec);
   1.240 +}
   1.241 +
   1.242 +NS_IMETHODIMP
   1.243 +nsJARURI::GetHasRef(bool *result)
   1.244 +{
   1.245 +    return mJAREntry->GetHasRef(result);
   1.246 +}
   1.247 +
   1.248 +NS_IMETHODIMP
   1.249 +nsJARURI::SetSpec(const nsACString& aSpec)
   1.250 +{
   1.251 +    return SetSpecWithBase(aSpec, nullptr);
   1.252 +}
   1.253 +
   1.254 +nsresult
   1.255 +nsJARURI::SetSpecWithBase(const nsACString &aSpec, nsIURI* aBaseURL)
   1.256 +{
   1.257 +    nsresult rv;
   1.258 +
   1.259 +    nsCOMPtr<nsIIOService> ioServ(do_GetIOService(&rv));
   1.260 +    NS_ENSURE_SUCCESS(rv, rv);
   1.261 +
   1.262 +    nsAutoCString scheme;
   1.263 +    rv = ioServ->ExtractScheme(aSpec, scheme);
   1.264 +    if (NS_FAILED(rv)) {
   1.265 +        // not an absolute URI
   1.266 +        if (!aBaseURL)
   1.267 +            return NS_ERROR_MALFORMED_URI;
   1.268 +
   1.269 +        nsRefPtr<nsJARURI> otherJAR;
   1.270 +        aBaseURL->QueryInterface(NS_GET_IID(nsJARURI), getter_AddRefs(otherJAR));
   1.271 +        NS_ENSURE_TRUE(otherJAR, NS_NOINTERFACE);
   1.272 +
   1.273 +        mJARFile = otherJAR->mJARFile;
   1.274 +
   1.275 +        nsCOMPtr<nsIStandardURL> entry(do_CreateInstance(NS_STANDARDURL_CONTRACTID));
   1.276 +        if (!entry)
   1.277 +            return NS_ERROR_OUT_OF_MEMORY;
   1.278 +
   1.279 +        rv = entry->Init(nsIStandardURL::URLTYPE_NO_AUTHORITY, -1,
   1.280 +                         aSpec, mCharsetHint.get(), otherJAR->mJAREntry);
   1.281 +        if (NS_FAILED(rv))
   1.282 +            return rv;
   1.283 +
   1.284 +        mJAREntry = do_QueryInterface(entry);
   1.285 +        if (!mJAREntry)
   1.286 +            return NS_NOINTERFACE;
   1.287 +
   1.288 +        return NS_OK;
   1.289 +    }
   1.290 +
   1.291 +    NS_ENSURE_TRUE(scheme.EqualsLiteral("jar"), NS_ERROR_MALFORMED_URI);
   1.292 +
   1.293 +    nsACString::const_iterator begin, end;
   1.294 +    aSpec.BeginReading(begin);
   1.295 +    aSpec.EndReading(end);
   1.296 +
   1.297 +    while (begin != end && *begin != ':')
   1.298 +        ++begin;
   1.299 +
   1.300 +    ++begin; // now we're past the "jar:"
   1.301 +
   1.302 +    // Search backward from the end for the "!/" delimiter. Remember, jar URLs
   1.303 +    // can nest, e.g.:
   1.304 +    //    jar:jar:http://www.foo.com/bar.jar!/a.jar!/b.html
   1.305 +    // This gets the b.html document from out of the a.jar file, that's 
   1.306 +    // contained within the bar.jar file.
   1.307 +    // Also, the outermost "inner" URI may be a relative URI:
   1.308 +    //   jar:../relative.jar!/a.html
   1.309 +
   1.310 +    nsACString::const_iterator delim_begin (begin),
   1.311 +                               delim_end   (end);
   1.312 +
   1.313 +    if (!RFindInReadable(NS_JAR_DELIMITER, delim_begin, delim_end))
   1.314 +        return NS_ERROR_MALFORMED_URI;
   1.315 +
   1.316 +    rv = ioServ->NewURI(Substring(begin, delim_begin), mCharsetHint.get(),
   1.317 +                        aBaseURL, getter_AddRefs(mJARFile));
   1.318 +    if (NS_FAILED(rv)) return rv;
   1.319 +
   1.320 +    NS_TryToSetImmutable(mJARFile);
   1.321 +
   1.322 +    // skip over any extra '/' chars
   1.323 +    while (*delim_end == '/')
   1.324 +        ++delim_end;
   1.325 +
   1.326 +    return SetJAREntry(Substring(delim_end, end));
   1.327 +}
   1.328 +
   1.329 +NS_IMETHODIMP
   1.330 +nsJARURI::GetPrePath(nsACString &prePath)
   1.331 +{
   1.332 +    prePath = NS_JAR_SCHEME;
   1.333 +    return NS_OK;
   1.334 +}
   1.335 +
   1.336 +NS_IMETHODIMP
   1.337 +nsJARURI::GetScheme(nsACString &aScheme)
   1.338 +{
   1.339 +    aScheme = "jar";
   1.340 +    return NS_OK;
   1.341 +}
   1.342 +
   1.343 +NS_IMETHODIMP
   1.344 +nsJARURI::SetScheme(const nsACString &aScheme)
   1.345 +{
   1.346 +    // doesn't make sense to set the scheme of a jar: URL
   1.347 +    return NS_ERROR_FAILURE;
   1.348 +}
   1.349 +
   1.350 +NS_IMETHODIMP
   1.351 +nsJARURI::GetUserPass(nsACString &aUserPass)
   1.352 +{
   1.353 +    return NS_ERROR_FAILURE;
   1.354 +}
   1.355 +
   1.356 +NS_IMETHODIMP
   1.357 +nsJARURI::SetUserPass(const nsACString &aUserPass)
   1.358 +{
   1.359 +    return NS_ERROR_FAILURE;
   1.360 +}
   1.361 +
   1.362 +NS_IMETHODIMP
   1.363 +nsJARURI::GetUsername(nsACString &aUsername)
   1.364 +{
   1.365 +    return NS_ERROR_FAILURE;
   1.366 +}
   1.367 +
   1.368 +NS_IMETHODIMP
   1.369 +nsJARURI::SetUsername(const nsACString &aUsername)
   1.370 +{
   1.371 +    return NS_ERROR_FAILURE;
   1.372 +}
   1.373 +
   1.374 +NS_IMETHODIMP
   1.375 +nsJARURI::GetPassword(nsACString &aPassword)
   1.376 +{
   1.377 +    return NS_ERROR_FAILURE;
   1.378 +}
   1.379 +
   1.380 +NS_IMETHODIMP
   1.381 +nsJARURI::SetPassword(const nsACString &aPassword)
   1.382 +{
   1.383 +    return NS_ERROR_FAILURE;
   1.384 +}
   1.385 +
   1.386 +NS_IMETHODIMP
   1.387 +nsJARURI::GetHostPort(nsACString &aHostPort)
   1.388 +{
   1.389 +    return NS_ERROR_FAILURE;
   1.390 +}
   1.391 +
   1.392 +NS_IMETHODIMP
   1.393 +nsJARURI::SetHostPort(const nsACString &aHostPort)
   1.394 +{
   1.395 +    return NS_ERROR_FAILURE;
   1.396 +}
   1.397 +
   1.398 +NS_IMETHODIMP
   1.399 +nsJARURI::GetHost(nsACString &aHost)
   1.400 +{
   1.401 +    return NS_ERROR_FAILURE;
   1.402 +}
   1.403 +
   1.404 +NS_IMETHODIMP
   1.405 +nsJARURI::SetHost(const nsACString &aHost)
   1.406 +{
   1.407 +    return NS_ERROR_FAILURE;
   1.408 +}
   1.409 +
   1.410 +NS_IMETHODIMP
   1.411 +nsJARURI::GetPort(int32_t *aPort)
   1.412 +{
   1.413 +    return NS_ERROR_FAILURE;
   1.414 +}
   1.415 + 
   1.416 +NS_IMETHODIMP
   1.417 +nsJARURI::SetPort(int32_t aPort)
   1.418 +{
   1.419 +    return NS_ERROR_FAILURE;
   1.420 +}
   1.421 +
   1.422 +NS_IMETHODIMP
   1.423 +nsJARURI::GetPath(nsACString &aPath)
   1.424 +{
   1.425 +    nsAutoCString entrySpec;
   1.426 +    mJAREntry->GetSpec(entrySpec);
   1.427 +    return FormatSpec(entrySpec, aPath, false);
   1.428 +}
   1.429 +
   1.430 +NS_IMETHODIMP
   1.431 +nsJARURI::SetPath(const nsACString &aPath)
   1.432 +{
   1.433 +    return NS_ERROR_FAILURE;
   1.434 +}
   1.435 +
   1.436 +NS_IMETHODIMP
   1.437 +nsJARURI::GetAsciiSpec(nsACString &aSpec)
   1.438 +{
   1.439 +    // XXX Shouldn't this like... make sure it returns ASCII or something?
   1.440 +    return GetSpec(aSpec);
   1.441 +}
   1.442 +
   1.443 +NS_IMETHODIMP
   1.444 +nsJARURI::GetAsciiHost(nsACString &aHost)
   1.445 +{
   1.446 +    return NS_ERROR_FAILURE;
   1.447 +}
   1.448 +
   1.449 +NS_IMETHODIMP
   1.450 +nsJARURI::GetOriginCharset(nsACString &aOriginCharset)
   1.451 +{
   1.452 +    aOriginCharset = mCharsetHint;
   1.453 +    return NS_OK;
   1.454 +}
   1.455 +
   1.456 +NS_IMETHODIMP
   1.457 +nsJARURI::Equals(nsIURI *other, bool *result)
   1.458 +{
   1.459 +    return EqualsInternal(other, eHonorRef, result);
   1.460 +}
   1.461 +
   1.462 +NS_IMETHODIMP
   1.463 +nsJARURI::EqualsExceptRef(nsIURI *other, bool *result)
   1.464 +{
   1.465 +    return EqualsInternal(other, eIgnoreRef, result);
   1.466 +}
   1.467 +
   1.468 +// Helper method:
   1.469 +/* virtual */ nsresult
   1.470 +nsJARURI::EqualsInternal(nsIURI *other,
   1.471 +                         nsJARURI::RefHandlingEnum refHandlingMode,
   1.472 +                         bool *result)
   1.473 +{
   1.474 +    *result = false;
   1.475 +
   1.476 +    if (!other)
   1.477 +        return NS_OK;	// not equal
   1.478 +
   1.479 +    nsRefPtr<nsJARURI> otherJAR;
   1.480 +    other->QueryInterface(NS_GET_IID(nsJARURI), getter_AddRefs(otherJAR));
   1.481 +    if (!otherJAR)
   1.482 +        return NS_OK;   // not equal
   1.483 +
   1.484 +    bool equal;
   1.485 +    nsresult rv = mJARFile->Equals(otherJAR->mJARFile, &equal);
   1.486 +    if (NS_FAILED(rv) || !equal) {
   1.487 +        return rv;   // not equal
   1.488 +    }
   1.489 +
   1.490 +    return refHandlingMode == eHonorRef ?
   1.491 +        mJAREntry->Equals(otherJAR->mJAREntry, result) :
   1.492 +        mJAREntry->EqualsExceptRef(otherJAR->mJAREntry, result);
   1.493 +}
   1.494 +
   1.495 +NS_IMETHODIMP
   1.496 +nsJARURI::SchemeIs(const char *i_Scheme, bool *o_Equals)
   1.497 +{
   1.498 +    NS_ENSURE_ARG_POINTER(o_Equals);
   1.499 +    if (!i_Scheme) return NS_ERROR_INVALID_ARG;
   1.500 +
   1.501 +    if (*i_Scheme == 'j' || *i_Scheme == 'J') {
   1.502 +        *o_Equals = PL_strcasecmp("jar", i_Scheme) ? false : true;
   1.503 +    } else {
   1.504 +        *o_Equals = false;
   1.505 +    }
   1.506 +    return NS_OK;
   1.507 +}
   1.508 +
   1.509 +NS_IMETHODIMP
   1.510 +nsJARURI::Clone(nsIURI **result)
   1.511 +{
   1.512 +    nsresult rv;
   1.513 +
   1.514 +    nsCOMPtr<nsIJARURI> uri;
   1.515 +    rv = CloneWithJARFileInternal(mJARFile, eHonorRef, getter_AddRefs(uri));
   1.516 +    if (NS_FAILED(rv)) return rv;
   1.517 +
   1.518 +    return CallQueryInterface(uri, result);
   1.519 +}
   1.520 +
   1.521 +NS_IMETHODIMP
   1.522 +nsJARURI::CloneIgnoringRef(nsIURI **result)
   1.523 +{
   1.524 +    nsresult rv;
   1.525 +
   1.526 +    nsCOMPtr<nsIJARURI> uri;
   1.527 +    rv = CloneWithJARFileInternal(mJARFile, eIgnoreRef, getter_AddRefs(uri));
   1.528 +    if (NS_FAILED(rv)) return rv;
   1.529 +
   1.530 +    return CallQueryInterface(uri, result);
   1.531 +}
   1.532 +
   1.533 +NS_IMETHODIMP
   1.534 +nsJARURI::Resolve(const nsACString &relativePath, nsACString &result)
   1.535 +{
   1.536 +    nsresult rv;
   1.537 +
   1.538 +    nsCOMPtr<nsIIOService> ioServ(do_GetIOService(&rv));
   1.539 +    if (NS_FAILED(rv))
   1.540 +      return rv;
   1.541 +
   1.542 +    nsAutoCString scheme;
   1.543 +    rv = ioServ->ExtractScheme(relativePath, scheme);
   1.544 +    if (NS_SUCCEEDED(rv)) {
   1.545 +        // then aSpec is absolute
   1.546 +        result = relativePath;
   1.547 +        return NS_OK;
   1.548 +    }
   1.549 +
   1.550 +    nsAutoCString resolvedPath;
   1.551 +    mJAREntry->Resolve(relativePath, resolvedPath);
   1.552 +    
   1.553 +    return FormatSpec(resolvedPath, result);
   1.554 +}
   1.555 +
   1.556 +////////////////////////////////////////////////////////////////////////////////
   1.557 +// nsIURL methods:
   1.558 +
   1.559 +NS_IMETHODIMP
   1.560 +nsJARURI::GetFilePath(nsACString& filePath)
   1.561 +{
   1.562 +    return mJAREntry->GetFilePath(filePath);
   1.563 +}
   1.564 +
   1.565 +NS_IMETHODIMP
   1.566 +nsJARURI::SetFilePath(const nsACString& filePath)
   1.567 +{
   1.568 +    return mJAREntry->SetFilePath(filePath);
   1.569 +}
   1.570 +
   1.571 +NS_IMETHODIMP
   1.572 +nsJARURI::GetQuery(nsACString& query)
   1.573 +{
   1.574 +    return mJAREntry->GetQuery(query);
   1.575 +}
   1.576 +
   1.577 +NS_IMETHODIMP
   1.578 +nsJARURI::SetQuery(const nsACString& query)
   1.579 +{
   1.580 +    return mJAREntry->SetQuery(query);
   1.581 +}
   1.582 +
   1.583 +NS_IMETHODIMP
   1.584 +nsJARURI::GetRef(nsACString& ref)
   1.585 +{
   1.586 +    return mJAREntry->GetRef(ref);
   1.587 +}
   1.588 +
   1.589 +NS_IMETHODIMP
   1.590 +nsJARURI::SetRef(const nsACString& ref)
   1.591 +{
   1.592 +    return mJAREntry->SetRef(ref);
   1.593 +}
   1.594 +
   1.595 +NS_IMETHODIMP
   1.596 +nsJARURI::GetDirectory(nsACString& directory)
   1.597 +{
   1.598 +    return mJAREntry->GetDirectory(directory);
   1.599 +}
   1.600 +
   1.601 +NS_IMETHODIMP
   1.602 +nsJARURI::SetDirectory(const nsACString& directory)
   1.603 +{
   1.604 +    return mJAREntry->SetDirectory(directory);
   1.605 +}
   1.606 +
   1.607 +NS_IMETHODIMP
   1.608 +nsJARURI::GetFileName(nsACString& fileName)
   1.609 +{
   1.610 +    return mJAREntry->GetFileName(fileName);
   1.611 +}
   1.612 +
   1.613 +NS_IMETHODIMP
   1.614 +nsJARURI::SetFileName(const nsACString& fileName)
   1.615 +{
   1.616 +    return mJAREntry->SetFileName(fileName);
   1.617 +}
   1.618 +
   1.619 +NS_IMETHODIMP
   1.620 +nsJARURI::GetFileBaseName(nsACString& fileBaseName)
   1.621 +{
   1.622 +    return mJAREntry->GetFileBaseName(fileBaseName);
   1.623 +}
   1.624 +
   1.625 +NS_IMETHODIMP
   1.626 +nsJARURI::SetFileBaseName(const nsACString& fileBaseName)
   1.627 +{
   1.628 +    return mJAREntry->SetFileBaseName(fileBaseName);
   1.629 +}
   1.630 +
   1.631 +NS_IMETHODIMP
   1.632 +nsJARURI::GetFileExtension(nsACString& fileExtension)
   1.633 +{
   1.634 +    return mJAREntry->GetFileExtension(fileExtension);
   1.635 +}
   1.636 +
   1.637 +NS_IMETHODIMP
   1.638 +nsJARURI::SetFileExtension(const nsACString& fileExtension)
   1.639 +{
   1.640 +    return mJAREntry->SetFileExtension(fileExtension);
   1.641 +}
   1.642 +
   1.643 +NS_IMETHODIMP
   1.644 +nsJARURI::GetCommonBaseSpec(nsIURI* uriToCompare, nsACString& commonSpec)
   1.645 +{
   1.646 +    commonSpec.Truncate();
   1.647 +
   1.648 +    NS_ENSURE_ARG_POINTER(uriToCompare);
   1.649 +    
   1.650 +    commonSpec.Truncate();
   1.651 +    nsCOMPtr<nsIJARURI> otherJARURI(do_QueryInterface(uriToCompare));
   1.652 +    if (!otherJARURI) {
   1.653 +        // Nothing in common
   1.654 +        return NS_OK;
   1.655 +    }
   1.656 +
   1.657 +    nsCOMPtr<nsIURI> otherJARFile;
   1.658 +    nsresult rv = otherJARURI->GetJARFile(getter_AddRefs(otherJARFile));
   1.659 +    if (NS_FAILED(rv)) return rv;
   1.660 +
   1.661 +    bool equal;
   1.662 +    rv = mJARFile->Equals(otherJARFile, &equal);
   1.663 +    if (NS_FAILED(rv)) return rv;
   1.664 +
   1.665 +    if (!equal) {
   1.666 +        // See what the JAR file URIs have in common
   1.667 +        nsCOMPtr<nsIURL> ourJARFileURL(do_QueryInterface(mJARFile));
   1.668 +        if (!ourJARFileURL) {
   1.669 +            // Not a URL, so nothing in common
   1.670 +            return NS_OK;
   1.671 +        }
   1.672 +        nsAutoCString common;
   1.673 +        rv = ourJARFileURL->GetCommonBaseSpec(otherJARFile, common);
   1.674 +        if (NS_FAILED(rv)) return rv;
   1.675 +
   1.676 +        commonSpec = NS_JAR_SCHEME + common;
   1.677 +        return NS_OK;
   1.678 +        
   1.679 +    }
   1.680 +    
   1.681 +    // At this point we have the same JAR file.  Compare the JAREntrys
   1.682 +    nsAutoCString otherEntry;
   1.683 +    rv = otherJARURI->GetJAREntry(otherEntry);
   1.684 +    if (NS_FAILED(rv)) return rv;
   1.685 +
   1.686 +    nsAutoCString otherCharset;
   1.687 +    rv = uriToCompare->GetOriginCharset(otherCharset);
   1.688 +    if (NS_FAILED(rv)) return rv;
   1.689 +
   1.690 +    nsCOMPtr<nsIURL> url;
   1.691 +    rv = CreateEntryURL(otherEntry, otherCharset.get(), getter_AddRefs(url));
   1.692 +    if (NS_FAILED(rv)) return rv;
   1.693 +
   1.694 +    nsAutoCString common;
   1.695 +    rv = mJAREntry->GetCommonBaseSpec(url, common);
   1.696 +    if (NS_FAILED(rv)) return rv;
   1.697 +
   1.698 +    rv = FormatSpec(common, commonSpec);
   1.699 +    return rv;
   1.700 +}
   1.701 +
   1.702 +NS_IMETHODIMP
   1.703 +nsJARURI::GetRelativeSpec(nsIURI* uriToCompare, nsACString& relativeSpec)
   1.704 +{
   1.705 +    GetSpec(relativeSpec);
   1.706 +
   1.707 +    NS_ENSURE_ARG_POINTER(uriToCompare);
   1.708 +
   1.709 +    nsCOMPtr<nsIJARURI> otherJARURI(do_QueryInterface(uriToCompare));
   1.710 +    if (!otherJARURI) {
   1.711 +        // Nothing in common
   1.712 +        return NS_OK;
   1.713 +    }
   1.714 +
   1.715 +    nsCOMPtr<nsIURI> otherJARFile;
   1.716 +    nsresult rv = otherJARURI->GetJARFile(getter_AddRefs(otherJARFile));
   1.717 +    if (NS_FAILED(rv)) return rv;
   1.718 +
   1.719 +    bool equal;
   1.720 +    rv = mJARFile->Equals(otherJARFile, &equal);
   1.721 +    if (NS_FAILED(rv)) return rv;
   1.722 +
   1.723 +    if (!equal) {
   1.724 +        // We live in different JAR files.  Nothing in common.
   1.725 +        return rv;
   1.726 +    }
   1.727 +
   1.728 +    // Same JAR file.  Compare the JAREntrys
   1.729 +    nsAutoCString otherEntry;
   1.730 +    rv = otherJARURI->GetJAREntry(otherEntry);
   1.731 +    if (NS_FAILED(rv)) return rv;
   1.732 +
   1.733 +    nsAutoCString otherCharset;
   1.734 +    rv = uriToCompare->GetOriginCharset(otherCharset);
   1.735 +    if (NS_FAILED(rv)) return rv;
   1.736 +
   1.737 +    nsCOMPtr<nsIURL> url;
   1.738 +    rv = CreateEntryURL(otherEntry, otherCharset.get(), getter_AddRefs(url));
   1.739 +    if (NS_FAILED(rv)) return rv;
   1.740 +
   1.741 +    nsAutoCString relativeEntrySpec;
   1.742 +    rv = mJAREntry->GetRelativeSpec(url, relativeEntrySpec);
   1.743 +    if (NS_FAILED(rv)) return rv;
   1.744 +
   1.745 +    if (!StringBeginsWith(relativeEntrySpec, NS_BOGUS_ENTRY_SCHEME)) {
   1.746 +        // An actual relative spec!
   1.747 +        relativeSpec = relativeEntrySpec;
   1.748 +    }
   1.749 +    return rv;
   1.750 +}
   1.751 +
   1.752 +////////////////////////////////////////////////////////////////////////////////
   1.753 +// nsIJARURI methods:
   1.754 +
   1.755 +NS_IMETHODIMP
   1.756 +nsJARURI::GetJARFile(nsIURI* *jarFile)
   1.757 +{
   1.758 +    return GetInnerURI(jarFile);
   1.759 +}
   1.760 +
   1.761 +NS_IMETHODIMP
   1.762 +nsJARURI::GetJAREntry(nsACString &entryPath)
   1.763 +{
   1.764 +    nsAutoCString filePath;
   1.765 +    mJAREntry->GetFilePath(filePath);
   1.766 +    NS_ASSERTION(filePath.Length() > 0, "path should never be empty!");
   1.767 +    // Trim off the leading '/'
   1.768 +    entryPath = Substring(filePath, 1, filePath.Length() - 1);
   1.769 +    return NS_OK;
   1.770 +}
   1.771 +
   1.772 +NS_IMETHODIMP
   1.773 +nsJARURI::SetJAREntry(const nsACString &entryPath)
   1.774 +{
   1.775 +    return CreateEntryURL(entryPath, mCharsetHint.get(),
   1.776 +                          getter_AddRefs(mJAREntry));
   1.777 +}
   1.778 +
   1.779 +NS_IMETHODIMP
   1.780 +nsJARURI::CloneWithJARFile(nsIURI *jarFile, nsIJARURI **result)
   1.781 +{
   1.782 +    return CloneWithJARFileInternal(jarFile, eHonorRef, result);
   1.783 +}
   1.784 +
   1.785 +nsresult
   1.786 +nsJARURI::CloneWithJARFileInternal(nsIURI *jarFile,
   1.787 +                                   nsJARURI::RefHandlingEnum refHandlingMode,
   1.788 +                                   nsIJARURI **result)
   1.789 +{
   1.790 +    if (!jarFile) {
   1.791 +        return NS_ERROR_INVALID_ARG;
   1.792 +    }
   1.793 +
   1.794 +    nsresult rv;
   1.795 +
   1.796 +    nsCOMPtr<nsIURI> newJARFile;
   1.797 +    rv = jarFile->Clone(getter_AddRefs(newJARFile));
   1.798 +    if (NS_FAILED(rv)) return rv;
   1.799 +
   1.800 +    NS_TryToSetImmutable(newJARFile);
   1.801 +
   1.802 +    nsCOMPtr<nsIURI> newJAREntryURI;
   1.803 +    rv = refHandlingMode == eHonorRef ?
   1.804 +        mJAREntry->Clone(getter_AddRefs(newJAREntryURI)) :
   1.805 +        mJAREntry->CloneIgnoringRef(getter_AddRefs(newJAREntryURI));
   1.806 +
   1.807 +    if (NS_FAILED(rv)) return rv;
   1.808 +
   1.809 +    nsCOMPtr<nsIURL> newJAREntry(do_QueryInterface(newJAREntryURI));
   1.810 +    NS_ASSERTION(newJAREntry, "This had better QI to nsIURL!");
   1.811 +    
   1.812 +    nsJARURI* uri = new nsJARURI();
   1.813 +    NS_ADDREF(uri);
   1.814 +    uri->mJARFile = newJARFile;
   1.815 +    uri->mJAREntry = newJAREntry;
   1.816 +    *result = uri;
   1.817 +
   1.818 +    return NS_OK;
   1.819 +}
   1.820 +
   1.821 +////////////////////////////////////////////////////////////////////////////////
   1.822 +
   1.823 +NS_IMETHODIMP
   1.824 +nsJARURI::GetInnerURI(nsIURI **uri)
   1.825 +{
   1.826 +    return NS_EnsureSafeToReturn(mJARFile, uri);
   1.827 +}
   1.828 +
   1.829 +NS_IMETHODIMP
   1.830 +nsJARURI::GetInnermostURI(nsIURI** uri)
   1.831 +{
   1.832 +    return NS_ImplGetInnermostURI(this, uri);
   1.833 +}
   1.834 +
   1.835 +////////////////////////////////////////////////////////////////////////////////
   1.836 +// nsIIPCSerializableURI methods:
   1.837 +
   1.838 +void
   1.839 +nsJARURI::Serialize(URIParams& aParams)
   1.840 +{
   1.841 +    JARURIParams params;
   1.842 +
   1.843 +    SerializeURI(mJARFile, params.jarFile());
   1.844 +    SerializeURI(mJAREntry, params.jarEntry());
   1.845 +    params.charset() = mCharsetHint;
   1.846 +
   1.847 +    aParams = params;
   1.848 +}
   1.849 +
   1.850 +bool
   1.851 +nsJARURI::Deserialize(const URIParams& aParams)
   1.852 +{
   1.853 +    if (aParams.type() != URIParams::TJARURIParams) {
   1.854 +        NS_ERROR("Received unknown parameters from the other process!");
   1.855 +        return false;
   1.856 +    }
   1.857 +
   1.858 +    const JARURIParams& params = aParams.get_JARURIParams();
   1.859 +
   1.860 +    nsCOMPtr<nsIURI> file = DeserializeURI(params.jarFile());
   1.861 +    if (!file) {
   1.862 +        NS_ERROR("Couldn't deserialize jar file URI!");
   1.863 +        return false;
   1.864 +    }
   1.865 +
   1.866 +    nsCOMPtr<nsIURI> entry = DeserializeURI(params.jarEntry());
   1.867 +    if (!entry) {
   1.868 +        NS_ERROR("Couldn't deserialize jar entry URI!");
   1.869 +        return false;
   1.870 +    }
   1.871 +
   1.872 +    nsCOMPtr<nsIURL> entryURL = do_QueryInterface(entry);
   1.873 +    if (!entryURL) {
   1.874 +        NS_ERROR("Couldn't QI jar entry URI to nsIURL!");
   1.875 +        return false;
   1.876 +    }
   1.877 +
   1.878 +    mJARFile.swap(file);
   1.879 +    mJAREntry.swap(entryURL);
   1.880 +    mCharsetHint = params.charset();
   1.881 +
   1.882 +    return true;
   1.883 +}

mercurial