void Test(const String& ct, const String& val = Null) { MIMEHeader h; h.Parse(ct); String s = AsString(h); LOG(ct); LOG(" " << h); if(val.GetCount()) ASSERT(s == val); etalon << "Test(" << AsCString(ct) << ",\r\n " << AsCString(s) << ");\r\n"; }
bool MHTMLParser::parseArchiveWithHeader( MIMEHeader* header, HeapVector<Member<ArchiveResource>>& resources) { if (!header) { DVLOG(1) << "Failed to parse MHTML part: no header."; return false; } if (!header->isMultipart()) { // With IE a page with no resource is not multi-part. bool endOfArchiveReached = false; ArchiveResource* resource = parseNextPart(*header, String(), String(), endOfArchiveReached); if (!resource) return false; resources.append(resource); return true; } // Skip the message content (it's a generic browser specific message). skipLinesUntilBoundaryFound(m_lineReader, header->endOfPartBoundary()); bool endOfArchive = false; while (!endOfArchive) { MIMEHeader* resourceHeader = MIMEHeader::parseHeader(&m_lineReader); if (!resourceHeader) { DVLOG(1) << "Failed to parse MHTML, invalid MIME header."; return false; } if (resourceHeader->contentType() == "multipart/alternative") { // Ignore IE nesting which makes little sense (IE seems to nest only some // of the frames). if (!parseArchiveWithHeader(resourceHeader, resources)) { DVLOG(1) << "Failed to parse MHTML subframe."; return false; } skipLinesUntilBoundaryFound(m_lineReader, header->endOfPartBoundary()); continue; } ArchiveResource* resource = parseNextPart(*resourceHeader, header->endOfPartBoundary(), header->endOfDocumentBoundary(), endOfArchive); if (!resource) { DVLOG(1) << "Failed to parse MHTML part."; return false; } resources.append(resource); } return true; }
PassRefPtr<ArchiveResource> MHTMLParser::parseNextPart(const MIMEHeader& mimeHeader, const String& endOfPartBoundary, const String& endOfDocumentBoundary, bool& endOfArchiveReached) { ASSERT(endOfPartBoundary.isEmpty() == endOfDocumentBoundary.isEmpty()); RefPtr<SharedBuffer> content = SharedBuffer::create(); const bool checkBoundary = !endOfPartBoundary.isEmpty(); bool endOfPartReached = false; String line; while (!(line = m_lineReader.nextLine()).isNull()) { if (checkBoundary && (line == endOfPartBoundary || line == endOfDocumentBoundary)) { endOfArchiveReached = (line == endOfDocumentBoundary); endOfPartReached = true; break; } // Note that we use line.utf8() and not line.ascii() as ascii turns special characters (such as tab, line-feed...) into '?'. content->append(line.utf8().data(), line.length()); if (mimeHeader.contentTransferEncoding() == MIMEHeader::QuotedPrintable) { // The line reader removes the \r\n, but we need them for the content in this case as the QuotedPrintable decoder expects CR-LF terminated lines. content->append("\r\n", 2); } } if (!endOfPartReached && checkBoundary) { LOG_ERROR("No bounday found for MHTML part."); return 0; } Vector<char> data; switch (mimeHeader.contentTransferEncoding()) { case MIMEHeader::Base64: if (!base64Decode(content->data(), content->size(), data)) { LOG_ERROR("Invalid base64 content for MHTML part."); return 0; } break; case MIMEHeader::QuotedPrintable: quotedPrintableDecode(content->data(), content->size(), data); break; case MIMEHeader::SevenBit: data.append(content->data(), content->size()); break; default: LOG_ERROR("Invalid encoding for MHTML part."); return 0; } RefPtr<SharedBuffer> contentBuffer = SharedBuffer::adoptVector(data); // FIXME: the URL in the MIME header could be relative, we should resolve it if it is. // The specs mentions 5 ways to resolve a URL: http://tools.ietf.org/html/rfc2557#section-5 // IE and Firefox (UNMht) seem to generate only absolute URLs. KURL location = KURL(KURL(), mimeHeader.contentLocation()); return ArchiveResource::create(contentBuffer, location, mimeHeader.contentType(), mimeHeader.charset(), String()); }
MIMEHeader* MIMEHeader::parseHeader(SharedBufferChunkReader* buffer) { MIMEHeader* mimeHeader = MIMEHeader::create(); KeyValueMap keyValuePairs = retrieveKeyValuePairs(buffer); KeyValueMap::iterator mimeParametersIterator = keyValuePairs.find("content-type"); if (mimeParametersIterator != keyValuePairs.end()) { ParsedContentType parsedContentType(mimeParametersIterator->value); mimeHeader->m_contentType = parsedContentType.mimeType(); if (!mimeHeader->isMultipart()) { mimeHeader->m_charset = parsedContentType.charset().stripWhiteSpace(); } else { mimeHeader->m_multipartType = parsedContentType.parameterValueForName("type"); mimeHeader->m_endOfPartBoundary = parsedContentType.parameterValueForName("boundary"); if (mimeHeader->m_endOfPartBoundary.isNull()) { DVLOG(1) << "No boundary found in multipart MIME header."; return nullptr; } mimeHeader->m_endOfPartBoundary.insert("--", 0); mimeHeader->m_endOfDocumentBoundary = mimeHeader->m_endOfPartBoundary; mimeHeader->m_endOfDocumentBoundary.append("--"); } } mimeParametersIterator = keyValuePairs.find("content-transfer-encoding"); if (mimeParametersIterator != keyValuePairs.end()) mimeHeader->m_contentTransferEncoding = parseContentTransferEncoding(mimeParametersIterator->value); mimeParametersIterator = keyValuePairs.find("content-location"); if (mimeParametersIterator != keyValuePairs.end()) mimeHeader->m_contentLocation = mimeParametersIterator->value; // See rfc2557 - section 8.3 - Use of the Content-ID header and CID URLs. mimeParametersIterator = keyValuePairs.find("content-id"); if (mimeParametersIterator != keyValuePairs.end()) mimeHeader->m_contentID = mimeParametersIterator->value; return mimeHeader; }
void HTTPPostRequestBodyParserTest::ReadMultiPartPost() { StartTrace(HTTPPostRequestBodyParserTest.ReadMultiPartPost); std::iostream *is = coast::system::OpenStream("MultiPartBody.txt", 0); t_assertm(is != 0, "expected 'MultiPartBody.txt' to be there"); if ( is ) { MIMEHeader mh; t_assertm(mh.ParseHeaders(*is, 4096, 4096), "expected global header parsing to succeed"); assertEqual(586L, mh.GetParsedHeaderLength()); HTTPPostRequestBodyParser sm(mh); t_assert(sm.Parse(*is)); Anything expected; Anything result = sm.GetContent(); delete is; t_assert(!GetConfig().IsNull()); assertAnyEqual(GetConfig()["MultiPartResult"], result); } // This sequence takes advantage of the String::SubString // feature to return the whole remainder of the string starting // from the first occurrence the substring-pattern has been found. // This relieves us from the need to create an expected result file // which we would use to verify the results. is = coast::system::OpenStream("MultiPartBody.txt", 0); if ( is ) { MIMEHeader mh; t_assertm(mh.ParseHeaders(*is, 4096, 4096), "expected global header parsing to succeed"); assertEqual(586L, mh.GetParsedHeaderLength()); HTTPPostRequestBodyParser sm(mh); t_assert(sm.Parse(*is)); String unparsedContent = sm.GetUnparsedContent(); delete is; is = coast::system::OpenStream("MultiPartBody.txt", 0); if (is) { char c; String tmp; while ((!!(*is).get(c))) { tmp.Append(c); } String final; final = tmp.SubString(unparsedContent); assertEqual(final, unparsedContent); delete is; } }
PassRefPtrWillBeRawPtr<ArchiveResource> MHTMLParser::parseNextPart(const MIMEHeader& mimeHeader, const String& endOfPartBoundary, const String& endOfDocumentBoundary, bool& endOfArchiveReached) { ASSERT(endOfPartBoundary.isEmpty() == endOfDocumentBoundary.isEmpty()); // If no content transfer encoding is specified, default to binary encoding. MIMEHeader::Encoding contentTransferEncoding = mimeHeader.contentTransferEncoding(); if (contentTransferEncoding == MIMEHeader::Unknown) contentTransferEncoding = MIMEHeader::Binary; RefPtr<SharedBuffer> content = SharedBuffer::create(); const bool checkBoundary = !endOfPartBoundary.isEmpty(); bool endOfPartReached = false; if (contentTransferEncoding == MIMEHeader::Binary) { if (!checkBoundary) { WTF_LOG_ERROR("Binary contents requires end of part"); return nullptr; } m_lineReader.setSeparator(endOfPartBoundary.utf8().data()); Vector<char> part; if (!m_lineReader.nextChunk(part)) { WTF_LOG_ERROR("Binary contents requires end of part"); return nullptr; } content->append(part); m_lineReader.setSeparator("\r\n"); Vector<char> nextChars; if (m_lineReader.peek(nextChars, 2) != 2) { WTF_LOG_ERROR("Invalid seperator."); return nullptr; } endOfPartReached = true; ASSERT(nextChars.size() == 2); endOfArchiveReached = (nextChars[0] == '-' && nextChars[1] == '-'); if (!endOfArchiveReached) { String line = m_lineReader.nextChunkAsUTF8StringWithLatin1Fallback(); if (!line.isEmpty()) { WTF_LOG_ERROR("No CRLF at end of binary section."); return nullptr; } } } else { String line; while (!(line = m_lineReader.nextChunkAsUTF8StringWithLatin1Fallback()).isNull()) { endOfArchiveReached = (line == endOfDocumentBoundary); if (checkBoundary && (line == endOfPartBoundary || endOfArchiveReached)) { endOfPartReached = true; break; } // Note that we use line.utf8() and not line.ascii() as ascii turns special characters (such as tab, line-feed...) into '?'. content->append(line.utf8().data(), line.length()); if (contentTransferEncoding == MIMEHeader::QuotedPrintable) { // The line reader removes the \r\n, but we need them for the content in this case as the QuotedPrintable decoder expects CR-LF terminated lines. content->append("\r\n", 2u); } } } if (!endOfPartReached && checkBoundary) { WTF_LOG_ERROR("No bounday found for MHTML part."); return nullptr; } Vector<char> data; switch (contentTransferEncoding) { case MIMEHeader::Base64: if (!base64Decode(content->data(), content->size(), data)) { WTF_LOG_ERROR("Invalid base64 content for MHTML part."); return nullptr; } break; case MIMEHeader::QuotedPrintable: quotedPrintableDecode(content->data(), content->size(), data); break; case MIMEHeader::EightBit: case MIMEHeader::SevenBit: case MIMEHeader::Binary: data.append(content->data(), content->size()); break; default: WTF_LOG_ERROR("Invalid encoding for MHTML part."); return nullptr; } RefPtr<SharedBuffer> contentBuffer = SharedBuffer::adoptVector(data); // FIXME: the URL in the MIME header could be relative, we should resolve it if it is. // The specs mentions 5 ways to resolve a URL: http://tools.ietf.org/html/rfc2557#section-5 // IE and Firefox (UNMht) seem to generate only absolute URLs. KURL location = KURL(KURL(), mimeHeader.contentLocation()); return ArchiveResource::create( contentBuffer, location, mimeHeader.contentID(), AtomicString(mimeHeader.contentType()), AtomicString(mimeHeader.charset())); }
void CHTTPDemux::DetectHandler(HTTPMessage* pMsg) { INT32 nProxyEnabled = 0; if (SUCCEEDED(m_proc->pc->registry->GetInt(REGISTRY_RTSPPROXY_ENABLED, &nProxyEnabled, m_proc))) { m_pResponse = new HTTPProtocol(); m_pResponse->AddRef(); return; } HTTPMessage::Tag tag = pMsg->tag(); if (tag == HTTPMessage::T_GET || tag == HTTPMessage::T_POST) { HTTPRequestMessage* pReq = (HTTPRequestMessage*)pMsg; const char* pUrl = pReq->url(); if (strncmp(pUrl, "/SmpDsBhgRl", 11) == 0) { if (tag == HTTPMessage::T_GET) { m_pResponse = new CRN1CloakGETHandler(); m_pResponse->AddRef(); } else { m_pResponse = new CRN1CloakPOSTHandler(); m_pResponse->AddRef(); } return; } #ifdef HELIX_FEATURE_SERVER_CLOAKV2 CloakV2SignatureEnforcer pEnforcer; if (SUCCEEDED(pEnforcer.EnforceCloakSignature(pReq))) { if (tag == HTTPMessage::T_GET) { m_pResponse = new CRN1CloakFallbackGETHandler(); m_pResponse->AddRef(); } else { m_pResponse = new CRN1CloakFallbackPOSTHandler(); m_pResponse->AddRef(); } return; } #endif //defined HELIX_FEATURE_SERVER_CLOAKV2 /* * If the Accept or Content-type header has * application/x-rtsp-tunnelled its a quicktime cloaked connection */ MIMEHeader* pUserAgentHdr = pMsg->getHeader("User-Agent"); MIMEHeader* pSessionHdr = pMsg->getHeader("x-sessioncookie"); if (pSessionHdr) { MIMEHeader* pAcceptHdr = pMsg->getHeader("Accept"); MIMEHeader* pContentTypeHdr = pMsg->getHeader("Content-type"); CHXString strValue; if (pAcceptHdr != NULL) { strValue.Empty(); pAcceptHdr->asString(strValue); if (strncmp(strValue, "application/x-rtsp-tunnelled", 28) == 0) { if (tag == HTTPMessage::T_GET) { m_pResponse = new CQTCloakGETHandler(); m_pResponse->AddRef(); } else { m_pResponse = new CQTCloakPOSTHandler(); m_pResponse->AddRef(); } return; } } if (pContentTypeHdr != NULL) { strValue.Empty(); pContentTypeHdr->asString(strValue); if (strncmp(strValue, "application/x-rtsp-tunnelled", 28) == 0) { if (tag == HTTPMessage::T_POST) { m_pResponse = new CQTCloakPOSTHandler(); m_pResponse->AddRef(); } else { m_pResponse = new CQTCloakGETHandler(); m_pResponse->AddRef(); } return; } } /* * If the User-Agent begins with "QTS " and there is an * x-sessioncookie header, it's a QT cloaking request. */ if (pUserAgentHdr != NULL) { pUserAgentHdr->asString(strValue); if (strncasecmp(strValue, "QTS ", 4) == 0) { if (tag == HTTPMessage::T_GET) { m_pResponse = new CQTCloakGETHandler(); m_pResponse->AddRef(); } else { m_pResponse = new CQTCloakPOSTHandler(); m_pResponse->AddRef(); } return; } } } #if defined(HELIX_FEATURE_SERVER_WMT_MMS) if (IsWMTHTTP(pUrl, pUserAgentHdr)) { m_pResponse = new WMTHttpProtocol(); m_pResponse->AddRef(); return; } #endif } m_pResponse = new HTTPProtocol(); m_pResponse->AddRef(); }
void CHTTPDemux::handleInput(IHXBuffer* pBuf) { UINT32 ulBufLen = 0; if (pBuf) { ulBufLen = pBuf->GetSize(); if (m_ulMsgLen+ulBufLen > MAX_HTTP_MSG_SIZE) { if (m_pSock) { IHXSockAddr* pAddr = 0; m_pSock->GetPeerAddr(&pAddr); if (pAddr) { IHXBuffer* pAddrBuf = 0; pAddr->GetAddr(&pAddrBuf); if (pAddrBuf) { fprintf(stderr, "W: Large HTTP message (greater than 64K) being received from addr <%s>.\n" " Possible DOS attack!\n", (const char *)pAddrBuf->GetBuffer()); pAddrBuf->Release(); } pAddr->Release(); } } Close(HXR_FAIL); return; } } if (m_pFragBuf == NULL) { pBuf->AddRef(); } else { IHXBuffer* pNewBuf = new CHXBuffer(); pNewBuf->AddRef(); pNewBuf->SetSize(m_pFragBuf->GetSize() + ulBufLen); memcpy(pNewBuf->GetBuffer(), m_pFragBuf->GetBuffer(), m_pFragBuf->GetSize()); memcpy(pNewBuf->GetBuffer()+m_pFragBuf->GetSize(), pBuf->GetBuffer(), ulBufLen); HX_RELEASE(m_pFragBuf); pBuf = pNewBuf; } while (pBuf != NULL && !m_bClosed) { BYTE* pData = pBuf->GetBuffer(); UINT32 uDataLen = pBuf->GetSize(); UINT32 uDataUsed = 0; IHXBuffer* pNewBuf = NULL; IHXBuffer* pContentBuf = NULL; BOOL bFirstRun = FALSE; BOOL bMsgTooLarge = FALSE; if (m_ReadState == DEMUX_READ_MSG) { HTTPMessage* pMsg = NULL; uDataUsed = uDataLen; pMsg = m_pParser->parse((const char*)pData, uDataUsed, bMsgTooLarge); if (pMsg == NULL) { if (bMsgTooLarge) { if (pBuf) pBuf->Release(); if (m_pSock) { IHXSockAddr* pAddr = 0; m_pSock->GetPeerAddr(&pAddr); if (pAddr) { IHXBuffer* pAddrBuf = 0; pAddr->GetAddr(&pAddrBuf); if (pAddrBuf) { fprintf(stderr, "W: Large amount of HTTP data being received from addr <%s>.\n" " Possible DOS attack!\n", (const char *)pAddrBuf->GetBuffer()); pAddrBuf->Release(); } pAddr->Release(); } } Close(HXR_FAIL); return; } break; } // Remove used data from the buffer if (uDataUsed == uDataLen) { HX_RELEASE(pBuf); } else { pNewBuf = new CHXStaticBuffer(pBuf, uDataUsed, uDataLen-uDataUsed); pNewBuf->AddRef(); HX_RELEASE(pBuf); pBuf = pNewBuf; } if (m_pResponse == NULL) { DetectHandler(pMsg); HX_ASSERT(m_pResponse != NULL); m_pResponse->Init(this); bFirstRun = TRUE; } if (m_pResponse->GetFeatureFlags() & HTTP_FEATURE_IGNORE_CONTENT_LENGTH) { // Cloaking V2. if (m_pResponse->GetFeatureFlags() & ( HTTP_FEATURE_V11_SUPPORT | HTTP_FEATURE_CHUNKED_ENCODING_SUPPORT)) { m_uContentRemain = 0; CHXString strEncoding = pMsg->getHeaderValue("Transfer-Encoding"); if (strEncoding == "chunked") { m_ReadState = DEMUX_READ_DATA; } } else // Far less strict for non-persistent HTTP/1.0 connections. { m_uContentRemain = 0; m_ReadState = DEMUX_READ_DATA; } } else { MIMEHeader* pHdr = pMsg->getHeader("Content-Length"); if (!pHdr) { m_uContentRemain = 0; } else { CHXString strLen; pHdr->asString(strLen); int iLen = atoi(strLen); if (iLen < 0 || iLen > 0xffff) { DPRINTF(D_ERROR, ("HTTP: Bad content length %d\n", iLen)); if (pBuf) pBuf->Release(); Close(HXR_FAIL); return; } m_uContentRemain = (UINT32)iLen; m_ReadState = DEMUX_READ_DATA; } } if (bFirstRun && m_pResponse->AutoDispatch()) { m_pSavedMessage = pMsg; static_cast<CHXServSocket*>(m_pSock)->Dispatch(); break; } DispatchMessage(pMsg); delete pMsg; } else if (m_ReadState == DEMUX_READ_DATA) { BOOL bEnforceContentLength = FALSE; if (m_pResponse->GetFeatureFlags() & HTTP_FEATURE_IGNORE_CONTENT_LENGTH) { HX_ASSERT(m_uContentRemain == 0); // This value not used. pContentBuf = pBuf; pBuf = NULL; } else { if (m_uContentRemain >= pBuf->GetSize()) { pContentBuf = pBuf; m_uContentRemain -= pBuf->GetSize(); pBuf = NULL; } else { pContentBuf = new CHXStaticBuffer(pBuf, 0, m_uContentRemain); pContentBuf->AddRef(); pNewBuf = new CHXStaticBuffer(pBuf, m_uContentRemain, pBuf->GetSize()-m_uContentRemain); pNewBuf->AddRef(); HX_RELEASE(pBuf); pBuf = pNewBuf; m_uContentRemain = 0; m_ReadState = DEMUX_READ_MSG; } } m_pResponse->OnData(pContentBuf); HX_RELEASE(pContentBuf); } } if (pBuf != NULL) { m_pFragBuf = pBuf; m_pFragBuf->AddRef(); } HX_RELEASE(pBuf); }
HX_RESULT HXCloakedV2TCPSocket::_DoProxyAuthentication(HTTPResponseMessage* pMess) { HX_RESULT res = HXR_FAIL; IHXCommonClassFactory* pCCF = NULL; CHXString getStr = ""; IHXKeyValueList* pRespHeaders = NULL; MIMEHeaderValue* pHeaderValue = NULL; MIMEHeader* pHeader = NULL; CHXString strHeader = ""; CHXString strTemp = ""; IHXBuffer* pBuffer = NULL; IHXRequest* pRequest = NULL; IHXValues* pValues = NULL; IHXClientAuthConversation* pClientAuth = NULL; IUnknown* pUnkConfig = NULL; IHXObjectConfiguration* pConfig = NULL; ////////////////////// // // XXXgfw I really don't think we need all this authentication // garbage. It really seems we only need to TLC to just give us a // dialog to do a user/pass request. It sure seems like this code // below is way overkill. Just check out ResponseReady(), the only // thing is needs from all this is just that one string. Oh well, // until I have time to figure out exactly how this all works (all // the calls through the core and into the TLC from here) I will // just leave it like the original cloaking. // ////////////////////// res = m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&pCCF); if( SUCCEEDED(res) ) { //pRequest will be freed in the ResponseReady() method. res = pCCF->CreateInstance(CLSID_IHXRequest, (void**)&pRequest); if( SUCCEEDED(res) ) { getStr = _GenerateGetRequest(); pRequest->SetURL((const char*)getStr); //Always returns HXR_OK; res = pCCF->CreateInstance(CLSID_IHXKeyValueList, (void**)&pRespHeaders); if( SUCCEEDED(res) ) { pHeader = pMess->getFirstHeader(); while (pHeader) { pHeaderValue = pHeader->getFirstHeaderValue(); strHeader = ""; while( pHeaderValue ) { pHeaderValue->asString(strTemp); strHeader += strTemp; pHeaderValue = pHeader->getNextHeaderValue(); if (pHeaderValue) { strHeader += ", "; } } pBuffer = NULL; CHXBuffer::FromCharArray((const char*)strHeader, &pBuffer); if( pBuffer ) { pRespHeaders->AddKeyValue(pHeader->name(), pBuffer); } HX_RELEASE(pBuffer); pHeader = pMess->getNextHeader(); } pValues = NULL; if (HXR_OK == pRespHeaders->QueryInterface(IID_IHXValues, (void**)&pValues)) { pRequest->SetResponseHeaders(pValues); } HX_RELEASE(pValues); } HX_RELEASE(pRespHeaders); if (HXR_OK == pRequest->GetResponseHeaders(pValues)) { res = pCCF->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer); if (SUCCEEDED(res)) { pBuffer->Set((UCHAR*)m_pszProxyName, strlen(m_pszProxyName)+1); pValues->SetPropertyCString("_server", pBuffer); HX_RELEASE(pBuffer); } // Add the protocol to the response headers because TLC needs it if (SUCCEEDED(pCCF->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer))) { pBuffer->Set((UCHAR*)"http", strlen("http") + 1); pValues->SetPropertyCString("_protocol", pBuffer); HX_RELEASE(pBuffer); } HX_RELEASE(pValues); } //We now need a CCF from the cloaking context, not our core's context. HX_RELEASE(pCCF); res = m_pCloakContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&pCCF); if(SUCCEEDED(res)) { res = pCCF->CreateInstance( CLSID_CHXClientAuthenticator, (void**)&pUnkConfig ); if(SUCCEEDED(res)) { res = pUnkConfig->QueryInterface(IID_IHXClientAuthConversation, (void**)&pClientAuth); if (SUCCEEDED(res)) { res = pUnkConfig->QueryInterface(IID_IHXObjectConfiguration, (void**)&pConfig); if (SUCCEEDED(res)) { pConfig->SetContext(m_pCloakContext); HX_RELEASE(pConfig); } if ( pClientAuth && !pClientAuth->IsDone() ) { HX_ASSERT(pRequest); //After this if/else, we continue in ResponseReady() after //the TLC calls us back. if (pRequest) { res = pClientAuth->MakeResponse(this, pRequest); } else { // Auth Failed! pClientAuth->Authenticated(FALSE); res = HXR_NOT_AUTHORIZED; res = ResponseReady(res, pRequest); } } } HX_RELEASE(pUnkConfig); } HX_RELEASE(pCCF); } } } //We return this in all cases. the connection will be started over in //the ResponseReady() method. res = HXR_NOT_AUTHORIZED; return res; }