LCOV - code coverage report
Current view: directory - netwerk/base/src - nsURIChecker.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 131 0 0.0 %
Date: 2012-06-02 Functions: 25 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2001
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Akkana Peck <akkana@netscape.com> (original author)
      24                 :  *   Darin Fisher <darin@meer.net>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "nsURIChecker.h"
      41                 : #include "nsIServiceManager.h"
      42                 : #include "nsIAuthPrompt.h"
      43                 : #include "nsIHttpChannel.h"
      44                 : #include "nsNetUtil.h"
      45                 : #include "nsString.h"
      46                 : #include "nsIAsyncVerifyRedirectCallback.h"
      47                 : 
      48                 : //-----------------------------------------------------------------------------
      49                 : 
      50                 : static bool
      51               0 : ServerIsNES3x(nsIHttpChannel *httpChannel)
      52                 : {
      53               0 :     nsCAutoString server;
      54               0 :     httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Server"), server);
      55                 :     // case sensitive string comparison is OK here.  the server string
      56                 :     // is a well-known value, so we should not have to worry about it
      57                 :     // being case-smashed or otherwise case-mutated.
      58                 :     return StringBeginsWith(server,
      59               0 :                             NS_LITERAL_CSTRING("Netscape-Enterprise/3."));
      60                 : }
      61                 : 
      62                 : //-----------------------------------------------------------------------------
      63                 : 
      64               0 : NS_IMPL_ISUPPORTS6(nsURIChecker,
      65                 :                    nsIURIChecker,
      66                 :                    nsIRequest,
      67                 :                    nsIRequestObserver,
      68                 :                    nsIStreamListener,
      69                 :                    nsIChannelEventSink,
      70                 :                    nsIInterfaceRequestor)
      71                 : 
      72               0 : nsURIChecker::nsURIChecker()
      73                 :     : mStatus(NS_OK)
      74                 :     , mIsPending(false)
      75               0 :     , mAllowHead(true)
      76                 : {
      77               0 : }
      78                 : 
      79                 : void
      80               0 : nsURIChecker::SetStatusAndCallBack(nsresult aStatus)
      81                 : {
      82               0 :     mStatus = aStatus;
      83               0 :     mIsPending = false;
      84                 : 
      85               0 :     if (mObserver) {
      86               0 :         mObserver->OnStartRequest(this, mObserverContext);
      87               0 :         mObserver->OnStopRequest(this, mObserverContext, mStatus);
      88               0 :         mObserver = nsnull;
      89               0 :         mObserverContext = nsnull;
      90                 :     }
      91               0 : }
      92                 : 
      93                 : nsresult
      94               0 : nsURIChecker::CheckStatus()
      95                 : {
      96               0 :     NS_ASSERTION(mChannel, "no channel");
      97                 : 
      98                 :     nsresult status;
      99               0 :     nsresult rv = mChannel->GetStatus(&status);
     100                 :     // DNS errors and other obvious problems will return failure status
     101               0 :     if (NS_FAILED(rv) || NS_FAILED(status))
     102               0 :         return NS_BINDING_FAILED;
     103                 : 
     104                 :     // If status is zero, it might still be an error if it's http:
     105                 :     // http has data even when there's an error like a 404.
     106               0 :     nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
     107               0 :     if (!httpChannel)
     108               0 :         return NS_BINDING_SUCCEEDED;
     109                 : 
     110                 :     PRUint32 responseStatus;
     111               0 :     rv = httpChannel->GetResponseStatus(&responseStatus);
     112               0 :     if (NS_FAILED(rv))
     113               0 :         return NS_BINDING_FAILED;
     114                 : 
     115                 :     // If it's between 200-299, it's valid:
     116               0 :     if (responseStatus / 100 == 2)
     117               0 :         return NS_BINDING_SUCCEEDED;
     118                 : 
     119                 :     // If we got a 404 (not found), we need some extra checking:
     120                 :     // toplevel urls from Netscape Enterprise Server 3.6, like the old AOL-
     121                 :     // hosted http://www.mozilla.org, generate a 404 and will have to be
     122                 :     // retried without the head.
     123               0 :     if (responseStatus == 404) {
     124               0 :         if (mAllowHead && ServerIsNES3x(httpChannel)) {
     125               0 :             mAllowHead = false;
     126                 : 
     127                 :             // save the current value of mChannel in case we can't issue
     128                 :             // the new request for some reason.
     129               0 :             nsCOMPtr<nsIChannel> lastChannel = mChannel;
     130                 : 
     131               0 :             nsCOMPtr<nsIURI> uri;
     132                 :             PRUint32 loadFlags;
     133                 : 
     134               0 :             rv  = lastChannel->GetOriginalURI(getter_AddRefs(uri));
     135               0 :             rv |= lastChannel->GetLoadFlags(&loadFlags);
     136                 : 
     137                 :             // XXX we are carrying over the load flags, but what about other
     138                 :             // parameters that may have been set on lastChannel??
     139                 : 
     140               0 :             if (NS_SUCCEEDED(rv)) {
     141               0 :                 rv = Init(uri);
     142               0 :                 if (NS_SUCCEEDED(rv)) {
     143               0 :                     rv = mChannel->SetLoadFlags(loadFlags);
     144               0 :                     if (NS_SUCCEEDED(rv)) {
     145               0 :                         rv = AsyncCheck(mObserver, mObserverContext);
     146                 :                         // if we succeeded in loading the new channel, then we
     147                 :                         // want to return without notifying our observer.
     148               0 :                         if (NS_SUCCEEDED(rv))
     149               0 :                             return NS_BASE_STREAM_WOULD_BLOCK;
     150                 :                     }
     151                 :                 }
     152                 :             }
     153                 :             // it is important to update this so our observer will be able
     154                 :             // to access our baseChannel attribute if they want.
     155               0 :             mChannel = lastChannel;
     156                 :         }
     157                 :     }
     158                 : 
     159                 :     // If we get here, assume the resource does not exist.
     160               0 :     return NS_BINDING_FAILED;
     161                 : }
     162                 : 
     163                 : //-----------------------------------------------------------------------------
     164                 : // nsIURIChecker methods:
     165                 : //-----------------------------------------------------------------------------
     166                 : 
     167                 : NS_IMETHODIMP
     168               0 : nsURIChecker::Init(nsIURI *aURI)
     169                 : {
     170                 :     nsresult rv;
     171               0 :     nsCOMPtr<nsIIOService> ios = do_GetIOService(&rv);
     172               0 :     if (NS_FAILED(rv)) return rv;
     173                 : 
     174               0 :     rv = ios->NewChannelFromURI(aURI, getter_AddRefs(mChannel));
     175               0 :     if (NS_FAILED(rv)) return rv;
     176                 : 
     177               0 :     if (mAllowHead) {
     178               0 :         mAllowHead = false;
     179                 :         // See if it's an http channel, which needs special treatment:
     180               0 :         nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
     181               0 :         if (httpChannel) {
     182                 :             // We can have an HTTP channel that has a non-HTTP URL if
     183                 :             // we're doing FTP via an HTTP proxy, for example.  See for
     184                 :             // example bug 148813
     185               0 :             bool isReallyHTTP = false;
     186               0 :             aURI->SchemeIs("http", &isReallyHTTP);
     187               0 :             if (!isReallyHTTP)
     188               0 :                 aURI->SchemeIs("https", &isReallyHTTP);
     189               0 :             if (isReallyHTTP) {
     190               0 :                 httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("HEAD"));
     191                 :                 // set back to true so we'll know that this request is issuing
     192                 :                 // a HEAD request.  this is used down in OnStartRequest to
     193                 :                 // handle cases where we need to repeat the request as a normal
     194                 :                 // GET to deal with server borkage.
     195               0 :                 mAllowHead = true;
     196                 :             }
     197                 :         }
     198                 :     }
     199               0 :     return NS_OK;
     200                 : }
     201                 : 
     202                 : NS_IMETHODIMP
     203               0 : nsURIChecker::AsyncCheck(nsIRequestObserver *aObserver,
     204                 :                          nsISupports *aObserverContext)
     205                 : {
     206               0 :     NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED);
     207                 : 
     208                 :     // Hook us up to listen to redirects and the like (this creates a reference
     209                 :     // cycle!)
     210               0 :     mChannel->SetNotificationCallbacks(this);
     211                 :     
     212                 :     // and start the request:
     213               0 :     nsresult rv = mChannel->AsyncOpen(this, nsnull);
     214               0 :     if (NS_FAILED(rv))
     215               0 :         mChannel = nsnull;
     216                 :     else {
     217                 :         // ok, wait for OnStartRequest to fire.
     218               0 :         mIsPending = true;
     219               0 :         mObserver = aObserver;
     220               0 :         mObserverContext = aObserverContext;
     221                 :     }
     222               0 :     return rv;
     223                 : }
     224                 : 
     225                 : NS_IMETHODIMP
     226               0 : nsURIChecker::GetBaseChannel(nsIChannel **aChannel)
     227                 : {
     228               0 :     NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED);
     229               0 :     NS_ADDREF(*aChannel = mChannel);
     230               0 :     return NS_OK;
     231                 : }
     232                 : 
     233                 : //-----------------------------------------------------------------------------
     234                 : // nsIRequest methods:
     235                 : //-----------------------------------------------------------------------------
     236                 : 
     237                 : NS_IMETHODIMP
     238               0 : nsURIChecker::GetName(nsACString &aName)
     239                 : {
     240               0 :     NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED);
     241               0 :     return mChannel->GetName(aName);
     242                 : }
     243                 : 
     244                 : NS_IMETHODIMP
     245               0 : nsURIChecker::IsPending(bool *aPendingRet)
     246                 : {
     247               0 :     *aPendingRet = mIsPending;
     248               0 :     return NS_OK;
     249                 : }
     250                 : 
     251                 : NS_IMETHODIMP
     252               0 : nsURIChecker::GetStatus(nsresult* aStatusRet)
     253                 : {
     254               0 :     *aStatusRet = mStatus;
     255               0 :     return NS_OK;
     256                 : }
     257                 : 
     258                 : NS_IMETHODIMP
     259               0 : nsURIChecker::Cancel(nsresult status)
     260                 : {
     261               0 :     NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED);
     262               0 :     return mChannel->Cancel(status);
     263                 : }
     264                 : 
     265                 : NS_IMETHODIMP
     266               0 : nsURIChecker::Suspend()
     267                 : {
     268               0 :     NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED);
     269               0 :     return mChannel->Suspend();
     270                 : }
     271                 : 
     272                 : NS_IMETHODIMP
     273               0 : nsURIChecker::Resume()
     274                 : {
     275               0 :     NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED);
     276               0 :     return mChannel->Resume();
     277                 : }
     278                 : 
     279                 : NS_IMETHODIMP
     280               0 : nsURIChecker::GetLoadGroup(nsILoadGroup **aLoadGroup)
     281                 : {
     282               0 :     NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED);
     283               0 :     return mChannel->GetLoadGroup(aLoadGroup);
     284                 : }
     285                 : 
     286                 : NS_IMETHODIMP
     287               0 : nsURIChecker::SetLoadGroup(nsILoadGroup *aLoadGroup)
     288                 : {
     289               0 :     NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED);
     290               0 :     return mChannel->SetLoadGroup(aLoadGroup);
     291                 : }
     292                 : 
     293                 : NS_IMETHODIMP
     294               0 : nsURIChecker::GetLoadFlags(nsLoadFlags *aLoadFlags)
     295                 : {
     296               0 :     NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED);
     297               0 :     return mChannel->GetLoadFlags(aLoadFlags);
     298                 : }
     299                 : 
     300                 : NS_IMETHODIMP
     301               0 : nsURIChecker::SetLoadFlags(nsLoadFlags aLoadFlags)
     302                 : {
     303               0 :     NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED);
     304               0 :     return mChannel->SetLoadFlags(aLoadFlags);
     305                 : }
     306                 : 
     307                 : //-----------------------------------------------------------------------------
     308                 : // nsIRequestObserver methods:
     309                 : //-----------------------------------------------------------------------------
     310                 : 
     311                 : NS_IMETHODIMP
     312               0 : nsURIChecker::OnStartRequest(nsIRequest *aRequest, nsISupports *aCtxt)
     313                 : {
     314               0 :     NS_ASSERTION(aRequest == mChannel, "unexpected request");
     315                 : 
     316               0 :     nsresult rv = CheckStatus();
     317               0 :     if (rv != NS_BASE_STREAM_WOULD_BLOCK)
     318               0 :         SetStatusAndCallBack(rv);
     319                 : 
     320                 :     // cancel the request (we don't care to look at the data).
     321               0 :     return NS_BINDING_ABORTED;
     322                 : }
     323                 : 
     324                 : NS_IMETHODIMP
     325               0 : nsURIChecker::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
     326                 :                              nsresult statusCode)
     327                 : {
     328                 :     // NOTE: we may have kicked off a subsequent request, so we should not do
     329                 :     // any cleanup unless this request matches the one we are currently using.
     330               0 :     if (mChannel == request) {
     331                 :         // break reference cycle between us and the channel (see comment in
     332                 :         // AsyncCheckURI)
     333               0 :         mChannel = nsnull;
     334                 :     }
     335               0 :     return NS_OK;
     336                 : }
     337                 : 
     338                 : //-----------------------------------------------------------------------------
     339                 : // nsIStreamListener methods:
     340                 : //-----------------------------------------------------------------------------
     341                 : 
     342                 : NS_IMETHODIMP
     343               0 : nsURIChecker::OnDataAvailable(nsIRequest *aRequest, nsISupports *aCtxt,
     344                 :                                nsIInputStream *aInput, PRUint32 aOffset,
     345                 :                                PRUint32 aCount)
     346                 : {
     347               0 :     NS_NOTREACHED("nsURIChecker::OnDataAvailable");
     348               0 :     return NS_BINDING_ABORTED;
     349                 : }
     350                 : 
     351                 : //-----------------------------------------------------------------------------
     352                 : // nsIInterfaceRequestor methods:
     353                 : //-----------------------------------------------------------------------------
     354                 : 
     355                 : NS_IMETHODIMP
     356               0 : nsURIChecker::GetInterface(const nsIID & aIID, void **aResult)
     357                 : {
     358               0 :     if (mObserver && aIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
     359               0 :         nsCOMPtr<nsIInterfaceRequestor> req = do_QueryInterface(mObserver);
     360               0 :         if (req)
     361               0 :             return req->GetInterface(aIID, aResult);
     362                 :     }
     363               0 :     return QueryInterface(aIID, aResult);
     364                 : }
     365                 : 
     366                 : //-----------------------------------------------------------------------------
     367                 : // nsIChannelEventSink methods:
     368                 : //-----------------------------------------------------------------------------
     369                 : 
     370                 : NS_IMETHODIMP
     371               0 : nsURIChecker::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
     372                 :                                      nsIChannel *aNewChannel,
     373                 :                                      PRUint32 aFlags,
     374                 :                                      nsIAsyncVerifyRedirectCallback *callback)
     375                 : {
     376                 :     // We have a new channel
     377               0 :     mChannel = aNewChannel;
     378               0 :     callback->OnRedirectVerifyCallback(NS_OK);
     379               0 :     return NS_OK;
     380                 : }

Generated by: LCOV version 1.7