Coverage Report

Created: 2018-09-25 14:53

/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
}