/** * CRXHttpResponse.cpp */ #ifdef _WIN32 # pragma warning (disable:4996) #endif #include "CRXHttpResponse.h" #include #include #include #define CONTENT_LENGTH "Content-Length: " #define TRANSFER_ENCODING "Transfer-Encoding: " CRXHttpResponse::CRXHttpResponse (void) : mStatusCode (0), mIsChunked (false), mContentLength (0) { /*----------------------------------------------------------------*/ memset (&mContent, 0x00, sizeof (mContent)); /*----------------------------------------------------------------*/ } CRXHttpResponse::~CRXHttpResponse (void) { /*----------------------------------------------------------------*/ Reset (); /*----------------------------------------------------------------*/ } void CRXHttpResponse::Reset (void) { /*----------------------------------------------------------------*/ ResetMessage (); ResetContent (); /*----------------------------------------------------------------*/ } void CRXHttpResponse::ResetContent (void) { /*----------------------------------------------------------------*/ if (mContent.mBody) free (mContent.mBody); memset (&mContent, 0x00, sizeof (mContent)); /*----------------------------------------------------------------*/ } int CRXHttpResponse::SetResponseAll (const char * aHttpResponse, const int aResponseLength) { int aResult = 0; const char * aEndOfHeader = NULL; std::string aHeader; int aHeaderLength = 0; /*----------------------------------------------------------------*/ if (aResponseLength <= 0) return ERROR_HTTP_RESPONSE_INVALID_LENGTH; if (GetHeader ().rfind (CRLF2) == std::string::npos) { aEndOfHeader = strstr (aHttpResponse, CRLF2); if (aEndOfHeader == NULL) return ERROR_HTTP_RESPONSE_INVALID_FORMAT; aEndOfHeader += strlen (CRLF2); aHeaderLength = aEndOfHeader - aHttpResponse; aHeader.assign (aHttpResponse, aHeaderLength); SetHeader (aHeader.c_str ()); } aResult = SetContent (aHttpResponse + aHeaderLength, aResponseLength - aHeaderLength); if (aResult) { aResult = ERROR_HTTP_RESPONSE_FAILED_TO_PARSE_CONTENT; } /*----------------------------------------------------------------*/ return aResult; } void CRXHttpResponse::SetHeader (const char * aHttpMessage) { /*----------------------------------------------------------------*/ SetMessage (aHttpMessage); /*----------------------------------------------------------------*/ } std::string CRXHttpResponse::GetHeader (void) const { /*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/ return GetMessage (); } void CRXHttpResponse::Parse (void) { std::string aValue; char aStatusCode[64] = {0x00, }; char aStatusName[64] = {0x00, }; char aHttpVersion[64] = {0x00, }; size_t aBegin = 0; size_t aOffset = 0; /*----------------------------------------------------------------*/ aValue = GetHeader ().substr (0, GetHeader ().find (CRLF, 0)); /*---------------------------------------------------------------- * 1. separate first line to , and *----------------------------------------------------------------*/ sscanf (aValue.c_str (), "%[^ ] %[^ ] %[^ ]\r\n", aHttpVersion, aStatusCode, aStatusName); mHttpVersion.assign (aHttpVersion); mStatusString.assign (aStatusName); mStatusCode = atoi (aStatusCode); /*---------------------------------------------------------------- * 2. get Content-Length or check is chunked *----------------------------------------------------------------*/ aBegin = GetHeader ().find (CONTENT_LENGTH); if (aBegin == std::string::npos) { /* is really chunked encoding ? */ aBegin = GetHeader ().find (TRANSFER_ENCODING); if (aBegin == std::string::npos) return ; aBegin += strlen (TRANSFER_ENCODING); aOffset = GetHeader ().find (CRLF, aBegin) - aBegin; aValue = GetHeader ().substr (aBegin, aOffset); if (aValue == "chunked") { mIsChunked = true; return ; } } aBegin += strlen (CONTENT_LENGTH); aOffset = GetHeader ().find (CRLF, aBegin) - aBegin; aValue = GetHeader ().substr (aBegin, aOffset); mContentLength = atoi (aValue.c_str ()); /*----------------------------------------------------------------*/ } int CRXHttpResponse::SetContent (const char * aContent, const int aLength) { int aResult = 0; char * aReallocPtr = NULL; /*----------------------------------------------------------------*/ if (!mIsChunked) { if (mContentLength <= mContent.mLength) return aResult; if (mContent.mBody == NULL) { mContent.mBody = static_cast (calloc (mContentLength, 1)); if (mContent.mBody == NULL) { return ERROR_HTTP_RESPONSE_FAILED_TO_MEMORY_ALLOCATION; } } } else { mContentLength += aLength; aReallocPtr = static_cast (realloc (mContent.mBody, mContentLength)); if (aReallocPtr == NULL) { return ERROR_HTTP_RESPONSE_FAILED_TO_MEMORY_ALLOCATION; } mContent.mBody = aReallocPtr; } memcpy (mContent.mBody + mContent.mLength, aContent, aLength); mContent.mLength += aLength; /*----------------------------------------------------------------*/ return aResult; } int CRXHttpResponse::GetStatusCode (void) const { return mStatusCode; } bool CRXHttpResponse::IsChunked (void) const { return mIsChunked; } int CRXHttpResponse::GetContentLength (void) const { return mContentLength; } const char * CRXHttpResponse::GetContentBody (void) const { return mContent.mBody; }