int CHttpRequest::PostHTTP(CUrl& iUrl, const CString& RawData, const CString& iE, inetSocket& Sock){ CString Request; if (ProxyURL.StrLength() && Proxy.isValid()) { Request += "POST "; Request += iUrl.GetScheme(); Request+="://"; Request += iUrl.GetHost(); if (iUrl.GetPortValue() != 80) { Request+=":"; Request += iUrl.GetPort(); } Request += iUrl.GetUrlPath(); Request += " HTTP/1.0"; Request+=iE; } else { Request += "POST "; Request += iUrl.GetUrlPath(); Request += " HTTP/1.0"; Request+=iE; Request += "Host: "; Request += iUrl.GetHost(); Request+=iE; } for (int i=0;i<RHeaderParams.entries_count();i++) { Request+=RHeaderParams.get_name(i); Request+=": "; Request+=RHeaderParams.get_value(i); Request += iE; } Request += iE; Request += RawData; if (!Send(Sock, Request)) return 0; ProcessHeader(Sock); ProcessData(Sock); if (RData.StrLength()) { RHeaderResponse.clear(); RStatusValue = 200; RStatus = "200"; return 1; } else return 0; }
STDMETHODIMP CBHttpRequest::Open(BSTR strMethod, BSTR strUrl, VARIANT_BOOL bAsync, VARIANT varUser, VARIANT varPassword) { CUrl url; CStringA strObject; CStringA strUser; CStringA strPassword; Abort(); s_cs.Enter(); s_dwReqID ++; m_dwReqID = s_dwReqID; s_mapReq.SetAt(m_dwReqID, this); s_cs.Leave(); url.CrackUrl(CBStringA(strUrl)); m_bAsync = (bAsync != VARIANT_FALSE); strObject = url.GetUrlPath(); strObject.Append(url.GetExtraInfo()); if(varUser.vt != VT_ERROR) { HRESULT hr = varGetString(varUser, strUser); if(FAILED(hr))return hr; } if(varPassword.vt != VT_ERROR) { HRESULT hr = varGetString(varPassword, strPassword); if(FAILED(hr))return hr; } m_hConnection = InternetConnect(m_hSession, url.GetHostName(), url.GetPortNumber(), strUser.IsEmpty() ? NULL : (LPCSTR)strUser, strPassword.IsEmpty() ? NULL : (LPCSTR)strPassword, INTERNET_SERVICE_HTTP, 0, m_dwReqID); if(m_hConnection == NULL) return GetErrorResult(); m_hFile = HttpOpenRequest(m_hConnection, CBStringA(strMethod), strObject, NULL, NULL, NULL, m_dwFlags, m_dwReqID); if(m_hFile == NULL) return GetErrorResult(); m_eventComplete.Set(); return S_OK; }
int CHttpRequest::GetHTTP09(CUrl& iUrl, const CString& iE, inetSocket& Sock){ /* attempt a retrieval of HTTP/0.9 */ CString Request; if (RLimit) Request += "GET "; else Request+="HEAD "; Request += iUrl.GetScheme(); Request+="://"; Request += iUrl.GetHost(); if (iUrl.GetPortValue() != 80) { Request+=":"; Request += iUrl.GetPort(); } Request += iUrl.GetUrlPath(); Request+=iE; for (int i=0;i<RHeaderParams.entries_count();i++) { Request+=RHeaderParams.get_name(i); Request+=": "; Request+=RHeaderParams.get_value(i); Request += iE; } Request += iE; #ifdef _U_DEBUG cout << "# HTTP 0.9 Request: =====" << endl; cout << Request; cout << "=====================" << endl; #endif /* issue request */ if (!Send(Sock, Request)) return 0; RHeader.Free(); RData.Free(); RStatus.Free(); RStatusValue = -1; ProcessData(Sock); if (RData.StrLength()) { RHeaderResponse.clear(); RStatusValue = 200; RStatus = "200"; return 1; } else if (RStatusValue != -1) { return 0; } else { RStatusValue = HTTPR_USER + 3; return 0; } }
CVector<CString> CUrlTree::UrlToVector(const CUrl& Url) const { CVector<CString> Vector; CString MidString; MidString += Url.GetScheme(); MidString += ":/"; #ifdef _UNIX if (Url.GetScheme().Same(g_strProto_FILE)) { MidString += "/"; } #endif Vector += MidString; MidString = Url.GetHost(); if (MidString.GetLength() && Url.GetPortValue() != 80) { MidString += ":"; MidString += Url.GetPort(); } if (MidString.GetLength()) { Vector += MidString; } int HostVectorSize = Vector.GetSize(); CVector<CString> Vector2; CString::StrToVector(Url.GetUrlPath(), '/', &Vector2); Vector += Vector2; if (((int) Vector.GetSize() > HostVectorSize) && (!Vector[HostVectorSize].GetLength())) Vector.RemoveAt(HostVectorSize); return Vector; }
HRESULT FAsyncDownload::FHttpDownloadTP::ProcessDownload(FAsyncDownData *pData) { HRESULT hr = E_FAIL; FString ReqUrl = pData->m_pUrlInfo->m_DownloadUrl; UrlUnescapeInPlace(ReqUrl.GetBuffer(), 0); CUrl url; url.CrackUrl(ReqUrl); const tchar* pszUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"; FHInternet hIn = NULL; if (g_AppSettings.m_Proxy.GetLength() > 0) { hIn = InternetOpen(pszUserAgent, INTERNET_OPEN_TYPE_PROXY, g_AppSettings.m_Proxy, g_AppSettings.m_ProxyA, 0); } else { hIn = InternetOpen(pszUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); } if (NULL == hIn) return E_HTTP_NET_ERROR; FHInternet hCon = InternetConnect(hIn, url.GetHostName(), url.GetPortNumber(), url.GetUserName(), url.GetPassword(), INTERNET_SERVICE_HTTP, 0, 0); if (NULL == hCon) { _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: InternetConnect() failed: %d\n", GetLastError()); return E_HTTP_NET_ERROR; } ULONG ulRecvTimeout = 15000; InternetSetOption(hCon, INTERNET_OPTION_RECEIVE_TIMEOUT, &ulRecvTimeout, sizeof(ULONG)); FString StrRes = url.GetUrlPath(); StrRes+= url.GetExtraInfo(); FHInternet hReq = HttpOpenRequest(hCon, "GET", StrRes, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_DONT_CACHE, 0); if (NULL == hReq) { _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: HttpOpenRequest() failed: %d\n", GetLastError()); return E_HTTP_NET_ERROR; } size_type FileSize = 0; if (!(pData->m_pUrlInfo->m_dwDownloadFlags & HTTP_FLAG_NO_RESUME)) FileSize = GetFileSize(pData->m_pUrlInfo->m_DownloadFile); // See if file already exists on the disk. if (FileSize > 0) { FString StrRange; StrRange.Format("Range: bytes=%I64d-", FileSize); HttpAddRequestHeaders(hReq, StrRange, StrRange.GetLength(), HTTP_ADDREQ_FLAG_ADD_IF_NEW); } FString StrVersion; StrVersion.Format("LTV_VERSION: %s", g_AppSettings.m_AppVersion); HttpAddRequestHeaders(hReq, StrVersion, StrVersion.GetLength(), HTTP_ADDREQ_FLAG_ADD_IF_NEW); if (!HttpSendRequest(hReq, NULL, 0, NULL, 0)) { int err = GetLastError(); _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: HttpSendRequest() failed: %d (0x%x)\n", err, HRESULT_FROM_WIN32(err)); InternetCloseHandle(hCon); InternetCloseHandle(hIn); return E_HTTP_NET_ERROR; } const DWORD dwBufferSize = 8192; char pBuffer[dwBufferSize]; FHttpConnection FConn = hReq; DWORD dwStatusCode = FConn.GetStatusCode(); FString ReqContentType = pData->m_pUrlInfo->m_ContentType; pData->m_pUrlInfo->m_ContentType = FConn.GetHeader(HTTP_QUERY_CONTENT_TYPE); pData->m_pUrlInfo->m_dwStatusCode = dwStatusCode; if (!MatchContentType(ReqContentType, pData->m_pUrlInfo->m_ContentType)) { _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: Content type mismatch: %s/%s\n", ReqContentType, pData->m_pUrlInfo->m_ContentType); return E_NOINTERFACE; //E_NOINTERFACE = content type mismatch } if (dwStatusCode == 416 && FileSize > 0) { _DBGAlert("FAsyncDownload::FHttpDownloadTP::ProcessDownload: Server status code: %d. Download complete\n", dwStatusCode); return S_OK; } if (dwStatusCode < 200 || dwStatusCode > 206) { _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: Server status code: %d\n", dwStatusCode); if (dwStatusCode == 404) return E_HTTP_NOTFOUND; return E_HTTP_INVALID_STATUS; } CAtlFile OutFile; if (pData->m_pUrlInfo->m_dwDownloadFlags & HTTP_FLAG_NO_RESUME) DeleteFile(pData->m_pUrlInfo->m_DownloadFile); hr = OutFile.Create(pData->m_pUrlInfo->m_DownloadFile, GENERIC_WRITE, 0, OPEN_ALWAYS); if (FAILED(hr)) { _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: CreateFile failed: 0x%x, %d : %s\n", hr, GetLastError(), pData->m_pUrlInfo->m_DownloadFile); return E_HTTP_WRITE_FILE; } size_type llTotalRead = 0; size_type llSizeMax = 0; size_type ContentLen = FConn.GetContentLength(); pData->m_pUrlInfo->m_ContentLength = ContentLen; if (dwStatusCode == 206) { FString FStrRange = FConn.GetHeader(HTTP_QUERY_CONTENT_RANGE); if (FStrRange) { //Content-Range: bytes 21010-47021/47022 const char* pszBytes = strstr(FStrRange, "bytes "); if (pszBytes != NULL) { pszBytes+=sizeof("bytes"); LONGLONG llOffset = _strtoi64(pszBytes, NULL, 10); hr = OutFile.Seek(llOffset, FILE_BEGIN); llTotalRead = (size_type)llOffset; if (FAILED(hr)) { _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: Seek to position %d failed: 0x%x, %d\n", hr, GetLastError()); } const char* pszTotal = strchr(pszBytes, '/'); if (pszTotal != NULL) llSizeMax = _strtoi64(pszTotal + 1, NULL, 10); } } } else { if (ContentLen > 0 && ContentLen == FileSize) { OutFile.Close(); return S_OK; } } if (llSizeMax == 0) llSizeMax = ContentLen; pData->pBindStatusCallback.OnProgress((ULONG)llTotalRead, (ULONG)llSizeMax, BINDSTATUS_BEGINDOWNLOADDATA, L""); DWORD dwBytesRead = 0; for (;;) { if (!InternetReadFile(hReq, pBuffer, dwBufferSize, &dwBytesRead)) { _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: InternetReadFile() failed: %d\n", GetLastError()); OutFile.Close(); return E_HTTP_NET_ERROR; } if (dwBytesRead == 0) { hr = S_OK; break; } DWORD dwBytesWritten = 0; hr = OutFile.Write(pBuffer, dwBytesRead, &dwBytesWritten); if (FAILED(hr)) { _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: FileWrite failed: 0x%x, %d\n", hr, GetLastError()); OutFile.Close(); return E_HTTP_WRITE_FILE; } llTotalRead+=dwBytesRead; pData->pBindStatusCallback.OnProgress((ULONG)llTotalRead, llSizeMax > 0 ? (ULONG)llSizeMax : llTotalRead , BINDSTATUS_DOWNLOADINGDATA, L""); if (m_pThis->m_Stopping || pData->pBindStatusCallback.m_Abort) { _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: Download aborted\n", hr, GetLastError()); hr = E_ABORT; break; } } OutFile.Close(); return hr; }
int CHttpRequest::GetHTTP10(CUrl& iUrl, const CString& iE, inetSocket& Sock){ /* attempt a retrieval of HTTP/1.0 */ CString Request; if (ProxyURL.StrLength() && Proxy.isValid()) { if (RLimit) Request += "GET "; else Request+="HEAD "; Request += iUrl.GetScheme(); Request+="://"; Request += iUrl.GetHost(); if (iUrl.GetPortValue() != 80) { Request+=":"; Request += iUrl.GetPort(); } Request += iUrl.GetUrlPath(); Request += " HTTP/1.0"; Request+=iE; } else { if (RLimit) Request += "GET "; else Request+="HEAD "; Request += iUrl.GetUrlPath(); Request += " HTTP/1.0"; Request+=iE; Request += "Host: "; Request += iUrl.GetHost(); Request+=iE; } for (int i=0;i<RHeaderParams.entries_count();i++) { Request+=RHeaderParams.get_name(i); Request+=": "; Request+=RHeaderParams.get_value(i); Request += iE; } Request += iE; #ifdef _U_DEBUG cout << "# HTTP Request: =====" << endl; cout << Request; cout << "=====================" << endl; #endif /* issue request */ CString RLoc; if (!Send(Sock, Request)) return 0; ProcessHeader(Sock); ProcessData(Sock); switch(RStatusValue) { case 200: return 1; case 301: case 302: case 303: case 307: if (!FollowRedirections) return RStatusValue; RLoc = RHeaderResponse.get_value("Location"); if (RLoc.StrLength()) { /* HTTP 1.1 - Temporary Redirect is 302 and 307 RedirectVector is relevant for final URL address that could be retrieved */ if (!RedirectVector.Contains(RLoc)) { RedirectVector+=RLoc; CUrl NewURL(RLoc); if (!Proxy.isValid()) { inetSocket Sock2(NewURL.GetPortValue(), NewURL.GetHost()); return GetHTTP10(NewURL, iE, Sock2); } else { Sock.Reopen(); return GetHTTP10(NewURL, iE, Sock); } } } return RStatusValue; case 305: /* use proxy */ RLoc = RHeaderResponse.get_value("Location"); if (RLoc.StrLength()) { CUrl ProxyURL(RLoc); if (ProxyURL.isValid()) { inetSocket ProxySock(ProxyURL.GetPortValue(), ProxyURL.GetHost()); if (wsLastError.StrLength()) return RStatusValue; return GetHTTP10(iUrl, iE, ProxySock); } } return RStatusValue; default: return RStatusValue; } }