LCOV - code coverage report
Current view: directory - netwerk/protocol/http - nsHttpHeaderArray.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 97 86 88.7 %
Date: 2012-06-02 Functions: 10 10 100.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* vim:set ts=4 sw=4 sts=4 ci et: */
       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.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2001
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Darin Fisher <darin@netscape.com> (original author)
      25                 :  *   Patrick McManus <mcmanus@ducksong.com>
      26                 :  *   Jason Duell <jduell.mcbugs@gmail.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                 : #include "nsHttpHeaderArray.h"
      43                 : #include "nsHttp.h"
      44                 : 
      45                 : //-----------------------------------------------------------------------------
      46                 : // nsHttpHeaderArray <public>
      47                 : //-----------------------------------------------------------------------------
      48                 : nsresult
      49           32765 : nsHttpHeaderArray::SetHeader(nsHttpAtom header,
      50                 :                              const nsACString &value,
      51                 :                              bool merge)
      52                 : {
      53           32765 :     nsEntry *entry = nsnull;
      54                 :     PRInt32 index;
      55                 : 
      56           32765 :     index = LookupEntry(header, &entry);
      57                 : 
      58                 :     // If an empty value is passed in, then delete the header entry...
      59                 :     // unless we are merging, in which case this function becomes a NOP.
      60           32765 :     if (value.IsEmpty()) {
      61            3557 :         if (!merge && entry)
      62              12 :             mHeaders.RemoveElementAt(index);
      63            3557 :         return NS_OK;
      64                 :     }
      65                 : 
      66           29208 :     if (!entry) {
      67           27639 :         entry = mHeaders.AppendElement(); // new nsEntry()
      68           27639 :         if (!entry)
      69               0 :             return NS_ERROR_OUT_OF_MEMORY;
      70           27639 :         entry->header = header;
      71           27639 :         entry->value = value;
      72            1569 :     } else if (merge && !IsSingletonHeader(header)) {
      73               4 :         MergeHeader(header, entry, value);
      74                 :     } else {
      75                 :         // Replace the existing string with the new value
      76            1565 :         entry->value = value;
      77                 :     }
      78                 : 
      79           29208 :     return NS_OK;
      80                 : }
      81                 : 
      82                 : nsresult
      83           18781 : nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header, const nsACString &value)
      84                 : {
      85           18781 :     nsEntry *entry = nsnull;
      86                 :     PRInt32 index;
      87                 : 
      88           18781 :     index = LookupEntry(header, &entry);
      89                 : 
      90           18781 :     if (!entry) {
      91           18761 :         if (value.IsEmpty()) {
      92              39 :             if (!TrackEmptyHeader(header)) {
      93              13 :                 LOG(("Ignoring Empty Header: %s\n", header.get()));
      94              13 :                 return NS_OK; // ignore empty headers by default
      95                 :             }
      96                 :         }
      97           18748 :         entry = mHeaders.AppendElement(); //new nsEntry(header, value);
      98           18748 :         if (!entry)
      99               0 :             return NS_ERROR_OUT_OF_MEMORY;
     100           18748 :         entry->header = header;
     101           18748 :         entry->value = value;
     102              20 :     } else if (!IsSingletonHeader(header)) {
     103               6 :         MergeHeader(header, entry, value);
     104                 :     } else {
     105                 :         // Multiple instances of non-mergeable header received from network
     106                 :         // - ignore if same value
     107              14 :         if (!entry->value.Equals(value)) {
     108              12 :             if (IsSuspectDuplicateHeader(header)) {
     109                 :                 // reply may be corrupt/hacked (ex: CLRF injection attacks)
     110              11 :                 return NS_ERROR_CORRUPTED_CONTENT;
     111                 :             } // else silently drop value: keep value from 1st header seen
     112               1 :             LOG(("Header %s silently dropped as non mergeable header\n",
     113                 :                  header.get()));
     114                 :         }
     115                 :     }
     116                 : 
     117           18757 :     return NS_OK;
     118                 : }
     119                 : 
     120                 : void
     121              38 : nsHttpHeaderArray::ClearHeader(nsHttpAtom header)
     122                 : {
     123              38 :     mHeaders.RemoveElement(header, nsEntry::MatchHeader());
     124              38 : }
     125                 : 
     126                 : const char *
     127           44127 : nsHttpHeaderArray::PeekHeader(nsHttpAtom header)
     128                 : {
     129           44127 :     nsEntry *entry = nsnull;
     130           44127 :     LookupEntry(header, &entry);
     131           44127 :     return entry ? entry->value.get() : nsnull;
     132                 : }
     133                 : 
     134                 : nsresult
     135           13546 : nsHttpHeaderArray::GetHeader(nsHttpAtom header, nsACString &result)
     136                 : {
     137           13546 :     nsEntry *entry = nsnull;
     138           13546 :     LookupEntry(header, &entry);
     139           13546 :     if (!entry)
     140           10799 :         return NS_ERROR_NOT_AVAILABLE;
     141            2747 :     result = entry->value;
     142            2747 :     return NS_OK;
     143                 : }
     144                 : 
     145                 : nsresult
     146            1386 : nsHttpHeaderArray::VisitHeaders(nsIHttpHeaderVisitor *visitor)
     147                 : {
     148            1386 :     NS_ENSURE_ARG_POINTER(visitor);
     149            1386 :     PRUint32 i, count = mHeaders.Length();
     150            8830 :     for (i = 0; i < count; ++i) {
     151            7444 :         const nsEntry &entry = mHeaders[i];
     152            7444 :         if (NS_FAILED(visitor->VisitHeader(nsDependentCString(entry.header),
     153                 :                                            entry.value)))
     154               0 :             break;
     155                 :     }
     156            1386 :     return NS_OK;
     157                 : }
     158                 : 
     159                 : nsresult
     160           18781 : nsHttpHeaderArray::ParseHeaderLine(const char *line,
     161                 :                                    nsHttpAtom *hdr,
     162                 :                                    char **val)
     163                 : {
     164                 :     //
     165                 :     // BNF from section 4.2 of RFC 2616:
     166                 :     //
     167                 :     //   message-header = field-name ":" [ field-value ]
     168                 :     //   field-name     = token
     169                 :     //   field-value    = *( field-content | LWS )
     170                 :     //   field-content  = <the OCTETs making up the field-value
     171                 :     //                     and consisting of either *TEXT or combinations
     172                 :     //                     of token, separators, and quoted-string>
     173                 :     //
     174                 :     
     175                 :     // We skip over mal-formed headers in the hope that we'll still be able to
     176                 :     // do something useful with the response.
     177                 : 
     178           18781 :     char *p = (char *) strchr(line, ':');
     179           18781 :     if (!p) {
     180               0 :         LOG(("malformed header [%s]: no colon\n", line));
     181               0 :         return NS_OK;
     182                 :     }
     183                 : 
     184                 :     // make sure we have a valid token for the field-name
     185           18781 :     if (!nsHttp::IsValidToken(line, p)) {
     186               0 :         LOG(("malformed header [%s]: field-name not a token\n", line));
     187               0 :         return NS_OK;
     188                 :     }
     189                 :     
     190           18781 :     *p = 0; // null terminate field-name
     191                 : 
     192           18781 :     nsHttpAtom atom = nsHttp::ResolveAtom(line);
     193           18781 :     if (!atom) {
     194               0 :         LOG(("failed to resolve atom [%s]\n", line));
     195               0 :         return NS_OK;
     196                 :     }
     197                 : 
     198                 :     // skip over whitespace
     199           18781 :     p = net_FindCharNotInSet(++p, HTTP_LWS);
     200                 : 
     201                 :     // trim trailing whitespace - bug 86608
     202           18781 :     char *p2 = net_RFindCharNotInSet(p, HTTP_LWS);
     203                 : 
     204           18781 :     *++p2 = 0; // null terminate header value; if all chars starting at |p|
     205                 :                // consisted of LWS, then p2 would have pointed at |p-1|, so
     206                 :                // the prefix increment is always valid.
     207                 : 
     208                 :     // assign return values
     209           18781 :     if (hdr) *hdr = atom;
     210           18781 :     if (val) *val = p;
     211                 : 
     212                 :     // assign response header
     213           18781 :     return SetHeaderFromNet(atom, nsDependentCString(p, p2 - p));
     214                 : }
     215                 : 
     216                 : void
     217            2997 : nsHttpHeaderArray::Flatten(nsACString &buf, bool pruneProxyHeaders)
     218                 : {
     219            2997 :     PRUint32 i, count = mHeaders.Length();
     220           27390 :     for (i = 0; i < count; ++i) {
     221           24393 :         const nsEntry &entry = mHeaders[i];
     222                 :         // prune proxy headers if requested
     223           24393 :         if (pruneProxyHeaders && ((entry.header == nsHttp::Proxy_Authorization) || 
     224               0 :                                   (entry.header == nsHttp::Proxy_Connection)))
     225               0 :             continue;
     226           24393 :         buf.Append(entry.header);
     227           24393 :         buf.AppendLiteral(": ");
     228           24393 :         buf.Append(entry.value);
     229           24393 :         buf.AppendLiteral("\r\n");
     230                 :     }
     231            2997 : }
     232                 : 
     233                 : const char *
     234            8080 : nsHttpHeaderArray::PeekHeaderAt(PRUint32 index, nsHttpAtom &header)
     235                 : {
     236            8080 :     const nsEntry &entry = mHeaders[index];
     237                 : 
     238            8080 :     header = entry.header;
     239            8080 :     return entry.value.get();
     240                 : }
     241                 : 
     242                 : void
     243           10034 : nsHttpHeaderArray::Clear()
     244                 : {
     245           10034 :     mHeaders.Clear();
     246           10034 : }

Generated by: LCOV version 1.7