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

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

mercurial