/** * 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) { /*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/ } CRXHttpResponse::~CRXHttpResponse (void) { /*----------------------------------------------------------------*/ Reset (); /*----------------------------------------------------------------*/ } void CRXHttpResponse::Reset (void) { /*----------------------------------------------------------------*/ Get ().clear (); mContent.clear (); /*----------------------------------------------------------------*/ } void CRXHttpResponse::SetHeader (const char * aHeader) { /*----------------------------------------------------------------*/ Set (aHeader); /*----------------------------------------------------------------*/ } std::string CRXHttpResponse::GetHeader (void) const { /*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/ return Get (); } 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; unsigned int aSize = 0; char * aChunkedPtr = NULL; /*----------------------------------------------------------------*/ /*---------------------------------------------------------------- * 1. check parameter *----------------------------------------------------------------*/ if (aLength < 0) return ERROR_HTTP_RESPONSE_INVALID_LENGTH; /*---------------------------------------------------------------- * 2. resize memory and copy *----------------------------------------------------------------*/ aSize = mContent.size (); mContent.resize (aSize + aLength); memcpy (&mContent[0] + aSize, aContent, aLength); /*---------------------------------------------------------------- * 3. push data *----------------------------------------------------------------*/ aResult = mContent.size (); if (mIsChunked) { mContentLength += aLength; aSize = mContent.size (); if (aSize > strlen (CRLF) + strlen (CRLF2)) { aChunkedPtr = &mContent[0] + aSize - strlen (CRLF2); if (!strncmp (aChunkedPtr, CRLF2, strlen (CRLF2))) { for ( ; strncmp (aChunkedPtr--, CRLF, strlen (CRLF)) ; ); aResult = strtol (aChunkedPtr, NULL, 16); } } } /*---------------------------------------------------------------- * 4. check content size when is NOT chunked-encoding *----------------------------------------------------------------*/ if (!mIsChunked && mContent.size () >= mContentLength) return 0; /*----------------------------------------------------------------*/ 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.empty () ? "" : &mContent[0]; }