LCOV - code coverage report
Current view: directory - netwerk/protocol/http - nsHttpChunkedDecoder.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 56 42 75.0 %
Date: 2012-06-02 Functions: 2 2 100.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.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2001
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Darin Fisher <darin@netscape.com> (original author)
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsHttpChunkedDecoder.h"
      40                 : #include "nsHttp.h"
      41                 : 
      42                 : //-----------------------------------------------------------------------------
      43                 : // nsHttpChunkedDecoder <public>
      44                 : //-----------------------------------------------------------------------------
      45                 : 
      46                 : nsresult
      47               8 : nsHttpChunkedDecoder::HandleChunkedContent(char *buf,
      48                 :                                            PRUint32 count,
      49                 :                                            PRUint32 *contentRead,
      50                 :                                            PRUint32 *contentRemaining)
      51                 : {
      52               8 :     LOG(("nsHttpChunkedDecoder::HandleChunkedContent [count=%u]\n", count));
      53                 : 
      54               8 :     *contentRead = 0;
      55                 :     
      56                 :     // from RFC2617 section 3.6.1, the chunked transfer coding is defined as:
      57                 :     //
      58                 :     //   Chunked-Body    = *chunk
      59                 :     //                     last-chunk
      60                 :     //                     trailer
      61                 :     //                     CRLF
      62                 :     //   chunk           = chunk-size [ chunk-extension ] CRLF
      63                 :     //                     chunk-data CRLF
      64                 :     //   chunk-size      = 1*HEX
      65                 :     //   last-chunk      = 1*("0") [ chunk-extension ] CRLF
      66                 :     //       
      67                 :     //   chunk-extension = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
      68                 :     //   chunk-ext-name  = token
      69                 :     //   chunk-ext-val   = token | quoted-string
      70                 :     //   chunk-data      = chunk-size(OCTET)
      71                 :     //   trailer         = *(entity-header CRLF)
      72                 :     //
      73                 :     // the chunk-size field is a string of hex digits indicating the size of the
      74                 :     // chunk.  the chunked encoding is ended by any chunk whose size is zero, 
      75                 :     // followed by the trailer, which is terminated by an empty line.
      76                 : 
      77              36 :     while (count) {
      78              20 :         if (mChunkRemaining) {
      79               4 :             PRUint32 amt = NS_MIN(mChunkRemaining, count);
      80                 : 
      81               4 :             count -= amt;
      82               4 :             mChunkRemaining -= amt;
      83                 : 
      84               4 :             *contentRead += amt;
      85               4 :             buf += amt;
      86                 :         }
      87              16 :         else if (mReachedEOF)
      88               0 :             break; // done
      89                 :         else {
      90              16 :             PRUint32 bytesConsumed = 0;
      91                 : 
      92              16 :             nsresult rv = ParseChunkRemaining(buf, count, &bytesConsumed);
      93              16 :             if (NS_FAILED(rv)) return rv;
      94                 : 
      95              16 :             count -= bytesConsumed;
      96                 : 
      97              16 :             if (count) {
      98                 :                 // shift buf by bytesConsumed
      99              12 :                 memmove(buf, buf + bytesConsumed, count);
     100                 :             }
     101                 :         }
     102                 :     }
     103                 :     
     104               8 :     *contentRemaining = count;
     105               8 :     return NS_OK;
     106                 : }
     107                 : 
     108                 : //-----------------------------------------------------------------------------
     109                 : // nsHttpChunkedDecoder <private>
     110                 : //-----------------------------------------------------------------------------
     111                 : 
     112                 : nsresult
     113              16 : nsHttpChunkedDecoder::ParseChunkRemaining(char *buf,
     114                 :                                           PRUint32 count,
     115                 :                                           PRUint32 *bytesConsumed)
     116                 : {
     117              16 :     NS_PRECONDITION(mChunkRemaining == 0, "chunk remaining should be zero");
     118              16 :     NS_PRECONDITION(count, "unexpected");
     119                 : 
     120              16 :     *bytesConsumed = 0;
     121                 :     
     122              16 :     char *p = static_cast<char *>(memchr(buf, '\n', count));
     123              16 :     if (p) {
     124              16 :         *p = 0;
     125              16 :         if ((p > buf) && (*(p-1) == '\r')) // eliminate a preceding CR
     126              16 :             *(p-1) = 0;
     127              16 :         *bytesConsumed = p - buf + 1;
     128                 : 
     129                 :         // make buf point to the full line buffer to parse
     130              16 :         if (!mLineBuf.IsEmpty()) {
     131               0 :             mLineBuf.Append(buf);
     132               0 :             buf = (char *) mLineBuf.get();
     133                 :         }
     134                 : 
     135              16 :         if (mWaitEOF) {
     136               4 :             if (*buf) {
     137               0 :                 LOG(("got trailer: %s\n", buf));
     138                 :                 // allocate a header array for the trailers on demand
     139               0 :                 if (!mTrailers) {
     140               0 :                     mTrailers = new nsHttpHeaderArray();
     141                 :                 }
     142               0 :                 mTrailers->ParseHeaderLine(buf);
     143                 :             }
     144                 :             else {
     145               4 :                 mWaitEOF = false;
     146               4 :                 mReachedEOF = true;
     147               4 :                 LOG(("reached end of chunked-body\n"));
     148                 :             }
     149                 :         }
     150              12 :         else if (*buf) {
     151                 :             // ignore any chunk-extensions
     152               8 :             if ((p = PL_strchr(buf, ';')) != nsnull)
     153               0 :                 *p = 0;
     154                 : 
     155               8 :             if (!sscanf(buf, "%x", &mChunkRemaining)) {
     156               0 :                 LOG(("sscanf failed parsing hex on string [%s]\n", buf));
     157               0 :                 return NS_ERROR_UNEXPECTED;
     158                 :             }
     159                 : 
     160                 :             // we've discovered the last chunk
     161               8 :             if (mChunkRemaining == 0)
     162               4 :                 mWaitEOF = true;
     163                 :         }
     164                 : 
     165                 :         // ensure that the line buffer is clear
     166              16 :         mLineBuf.Truncate();
     167                 :     }
     168                 :     else {
     169                 :         // save the partial line; wait for more data
     170               0 :         *bytesConsumed = count;
     171                 :         // ignore a trailing CR
     172               0 :         if (buf[count-1] == '\r')
     173               0 :             count--;
     174               0 :         mLineBuf.Append(buf, count);
     175                 :     }
     176                 : 
     177              16 :     return NS_OK;
     178                 : }

Generated by: LCOV version 1.7