BOOL HttpRequest(HTTPREQ* req, const wchar_t* url, const wchar_t* header, DWORD header_length, const char* body, DWORD body_length) { BOOL ret = FALSE; req->internet = WinHttpOpen(NULL, NULL, NULL, NULL, NULL); if (req->internet != NULL) { URL_COMPONENTS urlinfo = {0}; urlinfo.dwStructSize = sizeof(URL_COMPONENTS); urlinfo.dwSchemeLength = (DWORD)-1; urlinfo.dwUserNameLength = (DWORD)-1; urlinfo.dwHostNameLength = (DWORD)-1; urlinfo.dwUrlPathLength = (DWORD)-1; urlinfo.dwExtraInfoLength = (DWORD)-1; urlinfo.dwPasswordLength = (DWORD)-1; if (WinHttpCrackUrl(url, wcslen(url), 0, &urlinfo)) { if (WinHttpSetTimeouts(req->internet, req->resolveTimeout, req->connectTimeout, req->sendTimeout, req->receiveTimeout)) { TCHAR* host = new TCHAR[urlinfo.dwHostNameLength + 1]; wmemset(host, 0, urlinfo.dwHostNameLength + 1); StrCpyN(host, urlinfo.lpszHostName, urlinfo.dwHostNameLength + 1); req->connect = WinHttpConnect(req->internet, host, urlinfo.nPort, 0); if (req->connect != NULL) { if (body == NULL || body_length == 0) req->request = WinHttpOpenRequest(req->connect, L"GET", urlinfo.lpszUrlPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); else req->request = WinHttpOpenRequest(req->connect, L"POST", urlinfo.lpszUrlPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); if (req->request != NULL) { if (WinHttpSendRequest(req->request, header, header_length, (void*)body, body_length, body_length, 0) && WinHttpReceiveResponse(req->request, 0)) { TCHAR status[16] = {0}; DWORD size = sizeof(status); if (WinHttpQueryHeaders(req->request, WINHTTP_QUERY_STATUS_CODE, NULL, status, &size, 0)) { if (StrCmp(status, L"200") == 0) { char buffer[4096] = {0}; DWORD length = 0; while (TRUE) { if (WinHttpReadData(req->request, buffer, sizeof(buffer), &length) && length > 0) { AppendBuffer(&req->buffer, req->dataLength, req->bufferLength, buffer, length); length = 0; } else break; } ret = TRUE; } } } } } SAFE_DELETE_ARRAY(host); } } } return ret; }
wchar_t *APICaller::GetHeader(HINTERNET request, int req) { wchar_t *headerBuffer = NULL; DWORD bytesRead = 0; // Get header info WinHttpQueryHeaders(request, WINHTTP_QUERY_CONTENT_ENCODING, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &bytesRead, WINHTTP_NO_HEADER_INDEX); if (bytesRead > 0) { headerBuffer = new wchar_t[bytesRead / sizeof(wchar_t)]; WinHttpQueryHeaders(request, WINHTTP_QUERY_CONTENT_ENCODING, WINHTTP_HEADER_NAME_BY_INDEX, headerBuffer, &bytesRead, WINHTTP_NO_HEADER_INDEX); } return headerBuffer; }
xlw::XlfOper HttpProtocol::Execute(const char* name, bool sendCaller, xlw::XlfOper* args, int argc) { REQUEST_CONTEXT context; context.hEvent = CreateEvent(0, 1, 0, 0); context.hConnect = WinHttpConnect(hSession, host, urlc.nPort, 0); int flags = WINHTTP_FLAG_BYPASS_PROXY_CACHE; if(urlc.nScheme == INTERNET_SCHEME_HTTPS) flags |= WINHTTP_FLAG_SECURE; context.hRequest = WinHttpOpenRequest(context.hConnect, L"POST", path, 0, 0, 0, flags); context.conf.beautify = 0; context.conf.indentString = ""; context.g = yajl_gen_alloc(&context.conf, 0); context.px = xlw::XlfOper(); //context.px->xltype = xltypeNil | xlbitDLLFree; GenerateRequest(context.g, name, sendCaller, args, argc); const unsigned char * buf; unsigned int len = 0; yajl_gen_get_buf(context.g, &buf, &len); BOOL res = FALSE; res = WinHttpSendRequest(context.hRequest, 0, 0, (LPVOID) buf, len, len, (DWORD_PTR) &context); if(!res) { const char* err = "#Could not connect to server"; Log::Error(err); WinHttpCloseHandle(context.hRequest); WinHttpCloseHandle(context.hConnect); context.px = xlw::XlfOper(err); return context.px; } // TODO timeout/background res = WinHttpReceiveResponse(context.hRequest, 0); if(!res) { const char* err = "#Error retrieving server response"; Log::Error(err); WinHttpCloseHandle(context.hRequest); WinHttpCloseHandle(context.hConnect); context.px = xlw::XlfOper(err); return context.px; } // Check http response code DWORD status; DWORD statusLength = 4; res = WinHttpQueryHeaders(context.hRequest, WINHTTP_QUERY_STATUS_CODE| WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &statusLength, 0); if(!res || status != 200) { Log::Error("Status code: %d", status); const char* err = "#Server returned an error"; WinHttpCloseHandle(context.hRequest); WinHttpCloseHandle(context.hConnect); context.px = xlw::XlfOper(err); return context.px; } ReadData(&context); WinHttpCloseHandle(context.hRequest); WinHttpCloseHandle(context.hConnect); yajl_gen_clear(context.g); yajl_gen_free(context.g); //context.px->xltype |= xlbitDLLFree; return context.px; }
bool CWinHttp::GetCookies() { bool bRet =false; GetCookiesLength(); m_cookies=new char[m_lenofcookie+1]; int n; if(!WinHttpQueryHeaders( hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, m_cookies, &m_lenofcookie, WINHTTP_NO_HEADER_INDEX )) { n=GetLastError(); goto exit0; } bRet=true; exit0: return bRet; }
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 CWinHttp::GetCookiesLength() { bool bRet =false; DWORD dwRead=1024*5; int n; WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_COOKIE , WINHTTP_HEADER_NAME_BY_INDEX, WINHTTP_NO_OUTPUT_BUFFER, &m_lenofcookie, WINHTTP_NO_HEADER_INDEX ); bRet=true; exit0: return bRet; }
static void test_redirect( void ) { static const WCHAR codeweavers[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0}; HANDLE ses, con, req; DWORD size, status; BOOL ret; struct info info, *context = &info; info.test = redirect_test; info.count = sizeof(redirect_test) / sizeof(redirect_test[0]); info.index = 0; info.wait = NULL; ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 ); 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, codeweavers, 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()); setup_test( &info, winhttp_receive_response, __LINE__ ); ret = WinHttpReceiveResponse( req, NULL ); ok(ret, "failed to receive response %u\n", GetLastError()); 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_close_handle, __LINE__ ); WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); WinHttpCloseHandle( ses ); }
bool CWinHttp::GetAllHeadersLength() { bool bRet =false; WinHttpQueryHeaders( hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, WINHTTP_NO_OUTPUT_BUFFER, &m_lenofallheaders, WINHTTP_NO_HEADER_INDEX ); bRet=true; exit0: return bRet; }
bool CWinHttp::GetAllHeaders() { bool bRet =false; GetAllHeadersLength(); m_strAllHeaders=new WCHAR[m_lenofallheaders+1]; if(!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, m_strAllHeaders, &m_lenofallheaders, WINHTTP_NO_HEADER_INDEX )) goto exit0; bRet=true; exit0: return bRet; }
DWORD OnHeadersAvailable( PMYCONTEXT pContext ) { DWORD dwError = ERROR_SUCCESS; DWORD dwFlags = WINHTTP_QUERY_FLAG_NUMBER | WINHTTP_QUERY_STATUS_CODE; DWORD StatusCode = 0; DWORD StatusCodeLength = sizeof(StatusCode); printf("OnHeadersAvailable\n"); if (!WinHttpQueryHeaders(pContext->RequestHandle, dwFlags, NULL, &StatusCode, &StatusCodeLength, NULL)) { dwError = GetLastError(); printf("OnHeadersAvailable: WinHttpQueryHeaders failed\n"); goto Exit; } printf("OnHeadersAvailable: Status=%d\n", StatusCode); dwError = StartReadData(pContext); if (dwError != ERROR_SUCCESS) { goto Exit; } Exit: return dwError; }
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); }
void shoes_winhttp(LPCWSTR host, INTERNET_PORT port, LPCWSTR path, TCHAR **mem, ULONG memlen, HANDLE file, LPDWORD size, shoes_download_handler handler, void *data) { DWORD len = 0, rlen = 0, status = 0, complete = 0, flen = 0, total = 0, written = 0; LPTSTR buf = SHOE_ALLOC_N(TCHAR, SHOES_BUFSIZE); LPTSTR fbuf = SHOE_ALLOC_N(TCHAR, SHOES_CHUNKSIZE); LPWSTR uagent = SHOE_ALLOC_N(WCHAR, SHOES_BUFSIZE); HINTERNET sess = NULL, conn = NULL, req = NULL; SHOES_TIME last = 0; if (buf == NULL || fbuf == NULL || uagent == NULL) goto done; _snwprintf(uagent, SHOES_BUFSIZE, L"Shoes/0.r%d (%S) %S/%d", SHOES_REVISION, SHOES_PLATFORM, SHOES_RELEASE_NAME, SHOES_BUILD_DATE); sess = WinHttpOpen(uagent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (sess == NULL) goto done; conn = WinHttpConnect(sess, host, port, 0); if (conn == NULL) goto done; req = WinHttpOpenRequest(conn, L"GET", path, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); if (req == NULL) goto done; if (!WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0)) goto done; if (!WinHttpReceiveResponse(req, NULL)) goto done; len = sizeof(DWORD); if (!WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &len, NULL)) goto done; else { shoes_download_event event; event.stage = SHOES_HTTP_STATUS; event.status = status; if (handler != NULL) handler(&event, data); } shoes_winhttp_headers(req, handler, data); *size = 0; len = sizeof(buf); if (WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH, NULL, buf, &len, NULL)) { *size = _wtoi((wchar_t *)buf); if (*mem != NULL && *size > memlen) { SHOE_REALLOC_N(*mem, char, (memlen = *size)); if (*mem == NULL) goto done; }
// Invia una richiesta HTTP e legge la risposta // Alloca il buffer con la risposta (che va poi liberato dal chiamante) DWORD HttpSocialRequest(WCHAR *Host, WCHAR *verb, WCHAR *resource, DWORD port, BYTE *s_buffer, DWORD sbuf_len, BYTE **r_buffer, DWORD *response_len, char *cookies) { WCHAR *cookies_w; DWORD cookies_len; DWORD dwStatusCode = 0; DWORD dwTemp = sizeof(dwStatusCode); DWORD n_read; char *types[] = { "*\x0/\x0*\x0",0 }; HINTERNET hConnect, hRequest; BYTE *ptr; DWORD flags = 0; BYTE temp_buffer[8*1024]; // Manda la richiesta cookies_len = strlen(cookies); if (cookies_len == 0) return SOCIAL_REQUEST_NETWORK_PROBLEM; cookies_len++; cookies_w = (WCHAR *)calloc(cookies_len, sizeof(WCHAR)); if (!cookies_w) return SOCIAL_REQUEST_NETWORK_PROBLEM; _snwprintf_s(cookies_w, cookies_len, _TRUNCATE, L"%S", cookies); if (port == 443) flags = WINHTTP_FLAG_SECURE; if ( !(hConnect = FNC(WinHttpConnect)( g_http_social_session, (LPCWSTR) Host, (INTERNET_PORT)port, 0))) { SAFE_FREE(cookies_w); return SOCIAL_REQUEST_NETWORK_PROBLEM; } if ( !(hRequest = FNC(WinHttpOpenRequest)( hConnect, verb, resource, NULL, WINHTTP_NO_REFERER, (LPCWSTR *) types, flags)) ) { SAFE_FREE(cookies_w); WinHttpCloseHandle(hConnect); return SOCIAL_REQUEST_NETWORK_PROBLEM; } if (!FNC(WinHttpAddRequestHeaders)(hRequest, L"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", -1, WINHTTP_ADDREQ_FLAG_REPLACE | WINHTTP_ADDREQ_FLAG_ADD)) { SAFE_FREE(cookies_w); WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return SOCIAL_REQUEST_NETWORK_PROBLEM; } if (!FNC(WinHttpAddRequestHeaders)(hRequest, cookies_w, -1, WINHTTP_ADDREQ_FLAG_REPLACE | WINHTTP_ADDREQ_FLAG_ADD)) { SAFE_FREE(cookies_w); WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return SOCIAL_REQUEST_NETWORK_PROBLEM; } if (!FNC(WinHttpSendRequest)(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, s_buffer, sbuf_len, sbuf_len, NULL)) { SAFE_FREE(cookies_w); WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return SOCIAL_REQUEST_NETWORK_PROBLEM; } SAFE_FREE(cookies_w); // Legge la risposta if(!FNC(WinHttpReceiveResponse)(hRequest, 0)) { WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return SOCIAL_REQUEST_NETWORK_PROBLEM; } if (!WinHttpQueryHeaders( hRequest, WINHTTP_QUERY_STATUS_CODE| WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwStatusCode, &dwTemp, NULL )) { WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return SOCIAL_REQUEST_NETWORK_PROBLEM; } if (dwStatusCode != HTTP_STATUS_OK) { WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return SOCIAL_REQUEST_BAD_COOKIE; } *response_len = 0; *r_buffer = NULL; for(;;) { if (!FNC(WinHttpReadData)(hRequest, temp_buffer, sizeof(temp_buffer), &n_read) || n_read==0 || n_read>sizeof(temp_buffer)) break; if (!(ptr = (BYTE *)realloc((*r_buffer), (*response_len) + n_read + sizeof(WCHAR)))) break; *r_buffer = ptr; memcpy(((*r_buffer) + (*response_len)), temp_buffer, n_read); *response_len = (*response_len) + n_read; // Null-termina sempre il buffer memset(((*r_buffer) + (*response_len)), 0, sizeof(WCHAR)); } if (!(*r_buffer)) { WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return SOCIAL_REQUEST_NETWORK_PROBLEM; } WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return SOCIAL_REQUEST_SUCCESS; }
static void CALLBACK progress_callback_http(HINTERNET handle, DWORD_PTR context, DWORD status, LPVOID buf, DWORD buflen) { BackgroundCopyFileImpl *file = (BackgroundCopyFileImpl *)context; BackgroundCopyJobImpl *job = file->owner; TRACE("%p, %p, %x, %p, %u\n", handle, file, status, buf, buflen); switch (status) { case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE: { DWORD code, len, size; size = sizeof(code); if (WinHttpQueryHeaders(handle, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &code, &size, NULL)) { if ((job->error.code = error_from_http_response(code))) { EnterCriticalSection(&job->cs); job->error.context = BG_ERROR_CONTEXT_REMOTE_FILE; if (job->error.file) IBackgroundCopyFile2_Release(job->error.file); job->error.file = &file->IBackgroundCopyFile2_iface; IBackgroundCopyFile2_AddRef(job->error.file); LeaveCriticalSection(&job->cs); transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR); } else { EnterCriticalSection(&job->cs); job->error.context = 0; if (job->error.file) { IBackgroundCopyFile2_Release(job->error.file); job->error.file = NULL; } LeaveCriticalSection(&job->cs); } } size = sizeof(len); if (WinHttpQueryHeaders(handle, WINHTTP_QUERY_CONTENT_LENGTH|WINHTTP_QUERY_FLAG_NUMBER, NULL, &len, &size, NULL)) { file->fileProgress.BytesTotal = len; } break; } case WINHTTP_CALLBACK_STATUS_READ_COMPLETE: { file->read_size = buflen; break; } case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR: { WINHTTP_ASYNC_RESULT *result = (WINHTTP_ASYNC_RESULT *)buf; job->error.code = result->dwError; transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR); break; } default: break; } SetEvent(job->wait); }
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; }
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; }
int __cdecl wmain( int argc, WCHAR **argv ) { DWORD dwError = ERROR_SUCCESS; HINTERNET hSession = NULL; HINTERNET hConnect = NULL; HINTERNET hRequest = NULL; DWORD dwStatusCode = 0; DWORD dwSize = sizeof(dwStatusCode); DWORD dwAutoLogonPolicy = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW; PWSTR pwszServerName = NULL; if (argc != 2) { wprintf(L"Usage: %s <servername>\n", argv[0]); goto Exit; } pwszServerName = argv[1]; // Use WinHttpOpen to obtain a session handle and specify no proxy hSession = WinHttpOpen(USER_AGENT, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (hSession == NULL) { dwError = GetLastError(); wprintf(L"WinHttpOpen failed with error %d\n", dwError); goto Exit; } // Use WinHttpConnect to specify target server and port hConnect = WinHttpConnect(hSession, pwszServerName, INTERNET_DEFAULT_HTTP_PORT, 0); if (hConnect == NULL) { dwError = GetLastError(); wprintf(L"WinHttpConnect failed with error %d\n", dwError); goto Exit; } // Use WinHttpOpenRequest to open a GET request and specify taget path hRequest = WinHttpOpenRequest(hConnect, L"GET", TARGET_PATH, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); if (hRequest == NULL) { dwError = GetLastError(); wprintf(L"WinHttpOpenRequest failed with error %d\n", dwError); goto Exit; } // Use WinHttpSetOption to set autologon policy to low level // to include the default credentials in a request if (!WinHttpSetOption(hRequest, WINHTTP_OPTION_AUTOLOGON_POLICY, &dwAutoLogonPolicy, sizeof(dwAutoLogonPolicy))) { dwError = GetLastError(); wprintf(L"WinHttpSetOption failed with error %d\n", dwError); goto Exit; } // Use WinHttpSetCredentials with NULL username and password // to use default credentials if (!WinHttpSetCredentials(hRequest, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL)) { dwError = GetLastError(); wprintf(L"WinHttpSetCredentials failed with error %d\n", dwError); goto Exit; } // Use WinHttpSendRequest to send the request and // specify no additional headers and request data if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) { dwError = GetLastError(); wprintf(L"WinHttpSendRequest failed with error %d\n", dwError); goto Exit; } // Use WinHttpReceiveResponse to receive the response if (!WinHttpReceiveResponse(hRequest, NULL)) { dwError = GetLastError(); wprintf(L"WinHttpReceiveResponse failed with error %d\n", dwError); goto Exit; } // Use WinHttpQueryHeaders to retrieve the status code if (!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_FLAG_NUMBER | WINHTTP_QUERY_STATUS_CODE, NULL, &dwStatusCode, &dwSize, NULL)) { dwError = GetLastError(); wprintf(L"WinHttpQueryHeaders failed with error %d\n", dwError); goto Exit; } // Expect to get status code 200 if(dwStatusCode == 200) { wprintf(L"Got expected status code=200\n"); } else { wprintf(L"Unexpected status code=%d\n", dwStatusCode); } Exit: if (hRequest != NULL) { WinHttpCloseHandle(hRequest); } if (hConnect != NULL) { WinHttpCloseHandle(hConnect); } if (hSession != NULL) { WinHttpCloseHandle(hSession); } return dwError; }
static void test_connection_cache( void ) { HANDLE ses, con, req; DWORD size, status; BOOL ret; struct info info, *context = &info; info.test = cache_test; info.count = sizeof(cache_test) / sizeof(cache_test[0]); info.index = 0; info.wait = NULL; ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 ); 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()); setup_test( &info, winhttp_receive_response, __LINE__ ); ret = WinHttpReceiveResponse( req, NULL ); ok(ret, "failed to receive response %u\n", GetLastError()); 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_close_handle, __LINE__ ); WinHttpCloseHandle( req ); 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()); ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) ); ok(ret, "failed to set context value %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()); setup_test( &info, winhttp_receive_response, __LINE__ ); ret = WinHttpReceiveResponse( req, NULL ); ok(ret, "failed to receive response %u\n", GetLastError()); 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_close_handle, __LINE__ ); WinHttpCloseHandle( req ); setup_test( &info, winhttp_close_handle, __LINE__ ); WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); WinHttpCloseHandle( ses ); Sleep(2000); /* make sure connection is evicted from cache */ info.index = 0; ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 ); 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()); ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) ); ok(ret, "failed to set context value %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()); setup_test( &info, winhttp_receive_response, __LINE__ ); ret = WinHttpReceiveResponse( req, NULL ); ok(ret, "failed to receive response %u\n", GetLastError()); 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_close_handle, __LINE__ ); WinHttpCloseHandle( req ); 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()); ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) ); ok(ret, "failed to set context value %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()); setup_test( &info, winhttp_receive_response, __LINE__ ); ret = WinHttpReceiveResponse( req, NULL ); ok(ret, "failed to receive response %u\n", GetLastError()); 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_close_handle, __LINE__ ); WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); WinHttpCloseHandle( ses ); Sleep(2000); /* make sure connection is evicted from cache */ }
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; }
// 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 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 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; }
// 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(); }
static int winhttp_stream_read( git_smart_subtransport_stream *stream, char *buffer, size_t buf_size, size_t *bytes_read) { winhttp_stream *s = (winhttp_stream *)stream; winhttp_subtransport *t = OWNING_SUBTRANSPORT(s); DWORD dw_bytes_read; char replay_count = 0; int error; replay: /* Enforce a reasonable cap on the number of replays */ if (++replay_count >= 7) { giterr_set(GITERR_NET, "Too many redirects or authentication replays"); return -1; } /* Connect if necessary */ if (!s->request && winhttp_stream_connect(s) < 0) return -1; if (!s->received_response) { DWORD status_code, status_code_length, content_type_length, bytes_written; char expected_content_type_8[MAX_CONTENT_TYPE_LEN]; wchar_t expected_content_type[MAX_CONTENT_TYPE_LEN], content_type[MAX_CONTENT_TYPE_LEN]; if (!s->sent_request) { if ((error = send_request(s, s->post_body_len, 0)) < 0) return error; s->sent_request = 1; } if (s->chunked) { assert(s->verb == post_verb); /* Flush, if necessary */ if (s->chunk_buffer_len > 0 && write_chunk(s->request, s->chunk_buffer, s->chunk_buffer_len) < 0) return -1; s->chunk_buffer_len = 0; /* Write the final chunk. */ if (!WinHttpWriteData(s->request, "0\r\n\r\n", 5, &bytes_written)) { giterr_set(GITERR_OS, "Failed to write final chunk"); return -1; } } else if (s->post_body) { char *buffer; DWORD len = s->post_body_len, bytes_read; if (INVALID_SET_FILE_POINTER == SetFilePointer(s->post_body, 0, 0, FILE_BEGIN) && NO_ERROR != GetLastError()) { giterr_set(GITERR_OS, "Failed to reset file pointer"); return -1; } buffer = git__malloc(CACHED_POST_BODY_BUF_SIZE); while (len > 0) { DWORD bytes_written; if (!ReadFile(s->post_body, buffer, min(CACHED_POST_BODY_BUF_SIZE, len), &bytes_read, NULL) || !bytes_read) { git__free(buffer); giterr_set(GITERR_OS, "Failed to read from temp file"); return -1; } if (!WinHttpWriteData(s->request, buffer, bytes_read, &bytes_written)) { git__free(buffer); giterr_set(GITERR_OS, "Failed to write data"); return -1; } len -= bytes_read; assert(bytes_read == bytes_written); } git__free(buffer); /* Eagerly close the temp file */ CloseHandle(s->post_body); s->post_body = NULL; } if (!WinHttpReceiveResponse(s->request, 0)) { giterr_set(GITERR_OS, "Failed to receive response"); return -1; } /* Verify that we got a 200 back */ status_code_length = sizeof(status_code); if (!WinHttpQueryHeaders(s->request, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &status_code, &status_code_length, WINHTTP_NO_HEADER_INDEX)) { giterr_set(GITERR_OS, "Failed to retrieve status code"); return -1; } /* The implementation of WinHTTP prior to Windows 7 will not * redirect to an identical URI. Some Git hosters use self-redirects * as part of their DoS mitigation strategy. Check first to see if we * have a redirect status code, and that we haven't already streamed * a post body. (We can't replay a streamed POST.) */ if (!s->chunked && (HTTP_STATUS_MOVED == status_code || HTTP_STATUS_REDIRECT == status_code || (HTTP_STATUS_REDIRECT_METHOD == status_code && get_verb == s->verb) || HTTP_STATUS_REDIRECT_KEEP_VERB == status_code)) { /* Check for Windows 7. This workaround is only necessary on * Windows Vista and earlier. Windows 7 is version 6.1. */ wchar_t *location; DWORD location_length; char *location8; /* OK, fetch the Location header from the redirect. */ if (WinHttpQueryHeaders(s->request, WINHTTP_QUERY_LOCATION, WINHTTP_HEADER_NAME_BY_INDEX, WINHTTP_NO_OUTPUT_BUFFER, &location_length, WINHTTP_NO_HEADER_INDEX) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { giterr_set(GITERR_OS, "Failed to read Location header"); return -1; } location = git__malloc(location_length); GITERR_CHECK_ALLOC(location); if (!WinHttpQueryHeaders(s->request, WINHTTP_QUERY_LOCATION, WINHTTP_HEADER_NAME_BY_INDEX, location, &location_length, WINHTTP_NO_HEADER_INDEX)) { giterr_set(GITERR_OS, "Failed to read Location header"); git__free(location); return -1; } /* Convert the Location header to UTF-8 */ if (git__utf16_to_8_alloc(&location8, location) < 0) { giterr_set(GITERR_OS, "Failed to convert Location header to UTF-8"); git__free(location); return -1; } git__free(location); /* Replay the request */ winhttp_stream_close(s); if (!git__prefixcmp_icase(location8, prefix_https)) { /* Upgrade to secure connection; disconnect and start over */ if (gitno_connection_data_from_url(&t->connection_data, location8, s->service_url) < 0) { git__free(location8); return -1; } winhttp_close_connection(t); if (winhttp_connect(t) < 0) return -1; } git__free(location8); goto replay; } /* Handle authentication failures */ if (HTTP_STATUS_DENIED == status_code && get_verb == s->verb) { int allowed_types; if (parse_unauthorized_response(s->request, &allowed_types, &t->auth_mechanism) < 0) return -1; if (allowed_types && (!t->cred || 0 == (t->cred->credtype & allowed_types))) { int cred_error = 1; /* Start with the user-supplied credential callback, if present */ if (t->owner->cred_acquire_cb) { cred_error = t->owner->cred_acquire_cb(&t->cred, t->owner->url, t->connection_data.user, allowed_types, t->owner->cred_acquire_payload); if (cred_error < 0) return cred_error; } /* Invoke the fallback credentials acquisition callback if necessary */ if (cred_error > 0) { cred_error = fallback_cred_acquire_cb(&t->cred, t->owner->url, t->connection_data.user, allowed_types, NULL); if (cred_error < 0) return cred_error; } if (!cred_error) { assert(t->cred); winhttp_stream_close(s); /* Successfully acquired a credential */ goto replay; } } } if (HTTP_STATUS_OK != status_code) { giterr_set(GITERR_NET, "Request failed with status code: %d", status_code); return -1; } /* Verify that we got the correct content-type back */ if (post_verb == s->verb) p_snprintf(expected_content_type_8, MAX_CONTENT_TYPE_LEN, "application/x-git-%s-result", s->service); else p_snprintf(expected_content_type_8, MAX_CONTENT_TYPE_LEN, "application/x-git-%s-advertisement", s->service); if (git__utf8_to_16(expected_content_type, MAX_CONTENT_TYPE_LEN, expected_content_type_8) < 0) { giterr_set(GITERR_OS, "Failed to convert expected content-type to wide characters"); return -1; } content_type_length = sizeof(content_type); if (!WinHttpQueryHeaders(s->request, WINHTTP_QUERY_CONTENT_TYPE, WINHTTP_HEADER_NAME_BY_INDEX, &content_type, &content_type_length, WINHTTP_NO_HEADER_INDEX)) { giterr_set(GITERR_OS, "Failed to retrieve response content-type"); return -1; } if (wcscmp(expected_content_type, content_type)) { giterr_set(GITERR_NET, "Received unexpected content-type"); return -1; } s->received_response = 1; } if (!WinHttpReadData(s->request, (LPVOID)buffer, (DWORD)buf_size, &dw_bytes_read)) { giterr_set(GITERR_OS, "Failed to read data"); return -1; } *bytes_read = dw_bytes_read; return 0; }
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 ); }
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; }
/*! * @brief Wrapper around WinHTTP-specific request response validation. * @param hReq HTTP request handle. * @param ctx The HTTP transport context. * @return An indication of the result of getting a response. */ static DWORD validate_response_winhttp(HANDLE hReq, HttpTransportContext* ctx) { DWORD statusCode; DWORD statusCodeSize = sizeof(statusCode); vdprintf("[PACKET RECEIVE WINHTTP] Getting the result code..."); if (WinHttpQueryHeaders(hReq, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusCodeSize, WINHTTP_NO_HEADER_INDEX)) { vdprintf("[PACKET RECEIVE WINHTTP] Returned status code is %d", statusCode); // did the request succeed? if (statusCode != 200) { // There are a few reasons why this could fail, including proxy related stuff. // If we fail, we're going to fallback to WinINET and see if that works instead. // there could be a number of reasons for failure, but we're only going to try // to handle the case where proxy authentication fails. We'll indicate failure and // let the switchover happen for us. // However, we won't do this in the case where cert hash verification is turned on, // because we don't want to expose people to MITM if they've explicitly asked us not // to. if (ctx->cert_hash == NULL && statusCode == 407) { return ERROR_WINHTTP_CANNOT_CONNECT; } // indicate something is up. return ERROR_BAD_CONFIGURATION; } } if (ctx->cert_hash != NULL) { vdprintf("[PACKET RECEIVE WINHTTP] validating certificate hash"); PCERT_CONTEXT pCertContext = NULL; DWORD dwCertContextSize = sizeof(pCertContext); if (!WinHttpQueryOption(hReq, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &pCertContext, &dwCertContextSize)) { dprintf("[PACKET RECEIVE WINHTTP] Failed to get the certificate context: %u", GetLastError()); return ERROR_WINHTTP_SECURE_INVALID_CERT; } DWORD dwHashSize = 20; BYTE hash[20]; if (!CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, hash, &dwHashSize)) { dprintf("[PACKET RECEIVE WINHTTP] Failed to get the certificate hash: %u", GetLastError()); return ERROR_WINHTTP_SECURE_INVALID_CERT; } if (memcmp(hash, ctx->cert_hash, CERT_HASH_SIZE) != 0) { dprintf("[SERVER] Server hash set to: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7], hash[8], hash[9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15], hash[16], hash[17], hash[18], hash[19]); dprintf("[PACKET RECEIVE WINHTTP] Certificate hash doesn't match, bailing out"); return ERROR_WINHTTP_SECURE_INVALID_CERT; } } return ERROR_SUCCESS; }
BOOL CSyoboiCalUtil::SendReserve(const vector<RESERVE_DATA>* reserveList, const vector<TUNER_RESERVE_INFO>* tunerList) { if( reserveList == NULL || tunerList == NULL ){ return FALSE; } if( reserveList->size() == 0 ){ return FALSE; } wstring iniAppPath = L""; GetModuleIniPath(iniAppPath); if( GetPrivateProfileInt(L"SYOBOI", L"use", 0, iniAppPath.c_str()) == 0 ){ return FALSE; } _OutputDebugString(L"★SyoboiCalUtil:SendReserve"); wstring textPath; GetModuleFolderPath(textPath); textPath += L"\\SyoboiCh.txt"; CParseServiceChgText srvChg; srvChg.ParseText(textPath.c_str()); wstring proxyServerName; wstring proxyUserName; wstring proxyPassword; if( GetPrivateProfileInt(L"SYOBOI", L"useProxy", 0, iniAppPath.c_str()) != 0 ){ proxyServerName = GetPrivateProfileToString(L"SYOBOI", L"ProxyServer", L"", iniAppPath.c_str()); proxyUserName = GetPrivateProfileToString(L"SYOBOI", L"ProxyID", L"", iniAppPath.c_str()); proxyPassword = GetPrivateProfileToString(L"SYOBOI", L"ProxyPWD", L"", iniAppPath.c_str()); } wstring id=GetPrivateProfileToString(L"SYOBOI", L"userID", L"", iniAppPath.c_str()); wstring pass=GetPrivateProfileToString(L"SYOBOI", L"PWD", L"", iniAppPath.c_str()); int slot = GetPrivateProfileInt(L"SYOBOI", L"slot", 0, iniAppPath.c_str()); wstring devcolors=GetPrivateProfileToString(L"SYOBOI", L"devcolors", L"", iniAppPath.c_str()); wstring epgurl=GetPrivateProfileToString(L"SYOBOI", L"epgurl", L"", iniAppPath.c_str()); if( id.size() == 0 ){ _OutputDebugString(L"★SyoboiCalUtil:NoUserID"); return FALSE; } //Authorization wstring auth = L""; auth = id; auth += L":"; auth += pass; string authA; WtoA(auth, authA); DWORD destSize = 0; Base64Enc(authA.c_str(), (DWORD)authA.size(), NULL, &destSize); vector<WCHAR> base64(destSize + 1, L'\0'); Base64Enc(authA.c_str(), (DWORD)authA.size(), &base64.front(), &destSize); //無駄なCRLFが混じることがあるため std::replace(base64.begin(), base64.end(), L'\r', L'\0'); std::replace(base64.begin(), base64.end(), L'\n', L'\0'); wstring authHead = L""; Format(authHead, L"Authorization: Basic %s\r\nContent-type: application/x-www-form-urlencoded\r\n", &base64.front()); //data wstring dataParam; wstring param; map<DWORD, wstring> tunerMap; for( size_t i=0; i<tunerList->size(); i++ ){ for( size_t j=0; j<(*tunerList)[i].reserveList.size(); j++ ){ tunerMap.insert(pair<DWORD, wstring>((*tunerList)[i].reserveList[j], (*tunerList)[i].tunerName)); } } map<DWORD, wstring>::iterator itrTuner; DWORD dataCount = 0; for(size_t i=0; i<reserveList->size(); i++ ){ if( dataCount>=200 ){ break; } const RESERVE_DATA* info = &(*reserveList)[i]; if( info->recSetting.recMode == RECMODE_NO || info->recSetting.recMode == RECMODE_VIEW ){ continue; } wstring device=L""; itrTuner = tunerMap.find(info->reserveID); if( itrTuner != tunerMap.end() ){ device = itrTuner->second; } wstring stationName = info->stationName; srvChg.ChgText(stationName); __int64 startTime = GetTimeStamp(info->startTime); Format(param, L"%I64d\t%I64d\t%s\t%s\t%s\t\t0\t%d\n", startTime, startTime+info->durationSecond, device.c_str(), info->title.c_str(), stationName.c_str(), info->reserveID ); dataParam+=param; } if(dataParam.size() == 0 ){ _OutputDebugString(L"★SyoboiCalUtil:NoReserve"); return FALSE; } string utf8; UrlEncodeUTF8(dataParam.c_str(), (DWORD)dataParam.size(), utf8); string data; Format(data, "slot=%d&data=%s",slot, utf8.c_str()); if( devcolors.size() > 0){ utf8 = ""; UrlEncodeUTF8(devcolors.c_str(), (DWORD)devcolors.size(), utf8); data += "&devcolors="; data += utf8; } if( epgurl.size() > 0){ utf8 = ""; UrlEncodeUTF8(epgurl.c_str(), (DWORD)epgurl.size(), utf8); data += "&epgurl="; data += utf8; } vector<char> dataBuff(data.begin(), data.end()); //URLの分解 URL_COMPONENTS stURL = {}; stURL.dwStructSize = sizeof(stURL); stURL.dwSchemeLength = (DWORD)-1; stURL.dwHostNameLength = (DWORD)-1; stURL.dwUrlPathLength = (DWORD)-1; stURL.dwExtraInfoLength = (DWORD)-1; if( WinHttpCrackUrl(SYOBOI_UP_URL, 0, 0, &stURL) == FALSE || stURL.dwHostNameLength == 0 ){ return FALSE; } wstring host(stURL.lpszHostName, stURL.dwHostNameLength); wstring sendUrl(stURL.lpszUrlPath, stURL.dwUrlPathLength + stURL.dwExtraInfoLength); HINTERNET session; if( proxyServerName.empty() ){ session = WinHttpOpen(L"EpgTimerSrv", WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); }else{ session = WinHttpOpen(L"EpgTimerSrv", WINHTTP_ACCESS_TYPE_NAMED_PROXY, proxyServerName.c_str(), WINHTTP_NO_PROXY_BYPASS, 0); } if( session == NULL ){ return FALSE; } LPCWSTR result = L"1"; HINTERNET connect = NULL; HINTERNET request = NULL; if( WinHttpSetTimeouts(session, 15000, 15000, 15000, 15000) == FALSE ){ result = L"0 SetTimeouts"; goto EXIT; } //コネクションオープン connect = WinHttpConnect(session, host.c_str(), stURL.nPort, 0); if( connect == NULL ){ result = L"0 Connect"; goto EXIT; } //リクエストオープン request = WinHttpOpenRequest(connect, L"POST", sendUrl.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, stURL.nPort == INTERNET_DEFAULT_HTTPS_PORT ? WINHTTP_FLAG_SECURE : 0); if( request == NULL ){ result = L"0 OpenRequest"; goto EXIT; } if( proxyServerName.empty() == false ){ //ProxyのIDかパスワードがあったらセット if( proxyUserName.empty() == false || proxyPassword.empty() == false ){ if( WinHttpSetCredentials(request, WINHTTP_AUTH_TARGET_PROXY, WINHTTP_AUTH_SCHEME_BASIC, proxyUserName.c_str(), proxyPassword.c_str(), NULL) == FALSE ){ result = L"0 SetCredentials"; goto EXIT; } } } if( WinHttpSendRequest(request, authHead.c_str(), (DWORD)-1, &dataBuff.front(), (DWORD)dataBuff.size(), (DWORD)dataBuff.size(), 0) == FALSE ){ result = L"0 SendRequest"; goto EXIT; } if( WinHttpReceiveResponse(request, NULL) == FALSE ){ result = L"0 ReceiveResponse"; goto EXIT; } //HTTPのステータスコード確認 DWORD statusCode; DWORD statusCodeSize = sizeof(statusCode); if( WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusCodeSize, WINHTTP_NO_HEADER_INDEX) == FALSE ){ statusCode = 0; } if( statusCode != 200 && statusCode != 201 ){ result = L"0 StatusNotOK"; goto EXIT; } EXIT: if( request != NULL ){ WinHttpCloseHandle(request); } if( connect != NULL ){ WinHttpCloseHandle(connect); } if( session != NULL ){ WinHttpCloseHandle(session); } _OutputDebugString(L"★SyoboiCalUtil:SendRequest res:%s", result); if( result[0] != L'1' ){ return FALSE; } return TRUE; }
void shoes_winhttp_headers(HINTERNET req, shoes_download_handler handler, void *data) { DWORD size; WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &size, WINHTTP_NO_HEADER_INDEX); if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) { int whdrlen = 0, hdrlen = 0; LPCWSTR whdr; LPSTR hdr = SHOE_ALLOC_N(CHAR, MAX_PATH); LPCWSTR hdrs = SHOE_ALLOC_N(WCHAR, size/sizeof(WCHAR)); BOOL res = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, WINHTTP_HEADER_NAME_BY_INDEX, (LPVOID)hdrs, &size, WINHTTP_NO_HEADER_INDEX); if (res) { for (whdr = hdrs; whdr - hdrs < size / sizeof(WCHAR); whdr += whdrlen) { WideCharToMultiByte(CP_UTF8, 0, whdr, -1, hdr, MAX_PATH, NULL, NULL); hdrlen = strlen(hdr); HTTP_HEADER(hdr, hdrlen, handler, data); whdrlen = wcslen(whdr) + 1; } } SHOE_FREE(hdrs); SHOE_FREE(hdr); } }