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