|
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 "nsIProgrammingLanguage.h" |
|
23 #include "mozilla/ipc/URIUtils.h" |
|
24 |
|
25 using namespace mozilla::ipc; |
|
26 |
|
27 static NS_DEFINE_CID(kJARURICID, NS_JARURI_CID); |
|
28 |
|
29 //////////////////////////////////////////////////////////////////////////////// |
|
30 |
|
31 nsJARURI::nsJARURI() |
|
32 { |
|
33 } |
|
34 |
|
35 nsJARURI::~nsJARURI() |
|
36 { |
|
37 } |
|
38 |
|
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 |
|
56 |
|
57 nsresult |
|
58 nsJARURI::Init(const char *charsetHint) |
|
59 { |
|
60 mCharsetHint = charsetHint; |
|
61 return NS_OK; |
|
62 } |
|
63 |
|
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:///") |
|
67 |
|
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"); |
|
77 |
|
78 nsAutoCString fileSpec; |
|
79 nsresult rv = mJARFile->GetSpec(fileSpec); |
|
80 if (NS_FAILED(rv)) return rv; |
|
81 |
|
82 if (aIncludeScheme) |
|
83 result = NS_JAR_SCHEME; |
|
84 else |
|
85 result.Truncate(); |
|
86 |
|
87 result.Append(fileSpec + NS_JAR_DELIMITER + |
|
88 Substring(entrySpec, 5, entrySpec.Length() - 5)); |
|
89 return NS_OK; |
|
90 } |
|
91 |
|
92 nsresult |
|
93 nsJARURI::CreateEntryURL(const nsACString& entryFilename, |
|
94 const char* charset, |
|
95 nsIURL** url) |
|
96 { |
|
97 *url = nullptr; |
|
98 |
|
99 nsCOMPtr<nsIStandardURL> stdURL(do_CreateInstance(NS_STANDARDURL_CONTRACTID)); |
|
100 if (!stdURL) { |
|
101 return NS_ERROR_OUT_OF_MEMORY; |
|
102 } |
|
103 |
|
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 } |
|
111 |
|
112 return CallQueryInterface(stdURL, url); |
|
113 } |
|
114 |
|
115 //////////////////////////////////////////////////////////////////////////////// |
|
116 // nsISerializable methods: |
|
117 |
|
118 NS_IMETHODIMP |
|
119 nsJARURI::Read(nsIObjectInputStream* aInputStream) |
|
120 { |
|
121 nsresult rv; |
|
122 |
|
123 nsCOMPtr<nsISupports> supports; |
|
124 rv = aInputStream->ReadObject(true, getter_AddRefs(supports)); |
|
125 NS_ENSURE_SUCCESS(rv, rv); |
|
126 |
|
127 mJARFile = do_QueryInterface(supports, &rv); |
|
128 NS_ENSURE_SUCCESS(rv, rv); |
|
129 |
|
130 rv = aInputStream->ReadObject(true, getter_AddRefs(supports)); |
|
131 NS_ENSURE_SUCCESS(rv, rv); |
|
132 |
|
133 mJAREntry = do_QueryInterface(supports); |
|
134 NS_ENSURE_SUCCESS(rv, rv); |
|
135 |
|
136 rv = aInputStream->ReadCString(mCharsetHint); |
|
137 return rv; |
|
138 } |
|
139 |
|
140 NS_IMETHODIMP |
|
141 nsJARURI::Write(nsIObjectOutputStream* aOutputStream) |
|
142 { |
|
143 nsresult rv; |
|
144 |
|
145 rv = aOutputStream->WriteCompoundObject(mJARFile, NS_GET_IID(nsIURI), |
|
146 true); |
|
147 NS_ENSURE_SUCCESS(rv, rv); |
|
148 |
|
149 rv = aOutputStream->WriteCompoundObject(mJAREntry, NS_GET_IID(nsIURL), |
|
150 true); |
|
151 NS_ENSURE_SUCCESS(rv, rv); |
|
152 |
|
153 rv = aOutputStream->WriteStringZ(mCharsetHint.get()); |
|
154 return rv; |
|
155 } |
|
156 |
|
157 //////////////////////////////////////////////////////////////////////////////// |
|
158 // nsIClassInfo methods: |
|
159 |
|
160 NS_IMETHODIMP |
|
161 nsJARURI::GetInterfaces(uint32_t *count, nsIID * **array) |
|
162 { |
|
163 *count = 0; |
|
164 *array = nullptr; |
|
165 return NS_OK; |
|
166 } |
|
167 |
|
168 NS_IMETHODIMP |
|
169 nsJARURI::GetHelperForLanguage(uint32_t language, nsISupports **_retval) |
|
170 { |
|
171 *_retval = nullptr; |
|
172 return NS_OK; |
|
173 } |
|
174 |
|
175 NS_IMETHODIMP |
|
176 nsJARURI::GetContractID(char * *aContractID) |
|
177 { |
|
178 *aContractID = nullptr; |
|
179 return NS_OK; |
|
180 } |
|
181 |
|
182 NS_IMETHODIMP |
|
183 nsJARURI::GetClassDescription(char * *aClassDescription) |
|
184 { |
|
185 *aClassDescription = nullptr; |
|
186 return NS_OK; |
|
187 } |
|
188 |
|
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 } |
|
197 |
|
198 NS_IMETHODIMP |
|
199 nsJARURI::GetImplementationLanguage(uint32_t *aImplementationLanguage) |
|
200 { |
|
201 *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; |
|
202 return NS_OK; |
|
203 } |
|
204 |
|
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 } |
|
212 |
|
213 NS_IMETHODIMP |
|
214 nsJARURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) |
|
215 { |
|
216 *aClassIDNoAlloc = kJARURICID; |
|
217 return NS_OK; |
|
218 } |
|
219 |
|
220 //////////////////////////////////////////////////////////////////////////////// |
|
221 // nsIURI methods: |
|
222 |
|
223 NS_IMETHODIMP |
|
224 nsJARURI::GetSpec(nsACString &aSpec) |
|
225 { |
|
226 nsAutoCString entrySpec; |
|
227 mJAREntry->GetSpec(entrySpec); |
|
228 return FormatSpec(entrySpec, aSpec); |
|
229 } |
|
230 |
|
231 NS_IMETHODIMP |
|
232 nsJARURI::GetSpecIgnoringRef(nsACString &aSpec) |
|
233 { |
|
234 nsAutoCString entrySpec; |
|
235 mJAREntry->GetSpecIgnoringRef(entrySpec); |
|
236 return FormatSpec(entrySpec, aSpec); |
|
237 } |
|
238 |
|
239 NS_IMETHODIMP |
|
240 nsJARURI::GetHasRef(bool *result) |
|
241 { |
|
242 return mJAREntry->GetHasRef(result); |
|
243 } |
|
244 |
|
245 NS_IMETHODIMP |
|
246 nsJARURI::SetSpec(const nsACString& aSpec) |
|
247 { |
|
248 return SetSpecWithBase(aSpec, nullptr); |
|
249 } |
|
250 |
|
251 nsresult |
|
252 nsJARURI::SetSpecWithBase(const nsACString &aSpec, nsIURI* aBaseURL) |
|
253 { |
|
254 nsresult rv; |
|
255 |
|
256 nsCOMPtr<nsIIOService> ioServ(do_GetIOService(&rv)); |
|
257 NS_ENSURE_SUCCESS(rv, rv); |
|
258 |
|
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; |
|
265 |
|
266 nsRefPtr<nsJARURI> otherJAR; |
|
267 aBaseURL->QueryInterface(NS_GET_IID(nsJARURI), getter_AddRefs(otherJAR)); |
|
268 NS_ENSURE_TRUE(otherJAR, NS_NOINTERFACE); |
|
269 |
|
270 mJARFile = otherJAR->mJARFile; |
|
271 |
|
272 nsCOMPtr<nsIStandardURL> entry(do_CreateInstance(NS_STANDARDURL_CONTRACTID)); |
|
273 if (!entry) |
|
274 return NS_ERROR_OUT_OF_MEMORY; |
|
275 |
|
276 rv = entry->Init(nsIStandardURL::URLTYPE_NO_AUTHORITY, -1, |
|
277 aSpec, mCharsetHint.get(), otherJAR->mJAREntry); |
|
278 if (NS_FAILED(rv)) |
|
279 return rv; |
|
280 |
|
281 mJAREntry = do_QueryInterface(entry); |
|
282 if (!mJAREntry) |
|
283 return NS_NOINTERFACE; |
|
284 |
|
285 return NS_OK; |
|
286 } |
|
287 |
|
288 NS_ENSURE_TRUE(scheme.EqualsLiteral("jar"), NS_ERROR_MALFORMED_URI); |
|
289 |
|
290 nsACString::const_iterator begin, end; |
|
291 aSpec.BeginReading(begin); |
|
292 aSpec.EndReading(end); |
|
293 |
|
294 while (begin != end && *begin != ':') |
|
295 ++begin; |
|
296 |
|
297 ++begin; // now we're past the "jar:" |
|
298 |
|
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 |
|
306 |
|
307 nsACString::const_iterator delim_begin (begin), |
|
308 delim_end (end); |
|
309 |
|
310 if (!RFindInReadable(NS_JAR_DELIMITER, delim_begin, delim_end)) |
|
311 return NS_ERROR_MALFORMED_URI; |
|
312 |
|
313 rv = ioServ->NewURI(Substring(begin, delim_begin), mCharsetHint.get(), |
|
314 aBaseURL, getter_AddRefs(mJARFile)); |
|
315 if (NS_FAILED(rv)) return rv; |
|
316 |
|
317 NS_TryToSetImmutable(mJARFile); |
|
318 |
|
319 // skip over any extra '/' chars |
|
320 while (*delim_end == '/') |
|
321 ++delim_end; |
|
322 |
|
323 return SetJAREntry(Substring(delim_end, end)); |
|
324 } |
|
325 |
|
326 NS_IMETHODIMP |
|
327 nsJARURI::GetPrePath(nsACString &prePath) |
|
328 { |
|
329 prePath = NS_JAR_SCHEME; |
|
330 return NS_OK; |
|
331 } |
|
332 |
|
333 NS_IMETHODIMP |
|
334 nsJARURI::GetScheme(nsACString &aScheme) |
|
335 { |
|
336 aScheme = "jar"; |
|
337 return NS_OK; |
|
338 } |
|
339 |
|
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 } |
|
346 |
|
347 NS_IMETHODIMP |
|
348 nsJARURI::GetUserPass(nsACString &aUserPass) |
|
349 { |
|
350 return NS_ERROR_FAILURE; |
|
351 } |
|
352 |
|
353 NS_IMETHODIMP |
|
354 nsJARURI::SetUserPass(const nsACString &aUserPass) |
|
355 { |
|
356 return NS_ERROR_FAILURE; |
|
357 } |
|
358 |
|
359 NS_IMETHODIMP |
|
360 nsJARURI::GetUsername(nsACString &aUsername) |
|
361 { |
|
362 return NS_ERROR_FAILURE; |
|
363 } |
|
364 |
|
365 NS_IMETHODIMP |
|
366 nsJARURI::SetUsername(const nsACString &aUsername) |
|
367 { |
|
368 return NS_ERROR_FAILURE; |
|
369 } |
|
370 |
|
371 NS_IMETHODIMP |
|
372 nsJARURI::GetPassword(nsACString &aPassword) |
|
373 { |
|
374 return NS_ERROR_FAILURE; |
|
375 } |
|
376 |
|
377 NS_IMETHODIMP |
|
378 nsJARURI::SetPassword(const nsACString &aPassword) |
|
379 { |
|
380 return NS_ERROR_FAILURE; |
|
381 } |
|
382 |
|
383 NS_IMETHODIMP |
|
384 nsJARURI::GetHostPort(nsACString &aHostPort) |
|
385 { |
|
386 return NS_ERROR_FAILURE; |
|
387 } |
|
388 |
|
389 NS_IMETHODIMP |
|
390 nsJARURI::SetHostPort(const nsACString &aHostPort) |
|
391 { |
|
392 return NS_ERROR_FAILURE; |
|
393 } |
|
394 |
|
395 NS_IMETHODIMP |
|
396 nsJARURI::GetHost(nsACString &aHost) |
|
397 { |
|
398 return NS_ERROR_FAILURE; |
|
399 } |
|
400 |
|
401 NS_IMETHODIMP |
|
402 nsJARURI::SetHost(const nsACString &aHost) |
|
403 { |
|
404 return NS_ERROR_FAILURE; |
|
405 } |
|
406 |
|
407 NS_IMETHODIMP |
|
408 nsJARURI::GetPort(int32_t *aPort) |
|
409 { |
|
410 return NS_ERROR_FAILURE; |
|
411 } |
|
412 |
|
413 NS_IMETHODIMP |
|
414 nsJARURI::SetPort(int32_t aPort) |
|
415 { |
|
416 return NS_ERROR_FAILURE; |
|
417 } |
|
418 |
|
419 NS_IMETHODIMP |
|
420 nsJARURI::GetPath(nsACString &aPath) |
|
421 { |
|
422 nsAutoCString entrySpec; |
|
423 mJAREntry->GetSpec(entrySpec); |
|
424 return FormatSpec(entrySpec, aPath, false); |
|
425 } |
|
426 |
|
427 NS_IMETHODIMP |
|
428 nsJARURI::SetPath(const nsACString &aPath) |
|
429 { |
|
430 return NS_ERROR_FAILURE; |
|
431 } |
|
432 |
|
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 } |
|
439 |
|
440 NS_IMETHODIMP |
|
441 nsJARURI::GetAsciiHost(nsACString &aHost) |
|
442 { |
|
443 return NS_ERROR_FAILURE; |
|
444 } |
|
445 |
|
446 NS_IMETHODIMP |
|
447 nsJARURI::GetOriginCharset(nsACString &aOriginCharset) |
|
448 { |
|
449 aOriginCharset = mCharsetHint; |
|
450 return NS_OK; |
|
451 } |
|
452 |
|
453 NS_IMETHODIMP |
|
454 nsJARURI::Equals(nsIURI *other, bool *result) |
|
455 { |
|
456 return EqualsInternal(other, eHonorRef, result); |
|
457 } |
|
458 |
|
459 NS_IMETHODIMP |
|
460 nsJARURI::EqualsExceptRef(nsIURI *other, bool *result) |
|
461 { |
|
462 return EqualsInternal(other, eIgnoreRef, result); |
|
463 } |
|
464 |
|
465 // Helper method: |
|
466 /* virtual */ nsresult |
|
467 nsJARURI::EqualsInternal(nsIURI *other, |
|
468 nsJARURI::RefHandlingEnum refHandlingMode, |
|
469 bool *result) |
|
470 { |
|
471 *result = false; |
|
472 |
|
473 if (!other) |
|
474 return NS_OK; // not equal |
|
475 |
|
476 nsRefPtr<nsJARURI> otherJAR; |
|
477 other->QueryInterface(NS_GET_IID(nsJARURI), getter_AddRefs(otherJAR)); |
|
478 if (!otherJAR) |
|
479 return NS_OK; // not equal |
|
480 |
|
481 bool equal; |
|
482 nsresult rv = mJARFile->Equals(otherJAR->mJARFile, &equal); |
|
483 if (NS_FAILED(rv) || !equal) { |
|
484 return rv; // not equal |
|
485 } |
|
486 |
|
487 return refHandlingMode == eHonorRef ? |
|
488 mJAREntry->Equals(otherJAR->mJAREntry, result) : |
|
489 mJAREntry->EqualsExceptRef(otherJAR->mJAREntry, result); |
|
490 } |
|
491 |
|
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; |
|
497 |
|
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 } |
|
505 |
|
506 NS_IMETHODIMP |
|
507 nsJARURI::Clone(nsIURI **result) |
|
508 { |
|
509 nsresult rv; |
|
510 |
|
511 nsCOMPtr<nsIJARURI> uri; |
|
512 rv = CloneWithJARFileInternal(mJARFile, eHonorRef, getter_AddRefs(uri)); |
|
513 if (NS_FAILED(rv)) return rv; |
|
514 |
|
515 return CallQueryInterface(uri, result); |
|
516 } |
|
517 |
|
518 NS_IMETHODIMP |
|
519 nsJARURI::CloneIgnoringRef(nsIURI **result) |
|
520 { |
|
521 nsresult rv; |
|
522 |
|
523 nsCOMPtr<nsIJARURI> uri; |
|
524 rv = CloneWithJARFileInternal(mJARFile, eIgnoreRef, getter_AddRefs(uri)); |
|
525 if (NS_FAILED(rv)) return rv; |
|
526 |
|
527 return CallQueryInterface(uri, result); |
|
528 } |
|
529 |
|
530 NS_IMETHODIMP |
|
531 nsJARURI::Resolve(const nsACString &relativePath, nsACString &result) |
|
532 { |
|
533 nsresult rv; |
|
534 |
|
535 nsCOMPtr<nsIIOService> ioServ(do_GetIOService(&rv)); |
|
536 if (NS_FAILED(rv)) |
|
537 return rv; |
|
538 |
|
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 } |
|
546 |
|
547 nsAutoCString resolvedPath; |
|
548 mJAREntry->Resolve(relativePath, resolvedPath); |
|
549 |
|
550 return FormatSpec(resolvedPath, result); |
|
551 } |
|
552 |
|
553 //////////////////////////////////////////////////////////////////////////////// |
|
554 // nsIURL methods: |
|
555 |
|
556 NS_IMETHODIMP |
|
557 nsJARURI::GetFilePath(nsACString& filePath) |
|
558 { |
|
559 return mJAREntry->GetFilePath(filePath); |
|
560 } |
|
561 |
|
562 NS_IMETHODIMP |
|
563 nsJARURI::SetFilePath(const nsACString& filePath) |
|
564 { |
|
565 return mJAREntry->SetFilePath(filePath); |
|
566 } |
|
567 |
|
568 NS_IMETHODIMP |
|
569 nsJARURI::GetQuery(nsACString& query) |
|
570 { |
|
571 return mJAREntry->GetQuery(query); |
|
572 } |
|
573 |
|
574 NS_IMETHODIMP |
|
575 nsJARURI::SetQuery(const nsACString& query) |
|
576 { |
|
577 return mJAREntry->SetQuery(query); |
|
578 } |
|
579 |
|
580 NS_IMETHODIMP |
|
581 nsJARURI::GetRef(nsACString& ref) |
|
582 { |
|
583 return mJAREntry->GetRef(ref); |
|
584 } |
|
585 |
|
586 NS_IMETHODIMP |
|
587 nsJARURI::SetRef(const nsACString& ref) |
|
588 { |
|
589 return mJAREntry->SetRef(ref); |
|
590 } |
|
591 |
|
592 NS_IMETHODIMP |
|
593 nsJARURI::GetDirectory(nsACString& directory) |
|
594 { |
|
595 return mJAREntry->GetDirectory(directory); |
|
596 } |
|
597 |
|
598 NS_IMETHODIMP |
|
599 nsJARURI::SetDirectory(const nsACString& directory) |
|
600 { |
|
601 return mJAREntry->SetDirectory(directory); |
|
602 } |
|
603 |
|
604 NS_IMETHODIMP |
|
605 nsJARURI::GetFileName(nsACString& fileName) |
|
606 { |
|
607 return mJAREntry->GetFileName(fileName); |
|
608 } |
|
609 |
|
610 NS_IMETHODIMP |
|
611 nsJARURI::SetFileName(const nsACString& fileName) |
|
612 { |
|
613 return mJAREntry->SetFileName(fileName); |
|
614 } |
|
615 |
|
616 NS_IMETHODIMP |
|
617 nsJARURI::GetFileBaseName(nsACString& fileBaseName) |
|
618 { |
|
619 return mJAREntry->GetFileBaseName(fileBaseName); |
|
620 } |
|
621 |
|
622 NS_IMETHODIMP |
|
623 nsJARURI::SetFileBaseName(const nsACString& fileBaseName) |
|
624 { |
|
625 return mJAREntry->SetFileBaseName(fileBaseName); |
|
626 } |
|
627 |
|
628 NS_IMETHODIMP |
|
629 nsJARURI::GetFileExtension(nsACString& fileExtension) |
|
630 { |
|
631 return mJAREntry->GetFileExtension(fileExtension); |
|
632 } |
|
633 |
|
634 NS_IMETHODIMP |
|
635 nsJARURI::SetFileExtension(const nsACString& fileExtension) |
|
636 { |
|
637 return mJAREntry->SetFileExtension(fileExtension); |
|
638 } |
|
639 |
|
640 NS_IMETHODIMP |
|
641 nsJARURI::GetCommonBaseSpec(nsIURI* uriToCompare, nsACString& commonSpec) |
|
642 { |
|
643 commonSpec.Truncate(); |
|
644 |
|
645 NS_ENSURE_ARG_POINTER(uriToCompare); |
|
646 |
|
647 commonSpec.Truncate(); |
|
648 nsCOMPtr<nsIJARURI> otherJARURI(do_QueryInterface(uriToCompare)); |
|
649 if (!otherJARURI) { |
|
650 // Nothing in common |
|
651 return NS_OK; |
|
652 } |
|
653 |
|
654 nsCOMPtr<nsIURI> otherJARFile; |
|
655 nsresult rv = otherJARURI->GetJARFile(getter_AddRefs(otherJARFile)); |
|
656 if (NS_FAILED(rv)) return rv; |
|
657 |
|
658 bool equal; |
|
659 rv = mJARFile->Equals(otherJARFile, &equal); |
|
660 if (NS_FAILED(rv)) return rv; |
|
661 |
|
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; |
|
672 |
|
673 commonSpec = NS_JAR_SCHEME + common; |
|
674 return NS_OK; |
|
675 |
|
676 } |
|
677 |
|
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; |
|
682 |
|
683 nsAutoCString otherCharset; |
|
684 rv = uriToCompare->GetOriginCharset(otherCharset); |
|
685 if (NS_FAILED(rv)) return rv; |
|
686 |
|
687 nsCOMPtr<nsIURL> url; |
|
688 rv = CreateEntryURL(otherEntry, otherCharset.get(), getter_AddRefs(url)); |
|
689 if (NS_FAILED(rv)) return rv; |
|
690 |
|
691 nsAutoCString common; |
|
692 rv = mJAREntry->GetCommonBaseSpec(url, common); |
|
693 if (NS_FAILED(rv)) return rv; |
|
694 |
|
695 rv = FormatSpec(common, commonSpec); |
|
696 return rv; |
|
697 } |
|
698 |
|
699 NS_IMETHODIMP |
|
700 nsJARURI::GetRelativeSpec(nsIURI* uriToCompare, nsACString& relativeSpec) |
|
701 { |
|
702 GetSpec(relativeSpec); |
|
703 |
|
704 NS_ENSURE_ARG_POINTER(uriToCompare); |
|
705 |
|
706 nsCOMPtr<nsIJARURI> otherJARURI(do_QueryInterface(uriToCompare)); |
|
707 if (!otherJARURI) { |
|
708 // Nothing in common |
|
709 return NS_OK; |
|
710 } |
|
711 |
|
712 nsCOMPtr<nsIURI> otherJARFile; |
|
713 nsresult rv = otherJARURI->GetJARFile(getter_AddRefs(otherJARFile)); |
|
714 if (NS_FAILED(rv)) return rv; |
|
715 |
|
716 bool equal; |
|
717 rv = mJARFile->Equals(otherJARFile, &equal); |
|
718 if (NS_FAILED(rv)) return rv; |
|
719 |
|
720 if (!equal) { |
|
721 // We live in different JAR files. Nothing in common. |
|
722 return rv; |
|
723 } |
|
724 |
|
725 // Same JAR file. Compare the JAREntrys |
|
726 nsAutoCString otherEntry; |
|
727 rv = otherJARURI->GetJAREntry(otherEntry); |
|
728 if (NS_FAILED(rv)) return rv; |
|
729 |
|
730 nsAutoCString otherCharset; |
|
731 rv = uriToCompare->GetOriginCharset(otherCharset); |
|
732 if (NS_FAILED(rv)) return rv; |
|
733 |
|
734 nsCOMPtr<nsIURL> url; |
|
735 rv = CreateEntryURL(otherEntry, otherCharset.get(), getter_AddRefs(url)); |
|
736 if (NS_FAILED(rv)) return rv; |
|
737 |
|
738 nsAutoCString relativeEntrySpec; |
|
739 rv = mJAREntry->GetRelativeSpec(url, relativeEntrySpec); |
|
740 if (NS_FAILED(rv)) return rv; |
|
741 |
|
742 if (!StringBeginsWith(relativeEntrySpec, NS_BOGUS_ENTRY_SCHEME)) { |
|
743 // An actual relative spec! |
|
744 relativeSpec = relativeEntrySpec; |
|
745 } |
|
746 return rv; |
|
747 } |
|
748 |
|
749 //////////////////////////////////////////////////////////////////////////////// |
|
750 // nsIJARURI methods: |
|
751 |
|
752 NS_IMETHODIMP |
|
753 nsJARURI::GetJARFile(nsIURI* *jarFile) |
|
754 { |
|
755 return GetInnerURI(jarFile); |
|
756 } |
|
757 |
|
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 } |
|
768 |
|
769 NS_IMETHODIMP |
|
770 nsJARURI::SetJAREntry(const nsACString &entryPath) |
|
771 { |
|
772 return CreateEntryURL(entryPath, mCharsetHint.get(), |
|
773 getter_AddRefs(mJAREntry)); |
|
774 } |
|
775 |
|
776 NS_IMETHODIMP |
|
777 nsJARURI::CloneWithJARFile(nsIURI *jarFile, nsIJARURI **result) |
|
778 { |
|
779 return CloneWithJARFileInternal(jarFile, eHonorRef, result); |
|
780 } |
|
781 |
|
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 } |
|
790 |
|
791 nsresult rv; |
|
792 |
|
793 nsCOMPtr<nsIURI> newJARFile; |
|
794 rv = jarFile->Clone(getter_AddRefs(newJARFile)); |
|
795 if (NS_FAILED(rv)) return rv; |
|
796 |
|
797 NS_TryToSetImmutable(newJARFile); |
|
798 |
|
799 nsCOMPtr<nsIURI> newJAREntryURI; |
|
800 rv = refHandlingMode == eHonorRef ? |
|
801 mJAREntry->Clone(getter_AddRefs(newJAREntryURI)) : |
|
802 mJAREntry->CloneIgnoringRef(getter_AddRefs(newJAREntryURI)); |
|
803 |
|
804 if (NS_FAILED(rv)) return rv; |
|
805 |
|
806 nsCOMPtr<nsIURL> newJAREntry(do_QueryInterface(newJAREntryURI)); |
|
807 NS_ASSERTION(newJAREntry, "This had better QI to nsIURL!"); |
|
808 |
|
809 nsJARURI* uri = new nsJARURI(); |
|
810 NS_ADDREF(uri); |
|
811 uri->mJARFile = newJARFile; |
|
812 uri->mJAREntry = newJAREntry; |
|
813 *result = uri; |
|
814 |
|
815 return NS_OK; |
|
816 } |
|
817 |
|
818 //////////////////////////////////////////////////////////////////////////////// |
|
819 |
|
820 NS_IMETHODIMP |
|
821 nsJARURI::GetInnerURI(nsIURI **uri) |
|
822 { |
|
823 return NS_EnsureSafeToReturn(mJARFile, uri); |
|
824 } |
|
825 |
|
826 NS_IMETHODIMP |
|
827 nsJARURI::GetInnermostURI(nsIURI** uri) |
|
828 { |
|
829 return NS_ImplGetInnermostURI(this, uri); |
|
830 } |
|
831 |
|
832 //////////////////////////////////////////////////////////////////////////////// |
|
833 // nsIIPCSerializableURI methods: |
|
834 |
|
835 void |
|
836 nsJARURI::Serialize(URIParams& aParams) |
|
837 { |
|
838 JARURIParams params; |
|
839 |
|
840 SerializeURI(mJARFile, params.jarFile()); |
|
841 SerializeURI(mJAREntry, params.jarEntry()); |
|
842 params.charset() = mCharsetHint; |
|
843 |
|
844 aParams = params; |
|
845 } |
|
846 |
|
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 } |
|
854 |
|
855 const JARURIParams& params = aParams.get_JARURIParams(); |
|
856 |
|
857 nsCOMPtr<nsIURI> file = DeserializeURI(params.jarFile()); |
|
858 if (!file) { |
|
859 NS_ERROR("Couldn't deserialize jar file URI!"); |
|
860 return false; |
|
861 } |
|
862 |
|
863 nsCOMPtr<nsIURI> entry = DeserializeURI(params.jarEntry()); |
|
864 if (!entry) { |
|
865 NS_ERROR("Couldn't deserialize jar entry URI!"); |
|
866 return false; |
|
867 } |
|
868 |
|
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 } |
|
874 |
|
875 mJARFile.swap(file); |
|
876 mJAREntry.swap(entryURL); |
|
877 mCharsetHint = params.charset(); |
|
878 |
|
879 return true; |
|
880 } |