XBOX::VError DecompressStream (XBOX::VStream& ioStream) { XBOX::VError error = VE_COMP_LIBRARY_NOT_FOUND; if (XBOX::VComponentManager::IsComponentAvailable ((XBOX::CType)CZipComponent::Component_Type)) { CZipComponent *zipComponent = (CZipComponent *)VComponentManager::RetainComponent ((CType)CZipComponent::Component_Type); if (zipComponent) { XBOX::VPtrStream decompressedStream; if ((XBOX::VE_OK == (error = ioStream.OpenReading())) && !decompressedStream.OpenWriting()) { error = zipComponent->ExpandStream (&ioStream, &decompressedStream); ioStream.CloseReading(); decompressedStream.CloseWriting(); if ((XBOX::VE_OK == error) && (!decompressedStream.IsEmpty())) { if (XBOX::VE_OK == (error = ioStream.OpenWriting())) { ioStream.SetSize (0); ioStream.PutData (decompressedStream.GetDataPtr(), decompressedStream.GetDataSize()); error = ioStream.CloseWriting(); } } } zipComponent->Release(); } } return error; }
XBOX::VError CompressStream (XBOX::VStream& ioStream, HTTPCompressionMethod inMethod) { if ((inMethod == COMPRESSION_NONE) || (inMethod > COMPRESSION_LAST_SUPPORTED_METHOD)) return VE_INVALID_PARAMETER; XBOX::VError error = VE_COMP_LIBRARY_NOT_FOUND; if (VHTTPServer::GetZipComponentAvailable()) { CZipComponent *zipComponent = VHTTPServer::RetainZipComponent(); if (NULL != zipComponent) { XBOX::VPtrStream compressedStream; EZipCompressionLevel compressionLevel = ((inMethod == COMPRESSION_GZIP) || (inMethod == COMPRESSION_X_GZIP)) ? eCompressionLevel_GZip_BestSpeed : eCompressionLevel_BestSpeed; if ((XBOX::VE_OK == (error = ioStream.OpenReading())) && !compressedStream.OpenWriting()) { error = zipComponent->CompressStream (&ioStream, compressionLevel, &compressedStream); ioStream.CloseReading(); compressedStream.CloseWriting(); if ((XBOX::VE_OK == error) && (!compressedStream.IsEmpty())) { if (XBOX::VE_OK == (error = ioStream.OpenWriting())) { ioStream.SetSize (0); ioStream.PutData (compressedStream.GetDataPtr(), compressedStream.GetDataSize()); ioStream.CloseWriting(); } } } XBOX::QuickReleaseRefCountable (zipComponent); } } return error; }
XBOX::VError VHTTPMessage::ReadFromStream (XBOX::VStream& inStream, const XBOX::VString& inBoundary) { #define MAX_BUFFER_LENGTH 32768 const char HTTP_CR = '\r'; const char HTTP_LF = '\n'; const char HTTP_CRLF [] = { HTTP_CR, HTTP_LF, 0 }; const char HTTP_CRLFCRLF [] = { HTTP_CR, HTTP_LF, HTTP_CR, HTTP_LF, 0 }; XBOX::VError streamError = XBOX::VE_OK; HTTPParsingState parsingState; XBOX::VError parsingError = XBOX::VE_OK; XBOX::VSize bufferSize = MAX_BUFFER_LENGTH; char * buffer = (char *)XBOX::vMalloc (bufferSize, 0); XBOX::VSize bufferOffset = 0; XBOX::VSize unreadBytes = 0; sLONG lineLen = 0; XBOX::VString header; XBOX::VString value; char * startLinePtr = NULL; char * endLinePtr = NULL; char * endHeaderPtr = NULL; sLONG endLineSize = sizeof (HTTP_CRLF) - 1; sLONG contentLength = 0; void * bodyContentBuffer = NULL; XBOX::VSize bodyContentSize = 0; const sLONG MAX_REQUEST_ENTITY_SIZE = XBOX::MaxLongInt; XBOX::VString boundaryEnd; char * boundary = NULL; bool stopReadingStream = false; if (!inBoundary.IsEmpty()) { boundaryEnd.AppendString ("--"); boundaryEnd.AppendString (inBoundary); boundary = new char[boundaryEnd.GetLength() + 1]; if (NULL != boundary) boundaryEnd.ToCString (boundary, boundaryEnd.GetLength() + 1); } if (NULL == buffer) return XBOX::VE_MEMORY_FULL; parsingState = PS_ReadingHeaders; XBOX::StErrorContextInstaller errorContext (XBOX::VE_STREAM_EOF, XBOX::VE_OK); bool isAlreadyReading = inStream.IsReading(); if (!isAlreadyReading) streamError = inStream.OpenReading(); while ((XBOX::VE_OK == streamError) && !stopReadingStream) { if (0 == unreadBytes) bufferOffset = 0; bufferSize = MAX_BUFFER_LENGTH - bufferOffset; streamError = inStream.GetData (buffer + bufferOffset, &bufferSize); unreadBytes = (bufferSize + bufferOffset); bufferOffset = 0; while ((unreadBytes > 0) && (XBOX::VE_OK == parsingError)) { if (parsingState <= PS_ReadingHeaders) { startLinePtr = buffer + bufferOffset; endLinePtr = strstr (startLinePtr, HTTP_CRLF); if ((NULL != endLinePtr) && (NULL == endHeaderPtr)) endHeaderPtr = strstr (startLinePtr, HTTP_CRLFCRLF); } /* Start to parse the Status-Line */ switch (parsingState) { case PS_ReadingHeaders: { if (NULL != endLinePtr) { if (startLinePtr != (endHeaderPtr + endLineSize)) { if (_ExtractHeaderValuePair (startLinePtr, endLinePtr, header, value)) { GetHeaders().SetHeaderValue (header, value, false); } } else /*if (startLinePtr == endHeaderPtr)*/ { parsingState = PS_ReadingBody; XBOX::VString contentLengthString; if (GetHeaders().GetHeaderValue (STRING_HEADER_CONTENT_LENGTH, contentLengthString)) contentLength = HTTPTools::GetLongFromString (contentLengthString); } } break; } case PS_ReadingBody: { if (!boundaryEnd.IsEmpty()) { if (NULL != boundary) { char *endBoundaryPtr = memstr (buffer + bufferOffset, unreadBytes, boundary, strlen (boundary)); if (NULL != endBoundaryPtr) { XBOX::VSize nbBytesToCopy = (endBoundaryPtr - (buffer + bufferOffset)); inStream.UngetData (endBoundaryPtr, unreadBytes - nbBytesToCopy); unreadBytes = nbBytesToCopy; if (NULL != memstr (endBoundaryPtr - 2, 2, HTTP_CRLF, 2)) unreadBytes -= 2; // Skip CRLF after boundary part stopReadingStream = true; } } } if (NULL == bodyContentBuffer) { // There's no Content-Length field in header if (0 == contentLength) { bodyContentBuffer = XBOX::vMalloc (bufferSize, 0); bodyContentSize = 0; } // There's one Content-Length, just check it match limits else if ((contentLength > 0) && (contentLength < MAX_REQUEST_ENTITY_SIZE)) { bodyContentBuffer = XBOX::vMalloc (contentLength, 0); bodyContentSize = 0; } } if ((NULL != bodyContentBuffer) && (bodyContentSize + unreadBytes < MAX_REQUEST_ENTITY_SIZE)) { XBOX::VSize nbBytesToCopy = unreadBytes; if (bodyContentSize + nbBytesToCopy > contentLength) bodyContentBuffer = XBOX::vRealloc (bodyContentBuffer, bodyContentSize + nbBytesToCopy); memcpy ((char *)(bodyContentBuffer) + bodyContentSize, buffer + bufferOffset, unreadBytes); bodyContentSize += unreadBytes; bufferOffset = unreadBytes = 0; } else { parsingError = XBOX::VE_MEMORY_FULL; if (NULL != bodyContentBuffer) { XBOX::vFree (bodyContentBuffer); bodyContentBuffer = NULL; } } break; } } if (XBOX::VE_OK != parsingError) break; if (NULL != endLinePtr) { lineLen = (endLinePtr - startLinePtr) + endLineSize; // to skip CRLF; bufferOffset += lineLen; unreadBytes -= lineLen; endLinePtr = NULL; } else { if (bufferOffset > 0) { memmove (buffer, buffer + bufferOffset, unreadBytes); buffer[unreadBytes] = 0; } bufferOffset = unreadBytes; break; } } if (XBOX::VE_OK != parsingError) break; } if (!isAlreadyReading) inStream.CloseReading(); if (XBOX::VE_STREAM_EOF == streamError) streamError = XBOX::VE_OK; if (!parsingError && !streamError) { if (NULL != bodyContentBuffer) { #if VERSIONDEBUG if ((contentLength > 0) && (bodyContentSize != contentLength)) assert (false); #endif GetBody().SetDataPtr (bodyContentBuffer, bodyContentSize); XBOX::VString contentType; XBOX::CharSet charSet = XBOX::VTC_UNKNOWN; /* Set VStream charset according to content-type header other else set default charset to UTF-8 */ if ((!GetHeaders().GetContentType (contentType, &charSet)) || (XBOX::VTC_UNKNOWN == charSet)) charSet = XBOX::VTC_UTF_8; GetBody().SetCharSet (charSet); } parsingState = PS_ParsingFinished; } else { if (NULL != bodyContentBuffer) XBOX::vFree (bodyContentBuffer); } delete [] boundary; boundary = NULL; XBOX::vFree (buffer); buffer = NULL; return streamError; #undef MAX_BUFFER_LENGTH }
XBOX::VError VMIMEMessage::ToStream (XBOX::VStream& outStream, sLONG inEncoding) { XBOX::VError error = XBOX::VE_OK; if (XBOX::VE_OK == outStream.OpenWriting()) { outStream.SetCarriageReturnMode(eCRM_CRLF); if (!fMIMEParts.empty()) { XBOX::VString string; XBOX::VString charsetName; bool bEncodeBody; // Encode using base64. for (XBOX::VectorOfMIMEPart::const_iterator it = fMIMEParts.begin(); it != fMIMEParts.end(); ++it) { outStream.PutPrintf ("\r\n--%S\r\n", &fBoundary); string.FromCString ("Content-Type: "); string.AppendString ((*it)->GetMediaType()); if (!(*it)->GetFileName().IsEmpty()) { string.AppendCString ("; name=\""); if (!(*it)->GetName().IsEmpty()) string.AppendString ((*it)->GetName()); else string.AppendString ((*it)->GetFileName()); string.AppendCString("\"\r\nContent-Disposition: "); string.AppendCString((*it)->IsInline() ? "inline; " : "attachment; "); string.AppendCString("filename=\""); string.AppendString ((*it)->GetFileName()); string.AppendCString ("\"\r\n"); if (inEncoding == ENCODING_BINARY) { string.AppendCString ("Content-Transfer-Encoding: 8bit\r\n"); bEncodeBody = false; } else { if ((inEncoding == ENCODING_BINARY_ONLY) && ((*it)->GetMediaTypeKind() == MIMETYPE_TEXT)) { bEncodeBody = false; } else { string.AppendCString ("Content-Transfer-Encoding: base64\r\n"); bEncodeBody = true; } } } else { if ((*it)->GetMediaTypeCharSet() != XBOX::VTC_UNKNOWN) { string.AppendCString ("; charset=\""); XBOX::VTextConverters::Get()->GetNameFromCharSet ((*it)->GetMediaTypeCharSet(), charsetName); string.AppendString (charsetName); string.AppendCString ("\""); } if (!(*it)->GetName().IsEmpty()) { string.AppendCString("; name=\""); string.AppendString((*it)->GetName()); string.AppendCString("\""); } string.AppendCString ("\r\n"); if ((*it)->IsInline()) string.AppendCString("Content-Disposition: inline\r\n"); if (inEncoding == ENCODING_7BIT || ((inEncoding == ENCODING_BINARY_ONLY) && ((*it)->GetMediaTypeKind() != MIMETYPE_TEXT))) { string.AppendCString ("Content-Transfer-Encoding: base64\r\n"); bEncodeBody = true; } else { string.AppendCString("Content-Transfer-Encoding: 8bit\r\n"); bEncodeBody = false; } } if ((*it)->GetContentID().GetLength()) { string.AppendCString("Content-ID: <"); string.AppendString((*it)->GetContentID()); string.AppendCString(">\r\n"); } string.AppendCString ("\r\n"); outStream.PutText (string); if (bEncodeBody) { XBOX::VMemoryBuffer<> buffer; if (XBOX::Base64Coder::Encode ((*it)->GetData().GetDataPtr(), (*it)->GetData().GetDataSize(), buffer, kBASE64_QUADS_PER_LINE)) { outStream.PutData (buffer.GetDataPtr(), buffer.GetDataSize()); } } else { outStream.PutData ((*it)->GetData().GetDataPtr(), (*it)->GetData().GetDataSize()); } } outStream.PutPrintf ("\r\n--%S--\r\n", &fBoundary); } outStream.CloseWriting(); } return error; }