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