diff options
Diffstat (limited to 'pki/base/tps/src/httpClient/response.cpp')
-rw-r--r-- | pki/base/tps/src/httpClient/response.cpp | 1115 |
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" ); - } - } -} |