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