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