32#include "httprequest.h"
46#define DEFAULT_KEEP_ALIVE_TIMEOUT 30000
49static const WCHAR attr_accept_charset[] = {
'A',
'c',
'c',
'e',
'p',
't',
'-',
'C',
'h',
'a',
'r',
's',
'e',
't', 0};
50static const WCHAR attr_accept_encoding[] = {
'A',
'c',
'c',
'e',
'p',
't',
'-',
'E',
'n',
'c',
'o',
'd',
'i',
'n',
'g',0};
51static const WCHAR attr_accept_language[] = {
'A',
'c',
'c',
'e',
'p',
't',
'-',
'L',
'a',
'n',
'g',
'u',
'a',
'g',
'e',0};
52static const WCHAR attr_accept_ranges[] = {
'A',
'c',
'c',
'e',
'p',
't',
'-',
'R',
'a',
'n',
'g',
'e',
's',0};
55static const WCHAR attr_authorization[] = {
'A',
'u',
't',
'h',
'o',
'r',
'i',
'z',
'a',
't',
'i',
'o',
'n',0};
56static const WCHAR attr_cache_control[] = {
'C',
'a',
'c',
'h',
'e',
'-',
'C',
'o',
'n',
't',
'r',
'o',
'l',0};
57static const WCHAR attr_connection[] = {
'C',
'o',
'n',
'n',
'e',
'c',
't',
'i',
'o',
'n',0};
58static const WCHAR attr_content_base[] = {
'C',
'o',
'n',
't',
'e',
'n',
't',
'-',
'B',
'a',
's',
'e',0};
59static const WCHAR attr_content_encoding[] = {
'C',
'o',
'n',
't',
'e',
'n',
't',
'-',
'E',
'n',
'c',
'o',
'd',
'i',
'n',
'g',0};
60static const WCHAR attr_content_id[] = {
'C',
'o',
'n',
't',
'e',
'n',
't',
'-',
'I',
'D',0};
61static const WCHAR attr_content_language[] = {
'C',
'o',
'n',
't',
'e',
'n',
't',
'-',
'L',
'a',
'n',
'g',
'u',
'a',
'g',
'e',0};
62static const WCHAR attr_content_length[] = {
'C',
'o',
'n',
't',
'e',
'n',
't',
'-',
'L',
'e',
'n',
'g',
't',
'h',0};
63static const WCHAR attr_content_location[] = {
'C',
'o',
'n',
't',
'e',
'n',
't',
'-',
'L',
'o',
'c',
'a',
't',
'i',
'o',
'n',0};
64static const WCHAR attr_content_md5[] = {
'C',
'o',
'n',
't',
'e',
'n',
't',
'-',
'M',
'D',
'5',0};
65static const WCHAR attr_content_range[] = {
'C',
'o',
'n',
't',
'e',
'n',
't',
'-',
'R',
'a',
'n',
'g',
'e',0};
66static const WCHAR attr_content_transfer_encoding[] = {
'C',
'o',
'n',
't',
'e',
'n',
't',
'-',
'T',
'r',
'a',
'n',
's',
'f',
'e',
'r',
'-',
'E',
'n',
'c',
'o',
'd',
'i',
'n',
'g',0};
67static const WCHAR attr_content_type[] = {
'C',
'o',
'n',
't',
'e',
'n',
't',
'-',
'T',
'y',
'p',
'e',0};
76static const WCHAR attr_if_modified_since[] = {
'I',
'f',
'-',
'M',
'o',
'd',
'i',
'f',
'i',
'e',
'd',
'-',
'S',
'i',
'n',
'c',
'e',0};
77static const WCHAR attr_if_none_match[] = {
'I',
'f',
'-',
'N',
'o',
'n',
'e',
'-',
'M',
'a',
't',
'c',
'h',0};
79static const WCHAR attr_if_unmodified_since[] = {
'I',
'f',
'-',
'U',
'n',
'm',
'o',
'd',
'i',
'f',
'i',
'e',
'd',
'-',
'S',
'i',
'n',
'c',
'e',0};
80static const WCHAR attr_last_modified[] = {
'L',
'a',
's',
't',
'-',
'M',
'o',
'd',
'i',
'f',
'i',
'e',
'd',0};
82static const WCHAR attr_max_forwards[] = {
'M',
'a',
'x',
'-',
'F',
'o',
'r',
'w',
'a',
'r',
'd',
's',0};
83static const WCHAR attr_mime_version[] = {
'M',
'i',
'm',
'e',
'-',
'V',
'e',
'r',
's',
'i',
'o',
'n',0};
85static const WCHAR attr_proxy_authenticate[] = {
'P',
'r',
'o',
'x',
'y',
'-',
'A',
'u',
't',
'h',
'e',
'n',
't',
'i',
'c',
'a',
't',
'e',0};
86static const WCHAR attr_proxy_authorization[] = {
'P',
'r',
'o',
'x',
'y',
'-',
'A',
'u',
't',
'h',
'o',
'r',
'i',
'z',
'a',
't',
'i',
'o',
'n',0};
87static const WCHAR attr_proxy_connection[] = {
'P',
'r',
'o',
'x',
'y',
'-',
'C',
'o',
'n',
'n',
'e',
'c',
't',
'i',
'o',
'n',0};
91static const WCHAR attr_retry_after[] = {
'R',
'e',
't',
'r',
'y',
'-',
'A',
'f',
't',
'e',
'r',0};
93static const WCHAR attr_set_cookie[] = {
'S',
'e',
't',
'-',
'C',
'o',
'o',
'k',
'i',
'e',0};
95static const WCHAR attr_transfer_encoding[] = {
'T',
'r',
'a',
'n',
's',
'f',
'e',
'r',
'-',
'E',
'n',
'c',
'o',
'd',
'i',
'n',
'g',0};
96static const WCHAR attr_unless_modified_since[] = {
'U',
'n',
'l',
'e',
's',
's',
'-',
'M',
'o',
'd',
'i',
'f',
'i',
'e',
'd',
'-',
'S',
'i',
'n',
'c',
'e',0};
99static const WCHAR attr_user_agent[] = {
'U',
's',
'e',
'r',
'-',
'A',
'g',
'e',
'n',
't',0};
103static const WCHAR attr_www_authenticate[] = {
'W',
'W',
'W',
'-',
'A',
'u',
't',
'h',
'e',
'n',
't',
'i',
'c',
'a',
't',
'e',0};
194 TRACE(
"returning task %p\n", task);
289 TRACE(
"queueing task %p\n", task );
306 if (
c < 32 ||
c == 127)
return FALSE;
313 case '\\':
case '\"':
362 while (*
q ==
' ')
q++;
388 if (!requested_index)
break;
404 hdrs = heap_alloc_zero(
sizeof(
struct header) );
405 if (!hdrs)
return FALSE;
457 hdr.is_request = request_only;
467 int len, len_orig, len_value;
473 len = len_orig + len_value + 2;
487 hdr.is_request = request_only;
513 if (
q[0] ==
'\n' &&
q[1] ==
'\r')
518 if (
q[0] ==
'\r' &&
q[1] ==
'\n')
break;
575 static const WCHAR http[] = {
'h',
't',
't',
'p',0};
576 static const WCHAR https[] = {
'h',
't',
't',
'p',
's',0};
577 static const WCHAR fmt[] = {
'%',
's',
':',
'/',
'/',
'%',
's',0};
593 static const WCHAR port_fmt[] = {
':',
'%',
'u',0};
605 static const WCHAR spaceW[] = {
' ',0},
crlfW[] = {
'\r',
'\n',0}, colonW[] = {
':',
' ',0};
606 static const WCHAR twocrlfW[] = {
'\r',
'\n',
'\r',
'\n',0};
649#define QUERY_MODIFIER_MASK (WINHTTP_QUERY_FLAG_REQUEST_HEADERS | WINHTTP_QUERY_FLAG_SYSTEMTIME | WINHTTP_QUERY_FLAG_NUMBER)
656 int requested_index, header_index = -1;
680 for (
len = 0; *
p;
p++)
if (*
p !=
'\r')
len++;
688 if (*
p !=
'\r') *
q = *
p;
785 FIXME(
"attribute %u not implemented\n",
attr);
794 if (header_index >= 0)
805 if (!
buffer ||
sizeof(
int) > *buflen)
816 *buflen =
sizeof(
int);
827 TRACE(
"returning time: %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n",
861 TRACE(
"%p, 0x%08x, %s, %p, %p, %p\n", hrequest,
level,
debugstr_w(
name),
buffer, buflen,
index);
925 DWORD index = 0, supported_schemes = 0, first_scheme = 0;
947 if (!first_scheme) first_scheme =
scheme;
948 supported_schemes |=
scheme;
955 *supported = supported_schemes;
956 *
first = first_scheme;
1010 static const char base64enc[] =
1011 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1016 base64[
n++] = base64enc[(
bin[0] & 0xfc) >> 2];
1017 x = (
bin[0] & 3) << 4;
1022 base64[
n++] = base64enc[
x];
1027 base64[
n++] = base64enc[
x | ((
bin[1] & 0xf0) >> 4)];
1028 x = (
bin[1] & 0x0f) << 2;
1033 base64[
n++] = base64enc[
x];
1037 base64[
n++] = base64enc[
x | ((
bin[2] & 0xc0) >> 6)];
1040 base64[
n++] = base64enc[
bin[2] & 0x3f];
1050 if (
c >=
'A' &&
c <=
'Z')
return c -
'A';
1051 if (
c >=
'a' &&
c <=
'z')
return c -
'a' + 26;
1052 if (
c >=
'0' &&
c <=
'9')
return c -
'0' + 52;
1053 if (
c ==
'+')
return 62;
1054 if (
c ==
'/')
return 63;
1061 char c0, c1, c2, c3;
1073 buf[
i + 0] = (c0 << 2) | (c1 >> 4);
1074 buf[
i + 1] = (c1 << 4) | (c2 >> 2);
1075 buf[
i + 2] = (c2 << 6) | c3;
1086 if (
buf)
buf[
i] = (c0 << 2) | (c1 >> 4);
1089 else if (
p[3] ==
'=')
1097 buf[
i + 0] = (c0 << 2) | (c1 >> 4);
1098 buf[
i + 1] = (c1 << 4) | (c2 >> 2);
1111 buf[
i + 0] = (c0 << 2) | (c1 >> 4);
1112 buf[
i + 1] = (c1 << 4) | (c2 >> 2);
1113 buf[
i + 2] = (c2 << 6) | c3;
1168 WCHAR auth_value[2048], *auth_reply;
1188 if (!has_auth_value)
return FALSE;
1221 int userlen, passlen;
1291 WARN(
"AcquireCredentialsHandleW for scheme %s failed with error 0x%08x\n",
1303 ERR(
"authentication scheme changed from %s to %s\n",
1315 in_desc.pBuffers = &
in;
1340 out_desc.pBuffers = &
out;
1353 TRACE(
"sending last auth packet\n");
1360 TRACE(
"sending next auth packet\n");
1364 ERR(
"InitializeSecurityContextW failed with error 0x%08x\n",
status);
1383 auth_reply[len_scheme] =
' ';
1394 static const WCHAR fmtW[] = {
'%',
's',
':',
'%',
'u',0};
1395 static const WCHAR connectW[] = {
'C',
'O',
'N',
'N',
'E',
'C',
'T', 0};
1396 static const WCHAR spaceW[] = {
' ',0},
crlfW[] = {
'\r',
'\n',0}, colonW[] = {
':',
' ',0};
1397 static const WCHAR twocrlfW[] = {
'\r',
'\n',
'\r',
'\n',0};
1446 int len, bytes_sent;
1467 switch (
addr->ss_family)
1476 WARN(
"unsupported address family %d\n",
addr->ss_family);
1488 0, 0, { (
DWORD_PTR)(__FILE__
": connection_pool_cs") }
1516 unsigned int remaining_connections;
1525 remaining_connections = 0;
1540 else remaining_connections++;
1547 }
while(remaining_connections);
1614 memset( &cred, 0,
sizeof(cred) );
1630 WARN(
"AcquireCredentialsHandleW failed: 0x%08x\n",
status );
1699 TRACE(
"connection %p no longer alive, closing\n",
netconn);
1824 static const WCHAR fmt[] = {
'%',
's',
':',
'%',
'u',0};
1910 DWORD chunk_size = 0;
1924 if (ch >=
'0' && ch <=
'9') chunk_size = chunk_size * 16 + ch -
'0';
1925 else if (ch >=
'a' && ch <=
'f') chunk_size = chunk_size * 16 + ch -
'a' + 10;
1926 else if (ch >=
'A' && ch <=
'F') chunk_size = chunk_size * 16 + ch -
'A' + 10;
1927 else if (ch ==
';' || ch ==
'\r' || ch ==
'\n')
1929 TRACE(
"reading %u byte chunk\n", chunk_size);
1969 if (len <= request->read_size)
return TRUE;
1977 static const WCHAR closeW[] = {
'c',
'l',
'o',
's',
'e',0};
1980 WCHAR connection[20];
2020 int count, bytes_read = 0;
2037 bytes_read +=
count;
2074 if (bytes_total >= bytes_left)
return;
2078 bytes_total += bytes_read;
2093#define ESCAPE_MASK_DEFAULT (ESCAPE_FLAG_NON_PRINTABLE | ESCAPE_FLAG_SPACE | ESCAPE_FLAG_UNSAFE |\
2094 ESCAPE_FLAG_DEL | ESCAPE_FLAG_8BIT)
2095#define ESCAPE_MASK_PERCENT (ESCAPE_FLAG_PERCENT | ESCAPE_MASK_DEFAULT)
2096#define ESCAPE_MASK_DISABLE (ESCAPE_FLAG_SPACE | ESCAPE_FLAG_8BIT | ESCAPE_FLAG_STRIP_CRLF)
2100 static const char unsafe[] =
"\"#<>[\\]^`{|}";
2101 const char *
ptr = unsafe;
2114 static const char hex[] =
"0123456789ABCDEF";
2118 for (
i = 0;
i <
len;
i++)
2163 DWORD len, len_path = 0, len_query = 0;
2177 len_path -= len_query;
2186 else query_flags = path_flags;
2211 *
len += len_path + 1;
2245 memcpy(
ptr,
"\r\n\r\n",
sizeof(
"\r\n\r\n") );
2255 static const WCHAR keep_alive[] = {
'K',
'e',
'e',
'p',
'-',
'A',
'l',
'i',
'v',
'e',0};
2256 static const WCHAR no_cache[] = {
'n',
'o',
'-',
'c',
'a',
'c',
'h',
'e',0};
2257 static const WCHAR length_fmt[] = {
'%',
'l',
'd',0};
2295 TRACE(
"failed to add request headers\n");
2300 WARN(
"failed to add cookie headers\n");
2321 len += optional_len;
2343 send_request(
s->hdr.request,
s->headers,
s->headers_len,
s->optional,
s->optional_len,
s->total_len,
s->context,
TRUE );
2356 TRACE(
"%p, %s, %u, %p, %u, %u, %lx\n", hrequest,
debugstr_wn(
headers, headers_len), headers_len,
optional,
2448 TRACE(
"%p, %x, 0x%08x, %s, %p, %p\n", hrequest,
target,
scheme,
debugstr_w(
username),
password,
params);
2540 bytes_read =
count + 1;
2554 TRACE(
"returning empty string\n");
2568#define MAX_REPLY_LEN 1460
2569#define INITIAL_HEADER_BUFFER_LEN 512
2573 static const WCHAR crlf[] = {
'\r',
'\n',0};
2579 WCHAR status_codeW[4];
2595 TRACE(
"version [%s] status code [%s] status text [%s]\n",
2604 status_codeW[
len] = 0;
2632 offset = buflen + crlf_len - 1;
2639 if (!*
buffer) buflen = 1;
2641 while (
len -
offset < buflen + crlf_len)
2663 offset += buflen + crlf_len - 1;
2710 memset( &uc, 0,
sizeof(uc) );
2744 TRACE(
"redirect from secure page to non-secure page\n");
2749 TRACE(
"redirect from non-secure page to secure page\n");
2811 static const WCHAR passportW[] = {
'P',
'a',
's',
's',
'p',
'o',
'r',
't',
'1',
'.',
'4'};
2826 static const WCHAR status401W[] = {
'4',
'0',
'1',0};
2833 for (
i = 0;
i <
len;
i++)
2835 if (
i <=
len - 3 &&
p[
i] ==
'3' &&
p[
i + 1] ==
'0' &&
p[
i + 2] ==
'2')
3112 if (
ret && written) *written = num_bytes;
3130 TRACE(
"%p, %p, %d, %p\n", hrequest,
buffer, to_write, written);