BOOL remaining = FALSE;
DWORD64 now;
+#ifdef __REACTOS__
now = GetTickCount();
+#else
+ now = GetTickCount64();
+#endif
LIST_FOR_EACH_ENTRY_SAFE(server, server_safe, &connection_pool, server_t, entry) {
LIST_FOR_EACH_ENTRY_SAFE(netconn, netconn_safe, &server->conn_pool, netconn_t, pool_entry) {
continue;
data++;
- set_cookie(host->lpszValue, request->path, name, data);
+ set_cookie(host->lpszValue, request->path, name, data, INTERNET_COOKIE_HTTPONLY);
heap_free(name);
}
}
TRACE("%p, %s, %i, %i\n", hHttpRequest, debugstr_wn(lpszHeader, dwHeaderLength), dwHeaderLength, dwModifier);
- if (!lpszHeader)
+ if (!lpszHeader)
return TRUE;
request = (http_request_t*) get_handle_object( hHttpRequest );
return;
}
#else
- // silence unused function warning
+ /* Silence unused function warning */
(void)collect_connections_proc;
#endif
static DWORD set_content_length(http_request_t *request)
{
static const WCHAR szChunked[] = {'c','h','u','n','k','e','d',0};
+ static const WCHAR headW[] = {'H','E','A','D',0};
WCHAR encoding[20];
DWORD size;
- if(request->status_code == HTTP_STATUS_NO_CONTENT) {
+ if(request->status_code == HTTP_STATUS_NO_CONTENT || !strcmpW(request->verb, headW)) {
request->contentLength = request->netconn_stream.content_length = 0;
return ERROR_SUCCESS;
}
HTTP_ProcessHeader(request, hostW, request->server->canon_host_port, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REQ);
- if (session->hostPort == INTERNET_INVALID_PORT_NUMBER)
- session->hostPort = INTERNET_DEFAULT_HTTP_PORT;
-
if (hIC->proxy && hIC->proxy[0] && !HTTP_ShouldBypassProxy(hIC, session->hostName))
HTTP_DealWithProxy( hIC, session, request );
return ERROR_HTTP_HEADER_NOT_FOUND;
}
- if (lpdwIndex) (*lpdwIndex)++;
-
/* coalesce value to requested type */
if (dwInfoLevel & HTTP_QUERY_FLAG_NUMBER && lpBuffer)
{
}
*lpdwBufferLength = len - sizeof(WCHAR);
}
+ if (lpdwIndex) (*lpdwIndex)++;
return ERROR_SUCCESS;
}
info_mod &= ~ modifier_flags[i].val;
}
}
-
+
if (info_mod) {
TRACE(" Unknown (%08x)", info_mod);
}
TRACE("\n");
}
-
+
request = (http_request_t*) get_handle_object( hHttpRequest );
if (NULL == request || request->hdr.htype != WH_HHTTPREQ)
{
urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
urlComponents.lpszScheme = (request->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp;
urlComponents.dwSchemeLength = 0;
- urlComponents.lpszHostName = session->hostName;
+ urlComponents.lpszHostName = request->server->name;
urlComponents.dwHostNameLength = 0;
- urlComponents.nPort = session->hostPort;
+ urlComponents.nPort = request->server->port;
urlComponents.lpszUserName = session->userName;
urlComponents.dwUserNameLength = 0;
urlComponents.lpszPassword = NULL;
}
else
session->hostName = heap_strdupW(hostName);
+ session->hostPort = urlComponents.nPort;
HTTP_ProcessHeader(request, hostW, session->hostName, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDHDR_FLAG_REQ);
return str;
}
-static DWORD HTTP_SecureProxyConnect(http_request_t *request)
-{
- server_t *server = request->server;
- LPWSTR requestString;
- INT len;
- INT cnt;
- INT responseLen;
- char *ascii_req;
- DWORD res;
-
- static const WCHAR connectW[] = {'C','O','N','N','E','C','T',0};
-
- TRACE("\n");
-
- requestString = build_request_header( request, connectW, server->host_port, g_szHttp1_1, TRUE );
-
- len = WideCharToMultiByte( CP_ACP, 0, requestString, -1,
- NULL, 0, NULL, NULL );
- len--; /* the nul terminator isn't needed */
- ascii_req = heap_alloc(len);
- WideCharToMultiByte( CP_ACP, 0, requestString, -1, ascii_req, len, NULL, NULL );
- heap_free( requestString );
-
- TRACE("full request -> %s\n", debugstr_an( ascii_req, len ) );
-
- NETCON_set_timeout( request->netconn, TRUE, request->send_timeout );
- res = NETCON_send( request->netconn, ascii_req, len, 0, &cnt );
- heap_free( ascii_req );
- if (res != ERROR_SUCCESS)
- return res;
-
- if (HTTP_GetResponseHeaders( request, &responseLen ) || !responseLen)
- return ERROR_HTTP_INVALID_HEADER;
-
- return ERROR_SUCCESS;
-}
-
static void HTTP_InsertCookies(http_request_t *request)
{
- DWORD cookie_size, size, cnt = 0;
- HTTPHEADERW *host;
WCHAR *cookies;
+ DWORD res;
- static const WCHAR cookieW[] = {'C','o','o','k','i','e',':',' ',0};
-
- host = HTTP_GetHeader(request, hostW);
- if(!host)
- return;
-
- if(get_cookie(host->lpszValue, request->path, NULL, &cookie_size) != ERROR_SUCCESS)
- return;
-
- size = sizeof(cookieW) + cookie_size * sizeof(WCHAR) + sizeof(szCrLf);
- if(!(cookies = heap_alloc(size)))
+ res = get_cookie_header(request->server->name, request->path, &cookies);
+ if(res != ERROR_SUCCESS || !cookies)
return;
- cnt += sprintfW(cookies, cookieW);
- get_cookie(host->lpszValue, request->path, cookies+cnt, &cookie_size);
- strcatW(cookies, szCrLf);
-
+ get_cookie_header(request->server->name, request->path, &cookies);
HTTP_HttpAddRequestHeadersW(request, cookies, strlenW(cookies), HTTP_ADDREQ_FLAG_REPLACE);
-
heap_free(cookies);
}
INTERNET_STATUS_CONNECTED_TO_SERVER,
request->server->addr_str, strlen(request->server->addr_str)+1);
- if(is_https) {
- /* Note: we differ from Microsoft's WinINet here. they seem to have
- * a bug that causes no status callbacks to be sent when starting
- * a tunnel to a proxy server using the CONNECT verb. i believe our
- * behaviour to be more correct and to not cause any incompatibilities
- * because using a secure connection through a proxy server is a rare
- * case that would be hard for anyone to depend on */
- if(request->proxy)
- res = HTTP_SecureProxyConnect(request);
- if(res == ERROR_SUCCESS)
- res = NETCON_secure_connect(request->netconn, request->server);
- }
-
- if(res != ERROR_SUCCESS) {
- http_release_netconn(request, FALSE);
- return res;
- }
-
*reusing = FALSE;
TRACE("Created connection to %s: %p\n", debugstr_w(request->server->name), netconn);
return ERROR_SUCCESS;
}
+static char *build_ascii_request( const WCHAR *str, void *data, DWORD data_len, DWORD *out_len )
+{
+ int len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
+ char *ret;
+
+ if (!(ret = heap_alloc( len + data_len ))) return NULL;
+ WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
+ if (data_len) memcpy( ret + len - 1, data, data_len );
+ *out_len = len + data_len - 1;
+ ret[*out_len] = 0;
+ return ret;
+}
+
/***********************************************************************
* HTTP_HttpSendRequestW (internal)
*
DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength,
DWORD dwContentLength, BOOL bEndRequest)
{
- INT cnt;
- BOOL redirected = FALSE;
- LPWSTR requestString = NULL;
- INT responseLen;
- BOOL loop_next;
static const WCHAR szContentLength[] =
{ 'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','l','i','\r','\n',0 };
+ BOOL redirected = FALSE, secure_proxy_connect = FALSE, loop_next;
+ LPWSTR requestString = NULL;
+ INT responseLen, cnt;
WCHAR contentLengthStr[sizeof szContentLength/2 /* includes \r\n */ + 20 /* int */ ];
DWORD res;
if (dwContentLength || strcmpW(request->verb, szGET))
{
sprintfW(contentLengthStr, szContentLength, dwContentLength);
- HTTP_HttpAddRequestHeadersW(request, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_REPLACE);
+ HTTP_HttpAddRequestHeadersW(request, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
request->bytesToWrite = dwContentLength;
}
if (request->session->appInfo->agent)
do
{
- DWORD len;
+ DWORD len, data_len = dwOptionalLength;
BOOL reusing_connection;
char *ascii_req;
if (!(request->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES))
HTTP_InsertCookies(request);
- if (request->proxy)
+ res = open_http_connection(request, &reusing_connection);
+ if (res != ERROR_SUCCESS)
+ break;
+
+ if (!reusing_connection && (request->hdr.dwFlags & INTERNET_FLAG_SECURE))
+ {
+ if (request->proxy) secure_proxy_connect = TRUE;
+ else
+ {
+ res = NETCON_secure_connect(request->netconn, request->server);
+ if (res != ERROR_SUCCESS)
+ {
+ WARN("failed to upgrade to secure connection\n");
+ http_release_netconn(request, FALSE);
+ break;
+ }
+ }
+ }
+ if (secure_proxy_connect)
+ {
+ static const WCHAR connectW[] = {'C','O','N','N','E','C','T',0};
+ const WCHAR *target = request->server->host_port;
+ requestString = build_request_header(request, connectW, target, g_szHttp1_1, TRUE);
+ }
+ else if (request->proxy && !(request->hdr.dwFlags & INTERNET_FLAG_SECURE))
{
WCHAR *url = build_proxy_path_url(request);
requestString = build_request_header(request, request->verb, url, request->version, TRUE);
else
requestString = build_request_header(request, request->verb, request->path, request->version, TRUE);
-
TRACE("Request header -> %s\n", debugstr_w(requestString) );
- res = open_http_connection(request, &reusing_connection);
- if (res != ERROR_SUCCESS)
- break;
-
/* send the request as ASCII, tack on the optional data */
- if (!lpOptional || redirected)
- dwOptionalLength = 0;
- len = WideCharToMultiByte( CP_ACP, 0, requestString, -1,
- NULL, 0, NULL, NULL );
- ascii_req = heap_alloc(len + dwOptionalLength);
- WideCharToMultiByte( CP_ACP, 0, requestString, -1,
- ascii_req, len, NULL, NULL );
- if( lpOptional )
- memcpy( &ascii_req[len-1], lpOptional, dwOptionalLength );
- len = (len + dwOptionalLength - 1);
- ascii_req[len] = 0;
+ if (!lpOptional || redirected || secure_proxy_connect)
+ data_len = 0;
+
+ ascii_req = build_ascii_request( requestString, lpOptional, data_len, &len );
TRACE("full request -> %s\n", debugstr_a(ascii_req) );
INTERNET_SendCallback(&request->hdr, request->hdr.dwContext,
continue;
}
- request->bytesWritten = dwOptionalLength;
+ request->bytesWritten = data_len;
INTERNET_SendCallback(&request->hdr, request->hdr.dwContext,
INTERNET_STATUS_REQUEST_SENT,
INTERNET_SendCallback(&request->hdr, request->hdr.dwContext,
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
-
+
if (HTTP_GetResponseHeaders(request, &responseLen))
{
http_release_netconn(request, FALSE);
}
}
}
+ if (secure_proxy_connect && request->status_code == HTTP_STATUS_OK)
+ {
+ int index;
+
+ res = NETCON_secure_connect(request->netconn, request->server);
+ if (res != ERROR_SUCCESS)
+ {
+ WARN("failed to upgrade to secure proxy connection\n");
+ http_release_netconn( request, FALSE );
+ break;
+ }
+ index = HTTP_GetCustomHeaderIndex(request, szProxy_Authorization, 0, TRUE);
+ if (index != -1) HTTP_DeleteCustomHeader(request, index);
+ destroy_authinfo(request->proxyAuthInfo);
+ request->proxyAuthInfo = NULL;
+
+ secure_proxy_connect = FALSE;
+ loop_next = TRUE;
+ }
}
else
res = ERROR_SUCCESS;
/* REPLACE wins out over ADD */
if (dwModifier & HTTP_ADDHDR_FLAG_REPLACE)
dwModifier &= ~HTTP_ADDHDR_FLAG_ADD;
-
+
if (dwModifier & HTTP_ADDHDR_FLAG_ADD)
index = -1;
else