1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim:set ts=4 sw=4 sts=4 et cin: */
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 : * Bradley Baetz <bbaetz@student.usyd.edu.au>
25 : * Malcolm Smith <malsmith@cs.rmit.edu.au>
26 : * Taras Glek <tglek@mozilla.com>
27 : *
28 : * Alternatively, the contents of this file may be used under the terms of
29 : * either the GNU General Public License Version 2 or later (the "GPL"), or
30 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 : * in which case the provisions of the GPL or the LGPL are applicable instead
32 : * of those above. If you wish to allow use of your version of this file only
33 : * under the terms of either the GPL or the LGPL, and not to allow others to
34 : * use your version of this file under the terms of the MPL, indicate your
35 : * decision by deleting the provisions above and replace them with the notice
36 : * and other provisions required by the GPL or the LGPL. If you do not delete
37 : * the provisions above, a recipient may use your version of this file under
38 : * the terms of any one of the MPL, the GPL or the LGPL.
39 : *
40 : * ***** END LICENSE BLOCK ***** */
41 :
42 : #ifndef nsNetUtil_h__
43 : #define nsNetUtil_h__
44 :
45 : #include "nsNetError.h"
46 : #include "nsNetCID.h"
47 : #include "nsStringGlue.h"
48 : #include "nsMemory.h"
49 : #include "nsCOMPtr.h"
50 : #include "prio.h" // for read/write flags, permissions, etc.
51 : #include "nsHashKeys.h"
52 :
53 : #include "plstr.h"
54 : #include "nsIURI.h"
55 : #include "nsIStandardURL.h"
56 : #include "nsIURLParser.h"
57 : #include "nsIUUIDGenerator.h"
58 : #include "nsIInputStream.h"
59 : #include "nsIOutputStream.h"
60 : #include "nsISafeOutputStream.h"
61 : #include "nsIStreamListener.h"
62 : #include "nsIRequestObserverProxy.h"
63 : #include "nsISimpleStreamListener.h"
64 : #include "nsILoadGroup.h"
65 : #include "nsIInterfaceRequestor.h"
66 : #include "nsIInterfaceRequestorUtils.h"
67 : #include "nsIIOService.h"
68 : #include "nsIServiceManager.h"
69 : #include "nsIChannel.h"
70 : #include "nsChannelProperties.h"
71 : #include "nsIInputStreamChannel.h"
72 : #include "nsITransport.h"
73 : #include "nsIStreamTransportService.h"
74 : #include "nsIHttpChannel.h"
75 : #include "nsIDownloader.h"
76 : #include "nsIStreamLoader.h"
77 : #include "nsIUnicharStreamLoader.h"
78 : #include "nsIPipe.h"
79 : #include "nsIProtocolHandler.h"
80 : #include "nsIFileProtocolHandler.h"
81 : #include "nsIStringStream.h"
82 : #include "nsILocalFile.h"
83 : #include "nsIFileStreams.h"
84 : #include "nsIFileURL.h"
85 : #include "nsIProtocolProxyService.h"
86 : #include "nsIProxyInfo.h"
87 : #include "nsIFileStreams.h"
88 : #include "nsIBufferedStreams.h"
89 : #include "nsIInputStreamPump.h"
90 : #include "nsIAsyncStreamCopier.h"
91 : #include "nsIPersistentProperties2.h"
92 : #include "nsISyncStreamListener.h"
93 : #include "nsInterfaceRequestorAgg.h"
94 : #include "nsINetUtil.h"
95 : #include "nsIURIWithPrincipal.h"
96 : #include "nsIAuthPrompt.h"
97 : #include "nsIAuthPrompt2.h"
98 : #include "nsIAuthPromptAdapterFactory.h"
99 : #include "nsComponentManagerUtils.h"
100 : #include "nsServiceManagerUtils.h"
101 : #include "nsINestedURI.h"
102 : #include "nsIMutable.h"
103 : #include "nsIPropertyBag2.h"
104 : #include "nsIWritablePropertyBag2.h"
105 : #include "nsIIDNService.h"
106 : #include "nsIChannelEventSink.h"
107 : #include "nsIChannelPolicy.h"
108 : #include "nsISocketProviderService.h"
109 : #include "nsISocketProvider.h"
110 : #include "nsIRedirectChannelRegistrar.h"
111 : #include "nsIMIMEHeaderParam.h"
112 : #include "mozilla/Services.h"
113 :
114 : #ifdef MOZILLA_INTERNAL_API
115 :
116 : inline already_AddRefed<nsIIOService>
117 233673 : do_GetIOService(nsresult* error = 0)
118 : {
119 233673 : already_AddRefed<nsIIOService> ret = mozilla::services::GetIOService();
120 233673 : if (error)
121 233645 : *error = ret.get() ? NS_OK : NS_ERROR_FAILURE;
122 : return ret;
123 : }
124 :
125 : inline already_AddRefed<nsINetUtil>
126 107308 : do_GetNetUtil(nsresult *error = 0)
127 : {
128 214616 : nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
129 107308 : already_AddRefed<nsINetUtil> ret = nsnull;
130 107308 : if (io)
131 107308 : CallQueryInterface(io, &ret.mRawPtr);
132 :
133 107308 : if (error)
134 107307 : *error = ret.get() ? NS_OK : NS_ERROR_FAILURE;
135 : return ret;
136 : }
137 : #else
138 : // Helper, to simplify getting the I/O service.
139 : inline const nsGetServiceByContractIDWithError
140 275 : do_GetIOService(nsresult* error = 0)
141 : {
142 275 : return nsGetServiceByContractIDWithError(NS_IOSERVICE_CONTRACTID, error);
143 : }
144 :
145 : // An alias to do_GetIOService
146 : inline const nsGetServiceByContractIDWithError
147 : do_GetNetUtil(nsresult* error = 0)
148 : {
149 : return do_GetIOService(error);
150 : }
151 : #endif
152 :
153 : // private little helper function... don't call this directly!
154 : inline nsresult
155 161423 : net_EnsureIOService(nsIIOService **ios, nsCOMPtr<nsIIOService> &grip)
156 : {
157 161423 : nsresult rv = NS_OK;
158 161423 : if (!*ios) {
159 160104 : grip = do_GetIOService(&rv);
160 160104 : *ios = grip;
161 : }
162 161423 : return rv;
163 : }
164 :
165 : inline nsresult
166 136821 : NS_NewURI(nsIURI **result,
167 : const nsACString &spec,
168 : const char *charset = nsnull,
169 : nsIURI *baseURI = nsnull,
170 : nsIIOService *ioService = nsnull) // pass in nsIIOService to optimize callers
171 : {
172 : nsresult rv;
173 273642 : nsCOMPtr<nsIIOService> grip;
174 136821 : rv = net_EnsureIOService(&ioService, grip);
175 136821 : if (ioService)
176 136821 : rv = ioService->NewURI(spec, charset, baseURI, result);
177 136821 : return rv;
178 : }
179 :
180 : inline nsresult
181 338 : NS_NewURI(nsIURI* *result,
182 : const nsAString& spec,
183 : const char *charset = nsnull,
184 : nsIURI* baseURI = nsnull,
185 : nsIIOService* ioService = nsnull) // pass in nsIIOService to optimize callers
186 : {
187 338 : return NS_NewURI(result, NS_ConvertUTF16toUTF8(spec), charset, baseURI, ioService);
188 : }
189 :
190 : inline nsresult
191 109505 : NS_NewURI(nsIURI* *result,
192 : const char *spec,
193 : nsIURI* baseURI = nsnull,
194 : nsIIOService* ioService = nsnull) // pass in nsIIOService to optimize callers
195 : {
196 109505 : return NS_NewURI(result, nsDependentCString(spec), nsnull, baseURI, ioService);
197 : }
198 :
199 : inline nsresult
200 333 : NS_NewFileURI(nsIURI* *result,
201 : nsIFile* spec,
202 : nsIIOService* ioService = nsnull) // pass in nsIIOService to optimize callers
203 : {
204 : nsresult rv;
205 666 : nsCOMPtr<nsIIOService> grip;
206 333 : rv = net_EnsureIOService(&ioService, grip);
207 333 : if (ioService)
208 333 : rv = ioService->NewFileURI(spec, result);
209 333 : return rv;
210 : }
211 :
212 : inline nsresult
213 4032 : NS_NewChannel(nsIChannel **result,
214 : nsIURI *uri,
215 : nsIIOService *ioService = nsnull, // pass in nsIIOService to optimize callers
216 : nsILoadGroup *loadGroup = nsnull,
217 : nsIInterfaceRequestor *callbacks = nsnull,
218 : PRUint32 loadFlags = nsIRequest::LOAD_NORMAL,
219 : nsIChannelPolicy *channelPolicy = nsnull)
220 : {
221 : nsresult rv;
222 8064 : nsCOMPtr<nsIIOService> grip;
223 4032 : rv = net_EnsureIOService(&ioService, grip);
224 4032 : if (ioService) {
225 8064 : nsCOMPtr<nsIChannel> chan;
226 4032 : rv = ioService->NewChannelFromURI(uri, getter_AddRefs(chan));
227 4032 : if (NS_SUCCEEDED(rv)) {
228 4028 : if (loadGroup)
229 0 : rv |= chan->SetLoadGroup(loadGroup);
230 4028 : if (callbacks)
231 483 : rv |= chan->SetNotificationCallbacks(callbacks);
232 4028 : if (loadFlags != nsIRequest::LOAD_NORMAL) {
233 : // Retain the LOAD_REPLACE load flag if set.
234 1064 : nsLoadFlags normalLoadFlags = 0;
235 1064 : chan->GetLoadFlags(&normalLoadFlags);
236 1064 : rv |= chan->SetLoadFlags(loadFlags |
237 : (normalLoadFlags &
238 1064 : nsIChannel::LOAD_REPLACE));
239 : }
240 4028 : if (channelPolicy) {
241 0 : nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(chan);
242 0 : if (props) {
243 0 : props->SetPropertyAsInterface(NS_CHANNEL_PROP_CHANNEL_POLICY,
244 0 : channelPolicy);
245 : }
246 : }
247 4028 : if (NS_SUCCEEDED(rv))
248 4028 : chan.forget(result);
249 : }
250 : }
251 4032 : return rv;
252 : }
253 :
254 : // Use this function with CAUTION. It creates a stream that blocks when you
255 : // Read() from it and blocking the UI thread is a bad idea. If you don't want
256 : // to implement a full blown asynchronous consumer (via nsIStreamListener) look
257 : // at nsIStreamLoader instead.
258 : inline nsresult
259 1 : NS_OpenURI(nsIInputStream **result,
260 : nsIURI *uri,
261 : nsIIOService *ioService = nsnull, // pass in nsIIOService to optimize callers
262 : nsILoadGroup *loadGroup = nsnull,
263 : nsIInterfaceRequestor *callbacks = nsnull,
264 : PRUint32 loadFlags = nsIRequest::LOAD_NORMAL,
265 : nsIChannel **channelOut = nsnull)
266 : {
267 : nsresult rv;
268 2 : nsCOMPtr<nsIChannel> channel;
269 1 : rv = NS_NewChannel(getter_AddRefs(channel), uri, ioService,
270 1 : loadGroup, callbacks, loadFlags);
271 1 : if (NS_SUCCEEDED(rv)) {
272 : nsIInputStream *stream;
273 1 : rv = channel->Open(&stream);
274 1 : if (NS_SUCCEEDED(rv)) {
275 1 : *result = stream;
276 1 : if (channelOut) {
277 0 : *channelOut = nsnull;
278 0 : channel.swap(*channelOut);
279 : }
280 : }
281 : }
282 1 : return rv;
283 : }
284 :
285 : inline nsresult
286 5 : NS_OpenURI(nsIStreamListener *listener,
287 : nsISupports *context,
288 : nsIURI *uri,
289 : nsIIOService *ioService = nsnull, // pass in nsIIOService to optimize callers
290 : nsILoadGroup *loadGroup = nsnull,
291 : nsIInterfaceRequestor *callbacks = nsnull,
292 : PRUint32 loadFlags = nsIRequest::LOAD_NORMAL)
293 : {
294 : nsresult rv;
295 10 : nsCOMPtr<nsIChannel> channel;
296 5 : rv = NS_NewChannel(getter_AddRefs(channel), uri, ioService,
297 5 : loadGroup, callbacks, loadFlags);
298 5 : if (NS_SUCCEEDED(rv))
299 5 : rv = channel->AsyncOpen(listener, context);
300 5 : return rv;
301 : }
302 :
303 : inline nsresult
304 : NS_MakeAbsoluteURI(nsACString &result,
305 : const nsACString &spec,
306 : nsIURI *baseURI,
307 : nsIIOService *unused = nsnull)
308 : {
309 : nsresult rv;
310 : if (!baseURI) {
311 : NS_WARNING("It doesn't make sense to not supply a base URI");
312 : result = spec;
313 : rv = NS_OK;
314 : }
315 : else if (spec.IsEmpty())
316 : rv = baseURI->GetSpec(result);
317 : else
318 : rv = baseURI->Resolve(spec, result);
319 : return rv;
320 : }
321 :
322 : inline nsresult
323 : NS_MakeAbsoluteURI(char **result,
324 : const char *spec,
325 : nsIURI *baseURI,
326 : nsIIOService *unused = nsnull)
327 : {
328 : nsresult rv;
329 : nsCAutoString resultBuf;
330 : rv = NS_MakeAbsoluteURI(resultBuf, nsDependentCString(spec), baseURI);
331 : if (NS_SUCCEEDED(rv)) {
332 : *result = ToNewCString(resultBuf);
333 : if (!*result)
334 : rv = NS_ERROR_OUT_OF_MEMORY;
335 : }
336 : return rv;
337 : }
338 :
339 : inline nsresult
340 0 : NS_MakeAbsoluteURI(nsAString &result,
341 : const nsAString &spec,
342 : nsIURI *baseURI,
343 : nsIIOService *unused = nsnull)
344 : {
345 : nsresult rv;
346 0 : if (!baseURI) {
347 0 : NS_WARNING("It doesn't make sense to not supply a base URI");
348 0 : result = spec;
349 0 : rv = NS_OK;
350 : }
351 : else {
352 0 : nsCAutoString resultBuf;
353 0 : if (spec.IsEmpty())
354 0 : rv = baseURI->GetSpec(resultBuf);
355 : else
356 0 : rv = baseURI->Resolve(NS_ConvertUTF16toUTF8(spec), resultBuf);
357 0 : if (NS_SUCCEEDED(rv))
358 0 : CopyUTF8toUTF16(resultBuf, result);
359 : }
360 0 : return rv;
361 : }
362 :
363 : /**
364 : * This function is a helper function to get a scheme's default port.
365 : */
366 : inline PRInt32
367 19 : NS_GetDefaultPort(const char *scheme,
368 : nsIIOService* ioService = nsnull)
369 : {
370 : nsresult rv;
371 :
372 38 : nsCOMPtr<nsIIOService> grip;
373 19 : net_EnsureIOService(&ioService, grip);
374 19 : if (!ioService)
375 0 : return -1;
376 :
377 38 : nsCOMPtr<nsIProtocolHandler> handler;
378 19 : rv = ioService->GetProtocolHandler(scheme, getter_AddRefs(handler));
379 19 : if (NS_FAILED(rv))
380 0 : return -1;
381 : PRInt32 port;
382 19 : rv = handler->GetDefaultPort(&port);
383 19 : return NS_SUCCEEDED(rv) ? port : -1;
384 : }
385 :
386 : /**
387 : * This function is a helper function to apply the ToAscii conversion
388 : * to a string
389 : */
390 : inline bool
391 : NS_StringToACE(const nsACString &idn, nsACString &result)
392 : {
393 : nsCOMPtr<nsIIDNService> idnSrv = do_GetService(NS_IDNSERVICE_CONTRACTID);
394 : if (!idnSrv)
395 : return false;
396 : nsresult rv = idnSrv->ConvertUTF8toACE(idn, result);
397 : if (NS_FAILED(rv))
398 : return false;
399 :
400 : return true;
401 : }
402 :
403 : /**
404 : * This function is a helper function to get a protocol's default port if the
405 : * URI does not specify a port explicitly. Returns -1 if this protocol has no
406 : * concept of ports or if there was an error getting the port.
407 : */
408 : inline PRInt32
409 2914 : NS_GetRealPort(nsIURI* aURI,
410 : nsIIOService* ioService = nsnull) // pass in nsIIOService to optimize callers
411 : {
412 : PRInt32 port;
413 2914 : nsresult rv = aURI->GetPort(&port);
414 2914 : if (NS_FAILED(rv))
415 2834 : return -1;
416 :
417 80 : if (port != -1)
418 61 : return port; // explicitly specified
419 :
420 : // Otherwise, we have to get the default port from the protocol handler
421 :
422 : // Need the scheme first
423 38 : nsCAutoString scheme;
424 19 : rv = aURI->GetScheme(scheme);
425 19 : if (NS_FAILED(rv))
426 0 : return -1;
427 :
428 19 : return NS_GetDefaultPort(scheme.get());
429 : }
430 :
431 : inline nsresult
432 1338 : NS_NewInputStreamChannel(nsIChannel **result,
433 : nsIURI *uri,
434 : nsIInputStream *stream,
435 : const nsACString &contentType,
436 : const nsACString *contentCharset)
437 : {
438 : nsresult rv;
439 : nsCOMPtr<nsIInputStreamChannel> isc =
440 2676 : do_CreateInstance(NS_INPUTSTREAMCHANNEL_CONTRACTID, &rv);
441 1338 : if (NS_FAILED(rv))
442 0 : return rv;
443 1338 : rv |= isc->SetURI(uri);
444 1338 : rv |= isc->SetContentStream(stream);
445 1338 : if (NS_FAILED(rv))
446 0 : return rv;
447 2676 : nsCOMPtr<nsIChannel> chan = do_QueryInterface(isc, &rv);
448 1338 : if (NS_FAILED(rv))
449 0 : return rv;
450 1338 : if (!contentType.IsEmpty())
451 1334 : rv |= chan->SetContentType(contentType);
452 1338 : if (contentCharset && !contentCharset->IsEmpty())
453 2 : rv |= chan->SetContentCharset(*contentCharset);
454 1338 : if (NS_SUCCEEDED(rv)) {
455 1338 : *result = nsnull;
456 1338 : chan.swap(*result);
457 : }
458 1338 : return rv;
459 : }
460 :
461 : inline nsresult
462 767 : NS_NewInputStreamChannel(nsIChannel **result,
463 : nsIURI *uri,
464 : nsIInputStream *stream,
465 2 : const nsACString &contentType = EmptyCString())
466 : {
467 767 : return NS_NewInputStreamChannel(result, uri, stream, contentType, nsnull);
468 : }
469 :
470 : inline nsresult
471 2 : NS_NewInputStreamChannel(nsIChannel **result,
472 : nsIURI *uri,
473 : nsIInputStream *stream,
474 : const nsACString &contentType,
475 : const nsACString &contentCharset)
476 : {
477 : return NS_NewInputStreamChannel(result, uri, stream, contentType,
478 2 : &contentCharset);
479 : }
480 :
481 : inline nsresult
482 5 : NS_NewInputStreamPump(nsIInputStreamPump **result,
483 : nsIInputStream *stream,
484 : PRInt64 streamPos = PRInt64(-1),
485 : PRInt64 streamLen = PRInt64(-1),
486 : PRUint32 segsize = 0,
487 : PRUint32 segcount = 0,
488 : bool closeWhenDone = false)
489 : {
490 : nsresult rv;
491 : nsCOMPtr<nsIInputStreamPump> pump =
492 10 : do_CreateInstance(NS_INPUTSTREAMPUMP_CONTRACTID, &rv);
493 5 : if (NS_SUCCEEDED(rv)) {
494 5 : rv = pump->Init(stream, streamPos, streamLen,
495 5 : segsize, segcount, closeWhenDone);
496 5 : if (NS_SUCCEEDED(rv)) {
497 5 : *result = nsnull;
498 5 : pump.swap(*result);
499 : }
500 : }
501 5 : return rv;
502 : }
503 :
504 : // NOTE: you will need to specify whether or not your streams are buffered
505 : // (i.e., do they implement ReadSegments/WriteSegments). the default
506 : // assumption of TRUE for both streams might not be right for you!
507 : inline nsresult
508 0 : NS_NewAsyncStreamCopier(nsIAsyncStreamCopier **result,
509 : nsIInputStream *source,
510 : nsIOutputStream *sink,
511 : nsIEventTarget *target,
512 : bool sourceBuffered = true,
513 : bool sinkBuffered = true,
514 : PRUint32 chunkSize = 0,
515 : bool closeSource = true,
516 : bool closeSink = true)
517 : {
518 : nsresult rv;
519 : nsCOMPtr<nsIAsyncStreamCopier> copier =
520 0 : do_CreateInstance(NS_ASYNCSTREAMCOPIER_CONTRACTID, &rv);
521 0 : if (NS_SUCCEEDED(rv)) {
522 0 : rv = copier->Init(source, sink, target, sourceBuffered, sinkBuffered,
523 0 : chunkSize, closeSource, closeSink);
524 0 : if (NS_SUCCEEDED(rv)) {
525 0 : *result = nsnull;
526 0 : copier.swap(*result);
527 : }
528 : }
529 0 : return rv;
530 : }
531 :
532 : inline nsresult
533 1404 : NS_NewLoadGroup(nsILoadGroup **result,
534 : nsIRequestObserver *obs)
535 : {
536 : nsresult rv;
537 : nsCOMPtr<nsILoadGroup> group =
538 2808 : do_CreateInstance(NS_LOADGROUP_CONTRACTID, &rv);
539 1404 : if (NS_SUCCEEDED(rv)) {
540 1404 : rv = group->SetGroupObserver(obs);
541 1404 : if (NS_SUCCEEDED(rv)) {
542 1404 : *result = nsnull;
543 1404 : group.swap(*result);
544 : }
545 : }
546 1404 : return rv;
547 : }
548 :
549 : inline nsresult
550 1 : NS_NewDownloader(nsIStreamListener **result,
551 : nsIDownloadObserver *observer,
552 : nsIFile *downloadLocation = nsnull)
553 : {
554 : nsresult rv;
555 : nsCOMPtr<nsIDownloader> downloader =
556 2 : do_CreateInstance(NS_DOWNLOADER_CONTRACTID, &rv);
557 1 : if (NS_SUCCEEDED(rv)) {
558 1 : rv = downloader->Init(observer, downloadLocation);
559 1 : if (NS_SUCCEEDED(rv))
560 1 : NS_ADDREF(*result = downloader);
561 : }
562 1 : return rv;
563 : }
564 :
565 : inline nsresult
566 0 : NS_NewStreamLoader(nsIStreamLoader **result,
567 : nsIStreamLoaderObserver *observer)
568 : {
569 : nsresult rv;
570 : nsCOMPtr<nsIStreamLoader> loader =
571 0 : do_CreateInstance(NS_STREAMLOADER_CONTRACTID, &rv);
572 0 : if (NS_SUCCEEDED(rv)) {
573 0 : rv = loader->Init(observer);
574 0 : if (NS_SUCCEEDED(rv)) {
575 0 : *result = nsnull;
576 0 : loader.swap(*result);
577 : }
578 : }
579 0 : return rv;
580 : }
581 :
582 : inline nsresult
583 0 : NS_NewStreamLoader(nsIStreamLoader **result,
584 : nsIURI *uri,
585 : nsIStreamLoaderObserver *observer,
586 : nsISupports *context = nsnull,
587 : nsILoadGroup *loadGroup = nsnull,
588 : nsIInterfaceRequestor *callbacks = nsnull,
589 : PRUint32 loadFlags = nsIRequest::LOAD_NORMAL,
590 : nsIURI *referrer = nsnull)
591 : {
592 : nsresult rv;
593 0 : nsCOMPtr<nsIChannel> channel;
594 0 : rv = NS_NewChannel(getter_AddRefs(channel),
595 : uri,
596 : nsnull,
597 : loadGroup,
598 : callbacks,
599 0 : loadFlags);
600 0 : if (NS_SUCCEEDED(rv)) {
601 0 : nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
602 0 : if (httpChannel)
603 0 : httpChannel->SetReferrer(referrer);
604 0 : rv = NS_NewStreamLoader(result, observer);
605 0 : if (NS_SUCCEEDED(rv))
606 0 : rv = channel->AsyncOpen(*result, context);
607 : }
608 0 : return rv;
609 : }
610 :
611 : inline nsresult
612 0 : NS_NewUnicharStreamLoader(nsIUnicharStreamLoader **result,
613 : nsIUnicharStreamLoaderObserver *observer)
614 : {
615 : nsresult rv;
616 : nsCOMPtr<nsIUnicharStreamLoader> loader =
617 0 : do_CreateInstance(NS_UNICHARSTREAMLOADER_CONTRACTID, &rv);
618 0 : if (NS_SUCCEEDED(rv)) {
619 0 : rv = loader->Init(observer);
620 0 : if (NS_SUCCEEDED(rv)) {
621 0 : *result = nsnull;
622 0 : loader.swap(*result);
623 : }
624 : }
625 0 : return rv;
626 : }
627 :
628 : inline nsresult
629 18 : NS_NewSyncStreamListener(nsIStreamListener **result,
630 : nsIInputStream **stream)
631 : {
632 : nsresult rv;
633 : nsCOMPtr<nsISyncStreamListener> listener =
634 36 : do_CreateInstance(NS_SYNCSTREAMLISTENER_CONTRACTID, &rv);
635 18 : if (NS_SUCCEEDED(rv)) {
636 18 : rv = listener->GetInputStream(stream);
637 18 : if (NS_SUCCEEDED(rv))
638 18 : NS_ADDREF(*result = listener); // cannot use nsCOMPtr::swap
639 : }
640 18 : return rv;
641 : }
642 :
643 : /**
644 : * Implement the nsIChannel::Open(nsIInputStream**) method using the channel's
645 : * AsyncOpen method.
646 : *
647 : * NOTE: Reading from the returned nsIInputStream may spin the current
648 : * thread's event queue, which could result in any event being processed.
649 : */
650 : inline nsresult
651 18 : NS_ImplementChannelOpen(nsIChannel *channel,
652 : nsIInputStream **result)
653 : {
654 36 : nsCOMPtr<nsIStreamListener> listener;
655 36 : nsCOMPtr<nsIInputStream> stream;
656 18 : nsresult rv = NS_NewSyncStreamListener(getter_AddRefs(listener),
657 36 : getter_AddRefs(stream));
658 18 : if (NS_SUCCEEDED(rv)) {
659 18 : rv = channel->AsyncOpen(listener, nsnull);
660 18 : if (NS_SUCCEEDED(rv)) {
661 : PRUint32 n;
662 : // block until the initial response is received or an error occurs.
663 18 : rv = stream->Available(&n);
664 18 : if (NS_SUCCEEDED(rv)) {
665 18 : *result = nsnull;
666 18 : stream.swap(*result);
667 : }
668 : }
669 : }
670 18 : return rv;
671 : }
672 :
673 : inline nsresult
674 399 : NS_NewRequestObserverProxy(nsIRequestObserver **result,
675 : nsIRequestObserver *observer,
676 : nsIEventTarget *target = nsnull)
677 : {
678 : nsresult rv;
679 : nsCOMPtr<nsIRequestObserverProxy> proxy =
680 798 : do_CreateInstance(NS_REQUESTOBSERVERPROXY_CONTRACTID, &rv);
681 399 : if (NS_SUCCEEDED(rv)) {
682 399 : rv = proxy->Init(observer, target);
683 399 : if (NS_SUCCEEDED(rv))
684 399 : NS_ADDREF(*result = proxy); // cannot use nsCOMPtr::swap
685 : }
686 399 : return rv;
687 : }
688 :
689 : inline nsresult
690 5733 : NS_NewSimpleStreamListener(nsIStreamListener **result,
691 : nsIOutputStream *sink,
692 : nsIRequestObserver *observer = nsnull)
693 : {
694 : nsresult rv;
695 : nsCOMPtr<nsISimpleStreamListener> listener =
696 11466 : do_CreateInstance(NS_SIMPLESTREAMLISTENER_CONTRACTID, &rv);
697 5733 : if (NS_SUCCEEDED(rv)) {
698 5733 : rv = listener->Init(sink, observer);
699 5733 : if (NS_SUCCEEDED(rv))
700 5733 : NS_ADDREF(*result = listener); // cannot use nsCOMPtr::swap
701 : }
702 5733 : return rv;
703 : }
704 :
705 : inline nsresult
706 3125 : NS_CheckPortSafety(PRInt32 port,
707 : const char *scheme,
708 : nsIIOService *ioService = nsnull)
709 : {
710 : nsresult rv;
711 6250 : nsCOMPtr<nsIIOService> grip;
712 3125 : rv = net_EnsureIOService(&ioService, grip);
713 3125 : if (ioService) {
714 : bool allow;
715 3125 : rv = ioService->AllowPort(port, scheme, &allow);
716 3125 : if (NS_SUCCEEDED(rv) && !allow) {
717 0 : NS_WARNING("port blocked");
718 0 : rv = NS_ERROR_PORT_ACCESS_NOT_ALLOWED;
719 : }
720 : }
721 3125 : return rv;
722 : }
723 :
724 : // Determine if this URI is using a safe port.
725 : inline nsresult
726 3673 : NS_CheckPortSafety(nsIURI *uri) {
727 : PRInt32 port;
728 3673 : nsresult rv = uri->GetPort(&port);
729 3673 : if (NS_FAILED(rv) || port == -1) // port undefined or default-valued
730 548 : return NS_OK;
731 6250 : nsCAutoString scheme;
732 3125 : uri->GetScheme(scheme);
733 3125 : return NS_CheckPortSafety(port, scheme.get());
734 : }
735 :
736 : inline nsresult
737 : NS_NewProxyInfo(const nsACString &type,
738 : const nsACString &host,
739 : PRInt32 port,
740 : PRUint32 flags,
741 : nsIProxyInfo **result)
742 : {
743 : nsresult rv;
744 : nsCOMPtr<nsIProtocolProxyService> pps =
745 : do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
746 : if (NS_SUCCEEDED(rv))
747 : rv = pps->NewProxyInfo(type, host, port, flags, PR_UINT32_MAX, nsnull,
748 : result);
749 : return rv;
750 : }
751 :
752 : inline nsresult
753 17093 : NS_GetFileProtocolHandler(nsIFileProtocolHandler **result,
754 : nsIIOService *ioService = nsnull)
755 : {
756 : nsresult rv;
757 34186 : nsCOMPtr<nsIIOService> grip;
758 17093 : rv = net_EnsureIOService(&ioService, grip);
759 17093 : if (ioService) {
760 34186 : nsCOMPtr<nsIProtocolHandler> handler;
761 17093 : rv = ioService->GetProtocolHandler("file", getter_AddRefs(handler));
762 17093 : if (NS_SUCCEEDED(rv))
763 17093 : rv = CallQueryInterface(handler, result);
764 : }
765 17093 : return rv;
766 : }
767 :
768 : inline nsresult
769 0 : NS_GetFileFromURLSpec(const nsACString &inURL,
770 : nsIFile **result,
771 : nsIIOService *ioService = nsnull)
772 : {
773 : nsresult rv;
774 0 : nsCOMPtr<nsIFileProtocolHandler> fileHandler;
775 0 : rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
776 0 : if (NS_SUCCEEDED(rv))
777 0 : rv = fileHandler->GetFileFromURLSpec(inURL, result);
778 0 : return rv;
779 : }
780 :
781 : inline nsresult
782 0 : NS_GetURLSpecFromFile(nsIFile *file,
783 : nsACString &url,
784 : nsIIOService *ioService = nsnull)
785 : {
786 : nsresult rv;
787 0 : nsCOMPtr<nsIFileProtocolHandler> fileHandler;
788 0 : rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
789 0 : if (NS_SUCCEEDED(rv))
790 0 : rv = fileHandler->GetURLSpecFromFile(file, url);
791 0 : return rv;
792 : }
793 :
794 : /**
795 : * Converts the nsIFile to the corresponding URL string.
796 : * Should only be called on files which are not directories,
797 : * is otherwise identical to NS_GetURLSpecFromFile, but is
798 : * usually more efficient.
799 : * Warning: this restriction may not be enforced at runtime!
800 : */
801 : inline nsresult
802 14178 : NS_GetURLSpecFromActualFile(nsIFile *file,
803 : nsACString &url,
804 : nsIIOService *ioService = nsnull)
805 : {
806 : nsresult rv;
807 28356 : nsCOMPtr<nsIFileProtocolHandler> fileHandler;
808 14178 : rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
809 14178 : if (NS_SUCCEEDED(rv))
810 14178 : rv = fileHandler->GetURLSpecFromActualFile(file, url);
811 14178 : return rv;
812 : }
813 :
814 : /**
815 : * Converts the nsIFile to the corresponding URL string.
816 : * Should only be called on files which are directories,
817 : * is otherwise identical to NS_GetURLSpecFromFile, but is
818 : * usually more efficient.
819 : * Warning: this restriction may not be enforced at runtime!
820 : */
821 : inline nsresult
822 : NS_GetURLSpecFromDir(nsIFile *file,
823 : nsACString &url,
824 : nsIIOService *ioService = nsnull)
825 : {
826 : nsresult rv;
827 : nsCOMPtr<nsIFileProtocolHandler> fileHandler;
828 : rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
829 : if (NS_SUCCEEDED(rv))
830 : rv = fileHandler->GetURLSpecFromDir(file, url);
831 : return rv;
832 : }
833 :
834 : /**
835 : * Obtains the referrer for a given channel. This first tries to obtain the
836 : * referrer from the property docshell.internalReferrer, and if that doesn't
837 : * work and the channel is an nsIHTTPChannel, we check it's referrer property.
838 : *
839 : * @returns NS_ERROR_NOT_AVAILABLE if no referrer is available.
840 : */
841 : inline nsresult
842 23 : NS_GetReferrerFromChannel(nsIChannel *channel,
843 : nsIURI **referrer)
844 : {
845 23 : nsresult rv = NS_ERROR_NOT_AVAILABLE;
846 23 : *referrer = nsnull;
847 :
848 46 : nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(channel));
849 23 : if (props) {
850 : // We have to check for a property on a property bag because the
851 : // referrer may be empty for security reasons (for example, when loading
852 : // an http page with an https referrer).
853 46 : rv = props->GetPropertyAsInterface(NS_LITERAL_STRING("docshell.internalReferrer"),
854 : NS_GET_IID(nsIURI),
855 23 : reinterpret_cast<void **>(referrer));
856 23 : if (NS_FAILED(rv))
857 23 : *referrer = nsnull;
858 : }
859 :
860 : // if that didn't work, we can still try to get the referrer from the
861 : // nsIHttpChannel (if we can QI to it)
862 23 : if (!(*referrer)) {
863 46 : nsCOMPtr<nsIHttpChannel> chan(do_QueryInterface(channel));
864 23 : if (chan) {
865 23 : rv = chan->GetReferrer(referrer);
866 23 : if (NS_FAILED(rv))
867 0 : *referrer = nsnull;
868 : }
869 : }
870 23 : return rv;
871 : }
872 :
873 : #ifdef MOZILLA_INTERNAL_API
874 : inline nsresult
875 : NS_ExamineForProxy(const char *scheme,
876 : const char *host,
877 : PRInt32 port,
878 : nsIProxyInfo **proxyInfo)
879 : {
880 : nsresult rv;
881 : nsCOMPtr<nsIProtocolProxyService> pps =
882 : do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
883 : if (NS_SUCCEEDED(rv)) {
884 : nsCAutoString spec(scheme);
885 : spec.Append("://");
886 : spec.Append(host);
887 : spec.Append(':');
888 : spec.AppendInt(port);
889 : // XXXXX - Under no circumstances whatsoever should any code which
890 : // wants a uri do this. I do this here because I do not, in fact,
891 : // actually want a uri (the dummy uris created here may not be
892 : // syntactically valid for the specific protocol), and all we need
893 : // is something which has a valid scheme, hostname, and a string
894 : // to pass to PAC if needed - bbaetz
895 : nsCOMPtr<nsIURI> uri =
896 : do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
897 : if (NS_SUCCEEDED(rv)) {
898 : rv = uri->SetSpec(spec);
899 : if (NS_SUCCEEDED(rv))
900 : rv = pps->Resolve(uri, 0, proxyInfo);
901 : }
902 : }
903 : return rv;
904 : }
905 : #endif
906 :
907 : inline nsresult
908 101 : NS_ParseContentType(const nsACString &rawContentType,
909 : nsCString &contentType,
910 : nsCString &contentCharset)
911 : {
912 : // contentCharset is left untouched if not present in rawContentType
913 : nsresult rv;
914 202 : nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
915 101 : NS_ENSURE_SUCCESS(rv, rv);
916 202 : nsCString charset;
917 : bool hadCharset;
918 101 : rv = util->ParseContentType(rawContentType, charset, &hadCharset,
919 101 : contentType);
920 101 : if (NS_SUCCEEDED(rv) && hadCharset)
921 4 : contentCharset = charset;
922 101 : return rv;
923 : }
924 :
925 : inline nsresult
926 0 : NS_ExtractCharsetFromContentType(const nsACString &rawContentType,
927 : nsCString &contentCharset,
928 : bool *hadCharset,
929 : PRInt32 *charsetStart,
930 : PRInt32 *charsetEnd)
931 : {
932 : // contentCharset is left untouched if not present in rawContentType
933 : nsresult rv;
934 0 : nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
935 0 : NS_ENSURE_SUCCESS(rv, rv);
936 :
937 0 : return util->ExtractCharsetFromContentType(rawContentType,
938 : contentCharset,
939 : charsetStart,
940 : charsetEnd,
941 0 : hadCharset);
942 : }
943 :
944 : inline nsresult
945 12186 : NS_NewLocalFileInputStream(nsIInputStream **result,
946 : nsIFile *file,
947 : PRInt32 ioFlags = -1,
948 : PRInt32 perm = -1,
949 : PRInt32 behaviorFlags = 0)
950 : {
951 : nsresult rv;
952 : nsCOMPtr<nsIFileInputStream> in =
953 24372 : do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID, &rv);
954 12186 : if (NS_SUCCEEDED(rv)) {
955 12186 : rv = in->Init(file, ioFlags, perm, behaviorFlags);
956 12186 : if (NS_SUCCEEDED(rv))
957 11674 : NS_ADDREF(*result = in); // cannot use nsCOMPtr::swap
958 : }
959 12186 : return rv;
960 : }
961 :
962 : inline nsresult
963 0 : NS_NewPartialLocalFileInputStream(nsIInputStream **result,
964 : nsIFile *file,
965 : PRUint64 offset,
966 : PRUint64 length,
967 : PRInt32 ioFlags = -1,
968 : PRInt32 perm = -1,
969 : PRInt32 behaviorFlags = 0)
970 : {
971 : nsresult rv;
972 : nsCOMPtr<nsIPartialFileInputStream> in =
973 0 : do_CreateInstance(NS_PARTIALLOCALFILEINPUTSTREAM_CONTRACTID, &rv);
974 0 : if (NS_SUCCEEDED(rv)) {
975 0 : rv = in->Init(file, offset, length, ioFlags, perm, behaviorFlags);
976 0 : if (NS_SUCCEEDED(rv))
977 0 : rv = CallQueryInterface(in, result);
978 : }
979 0 : return rv;
980 : }
981 :
982 : inline nsresult
983 979 : NS_NewLocalFileOutputStream(nsIOutputStream **result,
984 : nsIFile *file,
985 : PRInt32 ioFlags = -1,
986 : PRInt32 perm = -1,
987 : PRInt32 behaviorFlags = 0)
988 : {
989 : nsresult rv;
990 : nsCOMPtr<nsIFileOutputStream> out =
991 1958 : do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
992 979 : if (NS_SUCCEEDED(rv)) {
993 979 : rv = out->Init(file, ioFlags, perm, behaviorFlags);
994 979 : if (NS_SUCCEEDED(rv))
995 976 : NS_ADDREF(*result = out); // cannot use nsCOMPtr::swap
996 : }
997 979 : return rv;
998 : }
999 :
1000 : // returns a file output stream which can be QI'ed to nsISafeOutputStream.
1001 : inline nsresult
1002 32 : NS_NewSafeLocalFileOutputStream(nsIOutputStream **result,
1003 : nsIFile *file,
1004 : PRInt32 ioFlags = -1,
1005 : PRInt32 perm = -1,
1006 : PRInt32 behaviorFlags = 0)
1007 : {
1008 : nsresult rv;
1009 : nsCOMPtr<nsIFileOutputStream> out =
1010 64 : do_CreateInstance(NS_SAFELOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
1011 32 : if (NS_SUCCEEDED(rv)) {
1012 32 : rv = out->Init(file, ioFlags, perm, behaviorFlags);
1013 32 : if (NS_SUCCEEDED(rv))
1014 32 : NS_ADDREF(*result = out); // cannot use nsCOMPtr::swap
1015 : }
1016 32 : return rv;
1017 : }
1018 :
1019 : // returns the input end of a pipe. the output end of the pipe
1020 : // is attached to the original stream. data from the original
1021 : // stream is read into the pipe on a background thread.
1022 : inline nsresult
1023 : NS_BackgroundInputStream(nsIInputStream **result,
1024 : nsIInputStream *stream,
1025 : PRUint32 segmentSize = 0,
1026 : PRUint32 segmentCount = 0)
1027 : {
1028 : nsresult rv;
1029 : nsCOMPtr<nsIStreamTransportService> sts =
1030 : do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
1031 : if (NS_SUCCEEDED(rv)) {
1032 : nsCOMPtr<nsITransport> inTransport;
1033 : rv = sts->CreateInputTransport(stream, PRInt64(-1), PRInt64(-1),
1034 : true, getter_AddRefs(inTransport));
1035 : if (NS_SUCCEEDED(rv))
1036 : rv = inTransport->OpenInputStream(nsITransport::OPEN_BLOCKING,
1037 : segmentSize, segmentCount,
1038 : result);
1039 : }
1040 : return rv;
1041 : }
1042 :
1043 : // returns the output end of a pipe. the input end of the pipe
1044 : // is attached to the original stream. data written to the pipe
1045 : // is copied to the original stream on a background thread.
1046 : inline nsresult
1047 : NS_BackgroundOutputStream(nsIOutputStream **result,
1048 : nsIOutputStream *stream,
1049 : PRUint32 segmentSize = 0,
1050 : PRUint32 segmentCount = 0)
1051 : {
1052 : nsresult rv;
1053 : nsCOMPtr<nsIStreamTransportService> sts =
1054 : do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
1055 : if (NS_SUCCEEDED(rv)) {
1056 : nsCOMPtr<nsITransport> inTransport;
1057 : rv = sts->CreateOutputTransport(stream, PRInt64(-1), PRInt64(-1),
1058 : true, getter_AddRefs(inTransport));
1059 : if (NS_SUCCEEDED(rv))
1060 : rv = inTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING,
1061 : segmentSize, segmentCount,
1062 : result);
1063 : }
1064 : return rv;
1065 : }
1066 :
1067 : inline nsresult
1068 943 : NS_NewBufferedInputStream(nsIInputStream **result,
1069 : nsIInputStream *str,
1070 : PRUint32 bufferSize)
1071 : {
1072 : nsresult rv;
1073 : nsCOMPtr<nsIBufferedInputStream> in =
1074 1886 : do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID, &rv);
1075 943 : if (NS_SUCCEEDED(rv)) {
1076 943 : rv = in->Init(str, bufferSize);
1077 943 : if (NS_SUCCEEDED(rv))
1078 943 : NS_ADDREF(*result = in); // cannot use nsCOMPtr::swap
1079 : }
1080 943 : return rv;
1081 : }
1082 :
1083 : // note: the resulting stream can be QI'ed to nsISafeOutputStream iff the
1084 : // provided stream supports it.
1085 : inline nsresult
1086 1058 : NS_NewBufferedOutputStream(nsIOutputStream **result,
1087 : nsIOutputStream *str,
1088 : PRUint32 bufferSize)
1089 : {
1090 : nsresult rv;
1091 : nsCOMPtr<nsIBufferedOutputStream> out =
1092 2116 : do_CreateInstance(NS_BUFFEREDOUTPUTSTREAM_CONTRACTID, &rv);
1093 1058 : if (NS_SUCCEEDED(rv)) {
1094 1058 : rv = out->Init(str, bufferSize);
1095 1058 : if (NS_SUCCEEDED(rv))
1096 1058 : NS_ADDREF(*result = out); // cannot use nsCOMPtr::swap
1097 : }
1098 1058 : return rv;
1099 : }
1100 :
1101 : /**
1102 : * Attempts to buffer a given output stream. If this fails, it returns the
1103 : * passed-in output stream.
1104 : *
1105 : * @param aOutputStream
1106 : * The output stream we want to buffer. This cannot be null.
1107 : * @param aBufferSize
1108 : * The size of the buffer for the buffered output stream.
1109 : * @returns an nsIOutputStream that is buffered with the specified buffer size,
1110 : * or is aOutputStream if creating the new buffered stream failed.
1111 : */
1112 : inline already_AddRefed<nsIOutputStream>
1113 26 : NS_BufferOutputStream(nsIOutputStream *aOutputStream,
1114 : PRUint32 aBufferSize)
1115 : {
1116 26 : NS_ASSERTION(aOutputStream, "No output stream given!");
1117 :
1118 52 : nsCOMPtr<nsIOutputStream> bos;
1119 26 : nsresult rv = NS_NewBufferedOutputStream(getter_AddRefs(bos), aOutputStream,
1120 26 : aBufferSize);
1121 26 : if (NS_SUCCEEDED(rv))
1122 26 : return bos.forget();
1123 :
1124 0 : NS_ADDREF(aOutputStream);
1125 0 : return aOutputStream;
1126 : }
1127 :
1128 : // returns an input stream compatible with nsIUploadChannel::SetUploadStream()
1129 : inline nsresult
1130 0 : NS_NewPostDataStream(nsIInputStream **result,
1131 : bool isFile,
1132 : const nsACString &data,
1133 : PRUint32 encodeFlags,
1134 : nsIIOService *unused = nsnull)
1135 : {
1136 : nsresult rv;
1137 :
1138 0 : if (isFile) {
1139 0 : nsCOMPtr<nsILocalFile> file;
1140 0 : nsCOMPtr<nsIInputStream> fileStream;
1141 :
1142 0 : rv = NS_NewNativeLocalFile(data, false, getter_AddRefs(file));
1143 0 : if (NS_SUCCEEDED(rv)) {
1144 0 : rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file);
1145 0 : if (NS_SUCCEEDED(rv)) {
1146 : // wrap the file stream with a buffered input stream
1147 0 : rv = NS_NewBufferedInputStream(result, fileStream, 8192);
1148 : }
1149 : }
1150 0 : return rv;
1151 : }
1152 :
1153 : // otherwise, create a string stream for the data (copies)
1154 : nsCOMPtr<nsIStringInputStream> stream
1155 0 : (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv));
1156 0 : if (NS_FAILED(rv))
1157 0 : return rv;
1158 :
1159 0 : rv = stream->SetData(data.BeginReading(), data.Length());
1160 0 : if (NS_FAILED(rv))
1161 0 : return rv;
1162 :
1163 0 : NS_ADDREF(*result = stream);
1164 0 : return NS_OK;
1165 : }
1166 :
1167 : inline nsresult
1168 525 : NS_ReadInputStreamToBuffer(nsIInputStream *aInputStream,
1169 : void** aDest,
1170 : PRUint32 aCount)
1171 : {
1172 : nsresult rv;
1173 :
1174 525 : if (!*aDest) {
1175 0 : *aDest = malloc(aCount);
1176 0 : if (!*aDest)
1177 0 : return NS_ERROR_OUT_OF_MEMORY;
1178 : }
1179 :
1180 525 : char * p = reinterpret_cast<char*>(*aDest);
1181 : PRUint32 bytesRead;
1182 525 : PRUint32 totalRead = 0;
1183 0 : while (1) {
1184 525 : rv = aInputStream->Read(p + totalRead, aCount - totalRead, &bytesRead);
1185 525 : if (!NS_SUCCEEDED(rv))
1186 0 : return rv;
1187 525 : totalRead += bytesRead;
1188 525 : if (totalRead == aCount)
1189 : break;
1190 : // if Read reads 0 bytes, we've hit EOF
1191 0 : if (bytesRead == 0)
1192 0 : return NS_ERROR_UNEXPECTED;
1193 : }
1194 525 : return rv;
1195 : }
1196 :
1197 : inline nsresult
1198 525 : NS_ReadInputStreamToString(nsIInputStream *aInputStream,
1199 : nsACString &aDest,
1200 : PRUint32 aCount)
1201 : {
1202 525 : aDest.SetLength(aCount);
1203 525 : if (aDest.Length() != aCount)
1204 0 : return NS_ERROR_OUT_OF_MEMORY;
1205 525 : void* dest = aDest.BeginWriting();
1206 525 : return NS_ReadInputStreamToBuffer(aInputStream, &dest, aCount);
1207 : }
1208 :
1209 : inline nsresult
1210 0 : NS_LoadPersistentPropertiesFromURI(nsIPersistentProperties **result,
1211 : nsIURI *uri,
1212 : nsIIOService *ioService = nsnull)
1213 : {
1214 0 : nsCOMPtr<nsIInputStream> in;
1215 0 : nsresult rv = NS_OpenURI(getter_AddRefs(in), uri, ioService);
1216 0 : if (NS_SUCCEEDED(rv)) {
1217 : nsCOMPtr<nsIPersistentProperties> properties =
1218 0 : do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID, &rv);
1219 0 : if (NS_SUCCEEDED(rv)) {
1220 0 : rv = properties->Load(in);
1221 0 : if (NS_SUCCEEDED(rv)) {
1222 0 : *result = nsnull;
1223 0 : properties.swap(*result);
1224 : }
1225 : }
1226 : }
1227 0 : return rv;
1228 : }
1229 :
1230 : inline nsresult
1231 0 : NS_LoadPersistentPropertiesFromURISpec(nsIPersistentProperties **result,
1232 : const nsACString &spec,
1233 : const char *charset = nsnull,
1234 : nsIURI *baseURI = nsnull,
1235 : nsIIOService *ioService = nsnull)
1236 : {
1237 0 : nsCOMPtr<nsIURI> uri;
1238 : nsresult rv =
1239 0 : NS_NewURI(getter_AddRefs(uri), spec, charset, baseURI, ioService);
1240 :
1241 0 : if (NS_SUCCEEDED(rv))
1242 0 : rv = NS_LoadPersistentPropertiesFromURI(result, uri, ioService);
1243 :
1244 0 : return rv;
1245 : }
1246 :
1247 : /**
1248 : * NS_QueryNotificationCallbacks implements the canonical algorithm for
1249 : * querying interfaces from a channel's notification callbacks. It first
1250 : * searches the channel's notificationCallbacks attribute, and if the interface
1251 : * is not found there, then it inspects the notificationCallbacks attribute of
1252 : * the channel's loadGroup.
1253 : */
1254 : inline void
1255 311 : NS_QueryNotificationCallbacks(nsIChannel *channel,
1256 : const nsIID &iid,
1257 : void **result)
1258 : {
1259 311 : NS_PRECONDITION(channel, "null channel");
1260 311 : *result = nsnull;
1261 :
1262 622 : nsCOMPtr<nsIInterfaceRequestor> cbs;
1263 311 : channel->GetNotificationCallbacks(getter_AddRefs(cbs));
1264 311 : if (cbs)
1265 124 : cbs->GetInterface(iid, result);
1266 311 : if (!*result) {
1267 : // try load group's notification callbacks...
1268 498 : nsCOMPtr<nsILoadGroup> loadGroup;
1269 249 : channel->GetLoadGroup(getter_AddRefs(loadGroup));
1270 249 : if (loadGroup) {
1271 0 : loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
1272 0 : if (cbs)
1273 0 : cbs->GetInterface(iid, result);
1274 : }
1275 : }
1276 311 : }
1277 :
1278 : /* template helper */
1279 : template <class T> inline void
1280 156 : NS_QueryNotificationCallbacks(nsIChannel *channel,
1281 : nsCOMPtr<T> &result)
1282 : {
1283 156 : NS_QueryNotificationCallbacks(channel, NS_GET_TEMPLATE_IID(T),
1284 : getter_AddRefs(result));
1285 156 : }
1286 :
1287 : /**
1288 : * Alternate form of NS_QueryNotificationCallbacks designed for use by
1289 : * nsIChannel implementations.
1290 : */
1291 : inline void
1292 7995 : NS_QueryNotificationCallbacks(nsIInterfaceRequestor *callbacks,
1293 : nsILoadGroup *loadGroup,
1294 : const nsIID &iid,
1295 : void **result)
1296 : {
1297 7995 : *result = nsnull;
1298 :
1299 7995 : if (callbacks)
1300 5610 : callbacks->GetInterface(iid, result);
1301 7995 : if (!*result) {
1302 : // try load group's notification callbacks...
1303 7313 : if (loadGroup) {
1304 52 : nsCOMPtr<nsIInterfaceRequestor> cbs;
1305 26 : loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
1306 26 : if (cbs)
1307 0 : cbs->GetInterface(iid, result);
1308 : }
1309 : }
1310 7995 : }
1311 :
1312 : /**
1313 : * Wraps an nsIAuthPrompt so that it can be used as an nsIAuthPrompt2. This
1314 : * method is provided mainly for use by other methods in this file.
1315 : *
1316 : * *aAuthPrompt2 should be set to null before calling this function.
1317 : */
1318 : inline void
1319 4 : NS_WrapAuthPrompt(nsIAuthPrompt *aAuthPrompt, nsIAuthPrompt2** aAuthPrompt2)
1320 : {
1321 : nsCOMPtr<nsIAuthPromptAdapterFactory> factory =
1322 8 : do_GetService(NS_AUTHPROMPT_ADAPTER_FACTORY_CONTRACTID);
1323 4 : if (!factory)
1324 : return;
1325 :
1326 4 : NS_WARNING("Using deprecated nsIAuthPrompt");
1327 4 : factory->CreateAdapter(aAuthPrompt, aAuthPrompt2);
1328 : }
1329 :
1330 : /**
1331 : * Gets an auth prompt from an interface requestor. This takes care of wrapping
1332 : * an nsIAuthPrompt so that it can be used as an nsIAuthPrompt2.
1333 : */
1334 : inline void
1335 37 : NS_QueryAuthPrompt2(nsIInterfaceRequestor *aCallbacks,
1336 : nsIAuthPrompt2 **aAuthPrompt)
1337 : {
1338 37 : CallGetInterface(aCallbacks, aAuthPrompt);
1339 37 : if (*aAuthPrompt)
1340 26 : return;
1341 :
1342 : // Maybe only nsIAuthPrompt is provided and we have to wrap it.
1343 22 : nsCOMPtr<nsIAuthPrompt> prompt(do_GetInterface(aCallbacks));
1344 11 : if (!prompt)
1345 : return;
1346 :
1347 4 : NS_WrapAuthPrompt(prompt, aAuthPrompt);
1348 : }
1349 :
1350 : /**
1351 : * Gets an nsIAuthPrompt2 from a channel. Use this instead of
1352 : * NS_QueryNotificationCallbacks for better backwards compatibility.
1353 : */
1354 : inline void
1355 0 : NS_QueryAuthPrompt2(nsIChannel *aChannel,
1356 : nsIAuthPrompt2 **aAuthPrompt)
1357 : {
1358 0 : *aAuthPrompt = nsnull;
1359 :
1360 : // We want to use any auth prompt we can find on the channel's callbacks,
1361 : // and if that fails use the loadgroup's prompt (if any)
1362 : // Therefore, we can't just use NS_QueryNotificationCallbacks, because
1363 : // that would prefer a loadgroup's nsIAuthPrompt2 over a channel's
1364 : // nsIAuthPrompt.
1365 0 : nsCOMPtr<nsIInterfaceRequestor> callbacks;
1366 0 : aChannel->GetNotificationCallbacks(getter_AddRefs(callbacks));
1367 0 : if (callbacks) {
1368 0 : NS_QueryAuthPrompt2(callbacks, aAuthPrompt);
1369 0 : if (*aAuthPrompt)
1370 : return;
1371 : }
1372 :
1373 0 : nsCOMPtr<nsILoadGroup> group;
1374 0 : aChannel->GetLoadGroup(getter_AddRefs(group));
1375 0 : if (!group)
1376 : return;
1377 :
1378 0 : group->GetNotificationCallbacks(getter_AddRefs(callbacks));
1379 0 : if (!callbacks)
1380 : return;
1381 0 : NS_QueryAuthPrompt2(callbacks, aAuthPrompt);
1382 : }
1383 :
1384 : /* template helper */
1385 : template <class T> inline void
1386 1 : NS_QueryNotificationCallbacks(nsIInterfaceRequestor *callbacks,
1387 : nsILoadGroup *loadGroup,
1388 : nsCOMPtr<T> &result)
1389 : {
1390 1 : NS_QueryNotificationCallbacks(callbacks, loadGroup,
1391 : NS_GET_TEMPLATE_IID(T),
1392 : getter_AddRefs(result));
1393 1 : }
1394 :
1395 : /* template helper */
1396 : template <class T> inline void
1397 1 : NS_QueryNotificationCallbacks(const nsCOMPtr<nsIInterfaceRequestor> &aCallbacks,
1398 : const nsCOMPtr<nsILoadGroup> &aLoadGroup,
1399 : nsCOMPtr<T> &aResult)
1400 : {
1401 1 : NS_QueryNotificationCallbacks(aCallbacks.get(), aLoadGroup.get(), aResult);
1402 1 : }
1403 :
1404 : /* template helper */
1405 : template <class T> inline void
1406 152 : NS_QueryNotificationCallbacks(const nsCOMPtr<nsIChannel> &aChannel,
1407 : nsCOMPtr<T> &aResult)
1408 : {
1409 152 : NS_QueryNotificationCallbacks(aChannel.get(), aResult);
1410 152 : }
1411 :
1412 : /**
1413 : * This function returns a nsIInterfaceRequestor instance that returns the
1414 : * same result as NS_QueryNotificationCallbacks when queried. It is useful
1415 : * as the value for nsISocketTransport::securityCallbacks.
1416 : */
1417 : inline nsresult
1418 2989 : NS_NewNotificationCallbacksAggregation(nsIInterfaceRequestor *callbacks,
1419 : nsILoadGroup *loadGroup,
1420 : nsIInterfaceRequestor **result)
1421 : {
1422 5978 : nsCOMPtr<nsIInterfaceRequestor> cbs;
1423 2989 : if (loadGroup)
1424 8 : loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
1425 2989 : return NS_NewInterfaceRequestorAggregation(callbacks, cbs, result);
1426 : }
1427 :
1428 : /**
1429 : * Helper function for testing online/offline state of the browser.
1430 : */
1431 : inline bool
1432 17 : NS_IsOffline()
1433 : {
1434 17 : bool offline = true;
1435 34 : nsCOMPtr<nsIIOService> ios = do_GetIOService();
1436 17 : if (ios)
1437 17 : ios->GetOffline(&offline);
1438 17 : return offline;
1439 : }
1440 :
1441 : /**
1442 : * Helper functions for implementing nsINestedURI::innermostURI.
1443 : *
1444 : * Note that NS_DoImplGetInnermostURI is "private" -- call
1445 : * NS_ImplGetInnermostURI instead.
1446 : */
1447 : inline nsresult
1448 133 : NS_DoImplGetInnermostURI(nsINestedURI* nestedURI, nsIURI** result)
1449 : {
1450 133 : NS_PRECONDITION(nestedURI, "Must have a nested URI!");
1451 133 : NS_PRECONDITION(!*result, "Must have null *result");
1452 :
1453 266 : nsCOMPtr<nsIURI> inner;
1454 133 : nsresult rv = nestedURI->GetInnerURI(getter_AddRefs(inner));
1455 133 : NS_ENSURE_SUCCESS(rv, rv);
1456 :
1457 : // We may need to loop here until we reach the innermost
1458 : // URI.
1459 266 : nsCOMPtr<nsINestedURI> nestedInner(do_QueryInterface(inner));
1460 267 : while (nestedInner) {
1461 1 : rv = nestedInner->GetInnerURI(getter_AddRefs(inner));
1462 1 : NS_ENSURE_SUCCESS(rv, rv);
1463 1 : nestedInner = do_QueryInterface(inner);
1464 : }
1465 :
1466 : // Found the innermost one if we reach here.
1467 133 : inner.swap(*result);
1468 :
1469 133 : return rv;
1470 : }
1471 :
1472 : inline nsresult
1473 133 : NS_ImplGetInnermostURI(nsINestedURI* nestedURI, nsIURI** result)
1474 : {
1475 : // Make it safe to use swap()
1476 133 : *result = nsnull;
1477 :
1478 133 : return NS_DoImplGetInnermostURI(nestedURI, result);
1479 : }
1480 :
1481 : /**
1482 : * Helper function that ensures that |result| is a URI that's safe to
1483 : * return. If |uri| is immutable, just returns it, otherwise returns
1484 : * a clone. |uri| must not be null.
1485 : */
1486 : inline nsresult
1487 7844 : NS_EnsureSafeToReturn(nsIURI* uri, nsIURI** result)
1488 : {
1489 7844 : NS_PRECONDITION(uri, "Must have a URI");
1490 :
1491 : // Assume mutable until told otherwise
1492 7844 : bool isMutable = true;
1493 15688 : nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(uri));
1494 7844 : if (mutableObj) {
1495 2543 : nsresult rv = mutableObj->GetMutable(&isMutable);
1496 2543 : isMutable = NS_FAILED(rv) || isMutable;
1497 : }
1498 :
1499 7844 : if (!isMutable) {
1500 1875 : NS_ADDREF(*result = uri);
1501 1875 : return NS_OK;
1502 : }
1503 :
1504 5969 : nsresult rv = uri->Clone(result);
1505 5969 : if (NS_SUCCEEDED(rv) && !*result) {
1506 0 : NS_ERROR("nsIURI.clone contract was violated");
1507 0 : return NS_ERROR_UNEXPECTED;
1508 : }
1509 :
1510 5969 : return rv;
1511 : }
1512 :
1513 : /**
1514 : * Helper function that tries to set the argument URI to be immutable
1515 : */
1516 : inline void
1517 5880 : NS_TryToSetImmutable(nsIURI* uri)
1518 : {
1519 11760 : nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(uri));
1520 5880 : if (mutableObj) {
1521 5260 : mutableObj->SetMutable(false);
1522 : }
1523 5880 : }
1524 :
1525 : /**
1526 : * Helper function for calling ToImmutableURI. If all else fails, returns
1527 : * the input URI. The optional second arg indicates whether we had to fall
1528 : * back to the input URI. Passing in a null URI is ok.
1529 : */
1530 : inline already_AddRefed<nsIURI>
1531 2184 : NS_TryToMakeImmutable(nsIURI* uri,
1532 : nsresult* outRv = nsnull)
1533 : {
1534 : nsresult rv;
1535 4368 : nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
1536 :
1537 2184 : nsIURI* result = nsnull;
1538 2184 : if (NS_SUCCEEDED(rv)) {
1539 2184 : NS_ASSERTION(util, "do_GetNetUtil lied");
1540 2184 : rv = util->ToImmutableURI(uri, &result);
1541 : }
1542 :
1543 2184 : if (NS_FAILED(rv)) {
1544 0 : NS_IF_ADDREF(result = uri);
1545 : }
1546 :
1547 2184 : if (outRv) {
1548 0 : *outRv = rv;
1549 : }
1550 :
1551 2184 : return result;
1552 : }
1553 :
1554 : /**
1555 : * Helper function for testing whether the given URI, or any of its
1556 : * inner URIs, has all the given protocol flags.
1557 : */
1558 : inline nsresult
1559 105022 : NS_URIChainHasFlags(nsIURI *uri,
1560 : PRUint32 flags,
1561 : bool *result)
1562 : {
1563 : nsresult rv;
1564 210044 : nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
1565 105022 : NS_ENSURE_SUCCESS(rv, rv);
1566 :
1567 105022 : return util->URIChainHasFlags(uri, flags, result);
1568 : }
1569 :
1570 : /**
1571 : * Helper function for getting the innermost URI for a given URI. The return
1572 : * value could be just the object passed in if it's not a nested URI.
1573 : */
1574 : inline already_AddRefed<nsIURI>
1575 67935 : NS_GetInnermostURI(nsIURI *uri)
1576 : {
1577 67935 : NS_PRECONDITION(uri, "Must have URI");
1578 :
1579 135870 : nsCOMPtr<nsINestedURI> nestedURI(do_QueryInterface(uri));
1580 67935 : if (!nestedURI) {
1581 67804 : NS_ADDREF(uri);
1582 67804 : return uri;
1583 : }
1584 :
1585 131 : nsresult rv = nestedURI->GetInnermostURI(&uri);
1586 131 : if (NS_FAILED(rv)) {
1587 0 : return nsnull;
1588 : }
1589 :
1590 131 : return uri;
1591 : }
1592 :
1593 : /**
1594 : * Get the "final" URI for a channel. This is either the same as GetURI or
1595 : * GetOriginalURI, depending on whether this channel has
1596 : * nsIChanel::LOAD_REPLACE set. For channels without that flag set, the final
1597 : * URI is the original URI, while for ones with the flag the final URI is the
1598 : * channel URI.
1599 : */
1600 : inline nsresult
1601 634 : NS_GetFinalChannelURI(nsIChannel* channel, nsIURI** uri)
1602 : {
1603 634 : *uri = nsnull;
1604 634 : nsLoadFlags loadFlags = 0;
1605 634 : nsresult rv = channel->GetLoadFlags(&loadFlags);
1606 634 : NS_ENSURE_SUCCESS(rv, rv);
1607 :
1608 634 : if (loadFlags & nsIChannel::LOAD_REPLACE) {
1609 67 : return channel->GetURI(uri);
1610 : }
1611 :
1612 567 : return channel->GetOriginalURI(uri);
1613 : }
1614 :
1615 : // NS_SecurityHashURI must return the same hash value for any two URIs that
1616 : // compare equal according to NS_SecurityCompareURIs. Unfortunately, in the
1617 : // case of files, it's not clear we can do anything better than returning
1618 : // the schemeHash, so hashing files degenerates to storing them in a list.
1619 : inline PRUint32
1620 2828 : NS_SecurityHashURI(nsIURI* aURI)
1621 : {
1622 5656 : nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
1623 :
1624 5656 : nsCAutoString scheme;
1625 2828 : PRUint32 schemeHash = 0;
1626 2828 : if (NS_SUCCEEDED(baseURI->GetScheme(scheme)))
1627 2828 : schemeHash = mozilla::HashString(scheme);
1628 :
1629 : // TODO figure out how to hash file:// URIs
1630 2828 : if (scheme.EqualsLiteral("file"))
1631 0 : return schemeHash; // sad face
1632 :
1633 8484 : if (scheme.EqualsLiteral("imap") ||
1634 2828 : scheme.EqualsLiteral("mailbox") ||
1635 2828 : scheme.EqualsLiteral("news"))
1636 : {
1637 0 : nsCAutoString spec;
1638 0 : PRUint32 specHash = baseURI->GetSpec(spec);
1639 0 : if (NS_SUCCEEDED(specHash))
1640 0 : specHash = mozilla::HashString(spec);
1641 0 : return specHash;
1642 : }
1643 :
1644 5656 : nsCAutoString host;
1645 2828 : PRUint32 hostHash = 0;
1646 2828 : if (NS_SUCCEEDED(baseURI->GetAsciiHost(host)))
1647 2828 : hostHash = mozilla::HashString(host);
1648 :
1649 2828 : return mozilla::AddToHash(schemeHash, hostHash, NS_GetRealPort(baseURI));
1650 : }
1651 :
1652 : inline bool
1653 45 : NS_SecurityCompareURIs(nsIURI* aSourceURI,
1654 : nsIURI* aTargetURI,
1655 : bool aStrictFileOriginPolicy)
1656 : {
1657 : // Note that this is not an Equals() test on purpose -- for URIs that don't
1658 : // support host/port, we want equality to basically be object identity, for
1659 : // security purposes. Otherwise, for example, two javascript: URIs that
1660 : // are otherwise unrelated could end up "same origin", which would be
1661 : // unfortunate.
1662 45 : if (aSourceURI && aSourceURI == aTargetURI)
1663 : {
1664 0 : return true;
1665 : }
1666 :
1667 45 : if (!aTargetURI || !aSourceURI)
1668 : {
1669 0 : return false;
1670 : }
1671 :
1672 : // If either URI is a nested URI, get the base URI
1673 90 : nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(aSourceURI);
1674 90 : nsCOMPtr<nsIURI> targetBaseURI = NS_GetInnermostURI(aTargetURI);
1675 :
1676 : // If either uri is an nsIURIWithPrincipal
1677 90 : nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(sourceBaseURI);
1678 45 : if (uriPrinc) {
1679 0 : uriPrinc->GetPrincipalUri(getter_AddRefs(sourceBaseURI));
1680 : }
1681 :
1682 45 : uriPrinc = do_QueryInterface(targetBaseURI);
1683 45 : if (uriPrinc) {
1684 0 : uriPrinc->GetPrincipalUri(getter_AddRefs(targetBaseURI));
1685 : }
1686 :
1687 45 : if (!sourceBaseURI || !targetBaseURI)
1688 0 : return false;
1689 :
1690 : // Compare schemes
1691 90 : nsCAutoString targetScheme;
1692 45 : bool sameScheme = false;
1693 135 : if (NS_FAILED( targetBaseURI->GetScheme(targetScheme) ) ||
1694 45 : NS_FAILED( sourceBaseURI->SchemeIs(targetScheme.get(), &sameScheme) ) ||
1695 45 : !sameScheme)
1696 : {
1697 : // Not same-origin if schemes differ
1698 5 : return false;
1699 : }
1700 :
1701 : // special handling for file: URIs
1702 40 : if (targetScheme.EqualsLiteral("file"))
1703 : {
1704 : // in traditional unsafe behavior all files are the same origin
1705 0 : if (!aStrictFileOriginPolicy)
1706 0 : return true;
1707 :
1708 0 : nsCOMPtr<nsIFileURL> sourceFileURL(do_QueryInterface(sourceBaseURI));
1709 0 : nsCOMPtr<nsIFileURL> targetFileURL(do_QueryInterface(targetBaseURI));
1710 :
1711 0 : if (!sourceFileURL || !targetFileURL)
1712 0 : return false;
1713 :
1714 0 : nsCOMPtr<nsIFile> sourceFile, targetFile;
1715 :
1716 0 : sourceFileURL->GetFile(getter_AddRefs(sourceFile));
1717 0 : targetFileURL->GetFile(getter_AddRefs(targetFile));
1718 :
1719 0 : if (!sourceFile || !targetFile)
1720 0 : return false;
1721 :
1722 : // Otherwise they had better match
1723 0 : bool filesAreEqual = false;
1724 0 : nsresult rv = sourceFile->Equals(targetFile, &filesAreEqual);
1725 0 : return NS_SUCCEEDED(rv) && filesAreEqual;
1726 : }
1727 :
1728 : // Special handling for mailnews schemes
1729 120 : if (targetScheme.EqualsLiteral("imap") ||
1730 40 : targetScheme.EqualsLiteral("mailbox") ||
1731 40 : targetScheme.EqualsLiteral("news"))
1732 : {
1733 : // Each message is a distinct trust domain; use the
1734 : // whole spec for comparison
1735 0 : nsCAutoString targetSpec;
1736 0 : nsCAutoString sourceSpec;
1737 0 : return ( NS_SUCCEEDED( targetBaseURI->GetSpec(targetSpec) ) &&
1738 0 : NS_SUCCEEDED( sourceBaseURI->GetSpec(sourceSpec) ) &&
1739 0 : targetSpec.Equals(sourceSpec) );
1740 : }
1741 :
1742 : // Compare hosts
1743 80 : nsCAutoString targetHost;
1744 80 : nsCAutoString sourceHost;
1745 80 : if (NS_FAILED( targetBaseURI->GetAsciiHost(targetHost) ) ||
1746 40 : NS_FAILED( sourceBaseURI->GetAsciiHost(sourceHost) ))
1747 : {
1748 0 : return false;
1749 : }
1750 :
1751 80 : nsCOMPtr<nsIStandardURL> targetURL(do_QueryInterface(targetBaseURI));
1752 80 : nsCOMPtr<nsIStandardURL> sourceURL(do_QueryInterface(sourceBaseURI));
1753 40 : if (!targetURL || !sourceURL)
1754 : {
1755 4 : return false;
1756 : }
1757 :
1758 : #ifdef MOZILLA_INTERNAL_API
1759 36 : if (!targetHost.Equals(sourceHost, nsCaseInsensitiveCStringComparator() ))
1760 : #else
1761 : if (!targetHost.Equals(sourceHost, CaseInsensitiveCompare))
1762 : #endif
1763 : {
1764 3 : return false;
1765 : }
1766 :
1767 33 : return NS_GetRealPort(targetBaseURI) == NS_GetRealPort(sourceBaseURI);
1768 : }
1769 :
1770 : inline bool
1771 35 : NS_IsInternalSameURIRedirect(nsIChannel *aOldChannel,
1772 : nsIChannel *aNewChannel,
1773 : PRUint32 aFlags)
1774 : {
1775 35 : if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
1776 35 : return false;
1777 : }
1778 :
1779 0 : nsCOMPtr<nsIURI> oldURI, newURI;
1780 0 : aOldChannel->GetURI(getter_AddRefs(oldURI));
1781 0 : aNewChannel->GetURI(getter_AddRefs(newURI));
1782 :
1783 0 : if (!oldURI || !newURI) {
1784 0 : return false;
1785 : }
1786 :
1787 : bool res;
1788 0 : return NS_SUCCEEDED(oldURI->Equals(newURI, &res)) && res;
1789 : }
1790 :
1791 : inline nsresult
1792 0 : NS_LinkRedirectChannels(PRUint32 channelId,
1793 : nsIParentChannel *parentChannel,
1794 : nsIChannel** _result)
1795 : {
1796 : nsresult rv;
1797 :
1798 : nsCOMPtr<nsIRedirectChannelRegistrar> registrar =
1799 0 : do_GetService("@mozilla.org/redirectchannelregistrar;1", &rv);
1800 0 : NS_ENSURE_SUCCESS(rv, rv);
1801 :
1802 0 : return registrar->LinkChannels(channelId,
1803 : parentChannel,
1804 0 : _result);
1805 : }
1806 :
1807 : /**
1808 : * Helper function to create a random URL string that's properly formed
1809 : * but guaranteed to be invalid.
1810 : */
1811 : #define NS_FAKE_SCHEME "http://"
1812 : #define NS_FAKE_TLD ".invalid"
1813 : inline nsresult
1814 0 : NS_MakeRandomInvalidURLString(nsCString& result)
1815 : {
1816 : nsresult rv;
1817 : nsCOMPtr<nsIUUIDGenerator> uuidgen =
1818 0 : do_GetService("@mozilla.org/uuid-generator;1", &rv);
1819 0 : NS_ENSURE_SUCCESS(rv, rv);
1820 :
1821 : nsID idee;
1822 0 : rv = uuidgen->GenerateUUIDInPlace(&idee);
1823 0 : NS_ENSURE_SUCCESS(rv, rv);
1824 :
1825 : char chars[NSID_LENGTH];
1826 0 : idee.ToProvidedString(chars);
1827 :
1828 0 : result.AssignLiteral(NS_FAKE_SCHEME);
1829 : // Strip off the '{' and '}' at the beginning and end of the UUID
1830 0 : result.Append(chars + 1, NSID_LENGTH - 3);
1831 0 : result.AppendLiteral(NS_FAKE_TLD);
1832 :
1833 0 : return NS_OK;
1834 : }
1835 : #undef NS_FAKE_SCHEME
1836 : #undef NS_FAKE_TLD
1837 :
1838 : /**
1839 : * Helper function to determine whether urlString is Java-compatible --
1840 : * whether it can be passed to the Java URL(String) constructor without the
1841 : * latter throwing a MalformedURLException, or without Java otherwise
1842 : * mishandling it. This function (in effect) implements a scheme whitelist
1843 : * for Java.
1844 : */
1845 : inline nsresult
1846 0 : NS_CheckIsJavaCompatibleURLString(nsCString& urlString, bool *result)
1847 : {
1848 0 : *result = false; // Default to "no"
1849 :
1850 0 : nsresult rv = NS_OK;
1851 : nsCOMPtr<nsIURLParser> urlParser =
1852 0 : do_GetService(NS_STDURLPARSER_CONTRACTID, &rv);
1853 0 : if (NS_FAILED(rv) || !urlParser)
1854 0 : return NS_ERROR_FAILURE;
1855 :
1856 0 : bool compatible = true;
1857 0 : PRUint32 schemePos = 0;
1858 0 : PRInt32 schemeLen = 0;
1859 0 : urlParser->ParseURL(urlString.get(), -1, &schemePos, &schemeLen,
1860 0 : nsnull, nsnull, nsnull, nsnull);
1861 0 : if (schemeLen != -1) {
1862 0 : nsCString scheme;
1863 0 : scheme.Assign(urlString.get() + schemePos, schemeLen);
1864 : // By default Java only understands a small number of URL schemes, and of
1865 : // these only some can legitimately represent a browser page's "origin"
1866 : // (and be something we can legitimately expect Java to handle ... or not
1867 : // to mishandle).
1868 : //
1869 : // Besides those listed below, the OJI plugin understands the "jar",
1870 : // "mailto", "netdoc", "javascript" and "rmi" schemes, and Java Plugin2
1871 : // also understands the "about" scheme. We actually pass "about" URLs
1872 : // to Java ("about:blank" when processing a javascript: URL (one that
1873 : // calls Java) from the location bar of a blank page, and (in FF4 and up)
1874 : // "about:home" when processing a javascript: URL from the home page).
1875 : // And Java doesn't appear to mishandle them (for example it doesn't allow
1876 : // connections to "about" URLs). But it doesn't make any sense to do
1877 : // same-origin checks on "about" URLs, so we don't include them in our
1878 : // scheme whitelist.
1879 : //
1880 : // The OJI plugin doesn't understand "chrome" URLs (only Java Plugin2
1881 : // does) -- so we mustn't pass them to the OJI plugin. But we do need to
1882 : // pass "chrome" URLs to Java Plugin2: Java Plugin2 grants additional
1883 : // privileges to chrome "origins", and some extensions take advantage of
1884 : // this. For more information see bug 620773.
1885 : //
1886 : // As of FF4, we no longer support the OJI plugin.
1887 0 : if (PL_strcasecmp(scheme.get(), "http") &&
1888 0 : PL_strcasecmp(scheme.get(), "https") &&
1889 0 : PL_strcasecmp(scheme.get(), "file") &&
1890 0 : PL_strcasecmp(scheme.get(), "ftp") &&
1891 0 : PL_strcasecmp(scheme.get(), "gopher") &&
1892 0 : PL_strcasecmp(scheme.get(), "chrome"))
1893 0 : compatible = false;
1894 : } else {
1895 0 : compatible = false;
1896 : }
1897 :
1898 0 : *result = compatible;
1899 :
1900 0 : return NS_OK;
1901 : }
1902 :
1903 : /** Given the first (disposition) token from a Content-Disposition header,
1904 : * tell whether it indicates the content is inline or attachment
1905 : * @param aDispToken the disposition token from the content-disposition header
1906 : */
1907 : inline PRUint32
1908 17 : NS_GetContentDispositionFromToken(const nsAString& aDispToken)
1909 : {
1910 : // RFC 2183, section 2.8 says that an unknown disposition
1911 : // value should be treated as "attachment"
1912 : // If all of these tests eval to false, then we have a content-disposition of
1913 : // "attachment" or unknown
1914 115 : if (aDispToken.IsEmpty() ||
1915 17 : aDispToken.LowerCaseEqualsLiteral("inline") ||
1916 : // Broken sites just send
1917 : // Content-Disposition: filename="file"
1918 : // without a disposition token... screen those out.
1919 49 : StringHead(aDispToken, 8).LowerCaseEqualsLiteral("filename") ||
1920 : // Also in use is Content-Disposition: name="file"
1921 49 : StringHead(aDispToken, 4).LowerCaseEqualsLiteral("name"))
1922 1 : return nsIChannel::DISPOSITION_INLINE;
1923 :
1924 16 : return nsIChannel::DISPOSITION_ATTACHMENT;
1925 : }
1926 :
1927 : /** Determine the disposition (inline/attachment) of the content based on the
1928 : * Content-Disposition header
1929 : * @param aHeader the content-disposition header (full value)
1930 : * @param aChan the channel the header came from
1931 : */
1932 : inline PRUint32
1933 21 : NS_GetContentDispositionFromHeader(const nsACString& aHeader, nsIChannel *aChan = nsnull)
1934 : {
1935 : nsresult rv;
1936 42 : nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar = do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
1937 21 : if (NS_FAILED(rv))
1938 0 : return nsIChannel::DISPOSITION_ATTACHMENT;
1939 :
1940 42 : nsCAutoString fallbackCharset;
1941 21 : if (aChan) {
1942 42 : nsCOMPtr<nsIURI> uri;
1943 21 : aChan->GetURI(getter_AddRefs(uri));
1944 21 : if (uri)
1945 21 : uri->GetOriginCharset(fallbackCharset);
1946 : }
1947 :
1948 42 : nsAutoString dispToken;
1949 21 : rv = mimehdrpar->GetParameter(aHeader, "", fallbackCharset, true, nsnull,
1950 21 : dispToken);
1951 :
1952 21 : if (NS_FAILED(rv)) {
1953 : // special case (see bug 272541): empty disposition type handled as "inline"
1954 4 : if (rv == NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY)
1955 0 : return nsIChannel::DISPOSITION_INLINE;
1956 4 : return nsIChannel::DISPOSITION_ATTACHMENT;
1957 : }
1958 :
1959 17 : return NS_GetContentDispositionFromToken(dispToken);
1960 : }
1961 :
1962 : /** Extracts the filename out of a content-disposition header
1963 : * @param aFilename [out] The filename. Can be empty on error.
1964 : * @param aDisposition Value of a Content-Disposition header
1965 : * @param aURI Optional. Will be used to get a fallback charset for the
1966 : * filename, if it is QI'able to nsIURL
1967 : */
1968 : inline nsresult
1969 15 : NS_GetFilenameFromDisposition(nsAString& aFilename,
1970 : const nsACString& aDisposition,
1971 : nsIURI* aURI = nsnull)
1972 : {
1973 15 : aFilename.Truncate();
1974 :
1975 : nsresult rv;
1976 : nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar =
1977 30 : do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
1978 15 : if (NS_FAILED(rv))
1979 0 : return rv;
1980 :
1981 30 : nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
1982 :
1983 30 : nsCAutoString fallbackCharset;
1984 15 : if (url)
1985 15 : url->GetOriginCharset(fallbackCharset);
1986 : // Get the value of 'filename' parameter
1987 15 : rv = mimehdrpar->GetParameter(aDisposition, "filename",
1988 : fallbackCharset, true, nsnull,
1989 15 : aFilename);
1990 15 : if (NS_FAILED(rv) || aFilename.IsEmpty()) {
1991 : // Try 'name' parameter, instead.
1992 7 : rv = mimehdrpar->GetParameter(aDisposition, "name", fallbackCharset,
1993 7 : true, nsnull, aFilename);
1994 : }
1995 :
1996 15 : if (NS_FAILED(rv)) {
1997 7 : aFilename.Truncate();
1998 7 : return rv;
1999 : }
2000 :
2001 8 : if (aFilename.IsEmpty())
2002 0 : return NS_ERROR_NOT_AVAILABLE;
2003 :
2004 8 : return NS_OK;
2005 : }
2006 :
2007 : /**
2008 : * Make sure Personal Security Manager is initialized
2009 : */
2010 : inline void
2011 5 : net_EnsurePSMInit()
2012 : {
2013 : nsCOMPtr<nsISocketProviderService> spserv =
2014 10 : do_GetService(NS_SOCKETPROVIDERSERVICE_CONTRACTID);
2015 5 : if (spserv) {
2016 10 : nsCOMPtr<nsISocketProvider> provider;
2017 5 : spserv->GetSocketProvider("ssl", getter_AddRefs(provider));
2018 : }
2019 5 : }
2020 :
2021 : /**
2022 : * Test whether a URI is "about:blank". |uri| must not be null
2023 : */
2024 : inline bool
2025 0 : NS_IsAboutBlank(nsIURI *uri)
2026 : {
2027 : // GetSpec can be expensive for some URIs, so check the scheme first.
2028 0 : bool isAbout = false;
2029 0 : if (NS_FAILED(uri->SchemeIs("about", &isAbout)) || !isAbout) {
2030 0 : return false;
2031 : }
2032 :
2033 0 : nsCAutoString str;
2034 0 : uri->GetSpec(str);
2035 0 : return str.EqualsLiteral("about:blank");
2036 : }
2037 :
2038 :
2039 : inline nsresult
2040 3610 : NS_GenerateHostPort(const nsCString& host, PRInt32 port,
2041 : nsCString& hostLine)
2042 : {
2043 3610 : if (strchr(host.get(), ':')) {
2044 : // host is an IPv6 address literal and must be encapsulated in []'s
2045 0 : hostLine.Assign('[');
2046 : // scope id is not needed for Host header.
2047 0 : int scopeIdPos = host.FindChar('%');
2048 0 : if (scopeIdPos == -1)
2049 0 : hostLine.Append(host);
2050 0 : else if (scopeIdPos > 0)
2051 0 : hostLine.Append(Substring(host, 0, scopeIdPos));
2052 : else
2053 0 : return NS_ERROR_MALFORMED_URI;
2054 0 : hostLine.Append(']');
2055 : }
2056 : else
2057 3610 : hostLine.Assign(host);
2058 3610 : if (port != -1) {
2059 3138 : hostLine.Append(':');
2060 3138 : hostLine.AppendInt(port);
2061 : }
2062 3610 : return NS_OK;
2063 : }
2064 :
2065 : #endif // !nsNetUtil_h__
|