LCOV - code coverage report
Current view: top level - netwerk/protocol/data - nsDataHandler.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 57 111 51.4 %
Date: 2017-07-14 16:53:18 Functions: 9 15 60.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsDataChannel.h"
       7             : #include "nsDataHandler.h"
       8             : #include "nsNetCID.h"
       9             : #include "nsError.h"
      10             : #include "DataChannelChild.h"
      11             : #include "plstr.h"
      12             : 
      13             : static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
      14             : 
      15             : ////////////////////////////////////////////////////////////////////////////////
      16             : 
      17           3 : nsDataHandler::nsDataHandler() {
      18           3 : }
      19             : 
      20           0 : nsDataHandler::~nsDataHandler() {
      21           0 : }
      22             : 
      23         159 : NS_IMPL_ISUPPORTS(nsDataHandler, nsIProtocolHandler, nsISupportsWeakReference)
      24             : 
      25             : nsresult
      26           3 : nsDataHandler::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult) {
      27             : 
      28           3 :     nsDataHandler* ph = new nsDataHandler();
      29           3 :     if (ph == nullptr)
      30           0 :         return NS_ERROR_OUT_OF_MEMORY;
      31           3 :     NS_ADDREF(ph);
      32           3 :     nsresult rv = ph->QueryInterface(aIID, aResult);
      33           3 :     NS_RELEASE(ph);
      34           3 :     return rv;
      35             : }
      36             : 
      37             : ////////////////////////////////////////////////////////////////////////////////
      38             : // nsIProtocolHandler methods:
      39             : 
      40             : NS_IMETHODIMP
      41           0 : nsDataHandler::GetScheme(nsACString &result) {
      42           0 :     result.AssignLiteral("data");
      43           0 :     return NS_OK;
      44             : }
      45             : 
      46             : NS_IMETHODIMP
      47           0 : nsDataHandler::GetDefaultPort(int32_t *result) {
      48             :     // no ports for data protocol
      49           0 :     *result = -1;
      50           0 :     return NS_OK;
      51             : }
      52             : 
      53             : NS_IMETHODIMP
      54          12 : nsDataHandler::GetProtocolFlags(uint32_t *result) {
      55          12 :     *result = URI_NORELATIVE | URI_NOAUTH | URI_INHERITS_SECURITY_CONTEXT |
      56             :               URI_LOADABLE_BY_ANYONE | URI_NON_PERSISTABLE | URI_IS_LOCAL_RESOURCE |
      57             :               URI_SYNC_LOAD_IS_OK;
      58          12 :     return NS_OK;
      59             : }
      60             : 
      61             : NS_IMETHODIMP
      62           6 : nsDataHandler::NewURI(const nsACString &aSpec,
      63             :                       const char *aCharset, // ignore charset info
      64             :                       nsIURI *aBaseURI,
      65             :                       nsIURI **result) {
      66             :     nsresult rv;
      67          12 :     RefPtr<nsIURI> uri;
      68             : 
      69          12 :     nsCString spec(aSpec);
      70             : 
      71           6 :     if (aBaseURI && !spec.IsEmpty() && spec[0] == '#') {
      72             :         // Looks like a reference instead of a fully-specified URI.
      73             :         // --> initialize |uri| as a clone of |aBaseURI|, with ref appended.
      74           0 :         rv = aBaseURI->Clone(getter_AddRefs(uri));
      75           0 :         if (NS_FAILED(rv))
      76           0 :             return rv;
      77           0 :         rv = uri->SetRef(spec);
      78             :     } else {
      79             :         // Otherwise, we'll assume |spec| is a fully-specified data URI
      80          12 :         nsAutoCString contentType;
      81             :         bool base64;
      82           6 :         rv = ParseURI(spec, contentType, /* contentCharset = */ nullptr,
      83             :                       base64, /* dataBuffer = */ nullptr);
      84           6 :         if (NS_FAILED(rv))
      85           0 :             return rv;
      86             : 
      87             :         // Strip whitespace unless this is text, where whitespace is important
      88             :         // Don't strip escaped whitespace though (bug 391951)
      89           6 :         if (base64 || (strncmp(contentType.get(),"text/",5) != 0 &&
      90           0 :                        contentType.Find("xml") == kNotFound)) {
      91             :             // it's ascii encoded binary, don't let any spaces in
      92           0 :             if (!spec.StripWhitespace(mozilla::fallible)) {
      93           0 :                 return NS_ERROR_OUT_OF_MEMORY;
      94             :             }
      95             :         }
      96             : 
      97           6 :         uri = do_CreateInstance(kSimpleURICID, &rv);
      98           6 :         if (NS_FAILED(rv))
      99           0 :             return rv;
     100           6 :         rv = uri->SetSpec(spec);
     101             :     }
     102             : 
     103           6 :     if (NS_FAILED(rv))
     104           0 :         return rv;
     105             : 
     106           6 :     uri.forget(result);
     107           6 :     return rv;
     108             : }
     109             : 
     110             : NS_IMETHODIMP
     111           6 : nsDataHandler::NewChannel2(nsIURI* uri,
     112             :                            nsILoadInfo* aLoadInfo,
     113             :                            nsIChannel** result)
     114             : {
     115           6 :     NS_ENSURE_ARG_POINTER(uri);
     116             :     nsDataChannel* channel;
     117           6 :     if (XRE_IsParentProcess()) {
     118           2 :         channel = new nsDataChannel(uri);
     119             :     } else {
     120           4 :         channel = new mozilla::net::DataChannelChild(uri);
     121             :     }
     122           6 :     NS_ADDREF(channel);
     123             : 
     124           6 :     nsresult rv = channel->Init();
     125           6 :     if (NS_FAILED(rv)) {
     126           0 :         NS_RELEASE(channel);
     127           0 :         return rv;
     128             :     }
     129             : 
     130             :     // set the loadInfo on the new channel
     131           6 :     rv = channel->SetLoadInfo(aLoadInfo);
     132           6 :     if (NS_FAILED(rv)) {
     133           0 :         NS_RELEASE(channel);
     134           0 :         return rv;
     135             :     }
     136             : 
     137           6 :     *result = channel;
     138           6 :     return NS_OK;
     139             : }
     140             : 
     141             : NS_IMETHODIMP
     142           0 : nsDataHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
     143             : {
     144           0 :     return NewChannel2(uri, nullptr, result);
     145             : }
     146             : 
     147             : NS_IMETHODIMP
     148           0 : nsDataHandler::AllowPort(int32_t port, const char *scheme, bool *_retval) {
     149             :     // don't override anything.
     150           0 :     *_retval = false;
     151           0 :     return NS_OK;
     152             : }
     153             : 
     154             : #define BASE64_EXTENSION ";base64"
     155             : 
     156             : nsresult
     157          12 : nsDataHandler::ParseURI(nsCString& spec,
     158             :                         nsCString& contentType,
     159             :                         nsCString* contentCharset,
     160             :                         bool&    isBase64,
     161             :                         nsCString* dataBuffer)
     162             : {
     163          12 :     isBase64 = false;
     164             : 
     165             :     // move past "data:"
     166          12 :     const char* roBuffer = (const char*) PL_strcasestr(spec.get(), "data:");
     167          12 :     if (!roBuffer) {
     168             :         // malformed uri
     169           0 :         return NS_ERROR_MALFORMED_URI;
     170             :     }
     171          12 :     roBuffer += sizeof("data:") - 1;
     172             : 
     173             :     // First, find the start of the data
     174          12 :     const char* roComma = strchr(roBuffer, ',');
     175          12 :     const char* roHash = strchr(roBuffer, '#');
     176          12 :     if (!roComma || (roHash && roHash < roComma)) {
     177           0 :         return NS_ERROR_MALFORMED_URI;
     178             :     }
     179             : 
     180          12 :     if (roComma == roBuffer) {
     181             :         // nothing but data
     182          12 :         contentType.AssignLiteral("text/plain");
     183          12 :         if (contentCharset) {
     184           6 :             contentCharset->AssignLiteral("US-ASCII");
     185             :         }
     186             :     } else {
     187             :         // Make a copy of the non-data part so we can null out parts of it as
     188             :         // we go. This copy will be a small number of chars, in contrast to the
     189             :         // data which may be large.
     190           0 :         char* buffer = PL_strndup(roBuffer, roComma - roBuffer);
     191             : 
     192             :         // determine if the data is base64 encoded.
     193           0 :         char* base64 = PL_strcasestr(buffer, BASE64_EXTENSION);
     194           0 :         if (base64) {
     195           0 :             char *beyond = base64 + sizeof(BASE64_EXTENSION) - 1;
     196             :             // Per the RFC 2397 grammar, "base64" MUST be at the end of the
     197             :             // non-data part.
     198             :             //
     199             :             // But we also allow it in between parameters so a subsequent ";"
     200             :             // is ok as well (this deals with *broken* data URIs, see bug
     201             :             // 781693 for an example). Anything after "base64" in the non-data
     202             :             // part will be discarded in this case, however.
     203           0 :             if (*beyond == '\0' || *beyond == ';') {
     204           0 :                 isBase64 = true;
     205           0 :                 *base64 = '\0';
     206             :             }
     207             :         }
     208             : 
     209             :         // everything else is content type
     210           0 :         char *semiColon = (char *) strchr(buffer, ';');
     211           0 :         if (semiColon)
     212           0 :             *semiColon = '\0';
     213             : 
     214           0 :         if (semiColon == buffer || base64 == buffer) {
     215             :             // there is no content type, but there are other parameters
     216           0 :             contentType.AssignLiteral("text/plain");
     217             :         } else {
     218           0 :             contentType.Assign(buffer);
     219           0 :             ToLowerCase(contentType);
     220           0 :             if (!contentType.StripWhitespace(mozilla::fallible)) {
     221           0 :                 return NS_ERROR_OUT_OF_MEMORY;
     222             :             }
     223             :         }
     224             : 
     225           0 :         if (semiColon && contentCharset) {
     226           0 :             char *charset = PL_strcasestr(semiColon + 1, "charset=");
     227           0 :             if (charset) {
     228           0 :                 contentCharset->Assign(charset + sizeof("charset=") - 1);
     229           0 :                 if (!contentCharset->StripWhitespace(mozilla::fallible)) {
     230           0 :                     return NS_ERROR_OUT_OF_MEMORY;
     231             :                 }
     232             :             }
     233             :         }
     234             : 
     235           0 :         free(buffer);
     236             :     }
     237             : 
     238          12 :     if (dataBuffer) {
     239             :         // Split encoded data from terminal "#ref" (if present)
     240           6 :         const char* roData = roComma + 1;
     241             :         bool ok = !roHash
     242           6 :                 ? dataBuffer->Assign(roData, mozilla::fallible)
     243           6 :                 : dataBuffer->Assign(roData, roHash - roData, mozilla::fallible);
     244           6 :         if (!ok) {
     245           0 :             return NS_ERROR_OUT_OF_MEMORY;
     246             :         }
     247             :     }
     248             : 
     249          12 :     return NS_OK;
     250             : }

Generated by: LCOV version 1.13