//------------------------------------------------------------------------------------------------------------------------ const char *CHttpClient::SendRequest(const wchar_t * verb, const wchar_t * target_url, const wchar_t * headers, const wchar_t * body) { CParsedURL<wchar_t> url; url.Parse(target_url); HINTERNET hConnect = NULL, hRequest = NULL; if (hSession) // Specify an HTTP server. hConnect = WinHttpConnect(hSession, url.Base(), url.is_https ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0); if (hConnect) // Create an HTTP request handle. hRequest = WinHttpOpenRequest(hConnect, verb, url.Route(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); BOOL bResults = FALSE; if (hRequest) // Send a request. { if (body==nullptr) // indicates a GET request bResults = WinHttpSendRequest(hRequest, headers, wcslen(headers), WINHTTP_NO_REQUEST_DATA, 0, 0, NULL); else bResults = WinHttpSendRequest(hRequest, headers, wcslen(headers), (LPVOID)body, (DWORD)wcslen(body) * 2, (DWORD)wcslen(body) * 2, NULL); } if (bResults)// End the request. bResults = WinHttpReceiveResponse(hRequest, NULL); response.clear(); // Keep checking for data until there is nothing left. if (bResults) for (DWORD dwSize = 1; dwSize > 0;) { if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) // Check for available data. StoreErrorCode(); LPSTR pszOutBuffer = new char[dwSize + 1]; // Allocate space for the buffer. if (!pszOutBuffer) { //ReportError("Out of memory\n", -1); dwSize = 0; } else { ZeroMemory(pszOutBuffer, dwSize + 1); DWORD dwDownloaded = 0; if (WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded)) // Read the data. response.append(pszOutBuffer); else StoreErrorCode(); delete[] pszOutBuffer;// Free the memory allocated to the buffer. } } else // !bResults StoreErrorCode(); // Close any open handles. if (hRequest) WinHttpCloseHandle(hRequest); if (hConnect) WinHttpCloseHandle(hConnect); return last_err_code? nullptr : response.c_str(); }
bool uploadToImgur(Image* image, String& response) { MemWriteFile memRaw; image->writePNG(&memRaw); bool success = false; response = "Failed to connect"; HINTERNET hSession = WinHttpOpen(L"MuleView", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL, 0); if (hSession) { HINTERNET hConnect = WinHttpConnect(hSession, L"api.imgur.com", INTERNET_DEFAULT_HTTPS_PORT, 0); if (hConnect) { HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/3/image", L"HTTP/1.1", WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE); if (hRequest) { wchar_t* headers = L"Authorization: Client-ID b7668fe01959177\r\n" L"Content-Type: image/png\r\n"; BOOL result = WinHttpSendRequest(hRequest, headers, -1, memRaw.buffer(), memRaw.size(), memRaw.size(), NULL); if (result) result = WinHttpReceiveResponse(hRequest, NULL); DWORD avail; if (result) result = WinHttpQueryDataAvailable(hRequest, &avail); if (result) { char* ptr = new char[avail + 1]; WinHttpReadData(hRequest, ptr, avail, &avail); ptr[avail] = 0; LocalPtr<json::Value> value = json::Value::parse(File::memfile(ptr, avail, false)); json::Value* sub = (value && value->type() == json::Value::tObject ? value->get("data") : NULL); json::Value* sub2 = (sub && sub->type() == json::Value::tObject ? sub->get("id") : NULL); if (sub2 && sub2->type() == json::Value::tString) { success = true; response = sub2->getString(); } else { sub2 = (sub && sub->type() == json::Value::tObject ? sub->get("error") : NULL); if (sub2 && sub2->type() == json::Value::tString) response = sub2->getString(); } delete[] ptr; } WinHttpCloseHandle(hRequest); } WinHttpCloseHandle(hConnect); } WinHttpCloseHandle(hSession); } return success; }
LPBYTE Http::ReadData(HINTERNET hRequest, LPDWORD lpdwSize) { LPBYTE lpData = NULL; LPBYTE lpPrev = NULL; DWORD dwSize; DWORD dwTotalSize = 0; DWORD dwTotalSizePrev = 0; for (;;) { WinHttpQueryDataAvailable(hRequest, &dwSize); if (dwSize > 0) { dwTotalSizePrev = dwTotalSize; dwTotalSize += dwSize; lpData = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, dwTotalSize); if (lpPrev != NULL) { CopyMemory(lpData, lpPrev, dwTotalSizePrev); HeapFree(GetProcessHeap(), 0, lpPrev); } WinHttpReadData(hRequest, lpData + dwTotalSizePrev, dwSize, NULL); lpPrev = lpData; } else break; } *lpdwSize = dwTotalSize; return lpData; }
HRESULT GETRequest::get(LPDWORD readLength, LPVOID buffer) { DWORD tempSize = 1; DWORD dwDownloaded = 0; char* buf = (char*)buffer; if (this->length == 0) return E_INVALIDARG; *readLength = 0; while (tempSize > 0) { // Check for available data. tempSize = 0; if (!WinHttpQueryDataAvailable( this->hRequest, &tempSize)) { return E_FAIL; } if (*readLength + tempSize > this->length) tempSize = this->length - *readLength; if (tempSize == 0) { break; } // Read the Data. if (!WinHttpReadData( hRequest, buf, tempSize, &dwDownloaded)) { return E_FAIL; } *readLength += dwDownloaded; buf += dwDownloaded; }; return ERROR_SUCCESS; }
void WindowsHttpDownloader::InternalDownload() { while (1) { if (_abort_download) break; WaitForSingleObjectEx(_event_download, INFINITE, FALSE); if (_abort_download) break; DWORD download_size = 0; if (!WinHttpQueryDataAvailable(_http.request, &download_size)) break; if (download_size == 0) break; if (!_read_buf.Alloc(download_size)) break; if (!WinHttpReadData(_http.request, _read_buf.Get<void*>(), download_size, &download_size)) break; if (download_size == 0) break; std::lock_guard<decltype(_buf_lock)> lock(_buf_lock); _buffered.WriteBytes(_read_buf.Get<void*>(), download_size); if (!_buffered.IsBlockWriteable()) { ResetEvent(_event_download); SetEvent(_events[EventBuf]); } SetEvent(_events[EventDataAvailable]); } SetEvent(_events[EventEof]); }
void CWinHTTPUtil::StatusDataAvailable(DWORD size) { if( size > 0 ){ DL_DATA* item = new DL_DATA; item->size = size; item->data = new BYTE[item->size]; ZeroMemory(item->data, item->size); WinHttpReadData( this->request, item->data, item->size, NULL); if( this->saveFilePath.size() > 0 ){ HANDLE file = CreateFile( this->saveFilePath.c_str(), GENERIC_READ|GENERIC_WRITE , FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if( file != INVALID_HANDLE_VALUE){ SetFilePointer(file, 0,NULL, FILE_END ); DWORD write; WriteFile( file, item->data, item->size, &write, NULL ); CloseHandle(file); } SAFE_DELETE(item); }else{ this->dlBuffList.push_back(item); } WinHttpQueryDataAvailable( this->request, NULL); }else{ //DL終了 SetEvent(this->responseCompEvent); } }
bool CWinHttp::GetResponseConext() { bool bRet=false; DWORD dwSize=0 ; LPSTR pszOutBuffer; if( hRequest ) { do { // Check for available data. dwSize = 0; if( !WinHttpQueryDataAvailable( hRequest, &dwSize ) ) goto exit0; if(dwSize==0) break; else { // Allocate space for the buffer. pszOutBuffer = new char[dwSize+1]; // Read the data. ZeroMemory( pszOutBuffer, dwSize+1 ); if( !WinHttpReadData( hRequest, (LPVOID)pszOutBuffer, dwSize, 0) ) goto exit0; else { m_strResponseContent=m_strResponseContent+pszOutBuffer; } // Free the memory allocated to the buffer. delete [] pszOutBuffer; } } while( dwSize > 0 ); } bRet=true; exit0: assert(bRet!=false); return bRet; }
static HRESULT receive_message( struct channel *channel, ULONG max_len, char **ret, ULONG *ret_len ) { DWORD len, bytes_read, offset = 0, size = INITIAL_READ_BUFFER_SIZE; char *buf; if (!(buf = heap_alloc( size ))) return E_OUTOFMEMORY; *ret_len = 0; for (;;) { if (!WinHttpQueryDataAvailable( channel->http_request, &len )) { heap_free( buf ); return HRESULT_FROM_WIN32( GetLastError() ); } if (!len) break; if (*ret_len + len > max_len) { heap_free( buf ); return WS_E_QUOTA_EXCEEDED; } if (*ret_len + len > size) { char *tmp; DWORD new_size = max( *ret_len + len, size * 2 ); if (!(tmp = heap_realloc( buf, new_size ))) { heap_free( buf ); return E_OUTOFMEMORY; } buf = tmp; size = new_size; } if (!WinHttpReadData( channel->http_request, buf + offset, len, &bytes_read )) { heap_free( buf ); return HRESULT_FROM_WIN32( GetLastError() ); } if (!bytes_read) break; *ret_len += bytes_read; offset += bytes_read; } *ret = buf; return S_OK; }
void CWinHTTPUtil::StatusHeadersAvailable() { DWORD size = sizeof(DWORD); //HTTPのステータスコード確認 WinHttpQueryHeaders( this->request, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &this->responseStatusCode, &size, NULL ); //レスポンスヘッダを全部取得 WinHttpQueryHeaders( this->request, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &size, WINHTTP_NO_HEADER_INDEX); WCHAR* rawHeader = new WCHAR[size/sizeof(WCHAR) + 1]; ZeroMemory(rawHeader, sizeof(WCHAR) * (size/sizeof(WCHAR) + 1)); if( WinHttpQueryHeaders( this->request, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, rawHeader, &size, WINHTTP_NO_HEADER_INDEX) == TRUE ){ this->responseHTTPHeader = rawHeader; }else{ this->responseHTTPHeader = L""; } SAFE_DELETE_ARRAY(rawHeader) //ContentLengthを取得してみる DWORD fileLength = 0; size = sizeof(DWORD); if( WinHttpQueryHeaders( this->request, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER , NULL, &fileLength, &size, NULL ) == TRUE ){ this->responseContentSize = fileLength; }else{ this->responseContentSize = 0; } if( this->responseStatusCode == 200 || this->responseStatusCode == 201){ //サイズ0のファイル作成 if( this->saveFilePath.size() > 0 ){ HANDLE file = CreateFile( this->saveFilePath.c_str(), GENERIC_READ|GENERIC_WRITE , FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if( file != INVALID_HANDLE_VALUE){ CloseHandle(file); } } }else{ this->errEndCode = ERR_NW_FALSE; } WinHttpQueryDataAvailable( this->request, NULL); }
BOOL GetHttpResponse(PBYTE pBufOut,DWORD& dwBuf,HINTERNET hRequest) { dwBuf = 0; DWORD dwSize = 0; BOOL bResults = WinHttpReceiveResponse( hRequest, NULL); if(bResults) { do { // Check for available data. dwSize = 0; bResults = WinHttpQueryDataAvailable( hRequest, &dwSize); // Read the Data. ZeroMemory(pBufOut+dwBuf, dwSize+1); DWORD dwDownloaded=0; WinHttpReadData( hRequest, (LPVOID)(pBufOut+dwBuf), dwSize, &dwDownloaded); dwBuf+=dwDownloaded; } while (dwSize > 0); } return bResults; }
HRESULT GETRequest::import(WCHAR* localPath) { HANDLE handle = 0; char buffer[DAV_DATA_CHUNCK] = {0}; DWORD dwDownloaded = 1; DWORD NumberOfBytesWritten = 0; if (!buffer) return E_INVALIDARG; handle = CreateFile( localPath, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, // security attribute CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); // template file handle if (handle == INVALID_HANDLE_VALUE) return E_FAIL; while (dwDownloaded > 0) { // Check for available data. if (!WinHttpQueryDataAvailable( hRequest, &dwDownloaded)) return E_FAIL; // Read the Data. if (!WinHttpReadData( hRequest, buffer, DAV_DATA_CHUNCK, &dwDownloaded)) return E_FAIL; if (!WriteFile(handle, buffer, dwDownloaded, &NumberOfBytesWritten, NULL)) return E_FAIL; }; CloseHandle(handle); return ERROR_SUCCESS; }
BOOL HTTPGetFile (CTSTR url, CTSTR outputPath, CTSTR extraHeaders, int *responseCode) { HINTERNET hSession = NULL; HINTERNET hConnect = NULL; HINTERNET hRequest = NULL; URL_COMPONENTS urlComponents; BOOL secure = FALSE; BOOL ret = FALSE; String hostName, path; const TCHAR *acceptTypes[] = { TEXT("*/*"), NULL }; hostName.SetLength(256); path.SetLength(1024); zero(&urlComponents, sizeof(urlComponents)); urlComponents.dwStructSize = sizeof(urlComponents); urlComponents.lpszHostName = hostName; urlComponents.dwHostNameLength = hostName.Length(); urlComponents.lpszUrlPath = path; urlComponents.dwUrlPathLength = path.Length(); WinHttpCrackUrl(url, 0, 0, &urlComponents); if (urlComponents.nPort == 443) secure = TRUE; hSession = WinHttpOpen(OBS_VERSION_STRING, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!hSession) goto failure; hConnect = WinHttpConnect(hSession, hostName, secure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0); if (!hConnect) goto failure; hRequest = WinHttpOpenRequest(hConnect, TEXT("GET"), path, NULL, WINHTTP_NO_REFERER, acceptTypes, secure ? WINHTTP_FLAG_SECURE|WINHTTP_FLAG_REFRESH : WINHTTP_FLAG_REFRESH); if (!hRequest) goto failure; BOOL bResults = WinHttpSendRequest(hRequest, extraHeaders, extraHeaders ? -1 : 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); // End the request. if (bResults) bResults = WinHttpReceiveResponse(hRequest, NULL); else goto failure; TCHAR statusCode[8]; DWORD statusCodeLen; statusCodeLen = sizeof(statusCode); if (!WinHttpQueryHeaders (hRequest, WINHTTP_QUERY_STATUS_CODE, WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusCodeLen, WINHTTP_NO_HEADER_INDEX)) goto failure; *responseCode = wcstoul(statusCode, NULL, 10); if (bResults && *responseCode == 200) { BYTE buffer[16384]; DWORD dwSize, dwOutSize; XFile updateFile; if (!updateFile.Open(outputPath, XFILE_WRITE, CREATE_ALWAYS)) goto failure; do { // Check for available data. dwSize = 0; if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) goto failure; if (!WinHttpReadData(hRequest, (LPVOID)buffer, dwSize, &dwOutSize)) { goto failure; } else { if (!dwOutSize) break; if (!updateFile.Write(buffer, dwOutSize)) goto failure; } } while (dwSize > 0); updateFile.Close(); } ret = TRUE; failure: if (hSession) WinHttpCloseHandle(hSession); if (hConnect) WinHttpCloseHandle(hConnect); if (hRequest) WinHttpCloseHandle(hRequest); return ret; }
String HTTPGetString (CTSTR url, CTSTR extraHeaders, int *responseCode, String verb) { HINTERNET hSession = NULL; HINTERNET hConnect = NULL; HINTERNET hRequest = NULL; URL_COMPONENTS urlComponents; BOOL secure = FALSE; String result = ""; String body = TEXT(""); String nurl = url; String hostName, path; const TCHAR *acceptTypes[] = { TEXT("*/*"), NULL }; if (verb == TEXT("POST")){ CTSTR s = srchr(url, TEXT('?')); body = String(s + 1); nurl = nurl.Left(s - url); } hostName.SetLength(256); path.SetLength(1024); zero(&urlComponents, sizeof(urlComponents)); urlComponents.dwStructSize = sizeof(urlComponents); urlComponents.lpszHostName = hostName; urlComponents.dwHostNameLength = hostName.Length(); urlComponents.lpszUrlPath = path; urlComponents.dwUrlPathLength = path.Length(); WinHttpCrackUrl(nurl, 0, 0, &urlComponents); if (urlComponents.nPort == 443) secure = TRUE; hSession = WinHttpOpen(TEXT("gecko test"), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!hSession) goto failure; hConnect = WinHttpConnect(hSession, hostName, secure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0); if (!hConnect) goto failure; hRequest = WinHttpOpenRequest(hConnect, verb, path, NULL, WINHTTP_NO_REFERER, acceptTypes, secure ? WINHTTP_FLAG_SECURE|WINHTTP_FLAG_REFRESH : WINHTTP_FLAG_REFRESH); if (!hRequest) goto failure; BOOL bResults = WinHttpSendRequest(hRequest, extraHeaders, extraHeaders ? -1 : 0, body.Array(), body.Length(), body.Length(), 0); // End the request. if (bResults) bResults = WinHttpReceiveResponse(hRequest, NULL); else goto failure; TCHAR statusCode[8]; DWORD statusCodeLen; statusCodeLen = sizeof(statusCode); if (!WinHttpQueryHeaders (hRequest, WINHTTP_QUERY_STATUS_CODE, WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusCodeLen, WINHTTP_NO_HEADER_INDEX)) goto failure; *responseCode = wcstoul(statusCode, NULL, 10); if (bResults && *responseCode == 200) { CHAR buffer[16384]; DWORD dwSize, dwOutSize; do { // Check for available data. dwSize = 0; if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) goto failure; if (!WinHttpReadData(hRequest, (LPVOID)buffer, dwSize, &dwOutSize)) { goto failure; } else { if (!dwOutSize) break; // Ensure the string is terminated. buffer[dwOutSize] = 0; String b = String((LPCSTR)buffer); result.AppendString(b); } } while (dwSize > 0); } failure: if (hSession) WinHttpCloseHandle(hSession); if (hConnect) WinHttpCloseHandle(hConnect); if (hRequest) WinHttpCloseHandle(hRequest); return result; }
void main() { DWORD dwSize = 0; DWORD dwDownloaded = 0; LPSTR pszOutBuffer = NULL; HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL; BOOL bResults = FALSE; hSession=WinHttpOpen(L"User-Agent",WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,WINHTTP_NO_PROXY_NAME,WINHTTP_NO_PROXY_BYPASS,0); if(hSession) { hConnect=WinHttpConnect(hSession,L"kinggigi.sinaapp.com",INTERNET_DEFAULT_HTTP_PORT,0); } if(hConnect) { hRequest=WinHttpOpenRequest(hConnect, L"POST",L"hello.php",L"HTTP/1.1", WINHTTP_NO_REFERER,WINHTTP_DEFAULT_ACCEPT_TYPES,0); } LPCWSTR header=L"Content-type: application/x-www-form-urlencoded"; SIZE_T len = lstrlenW(header); WinHttpAddRequestHeaders(hRequest,header,DWORD(len), WINHTTP_ADDREQ_FLAG_ADD); if(hRequest) { std::string data="val1=10&val2=9"; const void *ss=(const char *)data.c_str(); bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, const_cast<void *>(ss), data.length(), data.length(), 0); ////bResults=WinHttpSendRequest(hRequest,WINHTTP_NO_ADDITIONAL_HEADERS, 0,WINHTTP_NO_REQUEST_DATA, 0, 0, 0 ); } if(bResults) { bResults=WinHttpReceiveResponse(hRequest,NULL); } if(bResults) { do { // Check for available data. dwSize = 0; if (!WinHttpQueryDataAvailable( hRequest, &dwSize)) { printf( "Error %u in WinHttpQueryDataAvailable.\n",GetLastError()); break; } if (!dwSize) break; pszOutBuffer = new char[dwSize+1]; if (!pszOutBuffer) { printf("Out of memory\n"); break; } ZeroMemory(pszOutBuffer, dwSize+1); if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded)) { printf( "Error %u in WinHttpReadData.\n", GetLastError()); } else { printf("%s", pszOutBuffer); } delete [] pszOutBuffer; if (!dwDownloaded) break; } while (dwSize > 0); } if (hRequest) WinHttpCloseHandle(hRequest); if (hConnect) WinHttpCloseHandle(hConnect); if (hSession) WinHttpCloseHandle(hSession); system("pause"); }
DWORD HTTPGetFile(String url, char * outHtml, unsigned &bufeLen, CTSTR extraHeaders, int *responseCode) { if (NULL == outHtml || 0 == bufeLen) { return 1; } unsigned nMaxBufLen = bufeLen; bufeLen = 0; HINTERNET hSession = NULL; HINTERNET hConnect = NULL; HINTERNET hRequest = NULL; URL_COMPONENTS urlComponents; BOOL secure = FALSE; DWORD ret = 1; String hostName, path; const TCHAR *acceptTypes[] = { TEXT("*/*"), NULL }; hostName.SetLength(256); path.SetLength(1024); zero(&urlComponents, sizeof(urlComponents)); urlComponents.dwStructSize = sizeof(urlComponents); urlComponents.lpszHostName = hostName; urlComponents.dwHostNameLength = hostName.Length(); urlComponents.lpszUrlPath = path; urlComponents.dwUrlPathLength = path.Length(); WinHttpCrackUrl(url, 0, 0, &urlComponents); if (urlComponents.nPort == 443) secure = TRUE; hSession = WinHttpOpen(TEXT("ButelLive agent"), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!hSession) goto failure; DWORD dwTimeOut = 5000; // ms DWORD dwSize = sizeof(DWORD); WinHttpSetOption(hSession, WINHTTP_OPTION_CONNECT_TIMEOUT, &dwTimeOut, dwSize); WinHttpSetOption(hSession, WINHTTP_OPTION_SEND_TIMEOUT, &dwTimeOut, dwSize); WinHttpSetOption(hSession, WINHTTP_OPTION_RECEIVE_TIMEOUT, &dwTimeOut, dwSize); hConnect = WinHttpConnect(hSession, hostName, urlComponents.nPort, 0); if (!hConnect) goto failure; hRequest = WinHttpOpenRequest(hConnect, TEXT("Get"), path, NULL, WINHTTP_NO_REFERER, acceptTypes, secure ? WINHTTP_FLAG_SECURE | WINHTTP_FLAG_REFRESH : WINHTTP_FLAG_REFRESH); if (!hRequest) goto failure; BOOL bResults = WinHttpSendRequest( hRequest, extraHeaders, extraHeaders ? -1 : 0, NULL, 0, 0, NULL ); // End the request. if (bResults) bResults = WinHttpReceiveResponse(hRequest, NULL); else goto failure; TCHAR statusCode[8]; DWORD statusCodeLen; statusCodeLen = sizeof(statusCode); if (!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE, WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusCodeLen, WINHTTP_NO_HEADER_INDEX)) { //ERROR_WINHTTP_HEADER_NOT_FOUND int error = GetLastError(); goto failure; } *responseCode = wcstoul(statusCode, NULL, 10); if (bResults && *responseCode == 200) { BYTE buffer[16384]; DWORD dwSize, dwOutSize; do { // Check for available data. dwSize = 0; if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) goto failure; if (!WinHttpReadData(hRequest, (LPVOID)buffer, dwSize, &dwOutSize)) { goto failure; } else { if (!dwOutSize) break; if (bufeLen + dwOutSize > nMaxBufLen) { goto failure; } //strHtml.AppendString((CTSTR)buffer, dwOutSize); memcpy(outHtml + bufeLen, buffer, dwOutSize); bufeLen += dwOutSize; outHtml[bufeLen] = '\0'; } } while (dwSize > 0); } ret = 0; failure: if (0 != ret) { DWORD dwError = GetLastError(); if (dwError != 0) { ret = dwError; } } if (hSession) WinHttpCloseHandle(hSession); if (hConnect) WinHttpCloseHandle(hConnect); if (hRequest) WinHttpCloseHandle(hRequest); return ret; }
static void test_async( void ) { HANDLE ses, con, req; DWORD size, status; BOOL ret; struct info info, *context = &info; char buffer[1024]; info.test = async_test; info.count = sizeof(async_test) / sizeof(async_test[0]); info.index = 0; info.wait = CreateEventW( NULL, FALSE, FALSE, NULL ); ses = WinHttpOpen( user_agent, 0, NULL, NULL, WINHTTP_FLAG_ASYNC ); ok(ses != NULL, "failed to open session %u\n", GetLastError()); WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 ); ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) ); ok(ret, "failed to set context value %u\n", GetLastError()); setup_test( &info, winhttp_connect, __LINE__ ); con = WinHttpConnect( ses, test_winehq, 0, 0 ); ok(con != NULL, "failed to open a connection %u\n", GetLastError()); setup_test( &info, winhttp_open_request, __LINE__ ); req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 ); ok(req != NULL, "failed to open a request %u\n", GetLastError()); setup_test( &info, winhttp_send_request, __LINE__ ); ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 ); ok(ret, "failed to send request %u\n", GetLastError()); WaitForSingleObject( info.wait, INFINITE ); setup_test( &info, winhttp_receive_response, __LINE__ ); ret = WinHttpReceiveResponse( req, NULL ); ok(ret, "failed to receive response %u\n", GetLastError()); WaitForSingleObject( info.wait, INFINITE ); size = sizeof(status); ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL ); ok(ret, "failed unexpectedly %u\n", GetLastError()); ok(status == 200, "request failed unexpectedly %u\n", status); setup_test( &info, winhttp_query_data, __LINE__ ); ret = WinHttpQueryDataAvailable( req, NULL ); ok(ret, "failed to query data available %u\n", GetLastError()); WaitForSingleObject( info.wait, INFINITE ); setup_test( &info, winhttp_read_data, __LINE__ ); ret = WinHttpReadData( req, buffer, sizeof(buffer), NULL ); ok(ret, "failed to query data available %u\n", GetLastError()); WaitForSingleObject( info.wait, INFINITE ); setup_test( &info, winhttp_close_handle, __LINE__ ); WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); WinHttpCloseHandle( ses ); WaitForSingleObject( info.wait, INFINITE ); CloseHandle( info.wait ); }
int APICaller::GetData(LPCWSTR path, char **dataOut) { char *readBuffer = NULL; DWORD cumulativeRead = 0; BOOL dataCompressed = FALSE; // Attempt to get a connection if (!GetConnection()) { return 0; } HINTERNET request = WinHttpOpenRequest(connection, L"GET", path, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE); if (request != NULL) { WinHttpAddRequestHeaders(request, L"Accept-Encoding: gzip, deflate", (DWORD)-1, WINHTTP_ADDREQ_FLAG_ADD); if (WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) { if (WinHttpReceiveResponse(request, NULL)) { DWORD toRead = 0; DWORD bytesRead = 0; do { if (!WinHttpQueryDataAvailable(request, &toRead)) { break; } if (toRead == 0) { break; } readBuffer = (char*)((readBuffer == NULL) ? malloc(toRead) : realloc(readBuffer, cumulativeRead + toRead + 1)); if (WinHttpReadData(request, readBuffer+cumulativeRead, toRead, &bytesRead)) { cumulativeRead += bytesRead; } } while (toRead > 0); readBuffer[cumulativeRead] = '\0'; //get compression status WCHAR *headerInfo = GetHeader(request, WINHTTP_QUERY_CONTENT_ENCODING); dataCompressed = wcswcs(headerInfo, L"gzip") != NULL; delete[] headerInfo; } } WinHttpCloseHandle(request); } //Decompress data if necessary if (readBuffer != NULL && cumulativeRead > 0) { if (dataCompressed) { char *inflateBuffer = new char[cumulativeRead*50]; cumulativeRead = decompress(readBuffer, cumulativeRead, inflateBuffer, cumulativeRead*50); inflateBuffer[cumulativeRead] = NULL; *dataOut = inflateBuffer; } else { char *buffer = new char[cumulativeRead+1]; memcpy(buffer, readBuffer, cumulativeRead+1); *dataOut = buffer; } free(readBuffer); } return cumulativeRead; }
string fetchUrl(string server, string path) { BOOL bResults = FALSE; HINTERNET hSession = NULL; HINTERNET hConnect = NULL; HINTERNET hRequest = NULL; string result; wstring wserver(server.begin(), server.end()); wstring wpath(path.begin(), path.end()); // Use WinHttpOpen to obtain a session handle. hSession = WinHttpOpen(L"Penis Browser/1.1", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); // Specify an HTTP server. if (hSession) hConnect = WinHttpConnect(hSession, wserver.c_str(), INTERNET_DEFAULT_HTTP_PORT, 0); // Create an HTTP request handle. if (hConnect) hRequest = WinHttpOpenRequest(hConnect, L"GET", wpath.c_str(), NULL, WINHTTP_NO_REFERER, NULL, NULL); // Send a request. if (hRequest) bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); // End the request. if (bResults) bResults = WinHttpReceiveResponse(hRequest, NULL); // Keep checking for data until there is nothing left. if (bResults) { DWORD dwSize = 0; do { DWORD dwDownloaded = 0; LPSTR pszOutBuffer; // Check for available data. WinHttpQueryDataAvailable(hRequest, &dwSize); // Allocate space for the buffer. pszOutBuffer = new char[dwSize + 1]; // Read the Data. ZeroMemory(pszOutBuffer, dwSize + 1); if (WinHttpReadData( hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded)) result.append(string(pszOutBuffer, dwDownloaded)); // Free the memory allocated to the buffer. delete[] pszOutBuffer; } while (dwSize > 0); } // Close any open handles. if (hRequest) WinHttpCloseHandle(hRequest); if (hConnect) WinHttpCloseHandle(hConnect); if (hSession) WinHttpCloseHandle(hSession); return result; }
bool GameJoltAPI::SendRequest( CStdString &output, CStdString url ) { // The private key must be set to send a request. if ( m_GamePrivateKey == _T("") ) { m_ErrorMessage += _T("(You must put in your game's private key before you can use any of the API functions.)"); return false; } //////////////////////////////////// // Let's form the URL first. url = GJAPI_ROOT + GJAPI_VERSION + url; CStdString signature( md5( CStdStringA( _T("http://") + GJAPI_SERVER + url + m_GamePrivateKey ) ) ); url += _T("&signature=") + signature; // Now let's build the request. BOOL ret = FALSE; HINTERNET hSession = NULL; HINTERNET hConnect = NULL; HINTERNET hRequest = NULL; hSession = WinHttpOpen ( L"Game Jolt API Construct/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 ); if ( hSession ) hConnect = WinHttpConnect ( hSession, CStdStringW( GJAPI_SERVER ), INTERNET_DEFAULT_PORT, 0 ); else m_ErrorMessage += _T("(Could not open HTTP session.)"); if ( hConnect ) hRequest = WinHttpOpenRequest ( hConnect, L"GET", CStdStringW( url ), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_REFRESH ); else m_ErrorMessage += _T("(Could not connect to the HTTP session.)"); if ( hRequest ) ret = WinHttpSendRequest ( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0 ); else m_ErrorMessage += _T("(Could not set up the HTTP request.)"); if ( ret ) ret = WinHttpReceiveResponse( hRequest, NULL ); else m_ErrorMessage += _T("(Could not send the HTTP request.)"); DWORD bufferSize = 0; DWORD outputDownloaded = 0; LPSTR outputBuffer = 0; // Keep checking for data until there is nothing left. if ( ret ) { do { // Check for available data. bufferSize = 0; WinHttpQueryDataAvailable( hRequest, &bufferSize ); // Allocate space for the buffer. outputBuffer = new char[bufferSize + 1]; if ( outputBuffer ) { // Read the data. ZeroMemory( outputBuffer, bufferSize + 1 ); if ( WinHttpReadData( hRequest, (LPVOID)outputBuffer, bufferSize, &outputDownloaded ) ) output += outputBuffer; // Free the memory allocated to the buffer. delete [] outputBuffer; } } while( bufferSize > 0 ); } else m_ErrorMessage += _T("(Did not get a response from the server.)"); if ( hRequest ) WinHttpCloseHandle( hRequest ); if ( hConnect ) WinHttpCloseHandle( hConnect ); if ( hSession ) WinHttpCloseHandle( hSession ); return true; }
bool HttpQuery(const HttpRequest& request, HttpResponse& response) { // initialize response.statusCode = -1; HINTERNET internet = NULL; HINTERNET connectedInternet = NULL; HINTERNET requestInternet = NULL; BOOL httpResult = FALSE; DWORD error = 0; std::deque<LPCWSTR> acceptTypes; std::deque<BufferPair> availableBuffers; // access http internet = WinHttpOpen(L"Raven", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0); error = GetLastError(); if (!internet) goto CLEANUP; // connect connectedInternet = WinHttpConnect(internet, request.server.c_str(), (int)request.port, 0); error = GetLastError(); if (!connectedInternet) goto CLEANUP; // open request for (int i = 0; i<(int)request.acceptTypes.size(); i++) { acceptTypes.push_front(request.acceptTypes[i].c_str()); } acceptTypes.push_front(0); requestInternet = WinHttpOpenRequest(connectedInternet, request.method.c_str(), request.query.c_str(), NULL, WINHTTP_NO_REFERER, &acceptTypes[0], (request.secure ? WINHTTP_FLAG_SECURE : 0)); error = GetLastError(); if (!requestInternet) goto CLEANUP; // authentication, cookie and request if (request.username != L"" && request.password != L"") { WinHttpSetCredentials(requestInternet, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, request.username.c_str(), request.password.c_str(), NULL); } if (request.contentType != L"") { httpResult = WinHttpAddRequestHeaders(requestInternet, (L"Content-type:" + request.contentType).c_str(), -1, WINHTTP_ADDREQ_FLAG_REPLACE | WINHTTP_ADDREQ_FLAG_ADD); } if (request.cookie != L"") { WinHttpAddRequestHeaders(requestInternet, (L"Cookie:" + request.cookie).c_str(), -1, WINHTTP_ADDREQ_FLAG_REPLACE | WINHTTP_ADDREQ_FLAG_ADD); } // extra headers for (auto it = request.extraHeaders.begin(); it != request.extraHeaders.end(); it++) { std::wstring key = it->first; std::wstring value = it->second; WinHttpAddRequestHeaders(requestInternet, (key + L":" + value).c_str(), -1, WINHTTP_ADDREQ_FLAG_REPLACE | WINHTTP_ADDREQ_FLAG_ADD); } if (request.body.size()>0) { httpResult = WinHttpSendRequest(requestInternet, WINHTTP_NO_ADDITIONAL_HEADERS, 0, (LPVOID)&request.body[0], (int)request.body.size(), (int)request.body.size(), NULL); } else { httpResult = WinHttpSendRequest(requestInternet, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, NULL); } error = GetLastError(); if (httpResult == FALSE) goto CLEANUP; // receive response httpResult = WinHttpReceiveResponse(requestInternet, NULL); error = GetLastError(); if (httpResult != TRUE) goto CLEANUP; DWORD headerLength = sizeof(DWORD); // read response status code DWORD statusCode = 0; httpResult = WinHttpQueryHeaders(requestInternet, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &headerLength, WINHTTP_NO_HEADER_INDEX); error = GetLastError(); if (httpResult == FALSE) goto CLEANUP; response.statusCode = statusCode; // read respons cookie httpResult = WinHttpQueryHeaders(requestInternet, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &headerLength, WINHTTP_NO_HEADER_INDEX); error = GetLastError(); if (error == ERROR_INSUFFICIENT_BUFFER) { wchar_t* rawHeader = new wchar_t[headerLength / sizeof(wchar_t)]; ZeroMemory(rawHeader, headerLength); httpResult = WinHttpQueryHeaders(requestInternet, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, rawHeader, &headerLength, WINHTTP_NO_HEADER_INDEX); const wchar_t* cookieStart = wcsstr(rawHeader, L"Cookie:"); if (cookieStart) { const wchar_t* cookieEnd = wcsstr(cookieStart, L";"); if (cookieEnd) { response.cookie = std::wstring(cookieStart + 7, cookieEnd - cookieStart - 7); } } delete[] rawHeader; } // read response body while (true) { DWORD bytesAvailable = 0; BOOL queryDataAvailableResult = WinHttpQueryDataAvailable(requestInternet, &bytesAvailable); error = GetLastError(); if (queryDataAvailableResult == TRUE && bytesAvailable != 0) { char* utf8 = new char[bytesAvailable]; DWORD bytesRead = 0; BOOL readDataResult = WinHttpReadData(requestInternet, utf8, bytesAvailable, &bytesRead); error = GetLastError(); if (readDataResult == TRUE) { availableBuffers.push_front(BufferPair(utf8, bytesRead)); } else { delete[] utf8; } } else { break; } } // concatincate response body int totalSize = 0; for each (BufferPair p in availableBuffers) { totalSize += p.length; } response.body.resize(totalSize); if (totalSize>0) { char* utf8 = new char[totalSize]; { char* temp = utf8; for each (BufferPair p in availableBuffers) { memcpy(temp, p.buffer, p.length); temp += p.length; } }
BOOL DoBlockingHttpGet( const char* sRequestedPage, char* pBufferOut, const unsigned int /*nBufferOutSize*/, DWORD* pBytesRead ) { BOOL bResults = FALSE, bSuccess = FALSE; HINTERNET hSession = nullptr, hConnect = nullptr, hRequest = nullptr; WCHAR wBuffer[1024]; size_t nTemp; char* sDataDestOffset = &pBufferOut[0]; DWORD nBytesToRead = 0; DWORD nBytesFetched = 0; char sClientName[1024]; sprintf_s( sClientName, 1024, "Retro Achievements Client" ); WCHAR wClientNameBuffer[1024]; mbstowcs_s( &nTemp, wClientNameBuffer, 1024, sClientName, strlen(sClientName)+1 ); // Use WinHttpOpen to obtain a session handle. hSession = WinHttpOpen( wClientNameBuffer, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); // Specify an HTTP server. if( hSession != nullptr ) { hConnect = WinHttpConnect( hSession, L"www.retroachievements.org", INTERNET_DEFAULT_HTTP_PORT, 0); // Create an HTTP Request handle. if( hConnect != nullptr ) { mbstowcs_s( &nTemp, wBuffer, 1024, sRequestedPage, strlen(sRequestedPage)+1 ); hRequest = WinHttpOpenRequest( hConnect, L"GET", wBuffer, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); // Send a Request. if( hRequest != nullptr ) { bResults = WinHttpSendRequest( hRequest, L"Content-Type: application/x-www-form-urlencoded", 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); if( WinHttpReceiveResponse( hRequest, NULL ) ) { nBytesToRead = 0; (*pBytesRead) = 0; WinHttpQueryDataAvailable( hRequest, &nBytesToRead ); while( nBytesToRead > 0 ) { char sHttpReadData[8192]; ZeroMemory( sHttpReadData, 8192*sizeof(char) ); assert( nBytesToRead <= 8192 ); if( nBytesToRead <= 8192 ) { nBytesFetched = 0; if( WinHttpReadData( hRequest, &sHttpReadData, nBytesToRead, &nBytesFetched ) ) { assert( nBytesToRead == nBytesFetched ); //Read: parse buffer memcpy( sDataDestOffset, sHttpReadData, nBytesFetched ); sDataDestOffset += nBytesFetched; (*pBytesRead) += nBytesFetched; } } bSuccess = TRUE; WinHttpQueryDataAvailable( hRequest, &nBytesToRead ); } } } } } // Close open handles. if (hRequest) WinHttpCloseHandle(hRequest); if (hConnect) WinHttpCloseHandle(hConnect); if (hSession) WinHttpCloseHandle(hSession); return bSuccess; }
DWORD WINAPI SendProc(LPVOID data) { DWORD dataSize = 0; DWORD bytesDownloaded = 0; LPSTR outBuffer; BOOL result = FALSE; HINTERNET session = NULL,connection = NULL,request = NULL; std::wstring *wurl = (std::wstring*)data; if( wurl == NULL ) { return result; } session = WinHttpOpen(GA_HOST.c_str(), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 ); if( session ) connection = WinHttpConnect( session, GA_HOST.c_str(), INTERNET_DEFAULT_HTTP_PORT, 0 ); if( connection ) request = WinHttpOpenRequest( connection, L"GET", wurl->c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0 ); if( request ) result = WinHttpSendRequest( request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0 ); //DWORD n = GetLastError(); if( result ) result = WinHttpReceiveResponse( request, NULL ); if( result ) { do { dataSize = 0; if( !WinHttpQueryDataAvailable( request, &dataSize ) ) return FALSE; outBuffer = new char[dataSize+1]; if( !outBuffer ) { return false; } else { ZeroMemory( outBuffer, dataSize+1 ); if( !WinHttpReadData( request, (LPVOID)outBuffer, dataSize, &bytesDownloaded ) ) { delete []outBuffer; return false; } // TODO: if you care about the response, please handle it here... // delete[] outBuffer; } } while( dataSize > 0 ); } // clean up if( request ) WinHttpCloseHandle( request ); if( connection ) WinHttpCloseHandle( connection ); if( session ) WinHttpCloseHandle( session ); delete wurl; return result; }
Response * WinHTTPSession::receive(HINTERNET wrequest, const Request & request, std::basic_string<WCHAR> & redirect) { if(!WinHttpReceiveResponse(wrequest, NULL)) { return new Response("Error receiving response: " + errorString()); } DWORD status = 0; DWORD statusSize = sizeof(status); if(!WinHttpQueryHeaders(wrequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &status, &statusSize, WINHTTP_NO_HEADER_INDEX)) { return new Response("Error getting status code: " + errorString()); } std::string url; if(!request.followRedirects()) { DWORD urlSize = 0; WinHttpQueryHeaders(wrequest, WINHTTP_QUERY_LOCATION, WINHTTP_HEADER_NAME_BY_INDEX, WINHTTP_NO_OUTPUT_BUFFER, &urlSize, WINHTTP_NO_HEADER_INDEX); if(GetLastError() == ERROR_INSUFFICIENT_BUFFER && urlSize % sizeof(WCHAR) == 0) { platform::WideString redirect; redirect.allocate(urlSize / sizeof(WCHAR)); if(WinHttpQueryHeaders(wrequest, WINHTTP_QUERY_LOCATION, WINHTTP_HEADER_NAME_BY_INDEX, redirect.data(), &urlSize, WINHTTP_NO_HEADER_INDEX)) { redirect.resize(urlSize / sizeof(WCHAR)); platform::WideString base(request.url()); platform::WideString wurl; wurl.allocate(2 * (base.size() + redirect.size())); urlSize = wurl.size(); if(InternetCombineUrlW(base, redirect, wurl.data(), &urlSize, ICU_BROWSER_MODE)) { wurl.resize(urlSize); url = wurl.toUTF8(); } } } } else { url = redirect.empty() ? request.url() : platform::WideString::toUTF8(redirect); } std::string data; DWORD size; for(;;) { // Check for available data. size = 0; if(!WinHttpQueryDataAvailable(wrequest, &size)) { return new Response("Error reading response: " + errorString()); } if(!size) { break; } size_t oldsize = data.size(); data.resize(oldsize + size); if(!WinHttpReadData(wrequest, &data[oldsize], size, &size)) { return new Response("Error reading response: " + errorString()); } data.resize(oldsize + size); } return new Response(status, data, url); }
BOOL HTTPGetFile (const _TCHAR *url, const _TCHAR *outputPath, const _TCHAR *extraHeaders, int *responseCode) { HINTERNET hSession = NULL; HINTERNET hConnect = NULL; HINTERNET hRequest = NULL; URL_COMPONENTS urlComponents; BOOL secure = FALSE; BOOL ret = FALSE; _TCHAR hostName[256]; _TCHAR path[1024]; const TCHAR *acceptTypes[] = { TEXT("*/*"), NULL }; ZeroMemory (&urlComponents, sizeof(urlComponents)); urlComponents.dwStructSize = sizeof(urlComponents); urlComponents.lpszHostName = hostName; urlComponents.dwHostNameLength = _countof(hostName); urlComponents.lpszUrlPath = path; urlComponents.dwUrlPathLength = _countof(path); WinHttpCrackUrl(url, 0, 0, &urlComponents); if (urlComponents.nPort == 443) secure = TRUE; hSession = WinHttpOpen(_T("OBS Updater/1.2"), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!hSession) { *responseCode = -1; goto failure; } hConnect = WinHttpConnect(hSession, hostName, secure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0); if (!hConnect) { *responseCode = -2; goto failure; } hRequest = WinHttpOpenRequest(hConnect, TEXT("GET"), path, NULL, WINHTTP_NO_REFERER, acceptTypes, secure ? WINHTTP_FLAG_SECURE|WINHTTP_FLAG_REFRESH : WINHTTP_FLAG_REFRESH); if (!hRequest) { *responseCode = -3; goto failure; } BOOL bResults = WinHttpSendRequest(hRequest, extraHeaders, extraHeaders ? -1 : 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); // End the request. if (bResults) bResults = WinHttpReceiveResponse(hRequest, NULL); else goto failure; TCHAR encoding[64]; DWORD encodingLen; TCHAR statusCode[8]; DWORD statusCodeLen; statusCodeLen = sizeof(statusCode); if (!WinHttpQueryHeaders (hRequest, WINHTTP_QUERY_STATUS_CODE, WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusCodeLen, WINHTTP_NO_HEADER_INDEX)) { *responseCode = -4; goto failure; } encoding[0] = 0; encodingLen = sizeof(encoding); if (!WinHttpQueryHeaders (hRequest, WINHTTP_QUERY_CONTENT_ENCODING, WINHTTP_HEADER_NAME_BY_INDEX, encoding, &encodingLen, WINHTTP_NO_HEADER_INDEX)) { if (GetLastError() != ERROR_WINHTTP_HEADER_NOT_FOUND) { *responseCode = -5; goto failure; } } BOOL gzip = FALSE; BYTE *outputBuffer = NULL; z_stream strm; if (!_tcscmp(encoding, _T("gzip"))) { gzip = TRUE; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit2(&strm, 16+MAX_WBITS); if (ret != Z_OK) goto failure; outputBuffer = (BYTE *)malloc(262144); if (!outputBuffer) { *responseCode = -6; goto failure; } } *responseCode = wcstoul(statusCode, NULL, 10); if (bResults && *responseCode == 200) { BYTE buffer[32768]; DWORD dwSize, dwOutSize, wrote; HANDLE updateFile; int lastPosition = 0; updateFile = CreateFile(outputPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (updateFile == INVALID_HANDLE_VALUE) { *responseCode = -7; goto failure; } do { // Check for available data. dwSize = 0; if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) { *responseCode = -8; goto failure; } dwSize = min(dwSize, sizeof(buffer)); if (!WinHttpReadData(hRequest, (LPVOID)buffer, dwSize, &dwOutSize)) { *responseCode = -9; goto failure; } else { if (!dwOutSize) break; if (gzip) { do { strm.avail_in = dwOutSize; strm.next_in = buffer; strm.avail_out = 262144; strm.next_out = outputBuffer; int zret = inflate(&strm, Z_NO_FLUSH); if (zret != Z_STREAM_END && zret != Z_OK) { inflateEnd(&strm); CloseHandle (updateFile); goto failure; } if (!WriteFile(updateFile, outputBuffer, 262144 - strm.avail_out, &wrote, NULL)) { *responseCode = -10; CloseHandle (updateFile); goto failure; } if (wrote != 262144 - strm.avail_out) { *responseCode = -11; CloseHandle (updateFile); goto failure; } completedFileSize += wrote; } while (strm.avail_out == 0); } else { if (!WriteFile(updateFile, buffer, dwOutSize, &wrote, NULL)) { *responseCode = -12; CloseHandle (updateFile); goto failure; } if (wrote != dwOutSize) { *responseCode = -13; CloseHandle (updateFile); goto failure; } completedFileSize += dwOutSize; } int position = (int)(((float)completedFileSize / (float)totalFileSize) * 100.0f); if (position > lastPosition) { lastPosition = position; SendDlgItemMessage (hwndMain, IDC_PROGRESS, PBM_SETPOS, position, 0); } } if (WaitForSingleObject(cancelRequested, 0) == WAIT_OBJECT_0) { *responseCode = -14; CloseHandle (updateFile); goto failure; } } while (dwSize > 0); CloseHandle (updateFile); } ret = TRUE; failure: if (outputBuffer) free(outputBuffer); if (hSession) WinHttpCloseHandle(hSession); if (hConnect) WinHttpCloseHandle(hConnect); if (hRequest) WinHttpCloseHandle(hRequest); return ret; }
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa383138%28v=vs.85%29.aspx void CALLBACK HttpProgress(HINTERNET hInternet, DWORD_PTR userdata, unsigned long status, void* info, unsigned long info_len) { UpdateData* data = (UpdateData*)userdata; switch(status){ case WINHTTP_CALLBACK_STATUS_DETECTING_PROXY: SetWindowText(data->status_text, L"detecting proxy..."); UpdateCheck_Progress(data, 10); break; case WINHTTP_CALLBACK_STATUS_RESOLVING_NAME: SetWindowText(data->status_text, L"resolving hostname..."); UpdateCheck_Progress(data, 20); break; case WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER: SetWindowText(data->status_text, L"connecting..."); UpdateCheck_Progress(data, 30); break; case WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER: SetWindowText(data->status_text, L"connected"); UpdateCheck_Progress(data, 40); break; case WINHTTP_CALLBACK_STATUS_REDIRECT: SetWindowText(data->status_text, L"redirecting..."); UpdateCheck_Progress(data, 50); break; case WINHTTP_CALLBACK_STATUS_SENDING_REQUEST: SetWindowText(data->status_text, L"sending request..."); UpdateCheck_Progress(data, 60); break; case WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE: SetWindowText(data->status_text, L"receiving data..."); UpdateCheck_Progress(data, 70); break; // case WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION: // SetWindowText(data->status_text, L"closing connection..."); // break; case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:{ DWORD http_status; DWORD size = sizeof(http_status); WinHttpQueryHeaders(hInternet, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &http_status, &size, WINHTTP_NO_HEADER_INDEX); if(http_status != HTTP_STATUS_OK){ PostMessage(data->update_window, WM_DOWNLOAD_RESULT, status, http_status); UpdateCheck_Free(data); break; } WinHttpQueryDataAvailable(hInternet, NULL); UpdateCheck_Progress(data, 75); break;} case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE: // still called after header error WinHttpReceiveResponse(hInternet, NULL); break; case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE: { SetWindowText(data->status_text, L"data..."); WinHttpReadData(hInternet, data->buffer, sizeof(data->buffer)-1, NULL); UpdateCheck_Progress(data, 90); break;} case WINHTTP_CALLBACK_STATUS_READ_COMPLETE: if(info_len){ // WinHttpReadData(hInternet, data->buffer, sizeof(data->buffer), NULL); data->buffer[info_len] = '\0'; } PostMessage(data->update_window, WM_DOWNLOAD_RESULT, 0, 0); UpdateCheck_Free(data); break; case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE: case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR: PostMessage(data->update_window, WM_DOWNLOAD_RESULT, status, (LPARAM)info); UpdateCheck_Free(data); break; case WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING: break; } }
bool KickStats::SendRequest() { if (!Connected()) return false; BOOL bResults = FALSE; DWORD dwSize = 0; DWORD dwDownloaded = 0; LPSTR pszOutBuffer; TCHAR statusCode[8]; DWORD statusCodeLen; int nStatusCode = -1; TCHAR contentLength[8]; DWORD contentLengthLen; long nContentlength = -1; int runs = 0; m_sContent.clear(); m_sContent.resize(0); bResults = WinHttpSendRequest(m_hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); int err = GetLastError(); if (bResults) bResults = WinHttpReceiveResponse(m_hRequest, NULL); statusCodeLen = sizeof(statusCode); WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_STATUS_CODE, WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusCodeLen, WINHTTP_NO_HEADER_INDEX); nStatusCode = _wtol(statusCode); contentLengthLen = sizeof(contentLength); WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_CONTENT_LENGTH, WINHTTP_HEADER_NAME_BY_INDEX, &contentLength, &contentLengthLen, WINHTTP_NO_HEADER_INDEX); nContentlength = _wtol(contentLength); // KickLog(L"=============="); if (bResults && nStatusCode == 200) { do { // Check for available data. dwSize = 0; dwDownloaded = 0; ++runs; if (runs > 1) { wchar_t str[1024]; swprintf(str, L"run: %d", runs); // KickLog(str); } if (!WinHttpQueryDataAvailable(m_hRequest, &dwSize)) MessageBox(NULL, L"WinHttpQueryDataAvailable failed", L"error", 1); // Allocate space for the buffer. pszOutBuffer = new char[dwSize + 1]; if (!pszOutBuffer) { KickLog(L"KickStats::SendRequest: Out of memory"); return false; } else { // Read the data. ZeroMemory(pszOutBuffer, dwSize + 1); if (!WinHttpReadData(m_hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded)) { KickLog(L"KickStats::SendRequest: WinHttpReadData failed"); delete[] pszOutBuffer; return false; } else { //wchar_t str[1024]; //swprintf(str, L"down: %d - size: %d - length: %d", dwDownloaded, dwSize, nContentlength); //KickLog(str); //KickLog(pszOutBuffer); m_sContent.append(pszOutBuffer); } // Free the memory allocated to the buffer. delete[] pszOutBuffer; } } while (dwSize > 0); } // KickLog(m_sContent); if (!bResults) MessageBox(NULL, L"WinHttpReceiveResponse failed", L"error", MB_OK); return true; }
int _tmain(int argc, _TCHAR* argv[]) { // WinHTTP Sessions Overview | https://msdn.microsoft.com/en-us/library/windows/desktop/aa384270(v=vs.85).aspx DWORD dwSize = 0; DWORD dwDownloaded = 0; LPSTR pszOutBuffer; BOOL bResults = FALSE; HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL; // Use WinHttpOpen to obtain a session handle. hSession = WinHttpOpen(L"WinHTTP Example/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); // Specify an HTTP server. if (hSession) hConnect = WinHttpConnect(hSession, L"www.microsoft.com", INTERNET_DEFAULT_HTTPS_PORT, 0); // Create an HTTP request handle. if (hConnect) hRequest = WinHttpOpenRequest(hConnect, L"GET", NULL, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE); // Send a request. if (hRequest) bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); // End the request. if (bResults) bResults = WinHttpReceiveResponse(hRequest, NULL); // Keep checking for data until there is nothing left. if (bResults) { do { // Check for available data. dwSize = 0; if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) printf("Error %u in WinHttpQueryDataAvailable.\n", GetLastError()); // Allocate space for the buffer. pszOutBuffer = new char[dwSize + 1]; if (!pszOutBuffer) { printf("Out of memory\n"); dwSize = 0; } else { // Read the data. ZeroMemory(pszOutBuffer, dwSize + 1); if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded)) printf("Error %u in WinHttpReadData.\n", GetLastError()); else printf("%s", pszOutBuffer); // Free the memory allocated to the buffer. delete[] pszOutBuffer; } } while (dwSize > 0); } // Report any errors. if (!bResults) printf("Error %d has occurred.\n", GetLastError()); // Close any open handles. if (hRequest) WinHttpCloseHandle(hRequest); if (hConnect) WinHttpCloseHandle(hConnect); if (hSession) WinHttpCloseHandle(hSession); return 0; }
char *HTTP_get_first_block_if_possible(wchar_t *host, wchar_t *path, wchar_t *agent_name) { BOOL bResults; HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL; char *rt; hSession = WinHttpOpen(agent_name, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (hSession==NULL) return NULL; hConnect = WinHttpConnect( hSession, host, INTERNET_DEFAULT_HTTP_PORT, 0); if (hConnect==NULL) return NULL; hRequest = WinHttpOpenRequest( hConnect, NULL, path, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); if (hRequest==NULL) return NULL; bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); // End the request. if(bResults==FALSE) return NULL; bResults = WinHttpReceiveResponse( hRequest, NULL ); if(bResults==FALSE) return NULL; LPSTR pszOutBuffer; DWORD dwDownloaded = 0; DWORD dwSize = 0; // Check only for first portion! if( !WinHttpQueryDataAvailable( hRequest, &dwSize ) ) return NULL; pszOutBuffer = malloc (dwSize+1); ZeroMemory(pszOutBuffer, dwSize+1); if(WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded)) rt=pszOutBuffer; else { free (pszOutBuffer); rt=NULL; }; if (hRequest) WinHttpCloseHandle(hRequest); if (hConnect) WinHttpCloseHandle(hConnect); if (hSession) WinHttpCloseHandle(hSession); return rt; };
// handle WinHTTP callbacks (which can be in a worker thread context) VOID CALLBACK WinHttpIO::asynccallback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength) { WinHttpContext* httpctx = (WinHttpContext*)dwContext; WinHttpIO* httpio = (WinHttpIO*)httpctx->httpio; if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING) { LOG_verbose << "Closing request"; assert(!httpctx->req); if (httpctx->gzip) { inflateEnd(&httpctx->z); } delete httpctx; return; } httpio->lock(); HttpReq* req = httpctx->req; // request cancellations that occured after asynccallback() was entered are caught here if (!req) { LOG_verbose << "Request cancelled"; httpio->unlock(); return; } switch (dwInternetStatus) { case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE: { DWORD size = *(DWORD*)lpvStatusInformation; if (!size) { if (req->binary) { LOG_debug << "[received " << (req->buf ? req->buflen : req->in.size()) << " bytes of raw data]"; } else { if(req->in.size() < 2048) { LOG_debug << "Received: " << req->in.c_str(); } else { LOG_debug << "Received: " << req->in.substr(0,2048).c_str(); } } LOG_debug << "Request finished with HTTP status: " << req->httpstatus; req->status = (req->httpstatus == 200 && (req->contentlength < 0 || req->contentlength == (req->buf ? req->bufpos : (int)req->in.size()))) ? REQ_SUCCESS : REQ_FAILURE; if (req->status == REQ_SUCCESS) { httpio->lastdata = Waiter::ds; } httpio->success = true; } else { LOG_verbose << "Data available. Remaining: " << size << " bytes"; char* ptr; if (httpctx->gzip) { m_off_t zprevsize = httpctx->zin.size(); httpctx->zin.resize(zprevsize + size); ptr = (char*)httpctx->zin.data() + zprevsize; } else { ptr = (char*)req->reserveput((unsigned*)&size); req->bufpos += size; } if (!WinHttpReadData(hInternet, ptr, size, NULL)) { LOG_err << "Unable to get more data. Code: " << GetLastError(); httpio->cancel(req); } } httpio->httpevent(); break; } case WINHTTP_CALLBACK_STATUS_READ_COMPLETE: LOG_verbose << "Read complete"; if (dwStatusInformationLength) { LOG_verbose << dwStatusInformationLength << " bytes received"; if (req->httpio) { req->httpio->lastdata = Waiter::ds; } if (httpctx->gzip) { httpctx->z.next_in = (Bytef*)lpvStatusInformation; httpctx->z.avail_in = dwStatusInformationLength; req->bufpos += httpctx->z.avail_out; int t = inflate(&httpctx->z, Z_SYNC_FLUSH); req->bufpos -= httpctx->z.avail_out; if ((char*)lpvStatusInformation + dwStatusInformationLength == httpctx->zin.data() + httpctx->zin.size()) { httpctx->zin.clear(); } if (t != Z_OK && (t != Z_STREAM_END || httpctx->z.avail_out)) { LOG_err << "GZIP error"; httpio->cancel(req); } } if (!WinHttpQueryDataAvailable(httpctx->hRequest, NULL)) { LOG_err << "Error on WinHttpQueryDataAvailable. Code: " << GetLastError(); httpio->cancel(req); httpio->httpevent(); } } break; case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE: { DWORD statusCode; DWORD statusCodeSize = sizeof(statusCode); if (!WinHttpQueryHeaders(httpctx->hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusCodeSize, WINHTTP_NO_HEADER_INDEX)) { LOG_err << "Error getting headers. Code: " << GetLastError(); httpio->cancel(req); httpio->httpevent(); } else { LOG_verbose << "Headers available"; req->httpstatus = statusCode; if (req->httpio) { req->httpio->lastdata = Waiter::ds; } if (!req->buf) { // obtain original content length - always present if gzip is in use DWORD contentLength; DWORD contentLengthSize = sizeof(contentLength); if (WinHttpQueryHeaders(httpctx->hRequest, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_NUMBER, L"Original-Content-Length", &contentLength, &contentLengthSize, WINHTTP_NO_HEADER_INDEX)) { LOG_verbose << "Content-Length: " << contentLength; req->setcontentlength(contentLength); // check for gzip content encoding WCHAR contentEncoding[16]; DWORD contentEncodingSize = sizeof(contentEncoding); httpctx->gzip = WinHttpQueryHeaders(httpctx->hRequest, WINHTTP_QUERY_CONTENT_ENCODING, WINHTTP_HEADER_NAME_BY_INDEX, &contentEncoding, &contentEncodingSize, WINHTTP_NO_HEADER_INDEX) && !wcscmp(contentEncoding, L"gzip"); if (httpctx->gzip) { LOG_verbose << "Using GZIP"; httpctx->z.zalloc = Z_NULL; httpctx->z.zfree = Z_NULL; httpctx->z.opaque = Z_NULL; httpctx->z.avail_in = 0; httpctx->z.next_in = Z_NULL; inflateInit2(&httpctx->z, MAX_WBITS+16); req->in.resize(contentLength); httpctx->z.avail_out = contentLength; httpctx->z.next_out = (unsigned char*)req->in.data(); } else { LOG_verbose << "Not using GZIP"; } } else { LOG_verbose << "Content-Length not available"; } } if (!WinHttpQueryDataAvailable(httpctx->hRequest, NULL)) { LOG_err << "Unable to query data. Code: " << GetLastError(); httpio->cancel(req); httpio->httpevent(); } else if (httpio->waiter && httpio->noinetds) { httpio->inetstatus(true); } } break; } case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR: { DWORD e = GetLastError(); LOG_err << "Request error. Code: " << e; if (httpio->waiter && e != ERROR_WINHTTP_TIMEOUT) { httpio->inetstatus(false); } } // fall through case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE: if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_SECURE_FAILURE) { LOG_err << "Security check failed. Code: " << (*(DWORD*)lpvStatusInformation); } httpio->cancel(req); httpio->httpevent(); break; case WINHTTP_CALLBACK_STATUS_SENDING_REQUEST: { if(MegaClient::disablepkp) { break; } PCCERT_CONTEXT cert; DWORD len = sizeof cert; if (WinHttpQueryOption(httpctx->hRequest, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &len)) { CRYPT_BIT_BLOB* pkey = &cert->pCertInfo->SubjectPublicKeyInfo.PublicKey; // this is an SSL connection: verify public key to prevent MITM attacks if (pkey->cbData != 270 || (memcmp(pkey->pbData, "\x30\x82\x01\x0a\x02\x82\x01\x01\x00" APISSLMODULUS1 "\x02" APISSLEXPONENTSIZE APISSLEXPONENT, 270) && memcmp(pkey->pbData, "\x30\x82\x01\x0a\x02\x82\x01\x01\x00" APISSLMODULUS2 "\x02" APISSLEXPONENTSIZE APISSLEXPONENT, 270))) { LOG_err << "Certificate error. Possible MITM attack!!"; CertFreeCertificateContext(cert); httpio->cancel(req); httpio->httpevent(); break; } CertFreeCertificateContext(cert); } break; } case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE: case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE: if (httpctx->postpos < httpctx->postlen) { LOG_verbose << "Chunk written"; unsigned pos = httpctx->postpos; unsigned t = httpctx->postlen - pos; if (t > HTTP_POST_CHUNK_SIZE) { t = HTTP_POST_CHUNK_SIZE; } httpctx->postpos += t; if (!WinHttpWriteData(httpctx->hRequest, (LPVOID)(httpctx->postdata + pos), t, NULL)) { LOG_err << "Error writting data. Code: " << GetLastError(); req->httpio->cancel(req); } httpio->httpevent(); } else { LOG_verbose << "Request written"; if (!WinHttpReceiveResponse(httpctx->hRequest, NULL)) { LOG_err << "Error receiving response. Code: " << GetLastError(); httpio->cancel(req); httpio->httpevent(); } httpctx->postdata = NULL; } } httpio->unlock(); }
khm_int32 HttpRequest::FetchResource(const wchar_t * domain, const wchar_t * resource, const wchar_t ** mimetypes) { HANDLE hFile = INVALID_HANDLE_VALUE; HINTERNET hSession = NULL; HINTERNET hConnect = NULL; HINTERNET hRequest = NULL; DWORD nTotalBytes = 0; BOOL bContinue = TRUE; khm_int32 rv = KHM_ERROR_GENERAL; hSession = WinHttpOpen(USER_AGENT, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (hSession == NULL) { ReportStatus(KHERR_ERROR, L"Can't create HTTP session", L"%s", GetLastErrorString().c_str()); goto done; } hConnect = WinHttpConnect(hSession, domain, INTERNET_DEFAULT_HTTP_PORT, 0); if (hConnect == NULL) { ReportStatus(KHERR_ERROR, L"Can't open HTTP connection", L"%s", GetLastErrorString().c_str()); goto done; } hRequest = WinHttpOpenRequest(hConnect, L"GET", resource, NULL, WINHTTP_NO_REFERER, mimetypes, WINHTTP_FLAG_ESCAPE_PERCENT); if (hRequest == NULL) { ReportStatus(KHERR_ERROR, L"Can't open request", L"%s", GetLastErrorString().c_str()); goto done; } { DWORD opt; opt = WINHTTP_DISABLE_AUTHENTICATION; if (!WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &opt, sizeof(opt))) goto done; opt = WINHTTP_DISABLE_COOKIES; if (!WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &opt, sizeof(opt))) goto done; opt = WINHTTP_DISABLE_KEEP_ALIVE; if (!WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &opt, sizeof(opt))) goto done; } rv = KHM_ERROR_NOT_FOUND; if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) { ReportStatus(KHERR_ERROR, L"Can't send request to server", L"Unable to send HTTP request to server at %s.\n" L"%s", domain, GetLastErrorString().c_str()); goto done; } if (!WinHttpReceiveResponse(hRequest, NULL)) { ReportStatus(KHERR_ERROR, L"Error while receiving response", L"%s", GetLastErrorString().c_str()); goto done; } rv = KHM_ERROR_GENERAL; { DWORD status = 0; DWORD nb = sizeof(status); if (!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &status, &nb, WINHTTP_NO_HEADER_INDEX)) { ReportStatus(KHERR_ERROR, L"Error while querying response status", L"%s", GetLastErrorString().c_str()); goto done; } if (status == HTTP_STATUS_NOT_FOUND) { switch (m_method) { case ByFavIcon: // Status reports are ignored for Favicon searches // anyway. break; case ByGravatar: ReportStatus(KHERR_ERROR, L"Could not find Gravatar", L"An icon could not be found for %s on %s.\n", m_target.c_str(), domain); break; default: ReportStatus(KHERR_ERROR, L"The requested resource was not found", L"The requested resource was not found on %s.", domain); break; } rv = KHM_ERROR_NOT_FOUND; goto done; } if (status != HTTP_STATUS_OK) { ReportStatus(KHERR_ERROR, L"The request failed", L"The server at %s returned an unexpected status (%d)", domain, status); rv = KHM_ERROR_GENERAL; goto done; } } { wchar_t contenttype[128]; DWORD nb = sizeof(contenttype); int i; if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_TYPE, WINHTTP_HEADER_NAME_BY_INDEX, contenttype, &nb, WINHTTP_NO_HEADER_INDEX)) { std::wstring::size_type epos; epos = m_path.rfind(L'.'); if (epos != std::wstring::npos) m_path.erase(epos); for (i=0; i < ARRAYLENGTH(content_type_map); i++) { if (!_wcsicmp(contenttype, content_type_map[i].content_type)) break; } if (i < ARRAYLENGTH(content_type_map)) { m_path.append(content_type_map[i].extension); } else { ReportStatus(KHERR_WARNING, L"Unknown content type", L"The content type %s was not expected for this request.", contenttype); } } else { ReportStatus(KHERR_WARNING, L"Could not query response content type", L"%s", GetLastErrorString().c_str()); } } /* The request went through. Create the file now */ hFile = CreateFile(m_path.c_str(), GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_TEMPORARY, NULL); if (hFile == INVALID_HANDLE_VALUE) { ReportStatus(KHERR_ERROR, L"Can't create file", L"%s", GetLastErrorString().c_str()); goto done; } while (nTotalBytes < MAX_ICON_SIZE && bContinue) { DWORD nBytes = 0; BYTE * buffer = NULL; DWORD nRead = 0; DWORD nWritten = 0; bContinue = FALSE; if (!WinHttpQueryDataAvailable(hRequest, &nBytes)) break; if (nBytes == 0) { bContinue = TRUE; break; } if (nBytes + nTotalBytes > MAX_ICON_SIZE) break; buffer = PNEW BYTE[nBytes]; if (buffer == NULL) break; if (!WinHttpReadData(hRequest, buffer, nBytes, &nRead) || nRead == 0) { /* Fail */ } else { /* Data found */ if (WriteFile(hFile, buffer, nRead, &nWritten, NULL)) bContinue = TRUE; } delete [] buffer; nTotalBytes += nBytes; } if (bContinue) { /* Done with file */ rv = KHM_ERROR_SUCCESS; } else { /* File is incomplete */ ReportStatus(KHERR_ERROR, L"Download incomplete", L"The download was terminated unexpectedly."); DeleteFile(m_path.c_str()); } done: if (hRequest) WinHttpCloseHandle(hRequest); if (hConnect) WinHttpCloseHandle(hConnect); if (hSession) WinHttpCloseHandle(hSession); if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); ReportComplete(KHM_SUCCEEDED(rv)); return rv; }