summaryrefslogtreecommitdiffstats
path: root/pki/base/tps/src/httpClient/response.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/tps/src/httpClient/response.cpp')
-rw-r--r--pki/base/tps/src/httpClient/response.cpp1115
1 files changed, 0 insertions, 1115 deletions
diff --git a/pki/base/tps/src/httpClient/response.cpp b/pki/base/tps/src/httpClient/response.cpp
deleted file mode 100644
index 89b900492..000000000
--- a/pki/base/tps/src/httpClient/response.cpp
+++ /dev/null
@@ -1,1115 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/** BEGIN COPYRIGHT BLOCK
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Copyright (C) 2007 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
-
-/**
- * HTTP response handler
- */
-
-#include <ctype.h>
-#include <string.h>
-#include <math.h>
-
-#include "nspr.h"
-#include "engine/RA.h"
-#include "main/Util.h"
-#include "httpClient/httpc/response.h"
-#include "httpClient/httpc/engine.h"
-//-- #include "httpClient/httpc/DebugLogger.h"
-#include "httpClient/httpc/PSPRUtil.h"
-#include "main/Memory.h"
-
-//-- static const char *DEBUG_MODULE = "httpclient";
-//-- static const char *DEBUG_CLASS_NAME = "PSHttpResponse";
-void printBuf(int , char* );
-
-/**
- * Constructor. This class is used by the HttpResponse class for reading and
- * processing data from the socket
- * @param socket The NSPR socket from which the response is expected
- * @param size The size of the internal buffer to hold data
- * @param timeout Timeout in seconds on receiving a response
- */
-
-RecvBuf::RecvBuf( const PRFileDesc *socket, int size, int timeout ) {
- _socket = socket;
- _allocSize = size;
- _buf = (char *)PR_Malloc(size);
- _curPos = 0;
- _curSize = 0;
- _chunkedMode = PR_FALSE;
- _currentChunkSize = _currentChunkBytesRead = 0;
- _timeout = PR_TicksPerSecond() * timeout;
- _content = NULL;
-}
-
-/**
- * Destructor
- */
-RecvBuf::~RecvBuf() {
- if( _buf != NULL ) {
- PR_Free( _buf );
- _buf = NULL;
- }
-}
-
-/**
- * Reads the specified number of bytes from the socket and place it into the buffer
- *
- * @param socket The NSPR socket from which the response is expected
- * @param size The size of the buffer
- * @return PR_TRUE on success, otherwise PR_FALSE
- */
-PRBool RecvBuf::_getBytes(int size) {
-//-- DebugLogger *logger = DebugLogger::GetDebugLogger( DEBUG_MODULE );
- PRErrorCode pec;
- _curPos = 0;
-
- int num =1;
- int i =0;
- PRBool endChunk= PR_FALSE;
- RA::Debug( LL_PER_PDU,
- "RecvBuf::_getBytes: ",
- "Start RecvBuf::_getBytes" );
- // actual reading from the socket happens here
- do {
- num = PR_Recv( (PRFileDesc*)_socket,
- &_buf[_curSize],
- _allocSize-_curSize,
- 0,
- _timeout );
- RA::Debug( LL_PER_PDU,
- "RecvBuf::_getBytes: ",
- "num of bytes read from the socket=%d",
- num );
- /*
- * in chunked mode, ending chunk contains a 0 to begin
- * loop through to see if it contains just 0 (skip carriage returns
- * endChunk indicates possible end chunk.
- */
- if ((_chunkedMode == PR_TRUE) && (num < 10)) {
- endChunk = PR_FALSE;
-
- for (i=0; i< num; i++) {
- if (endChunk == PR_TRUE) {
- if ((_buf[_curSize+i] == 13) || (_buf[_curSize+i] == 10))
- continue;
- else {
- endChunk = PR_FALSE;
- break; // not an endChunk
- }
- } else { // endChunk==PR_FALSE
- if (_buf[_curSize+i] == '0') {
- RA::Debug( LL_PER_PDU,
- "RecvBuf::_getBytes: ",
- "may be chunked mode end chunk" );
- endChunk = PR_TRUE;
- } else if ((_buf[_curSize+i] == 13) || (_buf[_curSize+i] == 10))
- continue;
- else {
- endChunk = PR_FALSE;
- break; // not an endChunk
- }
- }
- } // for
- }
-
- if (num >0)
- _curSize = _curSize+num;
-
- if (_chunkedMode == PR_FALSE) {
- if (getAllContent()) {
- RA::Debug( LL_PER_PDU,
- "RecvBuf::_getBytes: ",
- "Already got all the content, no need to call PR_Recv again." );
- break;
- }
- }
-
- if (endChunk == PR_TRUE)
- break;
- } while (num > 0);
-
- if (num <0) {
- pec = PR_GetError();
- RA::Debug( LL_PER_PDU,
- "RecvBuf::_getBytes: ",
- "error in pr_recv, err=%d",
- pec );
- }
-
- if ( _curSize <= 0 ) {
- return PR_FALSE;
- }
-
- _buf[_curSize] = '\0';
-//-- logger->Log( LOGLEVEL_FINEST, DEBUG_CLASS_NAME,
-//-- "getBytes",
-
- _content = (char *) PR_Malloc(_curSize+1);
- if (_content == NULL) {
- return PR_FALSE;
- }
- memcpy((char*) _content, (const char *)_buf, _curSize+1);
- _contentSize = _curSize +1;
-
- RA::Debug(LL_PER_PDU, "RecvBuf::_getBytes",
- "buffer received with size %d follows:", _contentSize);
- printBuf(_contentSize, _content);
-
- return PR_TRUE;
-}
-
-int RecvBuf::getAllContent() {
- //int result[10];
- //int j=0;
- //int k=0;
- int number = 0;
- for (int i=0; i<_curSize; i++) {
- if (_buf[i] == '\r') {
- if (i < (_curSize-3)) {
- if (_buf[i+1] == '\n' && _buf[i+2] == '\r'
- && _buf[i+3] == '\n') {
- // find content length
-// strcasestr may not be supported by Solaris
-// char *clen = strcasestr(_buf, "Content-length:");
- char *clen = strstr(_buf, "Content-Length:");
- if (clen != NULL) {
- clen = &clen[16];
- number = atoi(clen);
-/*
- while (1) {
- if ((number=Util::ascii2numeric(clen[j++])) >= 0) {
- result[k++] = number;
- } else {
- break;
- }
- }
-
- number = 0;
- for (int l=0; l<k; l++)
- number = (int)(number + result[l]*(float)pow((float)10, (float)k-l-1));
-*/
- RA::Debug( LL_PER_PDU,
- "RecvBuf::getAllContent: ",
- "content length number=%d",
- number );
- }
- int remainingBytes = _curSize - (i+4);
- RA::Debug( LL_PER_PDU,
- "RecvBuf::getAllContent: ",
- "remainingbytes=%d",
- remainingBytes );
- if (remainingBytes == number)
- return 1;
- }
- }
- }
- }
-
- return 0;
-}
-
-void printBuf(int len, char* buf) {
- RA::Debug(LL_PER_PDU, "response:printBuf",
- "Buffer print begins");
- RA::Debug(LL_PER_PDU, "response::printBuf",
- "%s", buf);
- RA::Debug(LL_PER_PDU, "response:printBuf",
- "Buffer print end");
- /*
- int times = len/256;
- if (len%256)
- times++;
- RA::Debug("response:printBuf",
- "%d times", times);
- RA::Debug("response:printBuf",
- "attempting to print the whole buffer:");
-
- int i;
-
- for (i = 0; i< times; i++) {
- char *temp;
- temp = PL_strdup((char *)buf+i*256);
- RA::Debug("response:printBuf",
- "%s", temp);
- }
- */
-}
-
-/**
- * gets the next char from the buffer. If all the data in the buffer is read,
- * read a chunk to the buffer
- * @returns - the next char from the data
- */
-char RecvBuf::_getChar() {
- if (_curPos >= _curSize) {
- if (!_getBytes(_allocSize)) {
- /* bugscape #55624: Solaris RA exited
- with a signal ABRT if we raised exception
- without handling it */
- return -1;
- /* throw RecvBuf::EndOfFile(); */
- }
- }
-
- return _buf[_curPos++];
-}
-
-
-/**
- * gets the next char from the buffer. If all the data in the buffer is read ,
- * read a chunk to the buffer
- * @returns - the next char from the data
- */
-char RecvBuf::getChar() {
- if (!_chunkedMode)
- return _getChar();
-
- else
- {
- if (_currentChunkSize == 0)
- {
- // read the chunk header
- char ch, chunkStr[20];
- int index = 0;
-
- while (!isspace(ch = _getChar()) )
- chunkStr[index++] = ch;
- chunkStr[index] = '\0';
-
- sscanf((char *)chunkStr, "%x", (unsigned int *)(&_currentChunkSize));
-
- if (ch != '\n')
- {
- char ch2 = _getChar();
- if (ch != '\r' || ch2 != '\n')
- {
- printf( "did not find CRLF after chunk");
- }
- }
-
- if (_currentChunkSize == 0)
- return -1;
-
- _currentChunkBytesRead = 1;
- return _buf[_curPos++];
- }
- else
- if (_currentChunkBytesRead < _currentChunkSize)
- {
- // read a byte from the chunk
- _currentChunkBytesRead++;
- return _getChar();
- }
- else
- {
- // read the chunk trailer
- char ch1 = _getChar();
- char ch2 = _getChar();
- if (ch1 != '\r' || ch2 != '\n')
- {
- printf( "did not find CRLF after chunk");
- };
- _currentChunkSize = _currentChunkBytesRead = 0;
- return getChar();
- };
- };
-
-}
-
-char *RecvBuf::get_content() {
- return _content;
-}
-
-int RecvBuf::get_contentSize() {
- return _contentSize;
-}
-
-/**
- * Decrements the pointer to the internal buffer so that the next read would
- * retrieve the last data again
- */
-void RecvBuf::putBack() {
- if (_curPos > 0) {
- _curPos--;
- if (_chunkedMode) {
- _currentChunkBytesRead--;
- }
- }
-}
-
-/**
- * Sets the chunked mode for reading data
- * Not used now..
- */
-void RecvBuf::setChunkedMode() {
- _chunkedMode = PR_TRUE;
- _currentChunkSize = _currentChunkBytesRead = 0;
-}
-
-/**
- * Gets the timeout in seconds for reading
- *
- * @return The timeout in seconds for reading
- */
-int RecvBuf::getTimeout() {
- return _timeout / PR_TicksPerSecond();
-}
-
-
-Response::Response(const PRFileDesc *sock, NetRequest *request) {
- _socket = sock;
- _request = request;
-}
-
-/**
- * Constructor
- */
-
-PSHttpResponse::PSHttpResponse( const PRFileDesc *sock,
- PSHttpRequest *request,
- int timeout , PRBool expectChunked):
- Response(sock, request) {
- _request = request;
- _proto = HTTPNA;
- _protocol = NULL;
- retcode =0 ;
- _statusNum = NULL;
- _statusString = NULL;
- _keepAlive = -1;
- _connectionClosed = 0;
- _bodyLength = -1;
- _content = NULL;
-
- _headers = new StringKeyCache("response",10*60);
- _expectChunked = expectChunked;
- _chunkedResponse = PR_FALSE;
- _timeout = timeout;
-}
-
-PSHttpResponse::~PSHttpResponse() {
- if( _protocol != NULL ) {
- PL_strfree( _protocol );
- _protocol = NULL;
- }
- if( _statusString != NULL ) {
- PL_strfree( _statusString );
- _statusString = NULL;
- }
- if( _statusNum != NULL ) {
- PL_strfree( _statusNum );
- _statusNum = NULL;
- }
- if (_headers) {
- Iterator* iterator = _headers->GetKeyIterator();
- while ( iterator->HasMore() ) {
- const char* name = (const char*)iterator->Next();
- CacheEntry* entry = _headers->Remove( name );
- if ( entry ) {
- char* value = (char*)entry->GetData();
- if( value != NULL ) {
- PL_strfree( value );
- value = NULL;
- }
- if( entry != NULL ) {
- delete entry;
- entry = NULL;
- }
- }
- }
- if( iterator != NULL ) {
- delete iterator;
- iterator = NULL;
- }
- if( _headers != NULL ) {
- delete _headers;
- _headers = NULL;
- }
- }
- _socket = 0;
-}
-
-long PSHttpResponse::getStatus() {
- return _statusNum ? atoi(_statusNum) : 0;
-}
-
-int PSHttpResponse::getReturnCode() {
- return retcode;
-}
-
-char * PSHttpResponse::getStatusString() {
- return _statusString?_statusString:(char*)"";
-}
-
-HttpProtocol PSHttpResponse::getProtocol() {
- // first check the response protocol
- if (_proto == HTTPNA) {
- if (_protocol) {
- int major, minor;
-
- sscanf(_protocol, "HTTP/%d.%d", &major, &minor);
-
- switch(major) {
- case 1:
- switch(minor) {
- case 0:
- _proto = HTTP10;
- break;
- case 1:
- _proto = HTTP11;
- break;
- }
- break;
- }
- } else {
- _proto = HTTP09;
- }
- }
-
- if (_proto == HTTP11) {
- // A 1.1 compliant server response shows the protocol as HTTP/1.1 even
- // for a HTTP/1.0 request, but it promises to only use HTTP/1.0 syntax.
- if (_request->getProtocol() == HTTP10) {
- _proto = HTTP10;
- }
- }
-
- return _proto;
-};
-
-char * PSHttpResponse::getHeader(const char *name) {
- CacheEntry *entry = _headers->Get(name);
- return entry ? (char *)entry->GetData() : NULL;
-}
-
-int PSHttpResponse::getHeaders(char ***keys) {
-
- return _headers->GetKeys( keys );
-
-}
-
-long PSHttpResponse::getBodyLength() {
- return _bodyLength;
-}
-
-char * PSHttpResponse::getContent() {
- return _content;
-}
-
-void PSHttpResponse::freeContent() {
- if( _content != NULL ) {
- PR_Free( _content );
- _content = NULL;
- }
-}
-
-int PSHttpResponse::getContentSize() {
-
- return _contentSize;
-}
-
-char *PSHttpResponse::toString() {
- char *resp = (char *)"";
- char **keys;
- char *headerBuf = NULL;
- int nHeaders = getHeaders( &keys );
- if ( nHeaders > 0 ) {
- char **values = new char*[nHeaders];
- int len = 0;
- int *keyLengths = new int[nHeaders];
- int *valueLengths = new int[nHeaders];
- int i;
- for( i = 0; i < nHeaders; i++ ) {
- keyLengths[i] = strlen( keys[i] );
- len += keyLengths[i] + 1;
- values[i] = getHeader(keys[i]);
- valueLengths[i] = strlen( values[i] );
- len += valueLengths[i] + 1;
- }
- headerBuf = new char[len + nHeaders * 2];
- char *p = headerBuf;
- for( i = 0; i < nHeaders; i++ ) {
- strcpy( p, keys[i] );
- p += keyLengths[i];
- *p++ = ':';
- strcpy( p, values[i] );
- p += valueLengths[i];
- *p++ = ',';
- }
- *p = 0;
- for( i = 0; i < nHeaders; i++ ) {
- if( keys[i] != NULL ) {
- delete [] keys[i];
- keys[i] = NULL;
- }
- }
- if( keys != NULL ) {
- delete [] keys;
- keys = NULL;
- }
- if( values != NULL ) {
- delete [] values;
- values = NULL;
- }
- if( keyLengths != NULL ) {
- delete [] keyLengths;
- keyLengths = NULL;
- }
- if( valueLengths != NULL ) {
- delete [] valueLengths;
- valueLengths = NULL;
- }
- }
-
- char *s = NULL;
- if ( headerBuf ) {
- s = PR_smprintf( "PSHttpResponse [%s\nbody bytes:%d]",
- headerBuf, _bodyLength );
- } else {
- s = PR_smprintf( "PSHttpResponse [body bytes:%d]", _bodyLength );
- }
- resp = new char[strlen(s) + 1];
- strcpy( resp, s );
- if( s != NULL ) {
- PR_smprintf_free( s );
- s = NULL;
- }
- return resp;
-}
-
-PRBool PSHttpResponse::checkKeepAlive() {
- HttpProtocol proto;
- const char *connectionHeader;
-//-- static const char *DEBUG_METHOD_NAME = "checkKeepAlive";
-//-- DebugLogger *logger = DebugLogger::GetDebugLogger( DEBUG_MODULE );
-
- if (_keepAlive < 0) {
- proto = getProtocol();
- if (proto == HTTP11) {
- // default is connection: keep-alive
- _keepAlive = 1;
- } else {
- // default is connection: close
- // _keepAlive = 0;
- //CMS needs keepalive with HTTP10 (so no chunked encoding)
- _keepAlive=1;
- }
-
- connectionHeader = _request->getHeader("connection");
- if (connectionHeader) {
- if (!PL_strcasecmp(connectionHeader, "keep-alive")) {
- _keepAlive = 1;
- } else if (!PL_strcasecmp(connectionHeader, "close")) {
- _keepAlive = 0;
- } else {
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::checkKeepAlive: ",
- "Unknown connection header" );
- }
- }
- }
-
- return (_keepAlive == 0?PR_FALSE:PR_TRUE);
-}
-
-PRBool PSHttpResponse::checkConnection() {
- // return true if the connection is OPEN
- return (_connectionClosed == 0?PR_TRUE:PR_FALSE);
-}
-
-
-int PSHttpResponse::_verifyStandardBody(RecvBuf &buf,
- int expectedBytes,
- PRBool check) {
- int bytesRead = 0;
- int curPos = 0;
- char ch;
-//-- static const char *DEBUG_METHOD_NAME = "_verifyStandardBody";
-//-- DebugLogger *logger = DebugLogger::GetDebugLogger( DEBUG_MODULE );
-
- while(expectedBytes > 0 ) {
- ch = buf.getChar();
- if (ch < 0 ) {
- break;
- }
- // if check is true, we think we know what the content looks like
- if ( check ) {
- if (ch != (char) curPos%256) {
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::_verifyStandardBody: ",
- "Response data corrupt at byte %d (%d, %d)",
- curPos,
- ch,
- ( curPos % 256 ) );
- check = PR_FALSE;
- break;
- }
- curPos++;
- }
-
- bytesRead++;
-
- if (expectedBytes > 0) {
- expectedBytes--;
- }
- }
-
- return bytesRead;
-}
-
-
-PRBool PSHttpResponse::_handleBody( RecvBuf &buf ) {
- char *clHeader; // content length header
- char *teHeader; // transfer-encoding header
- int expected_cl=-1; // expected content length
-//-- static const char *DEBUG_METHOD_NAME = "_handleBody";
-//-- DebugLogger *logger = DebugLogger::GetDebugLogger( DEBUG_MODULE );
-
- teHeader = getHeader("transfer-encoding");
- if (teHeader && !PL_strcasecmp(teHeader, "chunked")) {
- _chunkedResponse = PR_TRUE;
- buf.setChunkedMode();
- } else {
- _chunkedResponse = PR_FALSE;
- clHeader = getHeader("Content-length");
- if (clHeader) {
- expected_cl = atoi(clHeader);
- }
- }
-
- if (_request->getExpectStandardBody()) {
- _bodyLength = _verifyStandardBody(buf, expected_cl, PR_TRUE);
-
- } else {
- _bodyLength = _verifyStandardBody(buf, expected_cl, PR_FALSE);
- }
-
- if (expected_cl >= 0) {
- if (_bodyLength != expected_cl) {
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::_handleBody: ",
- "Content length was incorrect (%d/%d bytes)",
- _bodyLength,
- expected_cl );
- }
- }
-
- return PR_TRUE;
-}
-
-/**
- * Reads until the first space character
- *
- * @param buf Receive buffer to read from
- * @param headerBuf Array to read header into
- * @param len Size of headerBuf
- * @return Number of characters read, or -1 if too many
- */
-static int readHeader( RecvBuf& buf, char* headerBuf, int len ) {
- int index = 0;
-
- do {
- char ch = buf.getChar();
-
- if ( ch != -1 && !isspace(ch) ) {
- headerBuf[index++] = ch;
- if ( index >= (len-1) ) {
- return -1;
- }
- } else {
- headerBuf[index] = '\0';
- break;
- }
- } while( true );
- // RA::Debug( LL_PER_PDU,
- // "readHeader: ",
- // "headerBuf = %s",
- // headerBuf );
-
- return index;
-}
-
-
-PRBool PSHttpResponse::processResponse() {
- RecvBuf buf( _socket, 8192, _timeout );
-
- if (_expectChunked) {
- buf.setChunkedMode();
- }
-
-//-- static const char *DEBUG_METHOD_NAME = "processResponse";
-//-- DebugLogger *logger = DebugLogger::GetDebugLogger( DEBUG_MODULE );
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Entered processResponse()" );
-
- try {
- char tmp[2048];
- int tmpLen = sizeof(tmp);
-
- // Get protocol string
- int nRead = readHeader( buf, tmp, tmpLen );
-
- if ( nRead < 0 ) {
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Returned more than expected bytes %d "
- "in protocol header",
- sizeof( tmp ) );
- return PR_FALSE;
- }
-
- _protocol = PL_strdup(tmp);
-//-- logger->Log( LOGLEVEL_FINER, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Protocol header: %s",
- _protocol );
-
- // Get status num
- nRead = readHeader( buf, tmp, tmpLen );
- if ( nRead < 0 ) {
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Returned more than expected bytes %d "
- "in status header",
- tmpLen );
- return PR_FALSE;
- }
-
- _statusNum = PL_strdup( tmp );
-
-//-- logger->Log( LOGLEVEL_FINER, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Status header: %s",
- _statusNum );
- retcode = atoi( tmp );
-
- // Get status string
- int index = 0;
- do {
- char ch = buf.getChar();
- if ( ch != -1 && ch != '\r' ) {
- tmp[index++] = ch;
- if ( index >= (tmpLen-2) ) {
- tmp[index] = 0;
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Returned more than expected bytes %d "
- "in protocol header:\n%s",
- tmpLen,
- tmp );
- return PR_FALSE;
- }
- } else {
- break;
- }
- } while (true);
- tmp[index] = '\0';
- _statusString = PL_strdup( tmp );
-
- // Skip CRLF
- (void)buf.getChar();
-
- // loop over response headers
- index = 0;
-#ifdef CHECK
- PRBool doneParsing = PR_FALSE;
- PRBool atEOL = PR_FALSE;
- PRBool inName = PR_TRUE;
- char name[2048];
- int nameLen = sizeof(name);
-
- while ( !doneParsing ) {
- char value[2048];
- int valueLen = sizeof(value);
- char ch = buf.getChar();
-
- switch( ch ) {
- case ':':
- if ( inName ) {
- name[index] = '\0';
- index = 0;
- inName = PR_FALSE;
-
- nRead = readHeader( buf, value, valueLen );
- if ( nRead < 0 ) {
-//-- logger->Log( LOGLEVEL_SEVERE,
-//-- DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Name %s in header does not "
- "have a value",
- name );
- // return PR_FALSE;
- } else {
- value[index++] = ch;
- if ( index >= (int)(sizeof(value) - 1 ) ) {
-//-- logger->Log( LOGLEVEL_SEVERE,
-//-- DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Name %s in header does not "
- "have a value",
- name );
- // return PR_FALSE;
- }
- }
- break;
- case '\r':
- if ( inName && !atEOL ) {
- name[index] = '\0';
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Name %s in header does not "
- "have a value",
- name );
- // return PR_FALSE;
- }
- break;
- case '\n':
- if ( atEOL ) {
- doneParsing = PR_TRUE;
- break;
- }
- if ( inName ) {
- name[index] = '\0';
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Name %s in header does not "
- "have a value",
- name );
- // return PR_FALSE;
- }
- value[index] = '\0';
- index = 0;
- inName = PR_TRUE;
- _headers->Put(name, PL_strdup(value));
- atEOL = PR_TRUE;
- break;
- default:
- atEOL = PR_FALSE;
- if (inName) {
- name[index++] = ch;
- } else {
- value[index++] = ch;
- }
- if ( inName && (index >= (nameLen-2)) ) {
- name[index] = '\0';
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Name %s in header exceeds the expected "
- "%d max characters",
- name,
- nameLen );
- // return PR_FALSE;
- } else if ( !inName && (index >= (valueLen-1)) ) {
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Name %s in header does not "
- "have a value",
- name );
- // return PR_FALSE;
- }
- break;
- }
- }
-
- } //while
-#endif //CHECK
- } catch ( RecvBuf::EndOfFile & ) {
- if ( !_request->isHangupOk() ) {
-
- int errCode = PR_GetError();
- if ( PR_IO_TIMEOUT_ERROR == errCode ) {
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Timed out reading response (%d seconds)",
- buf.getTimeout() );
- } else {
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Received unexpected end of file from server\n%s",
- "XXX" );
- }
- }
- return PR_FALSE;
- }
-
- // Read the body (HEAD requests don't have bodies)
- // jpierre 1xx, 204 and 304 don't have bodies either
- if ( PL_strcmp(_request->getMethod(), "HEAD") &&
- (!((retcode>=100) && (retcode<200))) &&
- (retcode!=204) &&
- (retcode!=304) ) {
- if ( _handleBody(buf) == PR_FALSE ) {
- return PR_FALSE;
- }
- }
-
- if ( checkConnection() && !checkKeepAlive() ) {
- // if connection is still open, and we didn't expect a keepalive,
- // read another byte to see if the connection has closed.
- try {
- char ch;
- ch = buf.getChar();
- buf.putBack();
- // conflict!
-//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "Connection kept alive when it shouldn't" );
- } catch (RecvBuf::EndOfFile &) {
- _connectionClosed = 1;
- }
- }
-
- _checkResponseSanity();
- _content = (char *)buf.get_content();
- _contentSize = buf.get_contentSize();
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "processed Buffer contentSize=%d",
- getContentSize() );
- if (_content != NULL) {
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::processResponse: ",
- "processed Buffer content=%s",
- _content );
- }
- // char * yo = getContent();
-
- return PR_TRUE;
-}
-
-void PSHttpResponse::_checkResponseSanity() {
- char *clHeader = getHeader("Content-length");
- char *teHeader = getHeader("Transfer-encoding");
-//-- static const char *DEBUG_METHOD_NAME = "checkResponseSanity";
-//-- DebugLogger *logger = DebugLogger::GetDebugLogger( DEBUG_MODULE );
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::_checkResponseSanity: ",
- "in _checkResponseSanity" );
-
- ///////////////////////////////////////////////////
- // Check items relevant to HTTP/1.0 and HTTP/1.1 //
- ///////////////////////////////////////////////////
-
- // check for both content-length and chunked
- if ( clHeader && teHeader ) {
-//-- logger->Log( LOGLEVEL_FINER, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::_checkResponseSanity: ",
- "Response contains both content-length and "
- "transfer-encoding" );
- }
-
- // check for basic headers
- if ( !getHeader("Date") ) {
-//-- logger->Log( LOGLEVEL_WARNING, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::_checkResponseSanity: ",
- "Response does not contain a date header" );
- }
- if ( !getHeader("Server") ) {
-//-- logger->Log( LOGLEVEL_WARNING, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::_checkResponseSanity: ",
- "Response does not contain a server header" );
- }
-
- int expectedLength;
- if ((expectedLength = _request->getExpectedResponseLength()) > 0) {
- if (expectedLength != _bodyLength) {
-//-- logger->Log( LOGLEVEL_INFO, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::_checkResponseSanity: ",
- "Response body length does not match expected "
- "response length (%d/%d)",
- _bodyLength,
- expectedLength );
- }
- }
-
- ///////////////////////////////////////
- // Check items relevant to HTTP/1.0 //
- ///////////////////////////////////////
- if ( getProtocol() == HTTP10 ) {
- if ( _chunkedResponse ) {
-//-- logger->Log( LOGLEVEL_INFO, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::_checkResponseSanity: ",
- "Server sent a chunked HTTP/1.0 response" );
- }
- }
-
- ///////////////////////////////////////
- // Check items relevant to HTTP/1.1 //
- ///////////////////////////////////////
- if ( getProtocol() == HTTP11 ) {
- if ( (!clHeader && !_chunkedResponse) &&
- (!((retcode>=100) && (retcode<200))) &&
- (retcode!=204) &&
- (retcode!=304) ) {
-//-- logger->Log( LOGLEVEL_INFO, DEBUG_CLASS_NAME,
-//-- DEBUG_METHOD_NAME,
- RA::Debug( LL_PER_PDU,
- "PSHttpResponse::_checkResponseSanity: ",
- "Server responded with a HTTP/1.1 response without "
- "content-length or chunked encoding" );
- }
- }
-}