Back to index

lightning-sunbird  0.9+nobinonly
nsNetUtil.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* vim:set ts=4 sw=4 sts=4 et cin: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Bradley Baetz <bbaetz@student.usyd.edu.au>
00025  *   Malcolm Smith <malsmith@cs.rmit.edu.au>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #ifndef nsNetUtil_h__
00042 #define nsNetUtil_h__
00043 
00044 #include "nsNetError.h"
00045 #include "nsNetCID.h"
00046 #include "nsReadableUtils.h"
00047 #include "nsString.h"
00048 #include "nsMemory.h"
00049 #include "nsCOMPtr.h"
00050 #include "prio.h" // for read/write flags, permissions, etc.
00051 
00052 #include "nsIURI.h"
00053 #include "nsIInputStream.h"
00054 #include "nsIOutputStream.h"
00055 #include "nsISafeOutputStream.h"
00056 #include "nsIStreamListener.h"
00057 #include "nsIRequestObserverProxy.h"
00058 #include "nsIStreamListenerProxy.h" // XXX for nsIAsyncStreamListener
00059 #include "nsISimpleStreamListener.h"
00060 #include "nsILoadGroup.h"
00061 #include "nsIInterfaceRequestor.h"
00062 #include "nsIInterfaceRequestorUtils.h"
00063 #include "nsIIOService.h"
00064 #include "nsIServiceManager.h"
00065 #include "nsIChannel.h"
00066 #include "nsIInputStreamChannel.h"
00067 #include "nsITransport.h"
00068 #include "nsIStreamTransportService.h"
00069 #include "nsIHttpChannel.h"
00070 #include "nsIDownloader.h"
00071 #include "nsIStreamLoader.h"
00072 #include "nsIUnicharStreamLoader.h"
00073 #include "nsIPipe.h"
00074 #include "nsIProtocolHandler.h"
00075 #include "nsIFileProtocolHandler.h"
00076 #include "nsIStringStream.h"
00077 #include "nsILocalFile.h"
00078 #include "nsIFileStreams.h"
00079 #include "nsIProtocolProxyService.h"
00080 #include "nsIProxyInfo.h"
00081 #include "nsIFileStreams.h"
00082 #include "nsIBufferedStreams.h"
00083 #include "nsIInputStreamPump.h"
00084 #include "nsIAsyncStreamCopier.h"
00085 #include "nsIPersistentProperties2.h"
00086 #include "nsISyncStreamListener.h"
00087 #include "nsInterfaceRequestorAgg.h"
00088 #include "nsInt64.h"
00089 #include "nsINetUtil.h"
00090 
00091 // Helper, to simplify getting the I/O service.
00092 inline const nsGetServiceByCIDWithError
00093 do_GetIOService(nsresult* error = 0)
00094 {
00095     static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
00096     return nsGetServiceByCIDWithError(kIOServiceCID, error);
00097 }
00098 
00099 // private little helper function... don't call this directly!
00100 inline nsresult
00101 net_EnsureIOService(nsIIOService **ios, nsCOMPtr<nsIIOService> &grip)
00102 {
00103     nsresult rv = NS_OK;
00104     if (!*ios) {
00105         grip = do_GetIOService(&rv);
00106         *ios = grip;
00107     }
00108     return rv;
00109 }
00110 
00111 inline nsresult
00112 NS_NewURI(nsIURI **result, 
00113           const nsACString &spec, 
00114           const char *charset = nsnull,
00115           nsIURI *baseURI = nsnull,
00116           nsIIOService *ioService = nsnull)     // pass in nsIIOService to optimize callers
00117 {
00118     nsresult rv;
00119     nsCOMPtr<nsIIOService> grip;
00120     rv = net_EnsureIOService(&ioService, grip);
00121     if (ioService)
00122         rv = ioService->NewURI(spec, charset, baseURI, result);
00123     return rv; 
00124 }
00125 
00126 inline nsresult
00127 NS_NewURI(nsIURI* *result, 
00128           const nsAString& spec, 
00129           const char *charset = nsnull,
00130           nsIURI* baseURI = nsnull,
00131           nsIIOService* ioService = nsnull)     // pass in nsIIOService to optimize callers
00132 {
00133     return NS_NewURI(result, NS_ConvertUCS2toUTF8(spec), charset, baseURI, ioService);
00134 }
00135 
00136 inline nsresult
00137 NS_NewURI(nsIURI* *result, 
00138           const char *spec,
00139           nsIURI* baseURI = nsnull,
00140           nsIIOService* ioService = nsnull)     // pass in nsIIOService to optimize callers
00141 {
00142     return NS_NewURI(result, nsDependentCString(spec), nsnull, baseURI, ioService);
00143 }
00144 
00145 inline nsresult
00146 NS_NewFileURI(nsIURI* *result, 
00147               nsIFile* spec, 
00148               nsIIOService* ioService = nsnull)     // pass in nsIIOService to optimize callers
00149 {
00150     nsresult rv;
00151     nsCOMPtr<nsIIOService> grip;
00152     rv = net_EnsureIOService(&ioService, grip);
00153     if (ioService)
00154         rv = ioService->NewFileURI(spec, result);
00155     return rv;
00156 }
00157 
00158 inline nsresult
00159 NS_NewChannel(nsIChannel           **result, 
00160               nsIURI                *uri,
00161               nsIIOService          *ioService = nsnull,    // pass in nsIIOService to optimize callers
00162               nsILoadGroup          *loadGroup = nsnull,
00163               nsIInterfaceRequestor *callbacks = nsnull,
00164               PRUint32               loadFlags = nsIRequest::LOAD_NORMAL)
00165 {
00166     nsresult rv;
00167     nsCOMPtr<nsIIOService> grip;
00168     rv = net_EnsureIOService(&ioService, grip);
00169     if (ioService) {
00170         nsIChannel *chan;
00171         rv = ioService->NewChannelFromURI(uri, &chan);
00172         if (NS_SUCCEEDED(rv)) {
00173             if (loadGroup)
00174                 rv |= chan->SetLoadGroup(loadGroup);
00175             if (callbacks)
00176                 rv |= chan->SetNotificationCallbacks(callbacks);
00177             if (loadFlags != nsIRequest::LOAD_NORMAL)
00178                 rv |= chan->SetLoadFlags(loadFlags);
00179             if (NS_SUCCEEDED(rv))
00180                 *result = chan;
00181             else
00182                 NS_RELEASE(chan);
00183         }
00184     }
00185     return rv;
00186 }
00187 
00188 // Use this function with CAUTION. It creates a stream that blocks when you
00189 // Read() from it and blocking the UI thread is a bad idea. If you don't want
00190 // to implement a full blown asynchronous consumer (via nsIStreamListener) look
00191 // at nsIStreamLoader instead.
00192 inline nsresult
00193 NS_OpenURI(nsIInputStream       **result,
00194            nsIURI                *uri,
00195            nsIIOService          *ioService = nsnull,     // pass in nsIIOService to optimize callers
00196            nsILoadGroup          *loadGroup = nsnull,
00197            nsIInterfaceRequestor *callbacks = nsnull,
00198            PRUint32               loadFlags = nsIRequest::LOAD_NORMAL,
00199            nsIChannel           **channelOut = nsnull)
00200 {
00201     nsresult rv;
00202     nsCOMPtr<nsIChannel> channel;
00203     rv = NS_NewChannel(getter_AddRefs(channel), uri, ioService,
00204                        loadGroup, callbacks, loadFlags);
00205     if (NS_SUCCEEDED(rv)) {
00206         nsIInputStream *stream;
00207         rv = channel->Open(&stream);
00208         if (NS_SUCCEEDED(rv)) {
00209             *result = stream;
00210             if (channelOut) {
00211                 *channelOut = nsnull;
00212                 channel.swap(*channelOut);
00213             }
00214         }
00215     }
00216     return rv;
00217 }
00218 
00219 inline nsresult
00220 NS_OpenURI(nsIStreamListener     *listener, 
00221            nsISupports           *context, 
00222            nsIURI                *uri,
00223            nsIIOService          *ioService = nsnull,     // pass in nsIIOService to optimize callers
00224            nsILoadGroup          *loadGroup = nsnull,
00225            nsIInterfaceRequestor *callbacks = nsnull,
00226            PRUint32               loadFlags = nsIRequest::LOAD_NORMAL)
00227 {
00228     nsresult rv;
00229     nsCOMPtr<nsIChannel> channel;
00230     rv = NS_NewChannel(getter_AddRefs(channel), uri, ioService,
00231                        loadGroup, callbacks, loadFlags);
00232     if (NS_SUCCEEDED(rv))
00233         rv = channel->AsyncOpen(listener, context);
00234     return rv;
00235 }
00236 
00237 inline nsresult
00238 NS_MakeAbsoluteURI(nsACString       &result,
00239                    const nsACString &spec, 
00240                    nsIURI           *baseURI, 
00241                    nsIIOService     *unused = nsnull)
00242 {
00243     nsresult rv;
00244     if (!baseURI) {
00245         NS_WARNING("It doesn't make sense to not supply a base URI");
00246         result = spec;
00247         rv = NS_OK;
00248     }
00249     else if (spec.IsEmpty())
00250         rv = baseURI->GetSpec(result);
00251     else
00252         rv = baseURI->Resolve(spec, result);
00253     return rv;
00254 }
00255 
00256 inline nsresult
00257 NS_MakeAbsoluteURI(char        **result,
00258                    const char   *spec, 
00259                    nsIURI       *baseURI, 
00260                    nsIIOService *unused = nsnull)
00261 {
00262     nsresult rv;
00263     nsCAutoString resultBuf;
00264     rv = NS_MakeAbsoluteURI(resultBuf, nsDependentCString(spec), baseURI);
00265     if (NS_SUCCEEDED(rv)) {
00266         *result = ToNewCString(resultBuf);
00267         if (!*result)
00268             rv = NS_ERROR_OUT_OF_MEMORY;
00269     }
00270     return rv;
00271 }
00272 
00273 inline nsresult
00274 NS_MakeAbsoluteURI(nsAString       &result,
00275                    const nsAString &spec, 
00276                    nsIURI          *baseURI,
00277                    nsIIOService    *unused = nsnull)
00278 {
00279     nsresult rv;
00280     if (!baseURI) {
00281         NS_WARNING("It doesn't make sense to not supply a base URI");
00282         result = spec;
00283         rv = NS_OK;
00284     }
00285     else {
00286         nsCAutoString resultBuf;
00287         if (spec.IsEmpty())
00288             rv = baseURI->GetSpec(resultBuf);
00289         else
00290             rv = baseURI->Resolve(NS_ConvertUCS2toUTF8(spec), resultBuf);
00291         if (NS_SUCCEEDED(rv))
00292             CopyUTF8toUTF16(resultBuf, result);
00293     }
00294     return rv;
00295 }
00296 
00297 inline nsresult
00298 NS_NewInputStreamChannel(nsIChannel      **result,
00299                          nsIURI           *uri,
00300                          nsIInputStream   *stream,
00301                          const nsACString &contentType,
00302                          const nsACString *contentCharset)
00303 {
00304     nsresult rv;
00305     static NS_DEFINE_CID(kInputStreamChannelCID, NS_INPUTSTREAMCHANNEL_CID);
00306     nsCOMPtr<nsIInputStreamChannel> channel =
00307         do_CreateInstance(kInputStreamChannelCID, &rv);
00308     if (NS_SUCCEEDED(rv)) {
00309         rv |= channel->SetURI(uri);
00310         rv |= channel->SetContentStream(stream);
00311         rv |= channel->SetContentType(contentType);
00312         if (contentCharset && !contentCharset->IsEmpty()) {
00313             rv |= channel->SetContentCharset(*contentCharset);
00314         }
00315         if (NS_SUCCEEDED(rv))
00316             NS_ADDREF(*result = channel);
00317     }
00318     return rv;
00319 }
00320 
00321 inline nsresult
00322 NS_NewInputStreamChannel(nsIChannel      **result,
00323                          nsIURI           *uri,
00324                          nsIInputStream   *stream,
00325                          const nsACString &contentType    = EmptyCString())
00326 {
00327     return NS_NewInputStreamChannel(result, uri, stream, contentType, nsnull);
00328 }
00329 
00330 inline nsresult
00331 NS_NewInputStreamChannel(nsIChannel      **result,
00332                          nsIURI           *uri,
00333                          nsIInputStream   *stream,
00334                          const nsACString &contentType,
00335                          const nsACString &contentCharset)
00336 {
00337     return NS_NewInputStreamChannel(result, uri, stream, contentType,
00338                                     &contentCharset);
00339 }
00340 
00341 inline nsresult
00342 NS_NewInputStreamPump(nsIInputStreamPump **result,
00343                       nsIInputStream      *stream,
00344                       PRInt64              streamPos = nsInt64(-1),
00345                       PRInt64              streamLen = nsInt64(-1),
00346                       PRUint32             segsize = 0,
00347                       PRUint32             segcount = 0,
00348                       PRBool               closeWhenDone = PR_FALSE)
00349 {
00350     nsresult rv;
00351     static NS_DEFINE_CID(kInputStreamPumpCID, NS_INPUTSTREAMPUMP_CID);
00352     nsCOMPtr<nsIInputStreamPump> pump =
00353         do_CreateInstance(kInputStreamPumpCID, &rv);
00354     if (NS_SUCCEEDED(rv)) {
00355         rv = pump->Init(stream, streamPos, streamLen,
00356                         segsize, segcount, closeWhenDone);
00357         if (NS_SUCCEEDED(rv))
00358             NS_ADDREF(*result = pump);
00359     }
00360     return rv;
00361 }
00362 
00363 // NOTE: you will need to specify whether or not your streams are buffered
00364 // (i.e., do they implement ReadSegments/WriteSegments).  the default
00365 // assumption of TRUE for both streams might not be right for you!
00366 inline nsresult
00367 NS_NewAsyncStreamCopier(nsIAsyncStreamCopier **result,
00368                         nsIInputStream        *source,
00369                         nsIOutputStream       *sink,
00370                         nsIEventTarget        *target,
00371                         PRBool                 sourceBuffered = PR_TRUE,
00372                         PRBool                 sinkBuffered = PR_TRUE,
00373                         PRUint32               chunkSize = 0)
00374 {
00375     nsresult rv;
00376     static NS_DEFINE_CID(kAsyncStreamCopierCID, NS_ASYNCSTREAMCOPIER_CID);
00377     nsCOMPtr<nsIAsyncStreamCopier> copier =
00378         do_CreateInstance(kAsyncStreamCopierCID, &rv);
00379     if (NS_SUCCEEDED(rv)) {
00380         rv = copier->Init(source, sink, target, sourceBuffered, sinkBuffered, chunkSize);
00381         if (NS_SUCCEEDED(rv))
00382             NS_ADDREF(*result = copier);
00383     }
00384     return rv;
00385 }
00386 
00387 inline nsresult
00388 NS_NewLoadGroup(nsILoadGroup      **result,
00389                 nsIRequestObserver *obs)
00390 {
00391     nsresult rv;
00392     static NS_DEFINE_CID(kLoadGroupCID, NS_LOADGROUP_CID);
00393     nsCOMPtr<nsILoadGroup> group =
00394         do_CreateInstance(kLoadGroupCID, &rv);
00395     if (NS_SUCCEEDED(rv)) {
00396         rv = group->SetGroupObserver(obs);
00397         if (NS_SUCCEEDED(rv))
00398             NS_ADDREF(*result = group);
00399     }
00400     return rv;
00401 }
00402 
00403 inline nsresult
00404 NS_NewDownloader(nsIStreamListener   **result,
00405                  nsIDownloadObserver  *observer,
00406                  nsIFile              *downloadLocation = nsnull)
00407 {
00408     nsresult rv;
00409     static NS_DEFINE_CID(kDownloaderCID, NS_DOWNLOADER_CID);
00410     nsCOMPtr<nsIDownloader> downloader =
00411         do_CreateInstance(kDownloaderCID, &rv);
00412     if (NS_SUCCEEDED(rv)) {
00413         rv = downloader->Init(observer, downloadLocation);
00414         if (NS_SUCCEEDED(rv))
00415             NS_ADDREF(*result = downloader);
00416     }
00417     return rv;
00418 }
00419 
00420 inline nsresult
00421 NS_NewStreamLoader(nsIStreamLoader        **aResult,
00422                    nsIChannel              *aChannel,
00423                    nsIStreamLoaderObserver *aObserver,
00424                    nsISupports             *aContext)
00425 {
00426     nsresult rv;
00427     static NS_DEFINE_CID(kStreamLoaderCID, NS_STREAMLOADER_CID);
00428     nsCOMPtr<nsIStreamLoader> loader =
00429         do_CreateInstance(kStreamLoaderCID, &rv);
00430     if (NS_SUCCEEDED(rv)) {
00431         rv = loader->Init(aChannel, aObserver, aContext);
00432         if (NS_SUCCEEDED(rv))
00433             NS_ADDREF(*aResult = loader);
00434     }
00435     return rv;
00436 }
00437 
00438 inline nsresult
00439 NS_NewStreamLoader(nsIStreamLoader        **result,
00440                    nsIURI                  *uri,
00441                    nsIStreamLoaderObserver *observer,
00442                    nsISupports             *context   = nsnull,
00443                    nsILoadGroup            *loadGroup = nsnull,
00444                    nsIInterfaceRequestor   *callbacks = nsnull,
00445                    PRUint32                 loadFlags = nsIRequest::LOAD_NORMAL,
00446                    nsIURI                  *referrer  = nsnull)
00447 {
00448     nsresult rv;
00449     nsCOMPtr<nsIChannel> channel;
00450     rv = NS_NewChannel(getter_AddRefs(channel),
00451                        uri,
00452                        nsnull,
00453                        loadGroup,
00454                        callbacks,
00455                        loadFlags);
00456     if (NS_SUCCEEDED(rv)) {
00457         nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
00458         if (httpChannel)
00459             httpChannel->SetReferrer(referrer);
00460         rv = NS_NewStreamLoader(result, channel, observer, context);
00461     }
00462     return rv;
00463 }
00464 
00465 inline nsresult
00466 NS_NewUnicharStreamLoader(nsIUnicharStreamLoader        **aResult,
00467                           nsIChannel                     *aChannel,
00468                           nsIUnicharStreamLoaderObserver *aObserver,
00469                           nsISupports                    *aContext     = nsnull,
00470                           PRUint32                        aSegmentSize = nsIUnicharStreamLoader::DEFAULT_SEGMENT_SIZE)
00471 {
00472     nsresult rv;
00473     static NS_DEFINE_CID(kUnicharStreamLoaderCID, NS_UNICHARSTREAMLOADER_CID);
00474     nsCOMPtr<nsIUnicharStreamLoader> loader =
00475         do_CreateInstance(kUnicharStreamLoaderCID, &rv);
00476     if (NS_SUCCEEDED(rv)) {
00477         rv = loader->Init(aChannel, aObserver, aContext, aSegmentSize);
00478         if (NS_SUCCEEDED(rv))
00479             NS_ADDREF(*aResult = loader);
00480     }
00481     return rv;
00482 }
00483 
00484 inline nsresult
00485 NS_NewSyncStreamListener(nsIStreamListener **aResult,
00486                          nsIInputStream    **aStream)
00487 {
00488     nsresult rv;
00489     static NS_DEFINE_CID(kSyncStreamListenerCID, NS_SYNCSTREAMLISTENER_CID);
00490     nsCOMPtr<nsISyncStreamListener> listener =
00491         do_CreateInstance(kSyncStreamListenerCID, &rv);
00492     if (NS_SUCCEEDED(rv)) {
00493         rv = listener->GetInputStream(aStream);
00494         if (NS_SUCCEEDED(rv))
00495             NS_ADDREF(*aResult = listener);
00496     }
00497     return rv;
00498 }
00499 
00507 inline nsresult
00508 NS_ImplementChannelOpen(nsIChannel      *aChannel,
00509                         nsIInputStream **aResult)
00510 {
00511     nsCOMPtr<nsIStreamListener> listener;
00512     nsCOMPtr<nsIInputStream> stream;
00513     nsresult rv = NS_NewSyncStreamListener(getter_AddRefs(listener),
00514                                            getter_AddRefs(stream));
00515     if (NS_SUCCEEDED(rv)) {
00516         rv = aChannel->AsyncOpen(listener, nsnull);
00517         if (NS_SUCCEEDED(rv)) {
00518             PRUint32 n;
00519             // block until the initial response is received or an error occurs.
00520             rv = stream->Available(&n);
00521             if (NS_SUCCEEDED(rv))
00522                 NS_ADDREF(*aResult = stream);
00523         }
00524     }
00525     return rv;
00526 }
00527 
00528 inline nsresult
00529 NS_NewRequestObserverProxy(nsIRequestObserver **aResult,
00530                            nsIRequestObserver  *aObserver,
00531                            nsIEventQueue       *aEventQ = nsnull)
00532 {
00533     nsresult rv;
00534     static NS_DEFINE_CID(kRequestObserverProxyCID, NS_REQUESTOBSERVERPROXY_CID);
00535     nsCOMPtr<nsIRequestObserverProxy> proxy =
00536         do_CreateInstance(kRequestObserverProxyCID, &rv);
00537     if (NS_SUCCEEDED(rv)) {
00538         rv = proxy->Init(aObserver, aEventQ);
00539         if (NS_SUCCEEDED(rv))
00540             NS_ADDREF(*aResult = proxy);
00541     }
00542     return rv;
00543 }
00544 
00545 inline nsresult
00546 NS_NewSimpleStreamListener(nsIStreamListener **aResult,
00547                            nsIOutputStream    *aSink,
00548                            nsIRequestObserver *aObserver = nsnull)
00549 {
00550     nsresult rv;
00551     static NS_DEFINE_CID(kSimpleStreamListenerCID, NS_SIMPLESTREAMLISTENER_CID);
00552     nsCOMPtr<nsISimpleStreamListener> listener = 
00553         do_CreateInstance(kSimpleStreamListenerCID, &rv);
00554     if (NS_SUCCEEDED(rv)) {
00555         rv = listener->Init(aSink, aObserver);
00556         if (NS_SUCCEEDED(rv))
00557             NS_ADDREF(*aResult = listener);
00558     }
00559     return rv;
00560 }
00561 
00562 inline nsresult
00563 NS_NewAsyncStreamListener(nsIStreamListener **result,
00564                           nsIStreamListener  *receiver,
00565                           nsIEventQueue      *eventQueue)
00566 {
00567     nsresult rv;
00568     static NS_DEFINE_CID(kAsyncStreamListenerCID, NS_ASYNCSTREAMLISTENER_CID);
00569     nsCOMPtr<nsIAsyncStreamListener> lsnr =
00570         do_CreateInstance(kAsyncStreamListenerCID, &rv);
00571     if (NS_SUCCEEDED(rv)) {
00572         rv = lsnr->Init(receiver, eventQueue);
00573         if (NS_SUCCEEDED(rv))
00574             NS_ADDREF(*result = lsnr);
00575     }
00576     return rv;
00577 }
00578 
00579 inline nsresult
00580 NS_CheckPortSafety(PRInt32       port,
00581                    const char   *scheme,
00582                    nsIIOService *ioService = nsnull)
00583 {
00584     nsresult rv;
00585     nsCOMPtr<nsIIOService> grip;
00586     rv = net_EnsureIOService(&ioService, grip);
00587     if (ioService) {
00588         PRBool allow;
00589         rv = ioService->AllowPort(port, scheme, &allow);
00590         if (NS_SUCCEEDED(rv) && !allow)
00591             rv = NS_ERROR_PORT_ACCESS_NOT_ALLOWED;
00592     }
00593     return rv;
00594 }
00595 
00596 inline nsresult
00597 NS_NewProxyInfo(const nsACString &type,
00598                 const nsACString &host,
00599                 PRInt32           port,
00600                 PRUint32          flags,
00601                 nsIProxyInfo    **result)
00602 {
00603     nsresult rv;
00604     static NS_DEFINE_CID(kPPSServiceCID, NS_PROTOCOLPROXYSERVICE_CID);
00605     nsCOMPtr<nsIProtocolProxyService> pps = do_GetService(kPPSServiceCID, &rv);
00606     if (NS_SUCCEEDED(rv))
00607         rv = pps->NewProxyInfo(type, host, port, flags, PR_UINT32_MAX, nsnull,
00608                                result);
00609     return rv; 
00610 }
00611 
00612 inline nsresult
00613 NS_GetFileProtocolHandler(nsIFileProtocolHandler **result,
00614                           nsIIOService            *ioService = nsnull)
00615 {
00616     nsresult rv;
00617     nsCOMPtr<nsIIOService> grip;
00618     rv = net_EnsureIOService(&ioService, grip);
00619     if (ioService) {
00620         nsCOMPtr<nsIProtocolHandler> handler;
00621         rv = ioService->GetProtocolHandler("file", getter_AddRefs(handler));
00622         if (NS_SUCCEEDED(rv))
00623             rv = CallQueryInterface(handler, result);
00624     }
00625     return rv;
00626 }
00627 
00628 inline nsresult
00629 NS_GetFileFromURLSpec(const nsACString  &inURL,
00630                       nsIFile          **result,
00631                       nsIIOService      *ioService = nsnull)
00632 {
00633     nsresult rv;
00634     nsCOMPtr<nsIFileProtocolHandler> fileHandler;
00635     rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
00636     if (NS_SUCCEEDED(rv))
00637         rv = fileHandler->GetFileFromURLSpec(inURL, result);
00638     return rv;
00639 }
00640 
00641 inline nsresult
00642 NS_GetURLSpecFromFile(nsIFile      *aFile,
00643                       nsACString   &aUrl,
00644                       nsIIOService *ioService = nsnull)
00645 {
00646     nsresult rv;
00647     nsCOMPtr<nsIFileProtocolHandler> fileHandler;
00648     rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
00649     if (NS_SUCCEEDED(rv))
00650         rv = fileHandler->GetURLSpecFromFile(aFile, aUrl);
00651     return rv;
00652 }
00653 
00654 inline nsresult
00655 NS_ExamineForProxy(const char    *scheme,
00656                    const char    *host,
00657                    PRInt32        port, 
00658                    nsIProxyInfo **proxyInfo)
00659 {
00660     nsresult rv;
00661     static NS_DEFINE_CID(kPPSServiceCID, NS_PROTOCOLPROXYSERVICE_CID);
00662     nsCOMPtr<nsIProtocolProxyService> pps = do_GetService(kPPSServiceCID, &rv);
00663     if (NS_SUCCEEDED(rv)) {
00664         nsCAutoString spec(scheme);
00665         spec.Append("://");
00666         spec.Append(host);
00667         spec.Append(':');
00668         spec.AppendInt(port);
00669         // XXXXX - Under no circumstances whatsoever should any code which
00670         // wants a uri do this. I do this here because I do not, in fact,
00671         // actually want a uri (the dummy uris created here may not be 
00672         // syntactically valid for the specific protocol), and all we need
00673         // is something which has a valid scheme, hostname, and a string
00674         // to pass to PAC if needed - bbaetz
00675         static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);    
00676         nsCOMPtr<nsIURI> uri = do_CreateInstance(kStandardURLCID, &rv);
00677         if (NS_SUCCEEDED(rv)) {
00678             rv = uri->SetSpec(spec);
00679             if (NS_SUCCEEDED(rv))
00680                 rv = pps->Resolve(uri, 0, proxyInfo);
00681         }
00682     }
00683     return rv;
00684 }
00685 
00686 inline nsresult
00687 NS_ParseContentType(const nsACString &rawContentType,
00688                     nsCString        &contentType,
00689                     nsCString        &contentCharset)
00690 {
00691     // contentCharset is left untouched if not present in rawContentType
00692     nsresult rv;
00693     nsCOMPtr<nsINetUtil> util = do_GetIOService(&rv);
00694     NS_ENSURE_SUCCESS(rv, rv);
00695     nsCString charset;
00696     PRBool hadCharset;
00697     rv = util->ParseContentType(rawContentType, charset, &hadCharset,
00698                                 contentType);
00699     if (NS_SUCCEEDED(rv) && hadCharset)
00700         contentCharset = charset;
00701     return rv;
00702 }
00703 
00704 inline nsresult
00705 NS_NewLocalFileInputStream(nsIInputStream **aResult,
00706                            nsIFile         *aFile,
00707                            PRInt32          aIOFlags       = -1,
00708                            PRInt32          aPerm          = -1,
00709                            PRInt32          aBehaviorFlags = 0)
00710 {
00711     nsresult rv;
00712     static NS_DEFINE_CID(kLocalFileInputStreamCID, NS_LOCALFILEINPUTSTREAM_CID);
00713     nsCOMPtr<nsIFileInputStream> in =
00714         do_CreateInstance(kLocalFileInputStreamCID, &rv);
00715     if (NS_SUCCEEDED(rv)) {
00716         rv = in->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
00717         if (NS_SUCCEEDED(rv))
00718             NS_ADDREF(*aResult = in);
00719     }
00720     return rv;
00721 }
00722 
00723 inline nsresult
00724 NS_NewLocalFileOutputStream(nsIOutputStream **aResult,
00725                             nsIFile          *aFile,
00726                             PRInt32           aIOFlags       = -1,
00727                             PRInt32           aPerm          = -1,
00728                             PRInt32           aBehaviorFlags = 0)
00729 {
00730     nsresult rv;
00731     static NS_DEFINE_CID(kLocalFileOutputStreamCID, NS_LOCALFILEOUTPUTSTREAM_CID);
00732     nsCOMPtr<nsIFileOutputStream> out =
00733         do_CreateInstance(kLocalFileOutputStreamCID, &rv);
00734     if (NS_SUCCEEDED(rv)) {
00735         rv = out->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
00736         if (NS_SUCCEEDED(rv))
00737             NS_ADDREF(*aResult = out);
00738     }
00739     return rv;
00740 }
00741 
00742 // returns a file output stream which can be QI'ed to nsISafeOutputStream.
00743 inline nsresult
00744 NS_NewSafeLocalFileOutputStream(nsIOutputStream **aResult,
00745                                 nsIFile          *aFile,
00746                                 PRInt32           aIOFlags       = -1,
00747                                 PRInt32           aPerm          = -1,
00748                                 PRInt32           aBehaviorFlags = 0)
00749 {
00750     nsresult rv;
00751     static NS_DEFINE_CID(kSafeLocalFileOutputStreamCID, NS_SAFELOCALFILEOUTPUTSTREAM_CID);
00752     nsCOMPtr<nsIFileOutputStream> out =
00753         do_CreateInstance(kSafeLocalFileOutputStreamCID, &rv);
00754     if (NS_SUCCEEDED(rv)) {
00755         rv = out->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
00756         if (NS_SUCCEEDED(rv))
00757             NS_ADDREF(*aResult = out);
00758     }
00759     return rv;
00760 }
00761 
00762 // returns the input end of a pipe.  the output end of the pipe
00763 // is attached to the original stream.  data from the original
00764 // stream is read into the pipe on a background thread.
00765 inline nsresult
00766 NS_BackgroundInputStream(nsIInputStream **aResult,
00767                          nsIInputStream  *aStream,
00768                          PRUint32         aSegmentSize  = 0,
00769                          PRUint32         aSegmentCount = 0)
00770 {
00771     nsresult rv;
00772     nsCOMPtr<nsIStreamTransportService> sts =
00773         do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
00774     if (NS_SUCCEEDED(rv)) {
00775         nsCOMPtr<nsITransport> inTransport;
00776         rv = sts->CreateInputTransport(aStream, nsInt64(-1), nsInt64(-1), PR_TRUE,
00777                                        getter_AddRefs(inTransport));
00778         if (NS_SUCCEEDED(rv))
00779             rv = inTransport->OpenInputStream(nsITransport::OPEN_BLOCKING,
00780                                               aSegmentSize, aSegmentCount,
00781                                               aResult);
00782     }
00783     return rv;
00784 }
00785 
00786 // returns the output end of a pipe.  the input end of the pipe
00787 // is attached to the original stream.  data written to the pipe
00788 // is copied to the original stream on a background thread.
00789 inline nsresult
00790 NS_BackgroundOutputStream(nsIOutputStream **aResult,
00791                           nsIOutputStream  *aStream,
00792                           PRUint32          aSegmentSize  = 0,
00793                           PRUint32          aSegmentCount = 0)
00794 {
00795     nsresult rv;
00796     nsCOMPtr<nsIStreamTransportService> sts =
00797         do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
00798     if (NS_SUCCEEDED(rv)) {
00799         nsCOMPtr<nsITransport> inTransport;
00800         rv = sts->CreateOutputTransport(aStream, nsInt64(-1), nsInt64(-1), PR_TRUE,
00801                                         getter_AddRefs(inTransport));
00802         if (NS_SUCCEEDED(rv))
00803             rv = inTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING,
00804                                                aSegmentSize, aSegmentCount,
00805                                                aResult);
00806     }
00807     return rv;
00808 }
00809 
00810 inline nsresult
00811 NS_NewBufferedInputStream(nsIInputStream **aResult,
00812                           nsIInputStream *aStr,
00813                           PRUint32        aBufferSize)
00814 {
00815     nsresult rv;
00816     static NS_DEFINE_CID(kBufferedInputStreamCID, NS_BUFFEREDINPUTSTREAM_CID);
00817     nsCOMPtr<nsIBufferedInputStream> in =
00818         do_CreateInstance(kBufferedInputStreamCID, &rv);
00819     if (NS_SUCCEEDED(rv)) {
00820         rv = in->Init(aStr, aBufferSize);
00821         if (NS_SUCCEEDED(rv))
00822             NS_ADDREF(*aResult = in);
00823     }
00824     return rv;
00825 }
00826 
00827 // note: the resulting stream can be QI'ed to nsISafeOutputStream iff the
00828 // provided stream supports it.
00829 inline nsresult
00830 NS_NewBufferedOutputStream(nsIOutputStream **aResult,
00831                            nsIOutputStream  *aStr,
00832                            PRUint32          aBufferSize)
00833 {
00834     nsresult rv;
00835     static NS_DEFINE_CID(kBufferedOutputStreamCID, NS_BUFFEREDOUTPUTSTREAM_CID);
00836     nsCOMPtr<nsIBufferedOutputStream> out =
00837         do_CreateInstance(kBufferedOutputStreamCID, &rv);
00838     if (NS_SUCCEEDED(rv)) {
00839         rv = out->Init(aStr, aBufferSize);
00840         if (NS_SUCCEEDED(rv))
00841             NS_ADDREF(*aResult = out);
00842     }
00843     return rv;
00844 }
00845 
00846 // returns an input stream compatible with nsIUploadChannel::SetUploadStream()
00847 inline nsresult
00848 NS_NewPostDataStream(nsIInputStream  **result,
00849                      PRBool            isFile,
00850                      const nsACString &data,
00851                      PRUint32          encodeFlags,
00852                      nsIIOService     *unused = nsnull)
00853 {
00854     if (isFile) {
00855         nsresult rv;
00856         nsCOMPtr<nsILocalFile> file;
00857         nsCOMPtr<nsIInputStream> fileStream;
00858 
00859         rv = NS_NewNativeLocalFile(data, PR_FALSE, getter_AddRefs(file));
00860         if (NS_SUCCEEDED(rv)) {
00861             rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file);
00862             if (NS_SUCCEEDED(rv)) {
00863                 // wrap the file stream with a buffered input stream
00864                 rv = NS_NewBufferedInputStream(result, fileStream, 8192);
00865             }
00866         }
00867         return rv;
00868     }
00869 
00870     // otherwise, create a string stream for the data (copies)
00871     return NS_NewCStringInputStream(result, data);
00872 }
00873 
00874 inline nsresult
00875 NS_LoadPersistentPropertiesFromURI(nsIPersistentProperties **result,
00876                                    nsIURI                  *uri,
00877                                    nsIIOService            *ioService = nsnull)
00878 {
00879     nsCOMPtr<nsIInputStream> in;
00880     nsresult rv = NS_OpenURI(getter_AddRefs(in), uri, ioService);
00881     if (NS_SUCCEEDED(rv)) {
00882         nsCOMPtr<nsIPersistentProperties> properties = 
00883             do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID, &rv);
00884         if (NS_SUCCEEDED(rv)) {
00885             rv = properties->Load(in);
00886             if (NS_SUCCEEDED(rv))
00887                 NS_ADDREF(*result = properties);
00888         }
00889     }
00890     return rv;
00891 }
00892 
00893 inline nsresult
00894 NS_LoadPersistentPropertiesFromURISpec(nsIPersistentProperties **result,
00895                                        const nsACString        &spec,
00896                                        const char              *charset = nsnull,
00897                                        nsIURI                  *baseURI = nsnull,
00898                                        nsIIOService            *ioService = nsnull)     
00899 {
00900     nsCOMPtr<nsIURI> uri;
00901     nsresult rv = 
00902         NS_NewURI(getter_AddRefs(uri), spec, charset, baseURI, ioService);
00903 
00904     if (NS_SUCCEEDED(rv))
00905         rv = NS_LoadPersistentPropertiesFromURI(result, uri, ioService);
00906 
00907     return rv;
00908 }
00909 
00917 inline void
00918 NS_QueryNotificationCallbacks(nsIChannel   *aChannel,
00919                               const nsIID  &aIID,
00920                               void        **aResult)
00921 {
00922     NS_PRECONDITION(aChannel, "null channel");
00923     *aResult = nsnull;
00924 
00925     nsCOMPtr<nsIInterfaceRequestor> cbs;
00926     aChannel->GetNotificationCallbacks(getter_AddRefs(cbs));
00927     if (cbs)
00928         cbs->GetInterface(aIID, aResult);
00929     if (!*aResult) {
00930         // try load group's notification callbacks...
00931         nsCOMPtr<nsILoadGroup> loadGroup;
00932         aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
00933         if (loadGroup) {
00934             loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
00935             if (cbs)
00936                 cbs->GetInterface(aIID, aResult);
00937         }
00938     }
00939 }
00940 
00941 /* template helper */
00942 template <class T> inline void
00943 NS_QueryNotificationCallbacks(nsIChannel  *aChannel,
00944                               nsCOMPtr<T> &aResult)
00945 {
00946     NS_QueryNotificationCallbacks(aChannel, NS_GET_IID(T),
00947                                   getter_AddRefs(aResult));
00948 }
00949 
00954 inline void
00955 NS_QueryNotificationCallbacks(nsIInterfaceRequestor  *aCallbacks,
00956                               nsILoadGroup           *aLoadGroup,
00957                               const nsIID            &aIID,
00958                               void                  **aResult)
00959 {
00960     *aResult = nsnull;
00961 
00962     if (aCallbacks)
00963         aCallbacks->GetInterface(aIID, aResult);
00964     if (!*aResult) {
00965         // try load group's notification callbacks...
00966         if (aLoadGroup) {
00967             nsCOMPtr<nsIInterfaceRequestor> cbs;
00968             aLoadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
00969             if (cbs)
00970                 cbs->GetInterface(aIID, aResult);
00971         }
00972     }
00973 }
00974 
00975 /* template helper */
00976 template <class T> inline void
00977 NS_QueryNotificationCallbacks(nsIInterfaceRequestor *aCallbacks,
00978                               nsILoadGroup          *aLoadGroup,
00979                               nsCOMPtr<T>           &aResult)
00980 {
00981     NS_QueryNotificationCallbacks(aCallbacks, aLoadGroup,
00982                                   NS_GET_IID(T),
00983                                   getter_AddRefs(aResult));
00984 }
00985 
00986 /* template helper */
00987 template <class T> inline void
00988 NS_QueryNotificationCallbacks(const nsCOMPtr<nsIInterfaceRequestor> &aCallbacks,
00989                               const nsCOMPtr<nsILoadGroup>          &aLoadGroup,
00990                               nsCOMPtr<T>                     &aResult)
00991 {
00992     NS_QueryNotificationCallbacks(aCallbacks.get(), aLoadGroup.get(), aResult);
00993 }
00994 
00995 /* template helper */
00996 template <class T> inline void
00997 NS_QueryNotificationCallbacks(const nsCOMPtr<nsIChannel> &aChannel,
00998                               nsCOMPtr<T>          &aResult)
00999 {
01000     NS_QueryNotificationCallbacks(aChannel.get(), aResult);
01001 }
01002 
01008 inline nsresult
01009 NS_NewNotificationCallbacksAggregation(nsIInterfaceRequestor  *aCallbacks,
01010                                        nsILoadGroup           *aLoadGroup,
01011                                        nsIInterfaceRequestor **aResult)
01012 {
01013     nsCOMPtr<nsIInterfaceRequestor> cbs;
01014     if (aLoadGroup)
01015         aLoadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
01016     return NS_NewInterfaceRequestorAggregation(aCallbacks, cbs, aResult);
01017 }
01018 
01019 #endif // !nsNetUtil_h__