ReactOS 0.4.17-dev-1196-gb6224c3
http.c
Go to the documentation of this file.
1#ifdef __REACTOS__
2#include "precomp.h"
3#include "zlib.h"
4#else
5/*
6 * Wininet - HTTP Implementation
7 *
8 * Copyright 1999 Corel Corporation
9 * Copyright 2002 CodeWeavers Inc.
10 * Copyright 2002 TransGaming Technologies Inc.
11 * Copyright 2004 Mike McCormack for CodeWeavers
12 * Copyright 2005 Aric Stewart for CodeWeavers
13 * Copyright 2006 Robert Shearman for CodeWeavers
14 * Copyright 2011 Jacek Caban for CodeWeavers
15 *
16 * Ulrich Czekalla
17 * David Hammerton
18 *
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Lesser General Public
21 * License as published by the Free Software Foundation; either
22 * version 2.1 of the License, or (at your option) any later version.
23 *
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
28 *
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 */
33
34#include <stdlib.h>
35#include <stdarg.h>
36#include <stdio.h>
37#include <time.h>
38#include <assert.h>
39#include <errno.h>
40#include <limits.h>
41#include <zlib.h>
42
43#include "windef.h"
44#include "winbase.h"
45#include "wininet.h"
46#include "winerror.h"
47#include "winternl.h"
48#include "winsock2.h"
49#include "ws2ipdef.h"
50#define NO_SHLWAPI_STREAM
51#define NO_SHLWAPI_REG
52#define NO_SHLWAPI_GDI
53#include "shlwapi.h"
54#include "sspi.h"
55#include "wincrypt.h"
56#include "winuser.h"
57
58#include "internet.h"
59#include "resource.h"
60#include "wine/debug.h"
61#include "wine/exception.h"
62#endif /* defined(__REACTOS__) */
63
65
66#define HTTP_ADDHDR_FLAG_REQ 0x02000000
67
68#define COLLECT_TIME 60000
69
71{
78 void *auth_data;
79 unsigned int auth_data_len;
80 BOOL finished; /* finished authenticating */
81};
82
83
85{
86 struct list entry;
87
93
94typedef struct _authorizationData
95{
96 struct list entry;
97
107
110
113{
114 0, 0, &authcache_cs,
116 0, 0, { (DWORD_PTR)(__FILE__ ": authcache_cs") }
117};
118static CRITICAL_SECTION authcache_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
119
126static LPWSTR HTTP_build_req( LPCWSTR *list, int len );
128static UINT HTTP_DecodeBase64(LPCWSTR base64, LPSTR bin);
130
133{
134 0, 0, &connection_pool_cs,
136 0, 0, { (DWORD_PTR)(__FILE__ ": connection_pool_cs") }
137};
138static CRITICAL_SECTION connection_pool_cs = { &connection_pool_debug, -1, 0, 0, 0, 0 };
139
142
144{
146}
147
149{
151 return;
152
153#ifdef __REACTOS__
155#endif
156 list_remove(&server->entry);
157#ifdef __REACTOS__
159#endif
160
161 if(server->cert_chain)
162 CertFreeCertificateChain(server->cert_chain);
163 free(server->name);
164 free(server->scheme_host_port);
165 free(server);
166}
167
169{
170 BOOL default_port;
171 size_t name_len, len;
172 WCHAR *buf;
173
174 name_len = lstrlenW(server->name);
175 len = name_len + 10 /* strlen("://:<port>") */ + ARRAY_SIZE(L"https");
176 buf = malloc(len * sizeof(WCHAR));
177 if(!buf)
178 return FALSE;
179
180 swprintf(buf, len, L"%s://%s:%u", server->is_https ? L"https" : L"http", server->name, server->port);
181 server->scheme_host_port = buf;
182
183 server->host_port = server->scheme_host_port + 7 /* strlen("http://") */;
184 if(server->is_https)
185 server->host_port++;
186
187 default_port = server->port == (server->is_https ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT);
188 server->canon_host_port = default_port ? server->name : server->host_port;
189 return TRUE;
190}
191
193{
194 server_t *iter, *server = NULL;
195
197
199 if(iter->port == port && name.len == lstrlenW(iter->name) && !wcsnicmp(iter->name, name.str, name.len)
200 && iter->is_https == is_https) {
201 server = iter;
203 break;
204 }
205 }
206
207 if(!server && do_create) {
208 server = calloc(1, sizeof(*server));
209 if(server) {
210 server->ref = 2; /* list reference and return */
211 server->port = port;
212 server->is_https = is_https;
213 list_init(&server->conn_pool);
214 server->name = strndupW(name.str, name.len);
215 if(server->name && process_host_port(server)) {
217 }else {
218 free(server);
219 server = NULL;
220 }
221 }
222 }
223
225
226 return server;
227}
228
230{
231 netconn_t *netconn, *netconn_safe;
232 server_t *server, *server_safe;
233 BOOL remaining = FALSE;
234 DWORD64 now;
235
237
239 LIST_FOR_EACH_ENTRY_SAFE(netconn, netconn_safe, &server->conn_pool, netconn_t, pool_entry) {
240 if(collect_type > COLLECT_TIMEOUT || netconn->keep_until < now) {
241 TRACE("freeing %p\n", netconn);
242 list_remove(&netconn->pool_entry);
244 }else {
245 remaining = TRUE;
246 }
247 }
248
249 if(collect_type == COLLECT_CLEANUP) {
250 list_remove(&server->entry);
251 list_init(&server->entry);
253 }
254 }
255
256 return remaining;
257}
258
260{
261 BOOL remaining_conns;
262
263 SetThreadDescription(GetCurrentThread(), L"wine_wininet_collect_connections");
264 do {
265 /* FIXME: Use more sophisticated method */
266 Sleep(5000);
267
269
270 remaining_conns = collect_connections(COLLECT_TIMEOUT);
271 if(!remaining_conns)
273
275 }while(remaining_conns);
276
278}
279
280/***********************************************************************
281 * HTTP_GetHeader (internal)
282 *
283 * Headers section must be held
284 */
286{
287 int HeaderIndex = 0;
288 HeaderIndex = HTTP_GetCustomHeaderIndex(req, head, 0, TRUE);
289 if (HeaderIndex == -1)
290 return NULL;
291 else
292 return &req->custHeaders[HeaderIndex];
293}
294
296{
298 WCHAR *ret = NULL;
299
301 if ((header = HTTP_GetHeader( req, L"Host" ))) ret = wcsdup( header->lpszValue );
302 else ret = wcsdup( req->server->canon_host_port );
304 return ret;
305}
306
312};
313
314typedef struct {
316
321
322 enum {
329 CHUNKED_STREAM_STATE_ERROR
332
334{
335 stream->vtbl->destroy(stream);
336}
337
339{
342 req->read_pos = req->read_size = req->netconn_stream.content_read = 0;
343 req->content_pos = 0;
344 req->read_gzip = FALSE;
345}
346
347static void remove_header( http_request_t *request, const WCHAR *str, BOOL from_request )
348{
349 int index;
350 EnterCriticalSection( &request->headers_section );
351 index = HTTP_GetCustomHeaderIndex( request, str, 0, from_request );
353 LeaveCriticalSection( &request->headers_section );
354}
355
356typedef struct {
365
367{
368 gzip_stream_t *gzip_stream = (gzip_stream_t*)stream;
369 return gzip_stream->end_of_data
370 || (!gzip_stream->buf_size && gzip_stream->parent_stream->vtbl->end_of_data(gzip_stream->parent_stream, req));
371}
372
374 DWORD *read, BOOL allow_blocking)
375{
376 gzip_stream_t *gzip_stream = (gzip_stream_t*)stream;
377 z_stream *zstream = &gzip_stream->zstream;
378 DWORD current_read, ret_read = 0;
379 int zres;
381
382 TRACE("(%ld %x)\n", size, allow_blocking);
383
384 while(size && !gzip_stream->end_of_data) {
385 if(!gzip_stream->buf_size) {
386 if(gzip_stream->buf_pos) {
387 if(gzip_stream->buf_size)
388 memmove(gzip_stream->buf, gzip_stream->buf+gzip_stream->buf_pos, gzip_stream->buf_size);
389 gzip_stream->buf_pos = 0;
390 }
391 res = gzip_stream->parent_stream->vtbl->read(gzip_stream->parent_stream, req, gzip_stream->buf+gzip_stream->buf_size,
392 sizeof(gzip_stream->buf)-gzip_stream->buf_size, &current_read, allow_blocking);
393 if(res != ERROR_SUCCESS)
394 break;
395
396 gzip_stream->buf_size += current_read;
397 if(!current_read) {
398 WARN("unexpected end of data\n");
399 gzip_stream->end_of_data = TRUE;
400 break;
401 }
402 }
403
404 zstream->next_in = gzip_stream->buf+gzip_stream->buf_pos;
405 zstream->avail_in = gzip_stream->buf_size;
406 zstream->next_out = buf+ret_read;
407 zstream->avail_out = size;
408 zres = inflate(&gzip_stream->zstream, 0);
409 current_read = size - zstream->avail_out;
410 size -= current_read;
411 ret_read += current_read;
412 gzip_stream->buf_size -= zstream->next_in - (gzip_stream->buf+gzip_stream->buf_pos);
413 gzip_stream->buf_pos = zstream->next_in-gzip_stream->buf;
414 if(zres == Z_STREAM_END) {
415 TRACE("end of data\n");
416 gzip_stream->end_of_data = TRUE;
417 inflateEnd(zstream);
418 }else if(zres != Z_OK) {
419 WARN("inflate failed %d: %s\n", zres, debugstr_a(zstream->msg));
420 if(!ret_read)
422 break;
423 }
424
425 if(ret_read)
426 allow_blocking = FALSE;
427 }
428
429 TRACE("read %lu bytes\n", ret_read);
430 if(ret_read)
432 *read = ret_read;
433 return res;
434}
435
437{
438 gzip_stream_t *gzip_stream = (gzip_stream_t*)stream;
439 return gzip_stream->parent_stream->vtbl->drain_content(gzip_stream->parent_stream, req, allow_blocking);
440}
441
443{
444 gzip_stream_t *gzip_stream = (gzip_stream_t*)stream;
445
447
448 if(!gzip_stream->end_of_data)
449 inflateEnd(&gzip_stream->zstream);
450 free(gzip_stream);
451}
452
455 gzip_read,
458};
459
461{
462 return malloc(items * size);
463}
464
465static void wininet_zfree(voidpf opaque, voidpf address)
466{
467 free(address);
468}
469
471{
472 gzip_stream_t *gzip_stream;
473 int zres;
474
475 gzip_stream = calloc(1, sizeof(gzip_stream_t));
476 if(!gzip_stream)
477 return ERROR_OUTOFMEMORY;
478
479 gzip_stream->stream.vtbl = &gzip_stream_vtbl;
480 gzip_stream->zstream.zalloc = wininet_zalloc;
481 gzip_stream->zstream.zfree = wininet_zfree;
482
483 zres = inflateInit2(&gzip_stream->zstream, is_gzip ? 0x1f : -15);
484 if(zres != Z_OK) {
485 ERR("inflateInit failed: %d\n", zres);
486 free(gzip_stream);
487 return ERROR_OUTOFMEMORY;
488 }
489
490 remove_header(req, L"Content-Length", FALSE);
491
492 if(req->read_size) {
493 memcpy(gzip_stream->buf, req->read_buf+req->read_pos, req->read_size);
494 gzip_stream->buf_size = req->read_size;
495 req->read_pos = req->read_size = 0;
496 }
497
498 req->read_gzip = TRUE;
499 gzip_stream->parent_stream = req->data_stream;
500 req->data_stream = &gzip_stream->stream;
501 return ERROR_SUCCESS;
502}
503
504/***********************************************************************
505 * HTTP_FreeTokens (internal)
506 *
507 * Frees table of pointers.
508 */
509static void HTTP_FreeTokens(LPWSTR * token_array)
510{
511 int i;
512 for (i = 0; token_array[i]; i++) free(token_array[i]);
513 free(token_array);
514}
515
517{
518 /* If we don't have a path we set it to root */
519 if (NULL == request->path)
520 request->path = wcsdup(L"/");
521 else /* remove \r and \n*/
522 {
523 int nLen = lstrlenW(request->path);
524 while ((nLen >0 ) && ((request->path[nLen-1] == '\r')||(request->path[nLen-1] == '\n')))
525 {
526 nLen--;
527 request->path[nLen]='\0';
528 }
529 /* Replace '\' with '/' */
530 while (nLen>0) {
531 nLen--;
532 if (request->path[nLen] == '\\') request->path[nLen]='/';
533 }
534 }
535
537 request->path, lstrlenW(request->path), L"http://", lstrlenW(L"http://") )
538 && request->path[0] != '/') /* not an absolute path ?? --> fix it !! */
539 {
540 WCHAR *fixurl = malloc((wcslen(request->path) + 2) * sizeof(WCHAR));
541 *fixurl = '/';
542 lstrcpyW(fixurl + 1, request->path);
543 free(request->path);
544 request->path = fixurl;
545 }
546}
547
549 const WCHAR *path, const WCHAR *version, BOOL use_cr)
550{
551 LPWSTR requestString;
552 DWORD len, n;
553 LPCWSTR *req;
554 UINT i;
555
556 EnterCriticalSection( &request->headers_section );
557
558 /* allocate space for an array of all the string pointers to be added */
559 len = request->nCustHeaders * 5 + 10;
560 if (!(req = malloc( len * sizeof(const WCHAR *) )))
561 {
562 LeaveCriticalSection( &request->headers_section );
563 return NULL;
564 }
565
566 /* add the verb, path and HTTP version string */
567 n = 0;
568 req[n++] = verb;
569 req[n++] = L" ";
570 req[n++] = path;
571 req[n++] = L" ";
572 req[n++] = version;
573 if (use_cr)
574 req[n++] = L"\r";
575 req[n++] = L"\n";
576
577 /* Append custom request headers */
578 for (i = 0; i < request->nCustHeaders; i++)
579 {
580 if (request->custHeaders[i].wFlags & HDR_ISREQUEST)
581 {
582 req[n++] = request->custHeaders[i].lpszField;
583 req[n++] = L": ";
584 req[n++] = request->custHeaders[i].lpszValue;
585 if (use_cr)
586 req[n++] = L"\r";
587 req[n++] = L"\n";
588
589 TRACE("Adding custom header %s (%s)\n",
590 debugstr_w(request->custHeaders[i].lpszField),
591 debugstr_w(request->custHeaders[i].lpszValue));
592 }
593 }
594 if (use_cr)
595 req[n++] = L"\r";
596 req[n++] = L"\n";
597 req[n] = NULL;
598
599 requestString = HTTP_build_req( req, 4 );
600 free( req );
601 LeaveCriticalSection( &request->headers_section );
602 return requestString;
603}
604
606{
607 const WCHAR **req;
608 WCHAR *ret, buf[14];
609 DWORD i, n = 0;
610
611 EnterCriticalSection( &request->headers_section );
612
613 if (!(req = malloc((request->nCustHeaders * 5 + 8) * sizeof(WCHAR *))))
614 {
615 LeaveCriticalSection( &request->headers_section );
616 return NULL;
617 }
618
619 if (request->status_code)
620 {
621 req[n++] = request->version;
622 swprintf(buf, ARRAY_SIZE(buf), L" %u ", request->status_code);
623 req[n++] = buf;
624 req[n++] = request->statusText;
625 if (use_cr)
626 req[n++] = L"\r";
627 req[n++] = L"\n";
628 }
629
630 for(i = 0; i < request->nCustHeaders; i++)
631 {
632 if(!(request->custHeaders[i].wFlags & HDR_ISREQUEST)
633 && wcscmp(request->custHeaders[i].lpszField, L"Status"))
634 {
635 req[n++] = request->custHeaders[i].lpszField;
636 req[n++] = L": ";
637 req[n++] = request->custHeaders[i].lpszValue;
638 if(use_cr)
639 req[n++] = L"\r";
640 req[n++] = L"\n";
641
642 TRACE("Adding custom header %s (%s)\n",
643 debugstr_w(request->custHeaders[i].lpszField),
644 debugstr_w(request->custHeaders[i].lpszValue));
645 }
646 }
647 if(use_cr)
648 req[n++] = L"\r";
649 req[n++] = L"\n";
650 req[n] = NULL;
651
652 ret = HTTP_build_req(req, 0);
653 free(req);
654 LeaveCriticalSection( &request->headers_section );
655 return ret;
656}
657
659{
660 int HeaderIndex;
661 int numCookies = 0;
662 LPHTTPHEADERW setCookieHeader;
663
665 return;
666
667 EnterCriticalSection( &request->headers_section );
668
669 while((HeaderIndex = HTTP_GetCustomHeaderIndex(request, L"Set-Cookie", numCookies++, FALSE)) != -1)
670 {
671 const WCHAR *data;
673
674 setCookieHeader = &request->custHeaders[HeaderIndex];
675
676 if (!setCookieHeader->lpszValue)
677 continue;
678
679 data = wcschr(setCookieHeader->lpszValue, '=');
680 if(!data)
681 continue;
682
683 name = substr(setCookieHeader->lpszValue, data - setCookieHeader->lpszValue);
684 data++;
686 }
687
688 LeaveCriticalSection( &request->headers_section );
689}
690
692{
693 LPWSTR str = start;
694 LPWSTR end;
695
696 while (*str == ' ')
697 str++;
698
699 if (str != start)
700 memmove(start, str, sizeof(WCHAR) * (lstrlenW(str) + 1));
701
702 end = start + lstrlenW(start) - 1;
703 while (end >= start && *end == ' ')
704 {
705 *end = '\0';
706 end--;
707 }
708}
709
710static inline BOOL is_basic_auth_value( LPCWSTR pszAuthValue, LPWSTR *pszRealm )
711{
712 static const WCHAR szBasic[] = {'B','a','s','i','c'}; /* Note: not nul-terminated */
713 static const WCHAR szRealm[] = {'r','e','a','l','m'}; /* Note: not nul-terminated */
714 BOOL is_basic;
715 is_basic = !wcsnicmp(pszAuthValue, szBasic, ARRAY_SIZE(szBasic)) &&
716 ((pszAuthValue[ARRAY_SIZE(szBasic)] == ' ') || !pszAuthValue[ARRAY_SIZE(szBasic)]);
717 if (is_basic && pszRealm)
718 {
720 LPCWSTR ptr = &pszAuthValue[ARRAY_SIZE(szBasic)];
721 LPCWSTR realm;
722 ptr++;
723 *pszRealm=NULL;
724 token = wcschr(ptr,'=');
725 if (!token)
726 return TRUE;
727 realm = ptr;
728 while (*realm == ' ')
729 realm++;
730 if(!wcsnicmp(realm, szRealm, ARRAY_SIZE(szRealm)) &&
731 (realm[ARRAY_SIZE(szRealm)] == ' ' || realm[ARRAY_SIZE(szRealm)] == '='))
732 {
733 token++;
734 while (*token == ' ')
735 token++;
736 if (*token == '\0')
737 return TRUE;
738 *pszRealm = wcsdup(token);
739 strip_spaces(*pszRealm);
740 }
741 }
742
743 return is_basic;
744}
745
747{
748 if (!authinfo) return;
749
754
755 free(authinfo->auth_data);
757 free(authinfo);
758}
759
760static UINT retrieve_cached_basic_authorization(http_request_t *req, const WCHAR *host, const WCHAR *realm, char **auth_data)
761{
763 UINT rc = 0;
764
765 TRACE("Looking for authorization for %s:%s\n",debugstr_w(host),debugstr_w(realm));
766
769 {
770 if (!wcsicmp(host, ad->host) && (!realm || !wcscmp(realm, ad->realm)))
771 {
772 char *colon;
774
775 TRACE("Authorization found in cache\n");
776 *auth_data = malloc(ad->authorizationLen);
777 memcpy(*auth_data,ad->authorization,ad->authorizationLen);
778 rc = ad->authorizationLen;
779
780 /* update session username and password to reflect current credentials */
781 colon = strchr(ad->authorization, ':');
782 length = colon - ad->authorization;
783
784 free(req->session->userName);
785 free(req->session->password);
786
788 length++;
790 break;
791 }
792 }
794 return rc;
795}
796
797static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data, UINT auth_data_len)
798{
799 struct list *cursor;
801
802 TRACE("caching authorization for %s:%s = %s\n",debugstr_w(host),debugstr_w(realm),debugstr_an(auth_data,auth_data_len));
803
806 {
808 if (!wcsicmp(host,check->host) && !wcscmp(realm,check->realm))
809 {
810 ad = check;
811 break;
812 }
813 }
814
815 if (ad)
816 {
817 TRACE("Found match in cache, replacing\n");
818 free(ad->authorization);
819 ad->authorization = malloc(auth_data_len);
820 memcpy(ad->authorization, auth_data, auth_data_len);
821 ad->authorizationLen = auth_data_len;
822 }
823 else
824 {
825 ad = malloc(sizeof(basicAuthorizationData));
826 ad->host = wcsdup(host);
827 ad->realm = wcsdup(realm);
828 ad->authorization = malloc(auth_data_len);
829 memcpy(ad->authorization, auth_data, auth_data_len);
830 ad->authorizationLen = auth_data_len;
832 TRACE("authorization cached\n");
833 }
835}
836
838 SEC_WINNT_AUTH_IDENTITY_W *nt_auth_identity)
839{
841
842 TRACE("Looking for authorization for %s:%s\n", debugstr_w(host), debugstr_w(scheme));
843
846 if(!wcsicmp(host, ad->host) && !wcsicmp(scheme, ad->scheme)) {
847 TRACE("Authorization found in cache\n");
848
849 nt_auth_identity->User = wcsdup(ad->user);
850 nt_auth_identity->Password = wcsdup(ad->password);
851 nt_auth_identity->Domain = malloc(sizeof(WCHAR) * ad->domain_len);
852 if(!nt_auth_identity->User || !nt_auth_identity->Password ||
853 (!nt_auth_identity->Domain && ad->domain_len)) {
854 free(nt_auth_identity->User);
855 free(nt_auth_identity->Password);
856 free(nt_auth_identity->Domain);
857 break;
858 }
859
860 nt_auth_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
861 nt_auth_identity->UserLength = ad->user_len;
862 nt_auth_identity->PasswordLength = ad->password_len;
863 memcpy(nt_auth_identity->Domain, ad->domain, sizeof(WCHAR)*ad->domain_len);
864 nt_auth_identity->DomainLength = ad->domain_len;
866 return TRUE;
867 }
868 }
870
871 return FALSE;
872}
873
875 SEC_WINNT_AUTH_IDENTITY_W *nt_auth_identity)
876{
878 BOOL found = FALSE;
879
880 TRACE("Caching authorization for %s:%s\n", debugstr_w(host), debugstr_w(scheme));
881
884 if(!wcsicmp(host, ad->host) && !wcsicmp(scheme, ad->scheme)) {
885 found = TRUE;
886 break;
887 }
888
889 if(found) {
890 free(ad->user);
891 free(ad->password);
892 free(ad->domain);
893 } else {
894 ad = malloc(sizeof(authorizationData));
895 if(!ad) {
897 return;
898 }
899
900 ad->host = wcsdup(host);
901 ad->scheme = wcsdup(scheme);
903 }
904
905 ad->user = strndupW(nt_auth_identity->User, nt_auth_identity->UserLength);
906 ad->password = strndupW(nt_auth_identity->Password, nt_auth_identity->PasswordLength);
907 ad->domain = strndupW(nt_auth_identity->Domain, nt_auth_identity->DomainLength);
908 ad->user_len = nt_auth_identity->UserLength;
909 ad->password_len = nt_auth_identity->PasswordLength;
910 ad->domain_len = nt_auth_identity->DomainLength;
911
912 if(!ad->host || !ad->scheme || !ad->user || !ad->password
913 || (nt_auth_identity->Domain && !ad->domain)) {
914 free(ad->host);
915 free(ad->scheme);
916 free(ad->user);
917 free(ad->password);
918 free(ad->domain);
919 list_remove(&ad->entry);
920 free(ad);
921 }
922
924}
925
927{
928 authorizationData *ad, *sa_safe;
929 basicAuthorizationData *basic, *basic_safe;
930
932
934 {
935 free(basic->host);
936 free(basic->realm);
937 free(basic->authorization);
938
939 list_remove(&basic->entry);
940 free(basic);
941 }
942
944 {
945 free(ad->host);
946 free(ad->scheme);
947 free(ad->user);
948 free(ad->password);
949 free(ad->domain);
950 list_remove(&ad->entry);
951 free(ad);
952 }
953
955}
956
958 struct HttpAuthInfo **ppAuthInfo,
959 LPWSTR domain_and_username, LPWSTR password,
960 LPWSTR host )
961{
962 SECURITY_STATUS sec_status;
963 struct HttpAuthInfo *pAuthInfo = *ppAuthInfo;
964 BOOL first = FALSE;
965 LPWSTR szRealm = NULL;
966
967 TRACE("%s\n", debugstr_w(pszAuthValue));
968
969 if (!pAuthInfo)
970 {
972
973 first = TRUE;
974 pAuthInfo = malloc(sizeof(*pAuthInfo));
975 if (!pAuthInfo)
976 return FALSE;
977
978 SecInvalidateHandle(&pAuthInfo->cred);
979 SecInvalidateHandle(&pAuthInfo->ctx);
980 memset(&pAuthInfo->exp, 0, sizeof(pAuthInfo->exp));
981 pAuthInfo->attr = 0;
982 pAuthInfo->auth_data = NULL;
983 pAuthInfo->auth_data_len = 0;
984 pAuthInfo->finished = FALSE;
985
986 if (is_basic_auth_value(pszAuthValue,NULL))
987 {
988 pAuthInfo->scheme = wcsdup(L"Basic");
989 if (!pAuthInfo->scheme)
990 {
991 free(pAuthInfo);
992 return FALSE;
993 }
994 }
995 else
996 {
997 PVOID pAuthData;
998 SEC_WINNT_AUTH_IDENTITY_W nt_auth_identity;
999
1000 pAuthInfo->scheme = wcsdup(pszAuthValue);
1001 if (!pAuthInfo->scheme)
1002 {
1003 free(pAuthInfo);
1004 return FALSE;
1005 }
1006
1007 if (domain_and_username)
1008 {
1009 WCHAR *user = wcschr(domain_and_username, '\\');
1010 WCHAR *domain = domain_and_username;
1011
1012 /* FIXME: make sure scheme accepts SEC_WINNT_AUTH_IDENTITY before calling AcquireCredentialsHandle */
1013
1014 pAuthData = &nt_auth_identity;
1015
1016 if (user) user++;
1017 else
1018 {
1019 user = domain_and_username;
1020 domain = NULL;
1021 }
1022
1023 nt_auth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1024 nt_auth_identity.User = user;
1025 nt_auth_identity.UserLength = lstrlenW(nt_auth_identity.User);
1026 nt_auth_identity.Domain = domain;
1027 nt_auth_identity.DomainLength = domain ? user - domain - 1 : 0;
1028 nt_auth_identity.Password = password;
1029 nt_auth_identity.PasswordLength = lstrlenW(nt_auth_identity.Password);
1030
1031 cache_authorization(host, pAuthInfo->scheme, &nt_auth_identity);
1032 }
1033 else if(retrieve_cached_authorization(host, pAuthInfo->scheme, &nt_auth_identity))
1034 pAuthData = &nt_auth_identity;
1035 else
1036 /* use default credentials */
1037 pAuthData = NULL;
1038
1039 sec_status = AcquireCredentialsHandleW(NULL, pAuthInfo->scheme,
1041 pAuthData, NULL,
1042 NULL, &pAuthInfo->cred,
1043 &exp);
1044
1045 if(pAuthData && !domain_and_username) {
1046 free(nt_auth_identity.User);
1047 free(nt_auth_identity.Domain);
1048 free(nt_auth_identity.Password);
1049 }
1050
1051 if (sec_status == SEC_E_OK)
1052 {
1053 PSecPkgInfoW sec_pkg_info;
1054 sec_status = QuerySecurityPackageInfoW(pAuthInfo->scheme, &sec_pkg_info);
1055 if (sec_status == SEC_E_OK)
1056 {
1057 pAuthInfo->max_token = sec_pkg_info->cbMaxToken;
1058 FreeContextBuffer(sec_pkg_info);
1059 }
1060 }
1061 if (sec_status != SEC_E_OK)
1062 {
1063 WARN("AcquireCredentialsHandleW for scheme %s failed with error 0x%08lx\n",
1064 debugstr_w(pAuthInfo->scheme), sec_status);
1065 free(pAuthInfo->scheme);
1066 free(pAuthInfo);
1067 return FALSE;
1068 }
1069 }
1070 *ppAuthInfo = pAuthInfo;
1071 }
1072 else if (pAuthInfo->finished)
1073 return FALSE;
1074
1075 if ((lstrlenW(pszAuthValue) < lstrlenW(pAuthInfo->scheme)) ||
1076 wcsnicmp(pszAuthValue, pAuthInfo->scheme, lstrlenW(pAuthInfo->scheme)))
1077 {
1078 ERR("authentication scheme changed from %s to %s\n",
1079 debugstr_w(pAuthInfo->scheme), debugstr_w(pszAuthValue));
1080 return FALSE;
1081 }
1082
1083 if (is_basic_auth_value(pszAuthValue,&szRealm))
1084 {
1085 int userlen;
1086 int passlen;
1087 char *auth_data = NULL;
1088 UINT auth_data_len = 0;
1089
1090 TRACE("basic authentication realm %s\n",debugstr_w(szRealm));
1091
1092 if (!domain_and_username)
1093 {
1094 if (host && szRealm)
1096 if (auth_data_len == 0)
1097 {
1098 free(szRealm);
1099 return FALSE;
1100 }
1101 }
1102 else
1103 {
1104 userlen = WideCharToMultiByte(CP_UTF8, 0, domain_and_username, lstrlenW(domain_and_username), NULL, 0, NULL, NULL);
1106
1107 /* length includes a nul terminator, which will be re-used for the ':' */
1108 auth_data = malloc(userlen + 1 + passlen);
1109 if (!auth_data)
1110 {
1111 free(szRealm);
1112 return FALSE;
1113 }
1114
1115 WideCharToMultiByte(CP_UTF8, 0, domain_and_username, -1, auth_data, userlen, NULL, NULL);
1116 auth_data[userlen] = ':';
1117 WideCharToMultiByte(CP_UTF8, 0, password, -1, &auth_data[userlen+1], passlen, NULL, NULL);
1118 auth_data_len = userlen + 1 + passlen;
1119 if (host && szRealm)
1121 }
1122
1123 pAuthInfo->auth_data = auth_data;
1124 pAuthInfo->auth_data_len = auth_data_len;
1125 pAuthInfo->finished = TRUE;
1126 free(szRealm);
1127 return TRUE;
1128 }
1129 else
1130 {
1131 LPCWSTR pszAuthData;
1132 SecBufferDesc out_desc, in_desc;
1133 SecBuffer out, in;
1134 unsigned char *buffer;
1137
1138 in.BufferType = SECBUFFER_TOKEN;
1139 in.cbBuffer = 0;
1140 in.pvBuffer = NULL;
1141
1142 in_desc.ulVersion = 0;
1143 in_desc.cBuffers = 1;
1144 in_desc.pBuffers = &in;
1145
1146 pszAuthData = pszAuthValue + lstrlenW(pAuthInfo->scheme);
1147 if (*pszAuthData == ' ')
1148 {
1149 pszAuthData++;
1150 in.cbBuffer = HTTP_DecodeBase64(pszAuthData, NULL);
1151 in.pvBuffer = malloc(in.cbBuffer);
1152 HTTP_DecodeBase64(pszAuthData, in.pvBuffer);
1153 }
1154
1155 buffer = malloc(pAuthInfo->max_token);
1156
1157 out.BufferType = SECBUFFER_TOKEN;
1158 out.cbBuffer = pAuthInfo->max_token;
1159 out.pvBuffer = buffer;
1160
1161 out_desc.ulVersion = 0;
1162 out_desc.cBuffers = 1;
1163 out_desc.pBuffers = &out;
1164
1165 sec_status = InitializeSecurityContextW(first ? &pAuthInfo->cred : NULL,
1166 first ? NULL : &pAuthInfo->ctx,
1167 first ? request->server->name : NULL,
1168 context_req, 0, SECURITY_NETWORK_DREP,
1169 in.pvBuffer ? &in_desc : NULL,
1170 0, &pAuthInfo->ctx, &out_desc,
1171 &pAuthInfo->attr, &pAuthInfo->exp);
1172 if (sec_status == SEC_E_OK)
1173 {
1174 pAuthInfo->finished = TRUE;
1175 pAuthInfo->auth_data = out.pvBuffer;
1176 pAuthInfo->auth_data_len = out.cbBuffer;
1177 TRACE("sending last auth packet\n");
1178 }
1179 else if (sec_status == SEC_I_CONTINUE_NEEDED)
1180 {
1181 pAuthInfo->auth_data = out.pvBuffer;
1182 pAuthInfo->auth_data_len = out.cbBuffer;
1183 TRACE("sending next auth packet\n");
1184 }
1185 else
1186 {
1187 ERR("InitializeSecurityContextW returned error 0x%08lx\n", sec_status);
1188 free(out.pvBuffer);
1189 destroy_authinfo(pAuthInfo);
1190 *ppAuthInfo = NULL;
1191 return FALSE;
1192 }
1193 }
1194
1195 return TRUE;
1196}
1197
1198/***********************************************************************
1199 * HTTP_HttpAddRequestHeadersW (internal)
1200 */
1202 LPCWSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
1203{
1204 LPWSTR lpszStart;
1205 LPWSTR lpszEnd;
1206 LPWSTR buffer;
1208
1209 TRACE("copying header: %s\n", debugstr_wn(lpszHeader, dwHeaderLength));
1210
1211 if( dwHeaderLength == ~0U )
1212 len = lstrlenW(lpszHeader);
1213 else
1214 len = dwHeaderLength;
1215 buffer = malloc(sizeof(WCHAR) * (len + 1));
1216 lstrcpynW( buffer, lpszHeader, len + 1);
1217
1218 lpszStart = buffer;
1219
1220 do
1221 {
1222 LPWSTR * pFieldAndValue;
1223
1224 lpszEnd = lpszStart;
1225
1226 while (*lpszEnd != '\0')
1227 {
1228 if (*lpszEnd == '\r' || *lpszEnd == '\n')
1229 break;
1230 lpszEnd++;
1231 }
1232
1233 if (*lpszStart == '\0')
1234 break;
1235
1236 if (*lpszEnd == '\r' || *lpszEnd == '\n')
1237 {
1238 *lpszEnd = '\0';
1239 lpszEnd++; /* Jump over newline */
1240 }
1241 TRACE("interpreting header %s\n", debugstr_w(lpszStart));
1242 if (*lpszStart == '\0')
1243 {
1244 /* Skip 0-length headers */
1245 lpszStart = lpszEnd;
1247 continue;
1248 }
1249 pFieldAndValue = HTTP_InterpretHttpHeader(lpszStart);
1250 if (pFieldAndValue)
1251 {
1252 res = HTTP_ProcessHeader(request, pFieldAndValue[0],
1253 pFieldAndValue[1], dwModifier | HTTP_ADDHDR_FLAG_REQ);
1254 HTTP_FreeTokens(pFieldAndValue);
1255 }
1256
1257 lpszStart = lpszEnd;
1258 } while (res == ERROR_SUCCESS);
1259
1260 free(buffer);
1261 return res;
1262}
1263
1264/***********************************************************************
1265 * HttpAddRequestHeadersW (WININET.@)
1266 *
1267 * Adds one or more HTTP header to the request handler
1268 *
1269 * NOTE
1270 * On Windows if dwHeaderLength includes the trailing '\0', then
1271 * HttpAddRequestHeadersW() adds it too. However this results in an
1272 * invalid HTTP header which is rejected by some servers so we probably
1273 * don't need to match Windows on that point.
1274 *
1275 * RETURNS
1276 * TRUE on success
1277 * FALSE on failure
1278 *
1279 */
1281 LPCWSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
1282{
1285
1286 TRACE("%p, %s, %lu, %08lx\n", hHttpRequest, debugstr_wn(lpszHeader, dwHeaderLength), dwHeaderLength, dwModifier);
1287
1288 if (!lpszHeader)
1289 return TRUE;
1290
1291 request = (http_request_t*) get_handle_object( hHttpRequest );
1292 if (request && request->hdr.htype == WH_HHTTPREQ)
1293 res = HTTP_HttpAddRequestHeadersW( request, lpszHeader, dwHeaderLength, dwModifier );
1294 if( request )
1296
1297 if(res != ERROR_SUCCESS)
1299 return res == ERROR_SUCCESS;
1300}
1301
1302/***********************************************************************
1303 * HttpAddRequestHeadersA (WININET.@)
1304 *
1305 * Adds one or more HTTP header to the request handler
1306 *
1307 * RETURNS
1308 * TRUE on success
1309 * FALSE on failure
1310 *
1311 */
1313 LPCSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
1314{
1315 WCHAR *headers = NULL;
1316 BOOL r;
1317
1318 TRACE("%p, %s, %lu, %08lx\n", hHttpRequest, debugstr_an(lpszHeader, dwHeaderLength), dwHeaderLength, dwModifier);
1319
1320 if(lpszHeader)
1321 headers = strndupAtoW(lpszHeader, dwHeaderLength, &dwHeaderLength);
1322
1323 r = HttpAddRequestHeadersW(hHttpRequest, headers, dwHeaderLength, dwModifier);
1324
1325 free(headers);
1326 return r;
1327}
1328
1329static void free_accept_types( WCHAR **accept_types )
1330{
1331 WCHAR *ptr, **types = accept_types;
1332
1333 if (!types) return;
1334 while ((ptr = *types))
1335 {
1336 free(ptr);
1337 types++;
1338 }
1339 free(accept_types);
1340}
1341
1342static WCHAR **convert_accept_types( const char **accept_types )
1343{
1344 unsigned int count;
1345 const char **types = accept_types;
1346 WCHAR **typesW;
1347 BOOL invalid_pointer = FALSE;
1348
1349 if (!types) return NULL;
1350 count = 0;
1351 while (*types)
1352 {
1353 __TRY
1354 {
1355 /* find out how many there are */
1356 if (*types && **types)
1357 {
1358 TRACE("accept type: %s\n", debugstr_a(*types));
1359 count++;
1360 }
1361 }
1363 {
1364 WARN("invalid accept type pointer\n");
1365 invalid_pointer = TRUE;
1366 }
1367 __ENDTRY;
1368 types++;
1369 }
1370 if (invalid_pointer) return NULL;
1371 if (!(typesW = malloc(sizeof(WCHAR *) * (count + 1)))) return NULL;
1372 count = 0;
1373 types = accept_types;
1374 while (*types)
1375 {
1376 if (*types && **types) typesW[count++] = strdupAtoW(*types);
1377 types++;
1378 }
1379 typesW[count] = NULL;
1380 return typesW;
1381}
1382
1383/***********************************************************************
1384 * HttpOpenRequestA (WININET.@)
1385 *
1386 * Open a HTTP request handle
1387 *
1388 * RETURNS
1389 * HINTERNET a HTTP request handle on success
1390 * NULL on failure
1391 *
1392 */
1394 LPCSTR lpszVerb, LPCSTR lpszObjectName, LPCSTR lpszVersion,
1395 LPCSTR lpszReferrer , LPCSTR *lpszAcceptTypes,
1396 DWORD dwFlags, DWORD_PTR dwContext)
1397{
1398 LPWSTR szVerb = NULL, szObjectName = NULL;
1399 LPWSTR szVersion = NULL, szReferrer = NULL, *szAcceptTypes = NULL;
1400 HINTERNET rc = NULL;
1401
1402 TRACE("(%p, %s, %s, %s, %s, %p, %08lx, %08Ix)\n", hHttpSession,
1403 debugstr_a(lpszVerb), debugstr_a(lpszObjectName),
1404 debugstr_a(lpszVersion), debugstr_a(lpszReferrer), lpszAcceptTypes,
1405 dwFlags, dwContext);
1406
1407 if (lpszVerb)
1408 {
1409 szVerb = strdupAtoW(lpszVerb);
1410 if ( !szVerb )
1411 goto end;
1412 }
1413
1414 if (lpszObjectName)
1415 {
1416 szObjectName = strdupAtoW(lpszObjectName);
1417 if ( !szObjectName )
1418 goto end;
1419 }
1420
1421 if (lpszVersion)
1422 {
1423 szVersion = strdupAtoW(lpszVersion);
1424 if ( !szVersion )
1425 goto end;
1426 }
1427
1428 if (lpszReferrer)
1429 {
1430 szReferrer = strdupAtoW(lpszReferrer);
1431 if ( !szReferrer )
1432 goto end;
1433 }
1434
1435 szAcceptTypes = convert_accept_types( lpszAcceptTypes );
1436 rc = HttpOpenRequestW(hHttpSession, szVerb, szObjectName, szVersion, szReferrer,
1437 (const WCHAR **)szAcceptTypes, dwFlags, dwContext);
1438
1439end:
1440 free_accept_types(szAcceptTypes);
1441 free(szReferrer);
1442 free(szVersion);
1443 free(szObjectName);
1444 free(szVerb);
1445 return rc;
1446}
1447
1448/***********************************************************************
1449 * HTTP_EncodeBase64
1450 */
1451static UINT HTTP_EncodeBase64( LPCSTR bin, unsigned int len, LPWSTR base64 )
1452{
1453 UINT n = 0, x;
1454 static const CHAR HTTP_Base64Enc[] =
1455 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1456
1457 while( len > 0 )
1458 {
1459 /* first 6 bits, all from bin[0] */
1460 base64[n++] = HTTP_Base64Enc[(bin[0] & 0xfc) >> 2];
1461 x = (bin[0] & 3) << 4;
1462
1463 /* next 6 bits, 2 from bin[0] and 4 from bin[1] */
1464 if( len == 1 )
1465 {
1466 base64[n++] = HTTP_Base64Enc[x];
1467 base64[n++] = '=';
1468 base64[n++] = '=';
1469 break;
1470 }
1471 base64[n++] = HTTP_Base64Enc[ x | ( (bin[1]&0xf0) >> 4 ) ];
1472 x = ( bin[1] & 0x0f ) << 2;
1473
1474 /* next 6 bits 4 from bin[1] and 2 from bin[2] */
1475 if( len == 2 )
1476 {
1477 base64[n++] = HTTP_Base64Enc[x];
1478 base64[n++] = '=';
1479 break;
1480 }
1481 base64[n++] = HTTP_Base64Enc[ x | ( (bin[2]&0xc0 ) >> 6 ) ];
1482
1483 /* last 6 bits, all from bin [2] */
1484 base64[n++] = HTTP_Base64Enc[ bin[2] & 0x3f ];
1485 bin += 3;
1486 len -= 3;
1487 }
1488 base64[n] = 0;
1489 return n;
1490}
1491
1492static const signed char HTTP_Base64Dec[] =
1493{
1494 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00 */
1495 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10 */
1496 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20 */
1497 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30 */
1498 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40 */
1499 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50 */
1500 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60 */
1501 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 /* 0x70 */
1502};
1503
1504/***********************************************************************
1505 * HTTP_DecodeBase64
1506 */
1508{
1509 unsigned int n = 0;
1510
1511 while(*base64)
1512 {
1513 signed char in[4];
1514
1515 if (base64[0] >= ARRAY_SIZE(HTTP_Base64Dec) ||
1516 ((in[0] = HTTP_Base64Dec[base64[0]]) == -1) ||
1517 base64[1] >= ARRAY_SIZE(HTTP_Base64Dec) ||
1518 ((in[1] = HTTP_Base64Dec[base64[1]]) == -1))
1519 {
1520 WARN("invalid base64: %s\n", debugstr_w(base64));
1521 return 0;
1522 }
1523 if (bin)
1524 bin[n] = (unsigned char) (in[0] << 2 | in[1] >> 4);
1525 n++;
1526
1527 if ((base64[2] == '=') && (base64[3] == '='))
1528 break;
1529 if (base64[2] > ARRAY_SIZE(HTTP_Base64Dec) ||
1530 ((in[2] = HTTP_Base64Dec[base64[2]]) == -1))
1531 {
1532 WARN("invalid base64: %s\n", debugstr_w(&base64[2]));
1533 return 0;
1534 }
1535 if (bin)
1536 bin[n] = (unsigned char) (in[1] << 4 | in[2] >> 2);
1537 n++;
1538
1539 if (base64[3] == '=')
1540 break;
1541 if (base64[3] > ARRAY_SIZE(HTTP_Base64Dec) ||
1542 ((in[3] = HTTP_Base64Dec[base64[3]]) == -1))
1543 {
1544 WARN("invalid base64: %s\n", debugstr_w(&base64[3]));
1545 return 0;
1546 }
1547 if (bin)
1548 bin[n] = (unsigned char) (((in[2] << 6) & 0xc0) | in[3]);
1549 n++;
1550
1551 base64 += 4;
1552 }
1553
1554 return n;
1555}
1556
1557static WCHAR *encode_auth_data( const WCHAR *scheme, const char *data, UINT data_len )
1558{
1559 WCHAR *ret;
1560 UINT len, scheme_len = lstrlenW( scheme );
1561
1562 /* scheme + space + base64 encoded data (3/2/1 bytes data -> 4 bytes of characters) */
1563 len = scheme_len + 1 + ((data_len + 2) * 4) / 3;
1564 if (!(ret = malloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
1565 memcpy( ret, scheme, scheme_len * sizeof(WCHAR) );
1566 ret[scheme_len] = ' ';
1567 HTTP_EncodeBase64( data, data_len, ret + scheme_len + 1 );
1568 return ret;
1569}
1570
1571
1572/***********************************************************************
1573 * HTTP_InsertAuthorization
1574 *
1575 * Insert or delete the authorization field in the request header.
1576 */
1578{
1579 WCHAR *host, *authorization = NULL;
1580
1581 if (pAuthInfo)
1582 {
1583 if (pAuthInfo->auth_data_len)
1584 {
1585 if (!(authorization = encode_auth_data(pAuthInfo->scheme, pAuthInfo->auth_data, pAuthInfo->auth_data_len)))
1586 return FALSE;
1587
1588 /* clear the data as it isn't valid now that it has been sent to the
1589 * server, unless it's Basic authentication which doesn't do
1590 * connection tracking */
1591 if (wcsicmp(pAuthInfo->scheme, L"Basic"))
1592 {
1593 free(pAuthInfo->auth_data);
1594 pAuthInfo->auth_data = NULL;
1595 pAuthInfo->auth_data_len = 0;
1596 }
1597 }
1598
1599 TRACE("Inserting authorization: %s\n", debugstr_w(authorization));
1600
1601 HTTP_ProcessHeader(request, header, authorization,
1603 free(authorization);
1604 }
1605 else
1606 {
1607 UINT data_len;
1608 char *data;
1609
1610 /* Don't use cached credentials when a username or Authorization was specified */
1611 if ((request->session->userName && request->session->userName[0]) || wcscmp(header, L"Authorization"))
1612 return TRUE;
1613
1614 if (!(host = get_host_header(request)))
1615 return TRUE;
1616
1618 {
1619 TRACE("Found cached basic authorization for %s\n", debugstr_w(host));
1620
1621 if (!(authorization = encode_auth_data(L"Basic", data, data_len)))
1622 {
1623 free(data);
1624 free(host);
1625 return FALSE;
1626 }
1627
1628 TRACE("Inserting authorization: %s\n", debugstr_w(authorization));
1629
1630 HTTP_ProcessHeader(request, header, authorization,
1632 free(data);
1633 free(authorization);
1634 }
1635 free(host);
1636 }
1637 return TRUE;
1638}
1639
1641{
1642 DWORD size, len;
1643 WCHAR *url;
1644
1646 size = len + lstrlenW(req->path) + 1;
1647 if(*req->path != '/')
1648 size++;
1649 url = malloc(size * sizeof(WCHAR));
1650 if(!url)
1651 return NULL;
1652
1653 memcpy(url, req->server->scheme_host_port, len*sizeof(WCHAR));
1654 if(*req->path != '/')
1655 url[len++] = '/';
1656
1657 lstrcpyW(url+len, req->path);
1658
1659 TRACE("url=%s\n", debugstr_w(url));
1660 return url;
1661}
1662
1664{
1665 const WCHAR *dot, *ptr;
1666 int len;
1667
1668 if(domain.len == ARRAY_SIZE(L"<local>")-1 && !wcsnicmp(domain.str, L"<local>", domain.len) && !wcschr(server, '.' ))
1669 return TRUE;
1670
1671 if(domain.len && *domain.str != '*')
1672 return domain.len == lstrlenW(server) && !wcsnicmp(server, domain.str, domain.len);
1673
1674 if(domain.len < 2 || domain.str[1] != '.')
1675 return FALSE;
1676
1677 /* For a hostname to match a wildcard, the last domain must match
1678 * the wildcard exactly. E.g. if the wildcard is *.a.b, and the
1679 * hostname is www.foo.a.b, it matches, but a.b does not.
1680 */
1681 dot = wcschr(server, '.');
1682 if(!dot)
1683 return FALSE;
1684
1685 len = lstrlenW(dot + 1);
1686 if(len < domain.len - 2)
1687 return FALSE;
1688
1689 /* The server's domain is longer than the wildcard, so it
1690 * could be a subdomain. Compare the last portion of the
1691 * server's domain.
1692 */
1693 ptr = dot + 1 + len - domain.len + 2;
1694 if(!wcsnicmp(ptr, domain.str+2, domain.len-2))
1695 /* This is only a match if the preceding character is
1696 * a '.', i.e. that it is a matching domain. E.g.
1697 * if domain is '*.b.c' and server is 'www.ab.c' they
1698 * do not match.
1699 */
1700 return *(ptr - 1) == '.';
1701
1702 return len == domain.len-2 && !wcsnicmp(dot + 1, domain.str + 2, len);
1703}
1704
1706{
1707 LPCWSTR ptr;
1708 BOOL ret = FALSE;
1709
1710 if (!lpwai->proxyBypass) return FALSE;
1711 ptr = lpwai->proxyBypass;
1712 while(1) {
1713 LPCWSTR tmp = ptr;
1714
1715 ptr = wcschr( ptr, ';' );
1716 if (!ptr)
1717 ptr = wcschr( tmp, ' ' );
1718 if (!ptr)
1719 ptr = tmp + lstrlenW(tmp);
1720 ret = HTTP_DomainMatches( server, substr(tmp, ptr-tmp) );
1721 if (ret || !*ptr)
1722 break;
1723 ptr++;
1724 }
1725 return ret;
1726}
1727
1728/***********************************************************************
1729 * HTTP_DealWithProxy
1730 */
1732{
1733 static WCHAR szNul[] = L"";
1734 URL_COMPONENTSW UrlComponents = { sizeof(UrlComponents) };
1735 server_t *new_server = NULL;
1736 WCHAR *proxy;
1737
1739 if(!proxy)
1740 return FALSE;
1742 proxy, lstrlenW(L"http://"), L"http://", lstrlenW(L"http://"))) {
1743 WCHAR *proxy_url = malloc(wcslen(proxy) * sizeof(WCHAR) + sizeof(L"http://"));
1744 if(!proxy_url) {
1745 free(proxy);
1746 return FALSE;
1747 }
1748 lstrcpyW(proxy_url, L"http://");
1749 lstrcatW(proxy_url, proxy);
1750 free(proxy);
1751 proxy = proxy_url;
1752 }
1753
1754 UrlComponents.dwHostNameLength = 1;
1755 if(InternetCrackUrlW(proxy, 0, 0, &UrlComponents) && UrlComponents.dwHostNameLength) {
1756 if( !request->path )
1757 request->path = szNul;
1758
1759 new_server = get_server(substr(UrlComponents.lpszHostName, UrlComponents.dwHostNameLength),
1760 UrlComponents.nPort, UrlComponents.nScheme == INTERNET_SCHEME_HTTPS, TRUE);
1761 }
1762 free(proxy);
1763 if(!new_server)
1764 return FALSE;
1765
1766 request->proxy = new_server;
1767
1768 TRACE("proxy server=%s port=%d\n", debugstr_w(new_server->name), new_server->port);
1769 return TRUE;
1770}
1771
1773{
1774 server_t *server = request->proxy ? request->proxy : request->server;
1775 int addr_len;
1776
1777 if(server->addr_len)
1778 return ERROR_SUCCESS;
1779
1782 server->name,
1783 (lstrlenW(server->name)+1) * sizeof(WCHAR));
1784
1785 addr_len = sizeof(server->addr);
1786 if (!GetAddress(server->name, server->port, (SOCKADDR*)&server->addr, &addr_len, server->addr_str))
1788
1789 server->addr_len = addr_len;
1792 server->addr_str, strlen(server->addr_str)+1);
1793
1794 TRACE("resolved %s to %s\n", debugstr_w(server->name), server->addr_str);
1795 return ERROR_SUCCESS;
1796}
1797
1799{
1800 const WCHAR *host, *scheme;
1801 WCHAR *buf, *ptr;
1802 size_t len;
1803
1804 host = req->server->canon_host_port;
1805
1806 if (req->server->is_https)
1807 scheme = L"https://";
1808 else
1809 scheme = L"http://";
1810
1811 len = lstrlenW(scheme) + lstrlenW(host) + (req->path[0] != '/' ? 1 : 0) + lstrlenW(req->path);
1812 ptr = buf = malloc((len + 1) * sizeof(WCHAR));
1813 if(buf) {
1815 ptr += lstrlenW(ptr);
1816
1817 lstrcpyW(ptr, host);
1818 ptr += lstrlenW(ptr);
1819
1820 if(req->path[0] != '/')
1821 *ptr++ = '/';
1822
1823 lstrcpyW(ptr, req->path);
1824 ptr += lstrlenW(ptr);
1825 *ptr = 0;
1826 }
1827
1828 return buf;
1829}
1830
1831
1832/***********************************************************************
1833 * HTTPREQ_Destroy (internal)
1834 *
1835 * Deallocate request handle
1836 *
1837 */
1839{
1841 DWORD i;
1842
1843 TRACE("\n");
1844
1845 if(request->hCacheFile)
1846 CloseHandle(request->hCacheFile);
1847 if(request->req_file)
1848 req_file_release(request->req_file);
1849
1850 request->headers_section.DebugInfo->Spare[0] = 0;
1851 DeleteCriticalSection( &request->headers_section );
1852 request->read_section.DebugInfo->Spare[0] = 0;
1853 DeleteCriticalSection( &request->read_section );
1854 WININET_Release(&request->session->hdr);
1855
1856 destroy_authinfo(request->authInfo);
1857 destroy_authinfo(request->proxyAuthInfo);
1858
1859 if(request->server)
1860 server_release(request->server);
1861 if(request->proxy)
1862 server_release(request->proxy);
1863
1864 free(request->path);
1865 free(request->verb);
1867 free(request->statusText);
1868
1869 for (i = 0; i < request->nCustHeaders; i++)
1870 {
1871 free(request->custHeaders[i].lpszField);
1872 free(request->custHeaders[i].lpszValue);
1873 }
1874 destroy_data_stream(request->data_stream);
1875 free(request->custHeaders);
1876}
1877
1879{
1880 TRACE("%p %p %x\n",req, req->netconn, reuse);
1881
1882 if(!is_valid_netconn(req->netconn))
1883 return;
1884
1885 if(reuse && req->netconn->keep_alive) {
1886 BOOL run_collector;
1887
1889
1892 req->netconn = NULL;
1893
1894 run_collector = !collector_running;
1896
1898
1899 if(run_collector) {
1900 HANDLE thread = NULL;
1902
1903 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR*)WININET_hModule, &module);
1904 if(module)
1906 if(!thread) {
1910
1911 if(module)
1913 }
1914 else
1916 }
1917 return;
1918 }
1919
1922
1923 close_netconn(req->netconn);
1924
1927}
1928
1929static BOOL has_token(const WCHAR *str, const WCHAR *token)
1930{
1931 UINT len = wcslen(token);
1932 const WCHAR *next;
1933
1934 for (; *str; str = next + wcsspn(next, L" ,"))
1935 {
1936 next = str + wcscspn(str, L" ,");
1937 if (next - str != len) continue;
1938 if (wcsnicmp(str, token, len)) continue;
1939 return TRUE;
1940 }
1941
1942 return FALSE;
1943}
1944
1946{
1947 return !wcsicmp(version, L"HTTP/1.1") ? !has_token(connection, L"Close")
1948 : has_token(connection, L"Keep-Alive");
1949}
1950
1952{
1953 WCHAR szVersion[10];
1954 WCHAR szConnectionResponse[20];
1955 DWORD dwBufferSize = sizeof(szVersion);
1956
1957 /* as per RFC 2068, S8.1.2.1, if the client is HTTP/1.1 then assume that
1958 * the connection is keep-alive by default */
1960 *szVersion = 0;
1961
1962 dwBufferSize = sizeof(szConnectionResponse);
1963 if (HTTP_HttpQueryInfoW(request, HTTP_QUERY_PROXY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL) != ERROR_SUCCESS &&
1964 HTTP_HttpQueryInfoW(request, HTTP_QUERY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL) != ERROR_SUCCESS)
1965 *szConnectionResponse = 0;
1966
1967 return has_keep_alive(szVersion, szConnectionResponse);
1968}
1969
1971{
1973
1975}
1976
1977static DWORD str_to_buffer(const WCHAR *str, void *buffer, DWORD *size, BOOL unicode)
1978{
1979 int len;
1980 if (unicode)
1981 {
1982 WCHAR *buf = buffer;
1983
1984 if (str) len = lstrlenW(str);
1985 else len = 0;
1986 if (*size < (len + 1) * sizeof(WCHAR))
1987 {
1988 *size = (len + 1) * sizeof(WCHAR);
1990 }
1991 if (str) lstrcpyW(buf, str);
1992 else buf[0] = 0;
1993
1994 *size = len;
1995 return ERROR_SUCCESS;
1996 }
1997 else
1998 {
1999 char *buf = buffer;
2000
2001 if (str) len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
2002 else len = 1;
2003 if (*size < len)
2004 {
2005 *size = len;
2007 }
2008 if (str) WideCharToMultiByte(CP_ACP, 0, str, -1, buf, *size, NULL, NULL);
2009 else buf[0] = 0;
2010
2011 *size = len - 1;
2012 return ERROR_SUCCESS;
2013 }
2014}
2015
2017{
2019 DWORD len;
2020
2022 if(!context)
2023 return ERROR_NOT_SUPPORTED;
2024
2025 memset(info, 0, sizeof(*info));
2026 info->ftExpiry = context->pCertInfo->NotAfter;
2027 info->ftStart = context->pCertInfo->NotBefore;
2028 len = CertNameToStrA(context->dwCertEncodingType,
2029 &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR|CERT_NAME_STR_CRLF_FLAG, NULL, 0);
2030 info->lpszSubjectInfo = LocalAlloc(0, len);
2031 if(info->lpszSubjectInfo)
2032 CertNameToStrA(context->dwCertEncodingType,
2034 info->lpszSubjectInfo, len);
2035 len = CertNameToStrA(context->dwCertEncodingType,
2036 &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR|CERT_NAME_STR_CRLF_FLAG, NULL, 0);
2037 info->lpszIssuerInfo = LocalAlloc(0, len);
2038 if(info->lpszIssuerInfo)
2039 CertNameToStrA(context->dwCertEncodingType,
2041 info->lpszIssuerInfo, len);
2042 info->dwKeySize = NETCON_GetCipherStrength(req->netconn);
2043
2045 return ERROR_SUCCESS;
2046}
2047
2049{
2051
2052 switch(option) {
2054 {
2056
2057 FIXME("INTERNET_DIAGNOSTIC_SOCKET_INFO stub\n");
2058
2062 /* FIXME: can't get a SOCKET from our connection since we don't use
2063 * winsock
2064 */
2065 info->Socket = 0;
2066 /* FIXME: get source port from req->netConnection */
2067 info->SourcePort = 0;
2068 info->DestPort = req->server->port;
2069 info->Flags = 0;
2070 if (HTTP_KeepAlive(req))
2071 info->Flags |= IDSI_FLAG_KEEP_ALIVE;
2072 if (req->proxy)
2073 info->Flags |= IDSI_FLAG_PROXY;
2074 if (is_valid_netconn(req->netconn) && req->netconn->secure)
2075 info->Flags |= IDSI_FLAG_SECURE;
2076
2077 return ERROR_SUCCESS;
2078 }
2079
2080 case 98:
2081 TRACE("Queried undocumented option 98, forwarding to INTERNET_OPTION_SECURITY_FLAGS\n");
2082 /* fall through */
2084 {
2085 DWORD flags;
2086
2087 if (*size < sizeof(ULONG))
2089
2090 *size = sizeof(DWORD);
2092 *(DWORD *)buffer = flags;
2093
2094 TRACE("INTERNET_OPTION_SECURITY_FLAGS %lx\n", flags);
2095 return ERROR_SUCCESS;
2096 }
2097
2099 TRACE("INTERNET_OPTION_HANDLE_TYPE\n");
2100
2101 if (*size < sizeof(ULONG))
2103
2104 *size = sizeof(DWORD);
2106 return ERROR_SUCCESS;
2107
2108 case INTERNET_OPTION_URL: {
2109 WCHAR *url;
2110 DWORD res;
2111
2112 TRACE("INTERNET_OPTION_URL\n");
2113
2114 url = compose_request_url(req);
2115 if(!url)
2116 return ERROR_OUTOFMEMORY;
2117
2118 res = str_to_buffer(url, buffer, size, unicode);
2119 free(url);
2120 return res;
2121 }
2123 return str_to_buffer(req->session->appInfo->agent, buffer, size, unicode);
2125 return str_to_buffer(req->session->userName, buffer, size, unicode);
2127 return str_to_buffer(req->session->password, buffer, size, unicode);
2129 return str_to_buffer(req->session->appInfo->proxyUsername, buffer, size, unicode);
2131 return str_to_buffer(req->session->appInfo->proxyPassword, buffer, size, unicode);
2132
2136 DWORD nbytes, error;
2137 BOOL ret;
2138
2139 TRACE("INTERNET_OPTION_CACHE_TIMESTAMPS\n");
2140
2141 if(!req->req_file)
2142 return ERROR_FILE_NOT_FOUND;
2143
2144 if (*size < sizeof(*ts))
2145 {
2146 *size = sizeof(*ts);
2148 }
2149
2150 nbytes = 0;
2151 ret = GetUrlCacheEntryInfoW(req->req_file->url, NULL, &nbytes);
2152 error = GetLastError();
2154 {
2155 if (!(info = malloc(nbytes)))
2156 return ERROR_OUTOFMEMORY;
2157
2158 GetUrlCacheEntryInfoW(req->req_file->url, info, &nbytes);
2159
2160 ts->ftExpires = info->ExpireTime;
2161 ts->ftLastModified = info->LastModifiedTime;
2162
2163 free(info);
2164 *size = sizeof(*ts);
2165 return ERROR_SUCCESS;
2166 }
2167 return error;
2168 }
2169
2171 DWORD req_size;
2172
2173 TRACE("INTERNET_OPTION_DATAFILE_NAME\n");
2174
2175 if(!req->req_file) {
2176 *size = 0;
2178 }
2179
2180 if(unicode) {
2181 req_size = (lstrlenW(req->req_file->file_name)+1) * sizeof(WCHAR);
2182 if(*size < req_size)
2184
2185 *size = req_size;
2187 return ERROR_SUCCESS;
2188 }else {
2189 req_size = WideCharToMultiByte(CP_ACP, 0, req->req_file->file_name, -1, NULL, 0, NULL, NULL);
2190 if (req_size > *size)
2192
2194 -1, buffer, *size, NULL, NULL);
2195 return ERROR_SUCCESS;
2196 }
2197 }
2198
2200 if(!req->netconn)
2202
2203 if(*size < sizeof(INTERNET_CERTIFICATE_INFOA)) {
2206 }
2207
2209 }
2211 DWORD err;
2212 int needed;
2213 char subject[64];
2214 char issuer[64];
2215 char effective[64];
2216 char expiration[64];
2217 char protocol[64];
2218 char signature[64];
2219 char encryption[64];
2220 char privacy[64];
2221 char bits[16];
2222 char strength[16];
2223 char start_date[32];
2224 char start_time[32];
2225 char expiry_date[32];
2226 char expiry_time[32];
2227 SYSTEMTIME start, expiry;
2229
2230 if(!size)
2232
2233 if(!req->netconn) {
2234 *size = 0;
2236 }
2237
2238 if(!buffer) {
2239 *size = 1;
2241 }
2242
2243 if((err = get_security_cert_struct(req, &info)))
2244 return err;
2245
2246 LoadStringA(WININET_hModule, IDS_CERT_SUBJECT, subject, sizeof(subject));
2248 LoadStringA(WININET_hModule, IDS_CERT_EFFECTIVE, effective, sizeof(effective));
2249 LoadStringA(WININET_hModule, IDS_CERT_EXPIRATION, expiration, sizeof(expiration));
2252 LoadStringA(WININET_hModule, IDS_CERT_ENCRYPTION, encryption, sizeof(encryption));
2253 LoadStringA(WININET_hModule, IDS_CERT_PRIVACY, privacy, sizeof(privacy));
2255 strength, sizeof(strength));
2257
2258 FileTimeToSystemTime(&info.ftStart, &start);
2259 FileTimeToSystemTime(&info.ftExpiry, &expiry);
2260 GetDateFormatA(LOCALE_USER_DEFAULT, 0, &start, NULL, start_date, sizeof(start_date));
2261 GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &start, NULL, start_time, sizeof(start_time));
2262 GetDateFormatA(LOCALE_USER_DEFAULT, 0, &expiry, NULL, expiry_date, sizeof(expiry_date));
2263 GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &expiry, NULL, expiry_time, sizeof(expiry_time));
2264
2265 needed = _scprintf("%s:\r\n%s\r\n"
2266 "%s:\r\n%s\r\n"
2267 "%s:\t%s %s\r\n"
2268 "%s:\t%s %s\r\n"
2269 "%s:\t(null)\r\n"
2270 "%s:\t(null)\r\n"
2271 "%s:\t(null)\r\n"
2272 "%s:\t%s (%lu %s)",
2273 subject, info.lpszSubjectInfo,
2274 issuer, info.lpszIssuerInfo,
2275 effective, start_date, start_time,
2276 expiration, expiry_date, expiry_time,
2277 protocol, signature, encryption,
2278 privacy, strength, info.dwKeySize, bits);
2279
2280 if(needed < *size) {
2282 *size = snprintf(buffer, *size,
2283 "%s:\r\n%s\r\n"
2284 "%s:\r\n%s\r\n"
2285 "%s:\t%s %s\r\n"
2286 "%s:\t%s %s\r\n"
2287 "%s:\t(null)\r\n"
2288 "%s:\t(null)\r\n"
2289 "%s:\t(null)\r\n"
2290 "%s:\t%s (%lu %s)",
2291 subject, info.lpszSubjectInfo,
2292 issuer, info.lpszIssuerInfo,
2293 effective, start_date, start_time,
2294 expiration, expiry_date, expiry_time,
2295 protocol, signature, encryption,
2296 privacy, strength, info.dwKeySize, bits);
2297 }else {
2299 *size = 1;
2300 }
2301
2302 LocalFree(info.lpszSubjectInfo);
2303 LocalFree(info.lpszIssuerInfo);
2304 LocalFree(info.lpszProtocolName);
2305 LocalFree(info.lpszSignatureAlgName);
2306 LocalFree(info.lpszEncryptionAlgName);
2307 return err;
2308 }
2310 if (*size < sizeof(ULONG))
2312
2313 *size = sizeof(ULONG);
2314 *(ULONG *)buffer = hdr->connect_timeout;
2315 return ERROR_SUCCESS;
2317 DWORD flags = 0;
2318
2319 if (*size < sizeof(DWORD))
2321
2322 /* FIXME: Add support for:
2323 * INTERNET_REQFLAG_FROM_CACHE
2324 * INTERNET_REQFLAG_CACHE_WRITE_DISABLED
2325 */
2326
2327 if(req->proxy)
2329 if(!req->status_code)
2331
2332 TRACE("INTERNET_OPTION_REQUEST_FLAGS returning %lx\n", flags);
2333
2334 *size = sizeof(DWORD);
2335 *(DWORD*)buffer = flags;
2336 return ERROR_SUCCESS;
2337 }
2339 TRACE("INTERNET_OPTION_ERROR_MASK\n");
2340
2341 if (*size < sizeof(ULONG))
2343
2344 *(ULONG*)buffer = hdr->ErrorMask;
2345 *size = sizeof(ULONG);
2346 return ERROR_SUCCESS;
2348 TRACE("INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT\n");
2349
2350 if (*size < sizeof(PCCERT_CHAIN_CONTEXT))
2352
2353 if (!req->server->cert_chain)
2355
2357 *size = sizeof(PCCERT_CHAIN_CONTEXT);
2358
2359 return ERROR_SUCCESS;
2360 }
2361
2362 return INET_QueryOption(hdr, option, buffer, size, unicode);
2363}
2364
2366{
2368
2369 switch(option) {
2370 case 99: /* Undocumented, seems to be INTERNET_OPTION_SECURITY_FLAGS with argument validation */
2371 TRACE("Undocumented option 99\n");
2372
2373 if (!buffer || size != sizeof(DWORD))
2377
2378 /* fall through */
2380 {
2381 DWORD flags;
2382
2383 if (!buffer || size != sizeof(DWORD))
2385 flags = *(DWORD *)buffer;
2386 TRACE("INTERNET_OPTION_SECURITY_FLAGS %08lx\n", flags);
2388 req->security_flags |= flags;
2389 if(is_valid_netconn(req->netconn))
2390 req->netconn->security_flags |= flags;
2391 return ERROR_SUCCESS;
2392 }
2393
2395 free(req->session->userName);
2396 if (!(req->session->userName = wcsdup(buffer))) return ERROR_OUTOFMEMORY;
2397 return ERROR_SUCCESS;
2398
2400 free(req->session->password);
2401 if (!(req->session->password = wcsdup(buffer))) return ERROR_OUTOFMEMORY;
2402 return ERROR_SUCCESS;
2403
2407 return ERROR_SUCCESS;
2408
2412 return ERROR_SUCCESS;
2413
2414 }
2415
2416 return INET_SetOption(hdr, option, buffer, size);
2417}
2418
2420{
2421 WCHAR *header;
2422 DWORD header_len;
2423 BOOL res;
2424
2425 TRACE("%p\n", req);
2426
2427 CloseHandle(req->hCacheFile);
2428 req->hCacheFile = NULL;
2429
2431 header_len = (header ? lstrlenW(header) : 0);
2434 header, header_len, NULL, 0);
2435 if(res)
2436 req->req_file->is_committed = TRUE;
2437 else
2438 WARN("CommitUrlCacheEntry failed: %lu\n", GetLastError());
2439 free(header);
2440}
2441
2443{
2445 WCHAR *url;
2446 BOOL b = TRUE;
2447
2448 /* FIXME: We should free previous cache file earlier */
2449 if(req->req_file) {
2451 req->req_file = NULL;
2452 }
2453 if(req->hCacheFile) {
2454 CloseHandle(req->hCacheFile);
2455 req->hCacheFile = NULL;
2456 }
2457
2459 b = FALSE;
2460
2461 if(b) {
2462 int header_idx;
2463
2465
2466 header_idx = HTTP_GetCustomHeaderIndex(req, L"Cache-Control", 0, FALSE);
2467 if(header_idx != -1) {
2468 WCHAR *ptr;
2469
2470 for(ptr=req->custHeaders[header_idx].lpszValue; *ptr; ) {
2471 WCHAR *end;
2472
2473 while(*ptr==' ' || *ptr=='\t')
2474 ptr++;
2475
2476 end = wcschr(ptr, ',');
2477 if(!end)
2478 end = ptr + lstrlenW(ptr);
2479
2480 if(!wcsnicmp(ptr, L"no-cache", ARRAY_SIZE(L"no-cache")-1)
2481 || !wcsnicmp(ptr, L"no-store", ARRAY_SIZE(L"no-store")-1)) {
2482 b = FALSE;
2483 break;
2484 }
2485
2486 ptr = end;
2487 if(*ptr == ',')
2488 ptr++;
2489 }
2490 }
2491
2493 }
2494
2495 if(!b) {
2496 if(!(req->hdr.dwFlags & INTERNET_FLAG_NEED_FILE))
2497 return;
2498
2499 FIXME("INTERNET_FLAG_NEED_FILE is not supported correctly\n");
2500 }
2501
2502 url = compose_request_url(req);
2503 if(!url) {
2504 WARN("Could not get URL\n");
2505 return;
2506 }
2507
2508 b = CreateUrlCacheEntryW(url, req->contentLength == ~0 ? 0 : req->contentLength, NULL, file_name, 0);
2509 if(!b) {
2510 WARN("Could not create cache entry: %08lx\n", GetLastError());
2511 return;
2512 }
2513
2515 req->req_file->url = url;
2516 req->content_pos = 0;
2517 req->cache_size = 0;
2518
2521 if(req->hCacheFile == INVALID_HANDLE_VALUE) {
2522 WARN("Could not create file: %lu\n", GetLastError());
2523 req->hCacheFile = NULL;
2524 return;
2525 }
2526
2527 if(req->read_size) {
2528 DWORD written;
2529
2530 b = WriteFile(req->hCacheFile, req->read_buf+req->read_pos, req->read_size, &written, NULL);
2531 if(b)
2532 req->cache_size += written;
2533 else
2534 FIXME("WriteFile failed: %lu\n", GetLastError());
2535
2536 if(req->data_stream->vtbl->end_of_data(req->data_stream, req))
2537 commit_cache_entry(req);
2538 }
2539}
2540
2541/* read some more data into the read buffer (the read section must be held) */
2542static DWORD read_more_data( http_request_t *req, int maxlen )
2543{
2544 DWORD res;
2545 int len;
2546
2547 if (req->read_pos)
2548 {
2549 /* move existing data to the start of the buffer */
2550 if(req->read_size)
2551 memmove( req->read_buf, req->read_buf + req->read_pos, req->read_size );
2552 req->read_pos = 0;
2553 }
2554
2555 if (maxlen == -1) maxlen = sizeof(req->read_buf);
2556
2557 res = NETCON_recv( req->netconn, req->read_buf + req->read_size,
2558 maxlen - req->read_size, TRUE, &len );
2559 if(res == ERROR_SUCCESS)
2560 req->read_size += len;
2561
2562 return res;
2563}
2564
2565/* remove some amount of data from the read buffer (the read section must be held) */
2566static void remove_data( http_request_t *req, int count )
2567{
2568 if (!(req->read_size -= count)) req->read_pos = 0;
2569 else req->read_pos += count;
2570}
2571
2573{
2574 int count, bytes_read, pos = 0;
2575 DWORD res;
2576
2578 for (;;)
2579 {
2580 BYTE *eol = memchr( req->read_buf + req->read_pos, '\n', req->read_size );
2581
2582 if (eol)
2583 {
2584 count = eol - (req->read_buf + req->read_pos);
2585 bytes_read = count + 1;
2586 }
2587 else count = bytes_read = req->read_size;
2588
2589 count = min( count, *len - pos );
2590 memcpy( buffer + pos, req->read_buf + req->read_pos, count );
2591 pos += count;
2592 remove_data( req, bytes_read );
2593 if (eol) break;
2594
2595 if ((res = read_more_data( req, -1 )))
2596 {
2597 WARN( "read failed %lu\n", res );
2599 return res;
2600 }
2601 if (!req->read_size)
2602 {
2603 *len = 0;
2604 TRACE( "returning empty string\n" );
2606 return ERROR_SUCCESS;
2607 }
2608 }
2610
2611 if (pos < *len)
2612 {
2613 if (pos && buffer[pos - 1] == '\r') pos--;
2614 *len = pos + 1;
2615 }
2616 buffer[*len - 1] = 0;
2617 TRACE( "returning %s\n", debugstr_a(buffer));
2618 return ERROR_SUCCESS;
2619}
2620
2621/* check if we have reached the end of the data to read (the read section must be held) */
2623{
2624 return !req->read_size && req->data_stream->vtbl->end_of_data(req->data_stream, req);
2625}
2626
2628{
2629 DWORD res;
2630
2631 res = req->data_stream->vtbl->read(req->data_stream, req, buf, size, read, allow_blocking);
2632 if(res != ERROR_SUCCESS)
2633 *read = 0;
2634 assert(*read <= size);
2635
2636 if(req->hCacheFile) {
2637 if(*read) {
2638 BOOL bres;
2639 DWORD written;
2640
2641 bres = WriteFile(req->hCacheFile, buf, *read, &written, NULL);
2642 if(bres)
2643 req->cache_size += written;
2644 else
2645 FIXME("WriteFile failed: %lu\n", GetLastError());
2646 }
2647
2648 if((res == ERROR_SUCCESS && !*read) || req->data_stream->vtbl->end_of_data(req->data_stream, req))
2649 commit_cache_entry(req);
2650 }
2651
2652 return res;
2653}
2654
2655/* fetch some more data into the read buffer (the read section must be held) */
2657{
2658 DWORD res, read=0;
2659
2660 if(req->read_size == sizeof(req->read_buf))
2661 return ERROR_SUCCESS;
2662
2663 if(req->read_pos) {
2664 if(req->read_size)
2665 memmove(req->read_buf, req->read_buf+req->read_pos, req->read_size);
2666 req->read_pos = 0;
2667 }
2668
2669 res = read_http_stream(req, req->read_buf+req->read_size, sizeof(req->read_buf) - req->read_size,
2670 &read, allow_blocking);
2671 if(res != ERROR_SUCCESS)
2672 return res;
2673
2674 req->read_size += read;
2675
2676 TRACE("read %lu bytes, read_size %lu\n", read, req->read_size);
2677 if(read_bytes)
2678 *read_bytes = read;
2679 return res;
2680}
2681
2683{
2684 netconn_stream_t *netconn_stream = (netconn_stream_t*)stream;
2685 return netconn_stream->content_read == netconn_stream->content_length || !is_valid_netconn(req->netconn);
2686}
2687
2689 DWORD *read, BOOL allow_blocking)
2690{
2691 netconn_stream_t *netconn_stream = (netconn_stream_t*)stream;
2693 int ret = 0;
2694
2695 size = min(size, netconn_stream->content_length-netconn_stream->content_read);
2696
2697 if(size && is_valid_netconn(req->netconn)) {
2698 res = NETCON_recv(req->netconn, buf, size, allow_blocking, &ret);
2699 if(res == ERROR_SUCCESS) {
2700 if(!ret)
2701 netconn_stream->content_length = netconn_stream->content_read;
2702 netconn_stream->content_read += ret;
2703 }
2704 }
2705
2706 TRACE("res %lu read %u bytes\n", res, ret);
2707 *read = ret;
2708 return res;
2709}
2710
2712{
2713 netconn_stream_t *netconn_stream = (netconn_stream_t*)stream;
2714 BYTE buf[1024];
2715 int len, res;
2716 size_t size;
2717
2718 if(netconn_stream->content_length == ~0)
2719 return WSAEISCONN;
2720
2721 while(netconn_stream->content_read < netconn_stream->content_length) {
2722 size = min(sizeof(buf), netconn_stream->content_length-netconn_stream->content_read);
2723 res = NETCON_recv(req->netconn, buf, size, allow_blocking, &len);
2724 if(res)
2725 return res;
2726 if(!len)
2727 return WSAECONNABORTED;
2728
2729 netconn_stream->content_read += len;
2730 }
2731
2732 return ERROR_SUCCESS;
2733}
2734
2736{
2737}
2738
2744};
2745
2747{
2748 assert(stream->buf_size);
2749
2750 stream->buf_size--;
2751 return stream->buf[stream->buf_pos++];
2752}
2753
2755{
2756 chunked_stream_t *chunked_stream = (chunked_stream_t*)stream;
2757 switch(chunked_stream->state) {
2758 case CHUNKED_STREAM_STATE_DISCARD_EOL_AT_END:
2759 case CHUNKED_STREAM_STATE_END_OF_STREAM:
2760 case CHUNKED_STREAM_STATE_ERROR:
2761 return TRUE;
2762 default:
2763 return FALSE;
2764 }
2765}
2766
2768 DWORD *read, BOOL allow_blocking)
2769{
2770 chunked_stream_t *chunked_stream = (chunked_stream_t*)stream;
2771 DWORD ret_read = 0, res = ERROR_SUCCESS;
2772 BOOL continue_read = TRUE;
2773 int read_bytes;
2774 char ch;
2775
2776 do {
2777 TRACE("state %d\n", chunked_stream->state);
2778
2779 /* Ensure that we have data in the buffer for states that need it. */
2780 if(!chunked_stream->buf_size) {
2781 BOOL blocking_read = allow_blocking;
2782
2783 switch(chunked_stream->state) {
2784 case CHUNKED_STREAM_STATE_DISCARD_EOL_AT_END:
2785 case CHUNKED_STREAM_STATE_DISCARD_EOL_AFTER_SIZE:
2786 /* never allow blocking after 0 chunk size */
2787 if(!chunked_stream->chunk_size)
2788 blocking_read = FALSE;
2789 /* fall through */
2790 case CHUNKED_STREAM_STATE_READING_CHUNK_SIZE:
2791 case CHUNKED_STREAM_STATE_DISCARD_EOL_AFTER_DATA:
2792 chunked_stream->buf_pos = 0;
2793 res = NETCON_recv(req->netconn, chunked_stream->buf, sizeof(chunked_stream->buf), blocking_read, &read_bytes);
2794 if(res == ERROR_SUCCESS && read_bytes) {
2795 chunked_stream->buf_size += read_bytes;
2796 }else if(res == WSAEWOULDBLOCK) {
2797 if(ret_read || allow_blocking)
2799 continue_read = FALSE;
2800 continue;
2801 }else {
2802 chunked_stream->state = CHUNKED_STREAM_STATE_ERROR;
2803 }
2804 break;
2805 default:
2806 break;
2807 }
2808 }
2809
2810 switch(chunked_stream->state) {
2811 case CHUNKED_STREAM_STATE_READING_CHUNK_SIZE:
2812 ch = next_chunked_data_char(chunked_stream);
2813
2814 if(ch >= '0' && ch <= '9') {
2815 chunked_stream->chunk_size = chunked_stream->chunk_size * 16 + ch - '0';
2816 }else if(ch >= 'a' && ch <= 'f') {
2817 chunked_stream->chunk_size = chunked_stream->chunk_size * 16 + ch - 'a' + 10;
2818 }else if (ch >= 'A' && ch <= 'F') {
2819 chunked_stream->chunk_size = chunked_stream->chunk_size * 16 + ch - 'A' + 10;
2820 }else if (ch == ';' || ch == '\r' || ch == '\n') {
2821 TRACE("reading %lu byte chunk\n", chunked_stream->chunk_size);
2822 chunked_stream->buf_size++;
2823 chunked_stream->buf_pos--;
2824 if(req->contentLength == ~0) req->contentLength = chunked_stream->chunk_size;
2825 else req->contentLength += chunked_stream->chunk_size;
2826 chunked_stream->state = CHUNKED_STREAM_STATE_DISCARD_EOL_AFTER_SIZE;
2827 }
2828 break;
2829
2830 case CHUNKED_STREAM_STATE_DISCARD_EOL_AFTER_SIZE:
2831 ch = next_chunked_data_char(chunked_stream);
2832 if(ch == '\n')
2833 chunked_stream->state = chunked_stream->chunk_size
2834 ? CHUNKED_STREAM_STATE_READING_CHUNK
2835 : CHUNKED_STREAM_STATE_DISCARD_EOL_AT_END;
2836 else if(ch != '\r')
2837 WARN("unexpected char '%c'\n", ch);
2838 break;
2839
2840 case CHUNKED_STREAM_STATE_READING_CHUNK:
2841 assert(chunked_stream->chunk_size);
2842 if(!size) {
2843 continue_read = FALSE;
2844 break;
2845 }
2846 read_bytes = min(size, chunked_stream->chunk_size);
2847
2848 if(chunked_stream->buf_size) {
2849 if(read_bytes > chunked_stream->buf_size)
2850 read_bytes = chunked_stream->buf_size;
2851
2852 memcpy(buf+ret_read, chunked_stream->buf+chunked_stream->buf_pos, read_bytes);
2853 chunked_stream->buf_pos += read_bytes;
2854 chunked_stream->buf_size -= read_bytes;
2855 }else {
2856 res = NETCON_recv(req->netconn, (char*)buf+ret_read, read_bytes,
2857 allow_blocking, (int*)&read_bytes);
2858 if(res != ERROR_SUCCESS) {
2859 continue_read = FALSE;
2860 break;
2861 }
2862
2863 if(!read_bytes) {
2864 chunked_stream->state = CHUNKED_STREAM_STATE_ERROR;
2865 continue;
2866 }
2867 }
2868
2869 chunked_stream->chunk_size -= read_bytes;
2870 size -= read_bytes;
2871 ret_read += read_bytes;
2872 if(!chunked_stream->chunk_size)
2873 chunked_stream->state = CHUNKED_STREAM_STATE_DISCARD_EOL_AFTER_DATA;
2874 allow_blocking = FALSE;
2875 break;
2876
2877 case CHUNKED_STREAM_STATE_DISCARD_EOL_AFTER_DATA:
2878 ch = next_chunked_data_char(chunked_stream);
2879 if(ch == '\n')
2880 chunked_stream->state = CHUNKED_STREAM_STATE_READING_CHUNK_SIZE;
2881 else if(ch != '\r')
2882 WARN("unexpected char '%c'\n", ch);
2883 break;
2884
2885 case CHUNKED_STREAM_STATE_DISCARD_EOL_AT_END:
2886 ch = next_chunked_data_char(chunked_stream);
2887 if(ch == '\n')
2888 chunked_stream->state = CHUNKED_STREAM_STATE_END_OF_STREAM;
2889 else if(ch != '\r')
2890 WARN("unexpected char '%c'\n", ch);
2891 break;
2892
2893 case CHUNKED_STREAM_STATE_END_OF_STREAM:
2894 case CHUNKED_STREAM_STATE_ERROR:
2895 continue_read = FALSE;
2896 break;
2897 }
2898 } while(continue_read);
2899
2900 if(ret_read)
2902 if(res != ERROR_SUCCESS)
2903 return res;
2904
2905 TRACE("read %ld bytes\n", ret_read);
2906 *read = ret_read;
2907 return ERROR_SUCCESS;
2908}
2909
2911{
2912 chunked_stream_t *chunked_stream = (chunked_stream_t*)stream;
2913 BYTE buf[1024];
2914 DWORD size, res;
2915
2916 while(chunked_stream->state != CHUNKED_STREAM_STATE_END_OF_STREAM
2917 && chunked_stream->state != CHUNKED_STREAM_STATE_ERROR) {
2918 res = chunked_read(stream, req, buf, sizeof(buf), &size, allow_blocking);
2919 if(res != ERROR_SUCCESS)
2920 return res;
2921 }
2922
2923 if(chunked_stream->state != CHUNKED_STREAM_STATE_END_OF_STREAM)
2924 return ERROR_NO_DATA;
2925 return ERROR_SUCCESS;
2926}
2927
2929{
2930 chunked_stream_t *chunked_stream = (chunked_stream_t*)stream;
2931 free(chunked_stream);
2932}
2933
2939};
2940
2941/* set the request content length based on the headers */
2943{
2944 WCHAR contentLength[32];
2945 WCHAR encoding[20];
2946 DWORD size;
2947
2948 if(request->status_code == HTTP_STATUS_NO_CONTENT || request->status_code == HTTP_STATUS_NOT_MODIFIED ||
2949 !wcscmp(request->verb, L"HEAD"))
2950 {
2951 if (HTTP_GetCustomHeaderIndex(request, L"Content-Length", 0, FALSE) == -1 ||
2952 !wcscmp(request->verb, L"HEAD"))
2953 request->read_size = 0;
2954 request->contentLength = request->netconn_stream.content_length = 0;
2955 return ERROR_SUCCESS;
2956 }
2957
2958 size = sizeof(contentLength);
2960 contentLength, &size, NULL) != ERROR_SUCCESS ||
2961 !StrToInt64ExW(contentLength, STIF_DEFAULT, (LONGLONG*)&request->contentLength)) {
2962 request->contentLength = ~0;
2963 }
2964
2965 request->netconn_stream.content_length = request->contentLength;
2966 request->netconn_stream.content_read = request->read_size;
2967
2968 size = sizeof(encoding);
2970 !wcsicmp(encoding, L"chunked"))
2971 {
2972 chunked_stream_t *chunked_stream;
2973
2974 chunked_stream = malloc(sizeof(*chunked_stream));
2975 if(!chunked_stream)
2976 return ERROR_OUTOFMEMORY;
2977
2978 chunked_stream->data_stream.vtbl = &chunked_stream_vtbl;
2979 chunked_stream->buf_size = chunked_stream->buf_pos = 0;
2980 chunked_stream->chunk_size = 0;
2981 chunked_stream->state = CHUNKED_STREAM_STATE_READING_CHUNK_SIZE;
2982
2983 if(request->read_size) {
2985 chunked_stream->buf_size = request->read_size;
2987 }
2988
2989 request->data_stream = &chunked_stream->data_stream;
2990 request->contentLength = ~0;
2991 }
2992
2993 if(request->hdr.decoding) {
2994 int encoding_idx;
2995
2996 EnterCriticalSection( &request->headers_section );
2997
2998 encoding_idx = HTTP_GetCustomHeaderIndex(request, L"Content-Encoding", 0, FALSE);
2999 if(encoding_idx != -1) {
3000 if(!wcsicmp(request->custHeaders[encoding_idx].lpszValue, L"gzip")) {
3001 HTTP_DeleteCustomHeader(request, encoding_idx);
3002 LeaveCriticalSection( &request->headers_section );
3003 return init_gzip_stream(request, TRUE);
3004 }
3005 if(!wcsicmp(request->custHeaders[encoding_idx].lpszValue, L"deflate")) {
3006 HTTP_DeleteCustomHeader(request, encoding_idx);
3007 LeaveCriticalSection( &request->headers_section );
3009 }
3010 }
3011
3012 LeaveCriticalSection( &request->headers_section );
3013 }
3014
3015 return ERROR_SUCCESS;
3016}
3017
3019{
3021
3022 iar.dwResult = result;
3023 iar.dwError = error;
3024
3026 sizeof(INTERNET_ASYNC_RESULT));
3027}
3028
3030{
3031 DWORD res, read = 0;
3032
3033 TRACE("%p\n", req);
3034
3036
3037 res = refill_read_buffer(req, FALSE, &read);
3038 if(res == ERROR_SUCCESS)
3039 read += req->read_size;
3040
3042
3043 if(res != WSAEWOULDBLOCK && (res != ERROR_SUCCESS || !read)) {
3044 WARN("res %lu read %lu, closing connection\n", res, read);
3046 }
3047
3048 if(res != ERROR_SUCCESS && res != WSAEWOULDBLOCK) {
3049 send_request_complete(req, 0, res);
3050 return;
3051 }
3052
3054}
3055
3057{
3058 DWORD ret_read = 0, res;
3059 LARGE_INTEGER off;
3060 BYTE buf[1024];
3061
3062 while (req->content_pos > req->cache_size) {
3063 res = read_http_stream(req, (BYTE*)buf, min(sizeof(buf), req->content_pos - req->cache_size),
3064 &ret_read, allow_blocking);
3065 if (res != ERROR_SUCCESS)
3066 return res;
3067 if (!ret_read) {
3068 *read = 0;
3069 return ERROR_SUCCESS;
3070 }
3071 }
3072
3073 if (req->content_pos < req->cache_size) {
3074 off.QuadPart = req->content_pos;
3076 return GetLastError();
3077 if (!ReadFile(req->req_file->file_handle, buffer, size, &ret_read, NULL))
3078 return GetLastError();
3079 }
3080
3081 *read = ret_read;
3082 return ERROR_SUCCESS;
3083}
3084
3085/* read data from the http connection (the read section must be held) */
3086static DWORD HTTPREQ_Read(http_request_t *req, void *buffer, DWORD size, DWORD *read, BOOL allow_blocking)
3087{
3088 DWORD current_read = 0, ret_read = 0;
3090
3092
3093 if(req->read_size) {
3094 ret_read = min(size, req->read_size);
3095 memcpy(buffer, req->read_buf+req->read_pos, ret_read);
3096 req->read_size -= ret_read;
3097 req->read_pos += ret_read;
3098 req->content_pos += ret_read;
3099 allow_blocking = FALSE;
3100 }
3101
3102 if(ret_read < size) {
3103 res = read_http_stream(req, (BYTE*)buffer+ret_read, size-ret_read, &current_read, allow_blocking);
3104 if(res == ERROR_SUCCESS) {
3105 ret_read += current_read;
3106 req->content_pos += current_read;
3107 }
3108 else if(res == WSAEWOULDBLOCK && ret_read)
3110 }
3111
3113
3114 *read = ret_read;
3115 TRACE( "retrieved %lu bytes (res %lu)\n", ret_read, res );
3116
3117 if(res != WSAEWOULDBLOCK) {
3118 if(res != ERROR_SUCCESS)
3120 else if(!ret_read && drain_content(req, FALSE) == ERROR_SUCCESS)
3122 }
3123
3124 return res;
3125}
3126
3128{
3129 DWORD res;
3130
3131 TRACE("%p\n", req->netconn);
3132
3133 if(!is_valid_netconn(req->netconn))
3134 return ERROR_NO_DATA;
3135
3136 if(!wcscmp(req->verb, L"HEAD"))
3137 return ERROR_SUCCESS;
3138
3140 res = req->data_stream->vtbl->drain_content(req->data_stream, req, blocking);
3142 return res;
3143}
3144
3145typedef struct {
3147 void *buf;
3152
3154{
3156 http_request_t *req = (http_request_t*)task->hdr.hdr;
3157 DWORD res = ERROR_SUCCESS, read = task->read_pos, complete_arg = 0;
3158
3159 TRACE("req %p buf %p size %lu read_pos %lu ret_read %p\n", req, task->buf, task->size, task->read_pos, task->ret_read);
3160
3161 if(req->req_file && req->req_file->file_handle) {
3162 DWORD ret, ret_read;
3163 BYTE buf[1024];
3164 while (req->content_pos > req->cache_size) {
3165 ret = read_http_stream(req, (BYTE*)buf, min(sizeof(buf), req->content_pos - req->cache_size),
3166 &ret_read, TRUE);
3167 if(ret != ERROR_SUCCESS || !ret_read)
3168 break;
3169 }
3170 }
3171
3172 if(task->buf) {
3174 while (read < task->size) {
3175 res = HTTPREQ_Read(req, (char*)task->buf + read, task->size - read, &read_bytes, TRUE);
3176 if (res != ERROR_SUCCESS || !read_bytes)
3177 break;
3178 read += read_bytes;
3179 }
3180 }else {
3182 res = refill_read_buffer(req, TRUE, &read);
3184
3185 if(task->ret_read)
3186 complete_arg = read; /* QueryDataAvailable reports read bytes in request complete notification */
3187 if(res != ERROR_SUCCESS || !read)
3189 }
3190
3191 TRACE("res %lu read %lu\n", res, read);
3192
3193 if(task->ret_read)
3194 *task->ret_read = read;
3195
3196 /* FIXME: We should report bytes transferred before decoding content. */
3198
3199 if(res != ERROR_SUCCESS)
3200 complete_arg = res;
3201 send_request_complete(req, res == ERROR_SUCCESS, complete_arg);
3202}
3203
3204static DWORD async_read(http_request_t *req, void *buf, DWORD size, DWORD read_pos, DWORD *ret_read)
3205{
3207
3209 if(!task)
3210 return ERROR_OUTOFMEMORY;
3211
3212 task->buf = buf;
3213 task->size = size;
3214 task->read_pos = read_pos;
3215 task->ret_read = ret_read;
3216
3217 INTERNET_AsyncCall(&task->hdr);
3218 return ERROR_IO_PENDING;
3219}
3220
3221static DWORD HTTPREQ_SetFilePointer(object_header_t *hdr, LONG lDistanceToMove, DWORD dwMoveContext)
3222{
3225
3229 }
3230
3232
3233 switch (dwMoveContext) {
3234 case FILE_BEGIN:
3235 res = lDistanceToMove;
3236 break;
3237 case FILE_CURRENT:
3238 if(req->content_pos && lDistanceToMove < 0) {
3240 break;
3241 }
3242 res = req->content_pos + lDistanceToMove;
3243 break;
3244 case FILE_END:
3245 FIXME("dwMoveContext FILE_END not implemented\n");
3246 /* fallthrough */
3247 default:
3249 break;
3250 }
3251
3252 if(err == ERROR_SUCCESS) {
3253 req->content_pos = res;
3254 req->read_pos = req->read_size = 0;
3255 }
3256
3259 return res;
3260}
3261
3264{
3266 DWORD res = ERROR_SUCCESS, read = 0, cread, error = ERROR_SUCCESS;
3267 BOOL allow_blocking, notify_received = FALSE;
3268
3269 TRACE("(%p %p %lu %lx)\n", req, buf, size, flags);
3270
3271 if (flags & ~(IRF_ASYNC|IRF_NO_WAIT))
3272 FIXME("these dwFlags aren't implemented: 0x%lx\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT));
3273
3274 allow_blocking = !(req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC);
3275
3276 if(allow_blocking || TryEnterCriticalSection(&req->read_section)) {
3277 if(allow_blocking)
3279 if(hdr->dwError == ERROR_SUCCESS)
3280 hdr->dwError = INTERNET_HANDLE_IN_USE;
3281 else if(hdr->dwError == INTERNET_HANDLE_IN_USE)
3283
3284 if(req->read_size) {
3285 read = min(size, req->read_size);
3286 memcpy(buf, req->read_buf + req->read_pos, read);
3287 req->read_size -= read;
3288 req->read_pos += read;
3289 req->content_pos += read;
3290 }
3291
3292 if(read < size && req->req_file && req->req_file->file_handle) {
3293 res = read_req_file(req, (BYTE*)buf + read, size - read, &cread, allow_blocking);
3294 if(res == ERROR_SUCCESS) {
3295 read += cread;
3296 req->content_pos += cread;
3297 }
3298 }
3299
3300 if(res == ERROR_SUCCESS && read < size && (!read || !(flags & IRF_NO_WAIT)) && !end_of_read_data(req)) {
3304 notify_received = TRUE;
3305
3306 while(read < size) {
3307 res = HTTPREQ_Read(req, (char*)buf+read, size-read, &cread, allow_blocking);
3308 read += cread;
3309 if (res != ERROR_SUCCESS || !cread)
3310 break;
3311 }
3312 }
3313
3314 if(hdr->dwError == INTERNET_HANDLE_IN_USE)
3315 hdr->dwError = ERROR_SUCCESS;
3316 else
3317 error = hdr->dwError;
3318
3320 }else {
3322 }
3323
3324 if(res == WSAEWOULDBLOCK) {
3325 if(!(flags & IRF_NO_WAIT))
3326 return async_read(req, buf, size, read, ret_read);
3327 if(!read)
3328 return async_read(req, NULL, 0, 0, NULL);
3330 }
3331
3332 *ret_read = read;
3333 if (res != ERROR_SUCCESS)
3334 return res;
3335
3336 if(notify_received)
3338 &read, sizeof(read));
3339 return error;
3340}
3341
3343{
3344 DWORD res;
3346
3348
3349 *written = 0;
3350 res = NETCON_send(request->netconn, buffer, size, 0, (LPINT)written);
3351 if (res == ERROR_SUCCESS)
3352 request->bytesWritten += *written;
3353
3355 return res;
3356}
3357
3359{
3362 BOOL allow_blocking, notify_received = FALSE;
3363
3364 TRACE("(%p %p %lx %Ix)\n", req, available, flags, ctx);
3365
3366 if (flags & ~(IRF_ASYNC|IRF_NO_WAIT))
3367 FIXME("these dwFlags aren't implemented: 0x%lx\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT));
3368
3369 *available = 0;
3370 allow_blocking = !(req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC);
3371
3372 if(allow_blocking || TryEnterCriticalSection(&req->read_section)) {
3373 if(allow_blocking)
3375 if(hdr->dwError == ERROR_SUCCESS)
3376 hdr->dwError = INTERNET_HANDLE_IN_USE;
3377 else if(hdr->dwError == INTERNET_HANDLE_IN_USE)
3379
3380 avail = req->read_size;
3381 if(req->cache_size > req->content_pos)
3382 avail = max(avail, req->cache_size - req->content_pos);
3383
3384 if(!avail && !end_of_read_data(req)) {
3388 notify_received = TRUE;
3389
3390 res = refill_read_buffer(req, allow_blocking, &avail);
3391 }
3392
3393 if(hdr->dwError == INTERNET_HANDLE_IN_USE)
3394 hdr->dwError = ERROR_SUCCESS;
3395 else
3396 error = hdr->dwError;
3397
3399 }else {
3401 }
3402
3403 if(res == WSAEWOULDBLOCK)
3404 return async_read(req, NULL, 0, 0, available);
3405
3406 if (res != ERROR_SUCCESS)
3407 return res;
3408
3409 *available = avail;
3410 if(notify_received)
3412 &avail, sizeof(avail));
3413 return error;
3414}
3415
3417{
3419
3420 TRACE("(%p)\n", req);
3421
3422 if(!req->req_file) {
3423 WARN("No cache file name available\n");
3424 return ERROR_FILE_NOT_FOUND;
3425 }
3426
3427 *ret = req_file_addref(req->req_file);
3428 return ERROR_SUCCESS;
3429}
3430
3440 NULL,
3442};
3443
3444/***********************************************************************
3445 * HTTP_HttpOpenRequestW (internal)
3446 *
3447 * Open a HTTP request handle
3448 *
3449 * RETURNS
3450 * HINTERNET a HTTP request handle on success
3451 * NULL on failure
3452 *
3453 */
3455 LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
3456 LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
3457 DWORD dwFlags, DWORD_PTR dwContext, HINTERNET *ret)
3458{
3459 appinfo_t *hIC = session->appInfo;
3461 DWORD port, len;
3462
3463 TRACE("-->\n");
3464
3466 if(!request)
3467 return ERROR_OUTOFMEMORY;
3468
3469 request->hdr.htype = WH_HHTTPREQ;
3470 request->hdr.dwFlags = dwFlags;
3471 request->hdr.dwContext = dwContext;
3472 request->hdr.decoding = session->hdr.decoding;
3473 request->contentLength = ~0;
3474
3475 request->netconn_stream.data_stream.vtbl = &netconn_stream_vtbl;
3476 request->data_stream = &request->netconn_stream.data_stream;
3477 request->hdr.connect_timeout = session->hdr.connect_timeout;
3478 request->hdr.send_timeout = session->hdr.send_timeout;
3479 request->hdr.receive_timeout = session->hdr.receive_timeout;
3480
3482 request->headers_section.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": http_request_t.headers_section");
3483
3485 request->read_section.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": http_request_t.read_section");
3486
3488 request->session = session;
3489 list_add_head( &session->hdr.children, &request->hdr.entry );
3490
3491 port = session->hostPort;
3493 port = (session->hdr.dwFlags & INTERNET_FLAG_SECURE) ?
3495
3496 request->server = get_server(substrz(session->hostName), port, (dwFlags & INTERNET_FLAG_SECURE) != 0, TRUE);
3497 if(!request->server) {
3499 return ERROR_OUTOFMEMORY;
3500 }
3501
3506
3507 if (lpszObjectName && *lpszObjectName) {
3508 HRESULT rc;
3509 WCHAR dummy;
3510
3511 len = 1;
3512 rc = UrlCanonicalizeW(lpszObjectName, &dummy, &len, URL_ESCAPE_SPACES_ONLY);
3513 if (rc != E_POINTER)
3514 len = lstrlenW(lpszObjectName)+1;
3515 request->path = malloc(len * sizeof(WCHAR));
3516 rc = UrlCanonicalizeW(lpszObjectName, request->path, &len,
3518 if (rc != S_OK)
3519 {
3520 ERR("Unable to escape string!(%s) (%ld)\n",debugstr_w(lpszObjectName),rc);
3521 lstrcpyW(request->path,lpszObjectName);
3522 }
3523 }else {
3524 request->path = wcsdup(L"/");
3525 }
3526
3527 if (lpszReferrer && *lpszReferrer)
3529
3530 if (lpszAcceptTypes)
3531 {
3532 int i;
3533 for (i = 0; lpszAcceptTypes[i]; i++)
3534 {
3535 if (!*lpszAcceptTypes[i]) continue;
3536 HTTP_ProcessHeader(request, L"Accept", lpszAcceptTypes[i],
3540 }
3541 }
3542
3543 request->verb = wcsdup(lpszVerb && *lpszVerb ? lpszVerb : L"GET");
3544 request->version = wcsdup(lpszVersion && *lpszVersion ? lpszVersion : L"HTTP/1.1");
3545
3546 if (hIC->proxy && hIC->proxy[0] && !HTTP_ShouldBypassProxy(hIC, session->hostName))
3548
3549 INTERNET_SendCallback(&session->hdr, dwContext,
3551 sizeof(HINTERNET));
3552
3553 TRACE("<-- (%p)\n", request);
3554
3555 *ret = request->hdr.hInternet;
3556 return ERROR_SUCCESS;
3557}
3558
3559/***********************************************************************
3560 * HttpOpenRequestW (WININET.@)
3561 *
3562 * Open a HTTP request handle
3563 *
3564 * RETURNS
3565 * HINTERNET a HTTP request handle on success
3566 * NULL on failure
3567 *
3568 */
3570 LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
3571 LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
3572 DWORD dwFlags, DWORD_PTR dwContext)
3573{
3576 DWORD res;
3577
3578 TRACE("(%p, %s, %s, %s, %s, %p, %08lx, %08Ix)\n", hHttpSession,
3579 debugstr_w(lpszVerb), debugstr_w(lpszObjectName),
3580 debugstr_w(lpszVersion), debugstr_w(lpszReferrer), lpszAcceptTypes,
3581 dwFlags, dwContext);
3582 if(lpszAcceptTypes!=NULL)
3583 {
3584 int i;
3585 for(i=0;lpszAcceptTypes[i]!=NULL;i++)
3586 TRACE("\taccept type: %s\n",debugstr_w(lpszAcceptTypes[i]));
3587 }
3588
3589 session = (http_session_t*) get_handle_object( hHttpSession );
3590 if (NULL == session || session->hdr.htype != WH_HHTTPSESSION)
3591 {
3593 goto lend;
3594 }
3595
3596 /*
3597 * My tests seem to show that the windows version does not
3598 * become asynchronous until after this point. And anyhow
3599 * if this call was asynchronous then how would you get the
3600 * necessary HINTERNET pointer returned by this function.
3601 *
3602 */
3603 res = HTTP_HttpOpenRequestW(session, lpszVerb, lpszObjectName,
3604 lpszVersion, lpszReferrer, lpszAcceptTypes,
3605 dwFlags, dwContext, &handle);
3606lend:
3607 if( session )
3609 TRACE("returning %p\n", handle);
3610 if(res != ERROR_SUCCESS)
3612 return handle;
3613}
3614
3615static const LPCWSTR header_lookup[] = {
3616 L"Mime-Version", /* HTTP_QUERY_MIME_VERSION = 0 */
3617 L"Content-Type", /* HTTP_QUERY_CONTENT_TYPE = 1 */
3618 L"Content-Transfer-Encoding", /* HTTP_QUERY_CONTENT_TRANSFER_ENCODING = 2 */
3619 L"Content-ID", /* HTTP_QUERY_CONTENT_ID = 3 */
3620 NULL, /* HTTP_QUERY_CONTENT_DESCRIPTION = 4 */
3621 L"Content-Length", /* HTTP_QUERY_CONTENT_LENGTH = 5 */
3622 L"Content-Language", /* HTTP_QUERY_CONTENT_LANGUAGE = 6 */
3623 L"Allow", /* HTTP_QUERY_ALLOW = 7 */
3624 L"Public", /* HTTP_QUERY_PUBLIC = 8 */
3625 L"Date", /* HTTP_QUERY_DATE = 9 */
3626 L"Expires", /* HTTP_QUERY_EXPIRES = 10 */
3627 L"Last-Modified", /* HTTP_QUERY_LAST_MODIFIED = 11 */
3628 NULL, /* HTTP_QUERY_MESSAGE_ID = 12 */
3629 L"URI", /* HTTP_QUERY_URI = 13 */
3630 L"From", /* HTTP_QUERY_DERIVED_FROM = 14 */
3631 NULL, /* HTTP_QUERY_COST = 15 */
3632 NULL, /* HTTP_QUERY_LINK = 16 */
3633 L"Pragma", /* HTTP_QUERY_PRAGMA = 17 */
3634 NULL, /* HTTP_QUERY_VERSION = 18 */
3635 L"Status", /* HTTP_QUERY_STATUS_CODE = 19 */
3636 NULL, /* HTTP_QUERY_STATUS_TEXT = 20 */
3637 NULL, /* HTTP_QUERY_RAW_HEADERS = 21 */
3638 NULL, /* HTTP_QUERY_RAW_HEADERS_CRLF = 22 */
3639 L"Connection", /* HTTP_QUERY_CONNECTION = 23 */
3640 L"Accept", /* HTTP_QUERY_ACCEPT = 24 */
3641 L"Accept-Charset", /* HTTP_QUERY_ACCEPT_CHARSET = 25 */
3642 L"Accept-Encoding", /* HTTP_QUERY_ACCEPT_ENCODING = 26 */
3643 L"Accept-Language", /* HTTP_QUERY_ACCEPT_LANGUAGE = 27 */
3644 L"Authorization", /* HTTP_QUERY_AUTHORIZATION = 28 */
3645 L"Content-Encoding", /* HTTP_QUERY_CONTENT_ENCODING = 29 */
3646 NULL, /* HTTP_QUERY_FORWARDED = 30 */
3647 NULL, /* HTTP_QUERY_FROM = 31 */
3648 L"If-Modified-Since", /* HTTP_QUERY_IF_MODIFIED_SINCE = 32 */
3649 L"Location", /* HTTP_QUERY_LOCATION = 33 */
3650 NULL, /* HTTP_QUERY_ORIG_URI = 34 */
3651 L"Referer", /* HTTP_QUERY_REFERER = 35 */
3652 L"Retry-After", /* HTTP_QUERY_RETRY_AFTER = 36 */
3653 L"Server", /* HTTP_QUERY_SERVER = 37 */
3654 NULL, /* HTTP_TITLE = 38 */
3655 L"User-Agent", /* HTTP_QUERY_USER_AGENT = 39 */
3656 L"WWW-Authenticate", /* HTTP_QUERY_WWW_AUTHENTICATE = 40 */
3657 L"Proxy-Authenticate", /* HTTP_QUERY_PROXY_AUTHENTICATE = 41 */
3658 L"Accept-Ranges", /* HTTP_QUERY_ACCEPT_RANGES = 42 */
3659 L"Set-Cookie", /* HTTP_QUERY_SET_COOKIE = 43 */
3660 L"Cookie", /* HTTP_QUERY_COOKIE = 44 */
3661 NULL, /* HTTP_QUERY_REQUEST_METHOD = 45 */
3662 NULL, /* HTTP_QUERY_REFRESH = 46 */
3663 L"Content-Disposition", /* HTTP_QUERY_CONTENT_DISPOSITION = 47 */
3664 L"Age", /* HTTP_QUERY_AGE = 48 */
3665 L"Cache-Control", /* HTTP_QUERY_CACHE_CONTROL = 49 */
3666 L"Content-Base", /* HTTP_QUERY_CONTENT_BASE = 50 */
3667 L"Content-Location", /* HTTP_QUERY_CONTENT_LOCATION = 51 */
3668 L"Content-MD5", /* HTTP_QUERY_CONTENT_MD5 = 52 */
3669 L"Content-Range", /* HTTP_QUERY_CONTENT_RANGE = 53 */
3670 L"ETag", /* HTTP_QUERY_ETAG = 54 */
3671 L"Host", /* HTTP_QUERY_HOST = 55 */
3672 L"If-Match", /* HTTP_QUERY_IF_MATCH = 56 */
3673 L"If-None-Match", /* HTTP_QUERY_IF_NONE_MATCH = 57 */
3674 L"If-Range", /* HTTP_QUERY_IF_RANGE = 58 */
3675 L"If-Unmodified-Since", /* HTTP_QUERY_IF_UNMODIFIED_SINCE = 59 */
3676 L"Max-Forwards", /* HTTP_QUERY_MAX_FORWARDS = 60 */
3677 L"Proxy-Authorization", /* HTTP_QUERY_PROXY_AUTHORIZATION = 61 */
3678 L"Range", /* HTTP_QUERY_RANGE = 62 */
3679 L"Transfer-Encoding", /* HTTP_QUERY_TRANSFER_ENCODING = 63 */
3680 L"Upgrade", /* HTTP_QUERY_UPGRADE = 64 */
3681 L"Vary", /* HTTP_QUERY_VARY = 65 */
3682 L"Via", /* HTTP_QUERY_VIA = 66 */
3683 L"Warning", /* HTTP_QUERY_WARNING = 67 */
3684 L"Expect", /* HTTP_QUERY_EXPECT = 68 */
3685 L"Proxy-Connection", /* HTTP_QUERY_PROXY_CONNECTION = 69 */
3686 L"Unless-Modified-Since", /* HTTP_QUERY_UNLESS_MODIFIED_SINCE = 70 */
3687};
3688
3689/***********************************************************************
3690 * HTTP_HttpQueryInfoW (internal)
3691 */
3694{
3695 LPHTTPHEADERW lphttpHdr = NULL;
3697 INT requested_index = lpdwIndex ? *lpdwIndex : 0;
3698 DWORD level = (dwInfoLevel & ~HTTP_QUERY_MODIFIER_FLAGS_MASK);
3699 INT index = -1;
3700
3701 EnterCriticalSection( &request->headers_section );
3702
3703 /* Find requested header structure */
3704 switch (level)
3705 {
3706 case HTTP_QUERY_CUSTOM:
3707 if (!lpBuffer)
3708 {
3709 LeaveCriticalSection( &request->headers_section );
3711 }
3712 index = HTTP_GetCustomHeaderIndex(request, lpBuffer, requested_index, request_only);
3713 break;
3715 {
3717 DWORD len = 0;
3719
3720 if (request_only)
3722 else
3724 if (!headers)
3725 {
3726 LeaveCriticalSection( &request->headers_section );
3727 return ERROR_OUTOFMEMORY;
3728 }
3729
3730 len = lstrlenW(headers) * sizeof(WCHAR);
3731 if (len + sizeof(WCHAR) > *lpdwBufferLength)
3732 {
3733 len += sizeof(WCHAR);
3735 }
3736 else if (lpBuffer)
3737 {
3738 memcpy(lpBuffer, headers, len + sizeof(WCHAR));
3739 TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len / sizeof(WCHAR)));
3741 }
3743
3744 free(headers);
3745 LeaveCriticalSection( &request->headers_section );
3746 return res;
3747 }
3749 {
3751 DWORD len;
3752
3753 if (request_only)
3755 else
3757
3758 if (!headers)
3759 {
3760 LeaveCriticalSection( &request->headers_section );
3761 return ERROR_OUTOFMEMORY;
3762 }
3763
3764 len = lstrlenW(headers) * sizeof(WCHAR);
3765 if (len > *lpdwBufferLength)
3766 {
3768 free(headers);
3769 LeaveCriticalSection( &request->headers_section );
3771 }
3772
3773 if (lpBuffer)
3774 {
3775 DWORD i;
3776
3777 TRACE("returning data: %s\n", debugstr_wn(headers, len / sizeof(WCHAR)));
3778
3779 for (i = 0; i < len / sizeof(WCHAR); i++)
3780 {
3781 if (headers[i] == '\n')
3782 headers[i] = 0;
3783 }
3785 }
3786 *lpdwBufferLength = len - sizeof(WCHAR);
3787
3788 free(headers);
3789 LeaveCriticalSection( &request->headers_section );
3790 return ERROR_SUCCESS;
3791 }
3793 if (request->statusText)
3794 {
3795 DWORD len = lstrlenW(request->statusText);
3796 if (len + 1 > *lpdwBufferLength/sizeof(WCHAR))
3797 {
3798 *lpdwBufferLength = (len + 1) * sizeof(WCHAR);
3799 LeaveCriticalSection( &request->headers_section );
3801 }
3802 if (lpBuffer)
3803 {
3804 memcpy(lpBuffer, request->statusText, (len + 1) * sizeof(WCHAR));
3805 TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len));
3806 }
3807 *lpdwBufferLength = len * sizeof(WCHAR);
3808 LeaveCriticalSection( &request->headers_section );
3809 return ERROR_SUCCESS;
3810 }
3811 break;
3812 case HTTP_QUERY_VERSION:
3813 if (request->version)
3814 {
3816 if (len + 1 > *lpdwBufferLength/sizeof(WCHAR))
3817 {
3818 *lpdwBufferLength = (len + 1) * sizeof(WCHAR);
3819 LeaveCriticalSection( &request->headers_section );
3821 }
3822 if (lpBuffer)
3823 {
3824 memcpy(lpBuffer, request->version, (len + 1) * sizeof(WCHAR));
3825 TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len));
3826 }
3827 *lpdwBufferLength = len * sizeof(WCHAR);
3828 LeaveCriticalSection( &request->headers_section );
3829 return ERROR_SUCCESS;
3830 }
3831 break;
3834 requested_index,request_only);
3835 break;
3838
3839 if(request_only)
3840 {
3841 LeaveCriticalSection( &request->headers_section );
3843 }
3844
3845 if(requested_index)
3846 break;
3847
3849 if(*lpdwBufferLength >= sizeof(DWORD))
3850 *(DWORD*)lpBuffer = request->status_code;
3851 else
3853 *lpdwBufferLength = sizeof(DWORD);
3854 }else {
3855 WCHAR buf[12];
3856 DWORD size;
3857
3858 size = swprintf(buf, ARRAY_SIZE(buf), L"%u", request->status_code) * sizeof(WCHAR);
3859
3860 if(size <= *lpdwBufferLength) {
3861 memcpy(lpBuffer, buf, size+sizeof(WCHAR));
3862 }else {
3863 size += sizeof(WCHAR);
3865 }
3866
3868 }
3869 LeaveCriticalSection( &request->headers_section );
3870 return res;
3871 }
3872 default:
3874
3877 requested_index,request_only);
3878 }
3879
3880 if (index >= 0)
3881 lphttpHdr = &request->custHeaders[index];
3882
3883 /* Ensure header satisfies requested attributes */
3884 if (!lphttpHdr ||
3886 (~lphttpHdr->wFlags & HDR_ISREQUEST)))
3887 {
3888 LeaveCriticalSection( &request->headers_section );
3890 }
3891
3892 /* coalesce value to requested type */
3894 {
3895 unsigned long value;
3896
3897 if (*lpdwBufferLength != sizeof(DWORD))
3898 {
3899 LeaveCriticalSection( &request->headers_section );
3901 }
3902
3903 errno = 0;
3904 value = wcstoul( lphttpHdr->lpszValue, NULL, 10 );
3905 if (value > UINT_MAX || (value == ULONG_MAX && errno == ERANGE))
3906 {
3907 LeaveCriticalSection( &request->headers_section );
3909 }
3910
3911 *(DWORD *)lpBuffer = value;
3912 TRACE(" returning number: %lu\n", *(DWORD *)lpBuffer);
3913 }
3915 {
3916 SYSTEMTIME st;
3917
3918 if (!InternetTimeToSystemTimeW(lphttpHdr->lpszValue, &st, 0))
3919 {
3920 LeaveCriticalSection( &request->headers_section );
3922 }
3923 if (*lpdwBufferLength < sizeof(st))
3924 {
3925 *lpdwBufferLength = sizeof(st);
3926 LeaveCriticalSection( &request->headers_section );
3928 }
3929 TRACE(" returning time: %04u/%02u/%02u - %u - %02u:%02u:%02u.%02u\n",
3930 st.wYear, st.wMonth, st.wDay, st.wDayOfWeek, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
3931 memcpy(lpBuffer, &st, sizeof(st));
3932 *lpdwBufferLength = sizeof(st);
3933 }
3934 else if (lphttpHdr->lpszValue)
3935 {
3936 DWORD len = (lstrlenW(lphttpHdr->lpszValue) + 1) * sizeof(WCHAR);
3937
3938 if (len > *lpdwBufferLength)
3939 {
3941 LeaveCriticalSection( &request->headers_section );
3943 }
3944 if (lpBuffer)
3945 {
3946 memcpy(lpBuffer, lphttpHdr->lpszValue, len);
3947 TRACE("! returning string: %s\n", debugstr_w(lpBuffer));
3948 }
3949 *lpdwBufferLength = len - sizeof(WCHAR);
3950 }
3951 if (lpdwIndex) (*lpdwIndex)++;
3952
3953 LeaveCriticalSection( &request->headers_section );
3954 return ERROR_SUCCESS;
3955}
3956
3957/***********************************************************************
3958 * HttpQueryInfoW (WININET.@)
3959 *
3960 * Queries for information about an HTTP request
3961 *
3962 * RETURNS
3963 * TRUE on success
3964 * FALSE on failure
3965 *
3966 */
3969{
3971 DWORD res;
3972
3973 if (TRACE_ON(wininet)) {
3974#define FE(x) { x, #x }
3975 static const wininet_flag_info query_flags[] = {
4045 };
4046 static const wininet_flag_info modifier_flags[] = {
4051 };
4052#undef FE
4055 DWORD i;
4056
4057 TRACE("(%p, 0x%08lx)--> %ld\n", hHttpRequest, dwInfoLevel, info);
4058 TRACE(" Attribute:");
4059 for (i = 0; i < ARRAY_SIZE(query_flags); i++) {
4060 if (query_flags[i].val == info) {
4061 TRACE(" %s", query_flags[i].name);
4062 break;
4063 }
4064 }
4065 if (i == ARRAY_SIZE(query_flags)) {
4066 TRACE(" Unknown (%08lx)", info);
4067 }
4068
4069 TRACE(" Modifier:");
4070 for (i = 0; i < ARRAY_SIZE(modifier_flags); i++) {
4071 if (modifier_flags[i].val & info_mod) {
4072 TRACE(" %s", modifier_flags[i].name);
4073 info_mod &= ~ modifier_flags[i].val;
4074 }
4075 }
4076
4077 if (info_mod) {
4078 TRACE(" Unknown (%08lx)", info_mod);
4079 }
4080 TRACE("\n");
4081 }
4082
4083 request = (http_request_t*) get_handle_object( hHttpRequest );
4084 if (NULL == request || request->hdr.htype != WH_HHTTPREQ)
4085 {
4087 goto lend;
4088 }
4089
4090 if (lpBuffer == NULL)
4091 *lpdwBufferLength = 0;
4093 lpBuffer, lpdwBufferLength, lpdwIndex);
4094
4095lend:
4096 if( request )
4098
4099 TRACE("%lu <--\n", res);
4100
4102 return res == ERROR_SUCCESS;
4103}
4104
4105/***********************************************************************
4106 * HttpQueryInfoA (WININET.@)
4107 *
4108 * Queries for information about an HTTP request
4109 *
4110 * RETURNS
4111 * TRUE on success
4112 * FALSE on failure
4113 *
4114 */
4117{
4118 BOOL result;
4119 DWORD len;
4120 WCHAR* bufferW;
4121
4122 TRACE("%p %lx\n", hHttpRequest, dwInfoLevel);
4123
4126 {
4127 return HttpQueryInfoW( hHttpRequest, dwInfoLevel, lpBuffer,
4128 lpdwBufferLength, lpdwIndex );
4129 }
4130
4131 if (lpBuffer)
4132 {
4133 DWORD alloclen;
4134 len = (*lpdwBufferLength)*sizeof(WCHAR);
4136 {
4137 alloclen = MultiByteToWideChar( CP_ACP, 0, lpBuffer, -1, NULL, 0 ) * sizeof(WCHAR);
4138 if (alloclen < len)
4139 alloclen = len;
4140 }
4141 else
4142 alloclen = len;
4143 bufferW = malloc( alloclen );
4144 /* buffer is in/out because of HTTP_QUERY_CUSTOM */
4146 MultiByteToWideChar( CP_ACP, 0, lpBuffer, -1, bufferW, alloclen / sizeof(WCHAR) );
4147 } else
4148 {
4149 bufferW = NULL;
4150 len = 0;
4151 }
4152
4153 result = HttpQueryInfoW( hHttpRequest, dwInfoLevel, bufferW,
4154 &len, lpdwIndex );
4155 if( result )
4156 {
4157 len = WideCharToMultiByte( CP_ACP,0, bufferW, len / sizeof(WCHAR) + 1,
4159 *lpdwBufferLength = len - 1;
4160
4161 TRACE("lpBuffer: %s\n", debugstr_a(lpBuffer));
4162 }
4163 else
4164 /* since the strings being returned from HttpQueryInfoW should be
4165 * only ASCII characters, it is reasonable to assume that all of
4166 * the Unicode characters can be reduced to a single byte */
4167 *lpdwBufferLength = len / sizeof(WCHAR);
4168
4169 free( bufferW );
4170 return result;
4171}
4172
4174{
4175 static WCHAR szHttp[] = L"http";
4176 static WCHAR szHttps[] = L"https";
4177 http_session_t *session = request->session;
4178 URL_COMPONENTSW urlComponents = { sizeof(urlComponents) };
4179 WCHAR *orig_url = NULL, *redirect_url = NULL, *combined_url = NULL;
4180 DWORD url_length = 0, res;
4181 BOOL b;
4182
4183 url_length = 0;
4184 res = HTTP_HttpQueryInfoW(request, HTTP_QUERY_LOCATION, redirect_url, &url_length, NULL);
4186 redirect_url = malloc(url_length);
4187 res = HTTP_HttpQueryInfoW(request, HTTP_QUERY_LOCATION, redirect_url, &url_length, NULL);
4188 }
4189 if(res != ERROR_SUCCESS) {
4190 free(redirect_url);
4191 return NULL;
4192 }
4193
4194 urlComponents.dwSchemeLength = 1;
4195 b = InternetCrackUrlW(redirect_url, url_length / sizeof(WCHAR), 0, &urlComponents);
4196 if(b && urlComponents.dwSchemeLength &&
4197 urlComponents.nScheme != INTERNET_SCHEME_HTTP && urlComponents.nScheme != INTERNET_SCHEME_HTTPS) {
4198 TRACE("redirect to non-http URL\n");
4199 return NULL;
4200 }
4201
4202 urlComponents.lpszScheme = (request->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp;
4203 urlComponents.dwSchemeLength = 0;
4204 urlComponents.lpszHostName = request->server->name;
4205 urlComponents.nPort = request->server->port;
4206 urlComponents.lpszUserName = session->userName;
4207 urlComponents.lpszUrlPath = request->path;
4208
4209 b = InternetCreateUrlW(&urlComponents, 0, NULL, &url_length);
4211 orig_url = malloc(url_length);
4212
4213 /* convert from bytes to characters */
4214 url_length = url_length / sizeof(WCHAR) - 1;
4215 b = InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length);
4216 }
4217
4218 if(b) {
4219 url_length = 0;
4220 b = InternetCombineUrlW(orig_url, redirect_url, NULL, &url_length, ICU_ENCODE_SPACES_ONLY);
4222 combined_url = malloc(url_length * sizeof(WCHAR));
4223 b = InternetCombineUrlW(orig_url, redirect_url, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY);
4224 if(!b) {
4227 }
4228 }
4229 }
4230
4231 free(orig_url);
4232 free(redirect_url);
4233 return combined_url;
4234}
4235
4236
4237/***********************************************************************
4238 * HTTP_HandleRedirect (internal)
4239 */
4241{
4242 URL_COMPONENTSW urlComponents = { sizeof(urlComponents) };
4243 http_session_t *session = request->session;
4244 size_t url_len = lstrlenW(url);
4245
4246 if(url[0] == '/')
4247 {
4248 /* if it's an absolute path, keep the same session info */
4249 urlComponents.lpszUrlPath = url;
4250 urlComponents.dwUrlPathLength = url_len;
4251 }
4252 else
4253 {
4254 urlComponents.dwHostNameLength = 1;
4255 urlComponents.dwUserNameLength = 1;
4256 urlComponents.dwUrlPathLength = 1;
4257 if(!InternetCrackUrlW(url, url_len, 0, &urlComponents))
4258 return INTERNET_GetLastError();
4259
4260 if(!urlComponents.dwHostNameLength)
4262 }
4263
4265 url, (url_len + 1) * sizeof(WCHAR));
4266
4267 if(urlComponents.dwHostNameLength) {
4268 BOOL custom_port = FALSE;
4269 substr_t host;
4270
4271 if(urlComponents.nScheme == INTERNET_SCHEME_HTTP) {
4272 if(request->hdr.dwFlags & INTERNET_FLAG_SECURE) {
4273 TRACE("redirect from secure page to non-secure page\n");
4274 /* FIXME: warn about from secure redirect to non-secure page */
4275 request->hdr.dwFlags &= ~INTERNET_FLAG_SECURE;
4276 }
4277
4278 custom_port = urlComponents.nPort != INTERNET_DEFAULT_HTTP_PORT;
4279 }else if(urlComponents.nScheme == INTERNET_SCHEME_HTTPS) {
4280 if(!(request->hdr.dwFlags & INTERNET_FLAG_SECURE)) {
4281 TRACE("redirect from non-secure page to secure page\n");
4282 /* FIXME: notify about redirect to secure page */
4283 request->hdr.dwFlags |= INTERNET_FLAG_SECURE;
4284 }
4285
4286 custom_port = urlComponents.nPort != INTERNET_DEFAULT_HTTPS_PORT;
4287 }
4288
4289 free(session->hostName);
4290
4291 session->hostName = strndupW(urlComponents.lpszHostName, urlComponents.dwHostNameLength);
4292 session->hostPort = urlComponents.nPort;
4293
4294 free(session->userName);
4295 session->userName = NULL;
4296 if (urlComponents.dwUserNameLength)
4297 session->userName = strndupW(urlComponents.lpszUserName, urlComponents.dwUserNameLength);
4298
4300
4301 host = substr(urlComponents.lpszHostName, urlComponents.dwHostNameLength);
4302
4303 if(host.len != lstrlenW(request->server->name) || wcsnicmp(request->server->name, host.str, host.len)
4304 || request->server->port != urlComponents.nPort) {
4305 server_t *new_server;
4306
4307 new_server = get_server(host, urlComponents.nPort, urlComponents.nScheme == INTERNET_SCHEME_HTTPS, TRUE);
4308 server_release(request->server);
4309 request->server = new_server;
4310 }
4311
4312 if (custom_port)
4313 HTTP_ProcessHeader(request, L"Host", request->server->host_port,
4315 else
4316 HTTP_ProcessHeader(request, L"Host", request->server->name,
4318 }
4319
4320 free(request->path);
4321 request->path = NULL;
4322 if(urlComponents.dwUrlPathLength)
4323 {
4324 DWORD needed = 1;
4325 HRESULT rc;
4326 WCHAR dummy[] = L"";
4327 WCHAR *path;
4328
4329 path = strndupW(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength);
4331 if (rc != E_POINTER)
4332 ERR("Unable to escape string!(%s) (%ld)\n",debugstr_w(path),rc);
4333 request->path = malloc(needed * sizeof(WCHAR));
4334 rc = UrlEscapeW(path, request->path, &needed,
4336 if (rc != S_OK)
4337 {
4338 ERR("Unable to escape string!(%s) (%ld)\n",debugstr_w(path),rc);
4340 }
4341 free(path);
4342 }
4343
4344 /* Remove custom content-type/length headers on redirects. */
4345 remove_header(request, L"Content-Type", TRUE);
4346 remove_header(request, L"Content-Length", TRUE);
4347
4348 return ERROR_SUCCESS;
4349}
4350
4351/***********************************************************************
4352 * HTTP_build_req (internal)
4353 *
4354 * concatenate all the strings in the request together
4355 */
4357{
4358 LPCWSTR *t;
4359 LPWSTR str;
4360
4361 for( t = list; *t ; t++ )
4362 len += lstrlenW( *t );
4363 len++;
4364
4365 str = malloc(len * sizeof(WCHAR));
4366 *str = 0;
4367
4368 for( t = list; *t ; t++ )
4369 lstrcatW( str, *t );
4370
4371 return str;
4372}
4373
4375{
4376 WCHAR *cookies;
4377 DWORD res;
4378
4379 res = get_cookie_header(request->server->name, request->path, &cookies);
4380 if(res != ERROR_SUCCESS || !cookies)
4381 return;
4382
4385 free(cookies);
4386}
4387
4389{
4390 static const WCHAR days[7][4] = {L"sun",
4391 L"mon",
4392 L"tue",
4393 L"wed",
4394 L"thu",
4395 L"fri",
4396 L"sat"};
4397 unsigned int i;
4398 for (i = 0; i < ARRAY_SIZE(days); i++)
4399 if (!wcsicmp(day, days[i]))
4400 return i;
4401
4402 /* Invalid */
4403 return 7;
4404}
4405
4407{
4408 if (!wcsicmp(month, L"jan")) return 1;
4409 if (!wcsicmp(month, L"feb")) return 2;
4410 if (!wcsicmp(month, L"mar")) return 3;
4411 if (!wcsicmp(month, L"apr")) return 4;
4412 if (!wcsicmp(month, L"may")) return 5;
4413 if (!wcsicmp(month, L"jun")) return 6;
4414 if (!wcsicmp(month, L"jul")) return 7;
4415 if (!wcsicmp(month, L"aug")) return 8;
4416 if (!wcsicmp(month, L"sep")) return 9;
4417 if (!wcsicmp(month, L"oct")) return 10;
4418 if (!wcsicmp(month, L"nov")) return 11;
4419 if (!wcsicmp(month, L"dec")) return 12;
4420 /* Invalid */
4421 return 0;
4422}
4423
4424/* Parses the string pointed to by *str, assumed to be a 24-hour time HH:MM:SS,
4425 * optionally preceded by whitespace.
4426 * Upon success, returns TRUE, sets the wHour, wMinute, and wSecond fields of
4427 * st, and sets *str to the first character after the time format.
4428 */
4430{
4431 LPCWSTR ptr = *str;
4432 WCHAR *nextPtr;
4433 unsigned long num;
4434
4435 while (iswspace(*ptr))
4436 ptr++;
4437
4438 num = wcstoul(ptr, &nextPtr, 10);
4439 if (!nextPtr || nextPtr <= ptr || *nextPtr != ':')
4440 {
4441 ERR("unexpected time format %s\n", debugstr_w(ptr));
4442 return FALSE;
4443 }
4444 if (num > 23)
4445 {
4446 ERR("unexpected hour in time format %s\n", debugstr_w(ptr));
4447 return FALSE;
4448 }
4449 ptr = nextPtr + 1;
4450 st->wHour = (WORD)num;
4451 num = wcstoul(ptr, &nextPtr, 10);
4452 if (!nextPtr || nextPtr <= ptr || *nextPtr != ':')
4453 {
4454 ERR("unexpected time format %s\n", debugstr_w(ptr));
4455 return FALSE;
4456 }
4457 if (num > 59)
4458 {
4459 ERR("unexpected minute in time format %s\n", debugstr_w(ptr));
4460 return FALSE;
4461 }
4462 ptr = nextPtr + 1;
4463 st->wMinute = (WORD)num;
4464 num = wcstoul(ptr, &nextPtr, 10);
4465 if (!nextPtr || nextPtr <= ptr)
4466 {
4467 ERR("unexpected time format %s\n", debugstr_w(ptr));
4468 return FALSE;
4469 }
4470 if (num > 59)
4471 {
4472 ERR("unexpected second in time format %s\n", debugstr_w(ptr));
4473 return FALSE;
4474 }
4475 *str = nextPtr;
4476 st->wSecond = (WORD)num;
4477 return TRUE;
4478}
4479
4481{
4482 WCHAR day[4], *dayPtr, month[4], *monthPtr, *nextPtr;
4483 LPCWSTR ptr;
4484 SYSTEMTIME st = { 0 };
4485 unsigned long num;
4486
4487 for (ptr = value, dayPtr = day; *ptr && !iswspace(*ptr) &&
4488 dayPtr - day < ARRAY_SIZE(day) - 1; ptr++, dayPtr++)
4489 *dayPtr = *ptr;
4490 *dayPtr = 0;
4492 if (st.wDayOfWeek >= 7)
4493 {
4494 ERR("unexpected weekday %s\n", debugstr_w(day));
4495 return FALSE;
4496 }
4497
4498 while (iswspace(*ptr))
4499 ptr++;
4500
4501 for (monthPtr = month; !iswspace(*ptr) && monthPtr - month < ARRAY_SIZE(month) - 1;
4502 monthPtr++, ptr++)
4503 *monthPtr = *ptr;
4504 *monthPtr = 0;
4506 if (!st.wMonth || st.wMonth > 12)
4507 {
4508 ERR("unexpected month %s\n", debugstr_w(month));
4509 return FALSE;
4510 }
4511
4512 while (iswspace(*ptr))
4513 ptr++;
4514
4515 num = wcstoul(ptr, &nextPtr, 10);
4516 if (!nextPtr || nextPtr <= ptr || !num || num > 31)
4517 {
4518 ERR("unexpected day %s\n", debugstr_w(ptr));
4519 return FALSE;
4520 }
4521 ptr = nextPtr;
4522 st.wDay = (WORD)num;
4523
4524 while (iswspace(*ptr))
4525 ptr++;
4526
4527 if (!HTTP_ParseTime(&st, &ptr))
4528 return FALSE;
4529
4530 while (iswspace(*ptr))
4531 ptr++;
4532
4533 num = wcstoul(ptr, &nextPtr, 10);
4534 if (!nextPtr || nextPtr <= ptr || num < 1601 || num > 30827)
4535 {
4536 ERR("unexpected year %s\n", debugstr_w(ptr));
4537 return FALSE;
4538 }
4539 ptr = nextPtr;
4540 st.wYear = (WORD)num;
4541
4542 while (iswspace(*ptr))
4543 ptr++;
4544
4545 /* asctime() doesn't report a timezone, but some web servers do, so accept
4546 * with or without GMT.
4547 */
4548 if (*ptr && (wcscmp(ptr, L"GMT") && wcscmp(ptr, L"UTC")))
4549 {
4550 ERR("unexpected timezone %s\n", debugstr_w(ptr));
4551 return FALSE;
4552 }
4553 return SystemTimeToFileTime(&st, ft);
4554}
4555
4557{
4558 WCHAR *nextPtr, day[4], month[4], *monthPtr;
4559 LPCWSTR ptr;
4560 unsigned long num;
4561 SYSTEMTIME st = { 0 };
4562
4563 ptr = wcschr(value, ',');
4564 if (!ptr)
4565 return FALSE;
4566 if (ptr - value != 3)
4567 {
4568 WARN("unexpected weekday %s\n", debugstr_wn(value, ptr - value));
4569 return FALSE;
4570 }
4571 memcpy(day, value, (ptr - value) * sizeof(WCHAR));
4572 day[3] = 0;
4574 if (st.wDayOfWeek > 6)
4575 {
4576 WARN("unexpected weekday %s\n", debugstr_wn(value, ptr - value));
4577 return FALSE;
4578 }
4579 ptr++;
4580
4581 while (iswspace(*ptr))
4582 ptr++;
4583
4584 num = wcstoul(ptr, &nextPtr, 10);
4585 if (!nextPtr || nextPtr <= ptr || !num || num > 31)
4586 {
4587 WARN("unexpected day %s\n", debugstr_w(value));
4588 return FALSE;
4589 }
4590 ptr = nextPtr;
4591 st.wDay = (WORD)num;
4592
4593 while (iswspace(*ptr))
4594 ptr++;
4595
4596 for (monthPtr = month; !iswspace(*ptr) && monthPtr - month < ARRAY_SIZE(month) - 1;
4597 monthPtr++, ptr++)
4598 *monthPtr = *ptr;
4599 *monthPtr = 0;
4601 if (!st.wMonth || st.wMonth > 12)
4602 {
4603 WARN("unexpected month %s\n", debugstr_w(month));
4604 return FALSE;
4605 }
4606
4607 while (iswspace(*ptr))
4608 ptr++;
4609
4610 num = wcstoul(ptr, &nextPtr, 10);
4611 if (!nextPtr || nextPtr <= ptr || num < 1601 || num > 30827)
4612 {
4613 ERR("unexpected year %s\n", debugstr_w(value));
4614 return FALSE;
4615 }
4616 ptr = nextPtr;
4617 st.wYear = (WORD)num;
4618
4619 if (!HTTP_ParseTime(&st, &ptr))
4620 return FALSE;
4621
4622 while (iswspace(*ptr))
4623 ptr++;
4624
4625 if (wcscmp(ptr, L"GMT") && wcscmp(ptr, L"UTC"))
4626 {
4627 ERR("unexpected time zone %s\n", debugstr_w(ptr));
4628 return FALSE;
4629 }
4630 return SystemTimeToFileTime(&st, ft);
4631}
4632
4634{
4635 static const WCHAR days[7][10] = {L"sunday",
4636 L"monday",
4637 L"tuesday",
4638 L"wednesday",
4639 L"thursday",
4640 L"friday",
4641 L"saturday"};
4642 unsigned int i;
4643 for (i = 0; i < ARRAY_SIZE(days); i++)
4644 if (!wcsicmp(day, days[i]))
4645 return i;
4646
4647 /* Invalid */
4648 return 7;
4649}
4650
4652{
4653 WCHAR *nextPtr, day[10], month[4], *monthPtr;
4654 LPCWSTR ptr;
4655 unsigned long num;
4656 SYSTEMTIME st = { 0 };
4657
4658 ptr = wcschr(value, ',');
4659 if (!ptr)
4660 return FALSE;
4661 if (ptr - value == 3)
4662 {
4663 memcpy(day, value, (ptr - value) * sizeof(WCHAR));
4664 day[3] = 0;
4666 if (st.wDayOfWeek > 6)
4667 {
4668 ERR("unexpected weekday %s\n", debugstr_wn(value, ptr - value));
4669 return FALSE;
4670 }
4671 }
4672 else if (ptr - value < ARRAY_SIZE(day))
4673 {
4674 memcpy(day, value, (ptr - value) * sizeof(WCHAR));
4675 day[ptr - value + 1] = 0;
4677 if (st.wDayOfWeek > 6)
4678 {
4679 ERR("unexpected weekday %s\n", debugstr_wn(value, ptr - value));
4680 return FALSE;
4681 }
4682 }
4683 else
4684 {
4685 ERR("unexpected weekday %s\n", debugstr_wn(value, ptr - value));
4686 return FALSE;
4687 }
4688 ptr++;
4689
4690 while (iswspace(*ptr))
4691 ptr++;
4692
4693 num = wcstoul(ptr, &nextPtr, 10);
4694 if (!nextPtr || nextPtr <= ptr || !num || num > 31)
4695 {
4696 ERR("unexpected day %s\n", debugstr_w(value));
4697 return FALSE;
4698 }
4699 ptr = nextPtr;
4700 st.wDay = (WORD)num;
4701
4702 if (*ptr != '-')
4703 {
4704 ERR("unexpected month format %s\n", debugstr_w(ptr));
4705 return FALSE;
4706 }
4707 ptr++;
4708
4709 for (monthPtr = month; *ptr != '-' && monthPtr - month < ARRAY_SIZE(month) - 1;
4710 monthPtr++, ptr++)
4711 *monthPtr = *ptr;
4712 *monthPtr = 0;
4714 if (!st.wMonth || st.wMonth > 12)
4715 {
4716 ERR("unexpected month %s\n", debugstr_w(month));
4717 return FALSE;
4718 }
4719
4720 if (*ptr != '-')
4721 {
4722 ERR("unexpected year format %s\n", debugstr_w(ptr));
4723 return FALSE;
4724 }
4725 ptr++;
4726
4727 num = wcstoul(ptr, &nextPtr, 10);
4728 if (!nextPtr || nextPtr <= ptr || num < 1601 || num > 30827)
4729 {
4730 ERR("unexpected year %s\n", debugstr_w(value));
4731 return FALSE;
4732 }
4733 ptr = nextPtr;
4734 st.wYear = (WORD)num;
4735
4736 if (!HTTP_ParseTime(&st, &ptr))
4737 return FALSE;
4738
4739 while (iswspace(*ptr))
4740 ptr++;
4741
4742 if (wcscmp(ptr, L"GMT") && wcscmp(ptr, L"UTC"))
4743 {
4744 ERR("unexpected time zone %s\n", debugstr_w(ptr));
4745 return FALSE;
4746 }
4747 return SystemTimeToFileTime(&st, ft);
4748}
4749
4751{
4752 BOOL ret;
4753
4754 if (!wcscmp(value, L"0"))
4755 {
4756 ft->dwLowDateTime = ft->dwHighDateTime = 0;
4757 ret = TRUE;
4758 }
4759 else if (wcschr(value, ','))
4760 {
4762 if (!ret)
4763 {
4765 if (!ret)
4766 ERR("unexpected date format %s\n", debugstr_w(value));
4767 }
4768 }
4769 else
4770 {
4772 if (!ret)
4773 ERR("unexpected date format %s\n", debugstr_w(value));
4774 }
4775 return ret;
4776}
4777
4779{
4780 BOOL expirationFound = FALSE;
4781 int headerIndex;
4782
4783 EnterCriticalSection( &request->headers_section );
4784
4785 /* Look for a Cache-Control header with a max-age directive, as it takes
4786 * precedence over the Expires header.
4787 */
4788 headerIndex = HTTP_GetCustomHeaderIndex(request, L"Cache-Control", 0, FALSE);
4789 if (headerIndex != -1)
4790 {
4791 LPHTTPHEADERW ccHeader = &request->custHeaders[headerIndex];
4792 LPWSTR ptr;
4793
4794 for (ptr = ccHeader->lpszValue; ptr && *ptr; )
4795 {
4796 LPWSTR comma = wcschr(ptr, ','), end, equal;
4797
4798 if (comma)
4799 end = comma;
4800 else
4801 end = ptr + lstrlenW(ptr);
4802 for (equal = end - 1; equal > ptr && *equal != '='; equal--)
4803 ;
4804 if (*equal == '=')
4805 {
4806 if (!wcsnicmp(ptr, L"max-age", equal - ptr - 1))
4807 {
4808 LPWSTR nextPtr;
4809 unsigned long age;
4810
4811 age = wcstoul(equal + 1, &nextPtr, 10);
4812 if (nextPtr > equal + 1)
4813 {
4814 LARGE_INTEGER ft;
4815
4816 NtQuerySystemTime( &ft );
4817 /* Age is in seconds, FILETIME resolution is in
4818 * 100 nanosecond intervals.
4819 */
4820 ft.QuadPart += age * (ULONGLONG)1000000;
4821 request->expires.dwLowDateTime = ft.u.LowPart;
4822 request->expires.dwHighDateTime = ft.u.HighPart;
4823 expirationFound = TRUE;
4824 }
4825 }
4826 }
4827 if (comma)
4828 {
4829 ptr = comma + 1;
4830 while (iswspace(*ptr))
4831 ptr++;
4832 }
4833 else
4834 ptr = NULL;
4835 }
4836 }
4837 if (!expirationFound)
4838 {
4839 headerIndex = HTTP_GetCustomHeaderIndex(request, L"Expires", 0, FALSE);
4840 if (headerIndex != -1)
4841 {
4842 LPHTTPHEADERW expiresHeader = &request->custHeaders[headerIndex];
4843 FILETIME ft;
4844
4845 if (HTTP_ParseDate(expiresHeader->lpszValue, &ft))
4846 {
4847 expirationFound = TRUE;
4848 request->expires = ft;
4849 }
4850 }
4851 }
4852 if (!expirationFound)
4853 {
4855
4856 /* With no known age, default to 10 minutes until expiration. */
4857 NtQuerySystemTime( &t );
4858 t.QuadPart += 10 * 60 * (ULONGLONG)10000000;
4859 request->expires.dwLowDateTime = t.u.LowPart;
4860 request->expires.dwHighDateTime = t.u.HighPart;
4861 }
4862
4863 LeaveCriticalSection( &request->headers_section );
4864}
4865
4867{
4868 int headerIndex;
4869
4870 EnterCriticalSection( &request->headers_section );
4871
4872 headerIndex = HTTP_GetCustomHeaderIndex(request, L"Last-Modified", 0, FALSE);
4873 if (headerIndex != -1)
4874 {
4875 LPHTTPHEADERW expiresHeader = &request->custHeaders[headerIndex];
4876 FILETIME ft;
4877
4878 if (HTTP_ParseDate(expiresHeader->lpszValue, &ft))
4879 request->last_modified = ft;
4880 }
4881
4882 LeaveCriticalSection( &request->headers_section );
4883}
4884
4886{
4887 const WCHAR *connection = L"";
4888 int index;
4889
4891
4892 if ((index = HTTP_GetCustomHeaderIndex(req, L"Connection", 0, FALSE)) != -1 ||
4893 (index = HTTP_GetCustomHeaderIndex(req, L"Proxy-Connection", 0, FALSE)) != -1)
4896
4898}
4899
4901{
4903 DWORD res;
4904
4905 if (request->netconn)
4906 {
4908 {
4910 *reusing = TRUE;
4911 return ERROR_SUCCESS;
4912 }
4913
4914 TRACE("freeing netconn\n");
4916 request->netconn = NULL;
4917 }
4918
4920
4922 if(res != ERROR_SUCCESS)
4923 return res;
4924
4926
4927 while(!list_empty(&request->server->conn_pool)) {
4928 netconn = LIST_ENTRY(list_head(&request->server->conn_pool), netconn_t, pool_entry);
4929 list_remove(&netconn->pool_entry);
4930
4932 break;
4933
4934 TRACE("connection %p closed during idle\n", netconn);
4936 netconn = NULL;
4937 }
4938
4940
4941 if(netconn) {
4942 TRACE("<-- reusing %p netconn\n", netconn);
4944 *reusing = TRUE;
4945 return ERROR_SUCCESS;
4946 }
4947
4948 TRACE("connecting to %s, proxy %s\n", debugstr_w(request->server->name),
4949 request->proxy ? debugstr_w(request->proxy->name) : "(null)");
4950
4953 request->server->addr_str,
4954 strlen(request->server->addr_str)+1);
4955
4956 res = create_netconn(request->proxy ? request->proxy : request->server, request->security_flags,
4958 request->hdr.connect_timeout, &netconn);
4959 if(res != ERROR_SUCCESS) {
4960 ERR("create_netconn failed: %lu\n", res);
4961 return res;
4962 }
4963
4965
4968 request->server->addr_str, strlen(request->server->addr_str)+1);
4969
4970 *reusing = FALSE;
4971 TRACE("Created connection to %s: %p\n", debugstr_w(request->server->name), netconn);
4972 return ERROR_SUCCESS;
4973}
4974
4975static char *build_ascii_request( const WCHAR *str, void *data, DWORD data_len, DWORD *out_len )
4976{
4977 int len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
4978 char *ret;
4979
4980 if (!(ret = malloc( len + data_len ))) return NULL;
4981 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
4982 if (data_len) memcpy( ret + len - 1, data, data_len );
4983 *out_len = len + data_len - 1;
4984 ret[*out_len] = 0;
4985 return ret;
4986}
4987
4989{
4990 WCHAR buf[ARRAY_SIZE(L"Content-Length: %u\r\n") + 10];
4991
4992 swprintf( buf, ARRAY_SIZE(buf), L"Content-Length: %u\r\n", len );
4994}
4995
4996/***********************************************************************
4997 * HTTP_HttpSendRequestW (internal)
4998 *
4999 * Sends the specified request to the HTTP server
5000 *
5001 * RETURNS
5002 * ERROR_SUCCESS on success
5003 * win32 error code on failure
5004 *
5005 */
5007 DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength,
5008 DWORD dwContentLength, BOOL bEndRequest)
5009{
5010 BOOL redirected = FALSE, secure_proxy_connect = FALSE, loop_next;
5011 WCHAR *request_header = NULL;
5012 INT responseLen, cnt;
5013 DWORD res;
5014 const WCHAR *appinfo_agent;
5015
5016 TRACE("--> %p\n", request);
5017
5018 assert(request->hdr.htype == WH_HHTTPREQ);
5019
5020 /* if the verb is NULL default to GET */
5021 if (!request->verb)
5022 request->verb = wcsdup(L"GET");
5023
5024 HTTP_ProcessHeader(request, L"Host", request->server->canon_host_port,
5026
5027 if (dwContentLength || wcscmp(request->verb, L"GET"))
5028 {
5030 request->bytesToWrite = dwContentLength;
5031 }
5032
5033 appinfo_agent = request->session->appInfo->agent;
5034
5035 if (appinfo_agent && *appinfo_agent)
5036 {
5037 WCHAR *agent_header;
5038 int len;
5039
5040 len = lstrlenW(appinfo_agent) + lstrlenW(L"User-Agent: %s\r\n");
5041 agent_header = malloc(len * sizeof(WCHAR));
5042 swprintf(agent_header, len, L"User-Agent: %s\r\n", appinfo_agent);
5043
5045 free(agent_header);
5046 }
5048 {
5049 HTTP_HttpAddRequestHeadersW(request, L"Pragma: no-cache\r\n",
5050 lstrlenW(L"Pragma: no-cache\r\n"), HTTP_ADDREQ_FLAG_ADD_IF_NEW);
5051 }
5052 if ((request->hdr.dwFlags & INTERNET_FLAG_NO_CACHE_WRITE) && wcscmp(request->verb, L"GET"))
5053 {
5054 HTTP_HttpAddRequestHeadersW(request, L"Cache-Control: no-cache\r\n",
5055 lstrlenW(L"Cache-Control: no-cache\r\n"), HTTP_ADDREQ_FLAG_ADD_IF_NEW);
5056 }
5057
5058 /* add the headers the caller supplied */
5059 if (lpszHeaders)
5060 {
5061 if (dwHeaderLength == 0)
5062 dwHeaderLength = lstrlenW(lpszHeaders);
5063
5065 }
5066
5067 do
5068 {
5069 DWORD len, data_len = dwOptionalLength;
5070 BOOL reusing_connection;
5071 char *ascii_req;
5072
5073 loop_next = FALSE;
5074
5075 if(redirected) {
5076 request->contentLength = ~0;
5077 request->bytesToWrite = 0;
5078 }
5079
5080 if (TRACE_ON(wininet))
5081 {
5083
5084 EnterCriticalSection( &request->headers_section );
5085 host = HTTP_GetHeader(request, L"Host");
5086 TRACE("Going to url %s %s\n", debugstr_w(host->lpszValue), debugstr_w(request->path));
5087 LeaveCriticalSection( &request->headers_section );
5088 }
5089
5092 {
5093 HTTP_ProcessHeader(request, L"Connection", L"Keep-Alive",
5095 }
5096 HTTP_InsertAuthorization(request, request->authInfo, L"Authorization");
5097 HTTP_InsertAuthorization(request, request->proxyAuthInfo, L"Proxy-Authorization");
5098
5099 if (!(request->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES))
5101
5102 res = open_http_connection(request, &reusing_connection);
5103 if (res != ERROR_SUCCESS)
5104 break;
5105
5106 if (!reusing_connection && (request->hdr.dwFlags & INTERNET_FLAG_SECURE))
5107 {
5108 if (request->proxy) secure_proxy_connect = TRUE;
5109 else
5110 {
5112 if (res != ERROR_SUCCESS)
5113 {
5114 WARN("failed to upgrade to secure connection\n");
5116 break;
5117 }
5118 }
5119 }
5121 {
5122 const WCHAR *target = request->server->host_port;
5123
5124 if (HTTP_GetCustomHeaderIndex(request, L"Content-Length", 0, TRUE) >= 0)
5126
5127 request_header = build_request_header(request, L"CONNECT", target, L"HTTP/1.1", TRUE);
5128 }
5129 else if (request->proxy && !(request->hdr.dwFlags & INTERNET_FLAG_SECURE))
5130 {
5133 free(url);
5134 }
5135 else
5136 {
5137 if (request->proxy && HTTP_GetCustomHeaderIndex(request, L"Content-Length", 0, TRUE) >= 0)
5139
5141 }
5142
5143 TRACE("Request header -> %s\n", debugstr_w(request_header) );
5144
5145 /* send the request as ASCII, tack on the optional data */
5146 if (!lpOptional || redirected || secure_proxy_connect)
5147 data_len = 0;
5148
5149 ascii_req = build_ascii_request(request_header, lpOptional, data_len, &len);
5150 free(request_header);
5151 TRACE("full request -> %s\n", debugstr_a(ascii_req) );
5152
5155
5156 NETCON_set_timeout( request->netconn, TRUE, request->hdr.send_timeout );
5157 res = NETCON_send(request->netconn, ascii_req, len, 0, &cnt);
5158 free(ascii_req);
5159 if(res != ERROR_SUCCESS) {
5160 TRACE("send failed: %lu\n", res);
5161 if(!reusing_connection)
5162 break;
5164 loop_next = TRUE;
5165 continue;
5166 }
5167
5168 request->bytesWritten = data_len;
5169
5172 &len, sizeof(DWORD));
5173
5174 if (bEndRequest)
5175 {
5176 DWORD dwBufferSize;
5177
5180
5181 if (HTTP_GetResponseHeaders(request, &responseLen))
5182 {
5185 goto lend;
5186 }
5187 /* FIXME: We should know that connection is closed before sending
5188 * headers. Otherwise wrong callbacks are executed */
5189 if(!responseLen && reusing_connection) {
5190 TRACE("Connection closed by server, reconnecting\n");
5192 loop_next = TRUE;
5193 continue;
5194 }
5195
5198 sizeof(DWORD));
5199
5204
5206 if(res != ERROR_SUCCESS)
5207 goto lend;
5208 if(!request->contentLength && !secure_proxy_connect)
5210
5211 if (!(request->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && responseLen)
5212 {
5213 WCHAR *new_url;
5214
5215 switch(request->status_code) {
5217 case HTTP_STATUS_MOVED:
5220 new_url = get_redirect_url(request);
5221 if(!new_url)
5222 break;
5223
5224 if (wcscmp(request->verb, L"GET") && wcscmp(request->verb, L"HEAD") &&
5226 {
5227 free(request->verb);
5228 request->verb = wcsdup(L"GET");
5229 }
5231 res = HTTP_HandleRedirect(request, new_url);
5232 free(new_url);
5233 if (res == ERROR_SUCCESS)
5234 loop_next = TRUE;
5235 redirected = TRUE;
5236 }
5237 }
5238 if (!(request->hdr.dwFlags & INTERNET_FLAG_NO_AUTH) && res == ERROR_SUCCESS)
5239 {
5240 WCHAR szAuthValue[2048];
5241 dwBufferSize=2048;
5242 if (request->status_code == HTTP_STATUS_DENIED)
5243 {
5244 WCHAR *host = wcsdup(request->server->canon_host_port);
5245 DWORD dwIndex = 0;
5246 while (HTTP_HttpQueryInfoW(request,HTTP_QUERY_WWW_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex) == ERROR_SUCCESS)
5247 {
5248 if (HTTP_DoAuthorization(request, szAuthValue,
5249 &request->authInfo,
5250 request->session->userName,
5251 request->session->password, host))
5252 {
5254 {
5255 FIXME("Could not drain content\n");
5257 }
5258 loop_next = TRUE;
5259 break;
5260 }
5261
5262 dwBufferSize = 2048;
5263 }
5264 free(host);
5265
5266 if(!loop_next) {
5267 TRACE("Cleaning wrong authorization data\n");
5268 destroy_authinfo(request->authInfo);
5269 request->authInfo = NULL;
5270 }
5271 }
5272 if (request->status_code == HTTP_STATUS_PROXY_AUTH_REQ)
5273 {
5274 DWORD dwIndex = 0;
5275 while (HTTP_HttpQueryInfoW(request,HTTP_QUERY_PROXY_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex) == ERROR_SUCCESS)
5276 {
5277 if (HTTP_DoAuthorization(request, szAuthValue,
5278 &request->proxyAuthInfo,
5279 request->session->appInfo->proxyUsername,
5280 request->session->appInfo->proxyPassword,
5281 NULL))
5282 {
5284 {
5285 FIXME("Could not drain content\n");
5287 }
5288 loop_next = TRUE;
5289 break;
5290 }
5291
5292 dwBufferSize = 2048;
5293 }
5294
5295 if(!loop_next) {
5296 TRACE("Cleaning wrong proxy authorization data\n");
5297 destroy_authinfo(request->proxyAuthInfo);
5298 request->proxyAuthInfo = NULL;
5299 }
5300 }
5301 }
5302 if (secure_proxy_connect && request->status_code == HTTP_STATUS_OK)
5303 {
5305 if (res != ERROR_SUCCESS)
5306 {
5307 WARN("failed to upgrade to secure proxy connection\n");
5309 break;
5310 }
5311 remove_header(request, L"Proxy-Authorization", TRUE);
5312 destroy_authinfo(request->proxyAuthInfo);
5313 request->proxyAuthInfo = NULL;
5314 request->contentLength = 0;
5315 request->netconn_stream.content_length = 0;
5316
5318 loop_next = TRUE;
5319 }
5320 }
5321 else
5323 }
5324 while (loop_next);
5325
5326lend:
5327 /* TODO: send notification for P3P header */
5328
5329 if(res == ERROR_SUCCESS)
5331
5332 if (request->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
5333 {
5334 if (res == ERROR_SUCCESS) {
5335 if(bEndRequest && request->contentLength && request->bytesWritten == request->bytesToWrite)
5337 else
5339 request->session->hdr.dwInternalFlags & INET_OPENURL ? (DWORD_PTR)request->hdr.hInternet : 1, 0);
5340 }else {
5342 }
5343 }
5344
5345 TRACE("<--\n");
5346 return res;
5347}
5348
5349typedef struct {
5358
5359/***********************************************************************
5360 *
5361 * Helper functions for the HttpSendRequest(Ex) functions
5362 *
5363 */
5365{
5368
5369 TRACE("%p\n", request);
5370
5371 HTTP_HttpSendRequestW(request, task->headers, task->headers_len, task->optional,
5372 task->optional_len, task->content_len, task->end_request);
5373
5374 free(task->headers);
5375}
5376
5377
5379{
5380 INT responseLen;
5382
5384 WARN("Not connected\n");
5387 }
5388
5391
5392 if (HTTP_GetResponseHeaders(request, &responseLen) || !responseLen)
5394
5396 INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
5397
5398 /* process cookies here. Is this right? */
5403
5405 if(!request->contentLength)
5407 }
5408
5410 {
5411 switch(request->status_code) {
5413 case HTTP_STATUS_MOVED:
5416 WCHAR *new_url;
5417
5418 new_url = get_redirect_url(request);
5419 if(!new_url)
5420 break;
5421
5422 if (wcscmp(request->verb, L"GET") && wcscmp(request->verb, L"HEAD") &&
5424 {
5425 free(request->verb);
5426 request->verb = wcsdup(L"GET");
5427 }
5429 res = HTTP_HandleRedirect(request, new_url);
5430 free(new_url);
5431 if (res == ERROR_SUCCESS)
5433 }
5434 }
5435 }
5436
5437 if(res == ERROR_SUCCESS)
5439
5440 if (res == ERROR_SUCCESS && request->contentLength)
5442 else
5444
5445 return res;
5446}
5447
5448/***********************************************************************
5449 * HttpEndRequestA (WININET.@)
5450 *
5451 * Ends an HTTP request that was started by HttpSendRequestEx
5452 *
5453 * RETURNS
5454 * TRUE if successful
5455 * FALSE on failure
5456 *
5457 */
5459 LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
5460{
5461 TRACE("(%p, %p, %08lx, %08Ix)\n", hRequest, lpBuffersOut, dwFlags, dwContext);
5462
5463 if (lpBuffersOut)
5464 {
5466 return FALSE;
5467 }
5468
5469 return HttpEndRequestW(hRequest, NULL, dwFlags, dwContext);
5470}
5471
5472typedef struct {
5477
5479{
5481 http_request_t *req = (http_request_t*)task->hdr.hdr;
5482
5483 TRACE("%p\n", req);
5484
5485 HTTP_HttpEndRequestW(req, task->flags, task->context);
5486}
5487
5488/***********************************************************************
5489 * HttpEndRequestW (WININET.@)
5490 *
5491 * Ends an HTTP request that was started by HttpSendRequestEx
5492 *
5493 * RETURNS
5494 * TRUE if successful
5495 * FALSE on failure
5496 *
5497 */
5499 LPINTERNET_BUFFERSW lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
5500{
5502 DWORD res;
5503
5504 TRACE("%p %p %lx %Ix -->\n", hRequest, lpBuffersOut, dwFlags, dwContext);
5505
5506 if (lpBuffersOut)
5507 {
5509 return FALSE;
5510 }
5511
5512 request = (http_request_t*) get_handle_object( hRequest );
5513
5514 if (NULL == request || request->hdr.htype != WH_HHTTPREQ)
5515 {
5517 if (request)
5519 return FALSE;
5520 }
5521 request->hdr.dwFlags |= dwFlags;
5522
5523 if (request->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
5524 {
5526
5528 task->flags = dwFlags;
5529 task->context = dwContext;
5530
5531 INTERNET_AsyncCall(&task->hdr);
5533 }
5534 else
5535 res = HTTP_HttpEndRequestW(request, dwFlags, dwContext);
5536
5538 TRACE("%lu <--\n", res);
5539 if(res != ERROR_SUCCESS)
5541 return res == ERROR_SUCCESS;
5542}
5543
5544/***********************************************************************
5545 * HttpSendRequestExA (WININET.@)
5546 *
5547 * Sends the specified request to the HTTP server and allows chunked
5548 * transfers.
5549 *
5550 * RETURNS
5551 * Success: TRUE
5552 * Failure: FALSE, call GetLastError() for more information.
5553 */
5555 LPINTERNET_BUFFERSA lpBuffersIn,
5556 LPINTERNET_BUFFERSA lpBuffersOut,
5557 DWORD dwFlags, DWORD_PTR dwContext)
5558{
5559 INTERNET_BUFFERSW BuffersInW;
5560 BOOL rc = FALSE;
5561 DWORD headerlen;
5562 LPWSTR header = NULL;
5563
5564 TRACE("(%p, %p, %p, %08lx, %08Ix)\n", hRequest, lpBuffersIn,
5565 lpBuffersOut, dwFlags, dwContext);
5566
5567 if (lpBuffersIn)
5568 {
5569 BuffersInW.dwStructSize = sizeof(LPINTERNET_BUFFERSW);
5570 if (lpBuffersIn->lpcszHeader)
5571 {
5572 if (lpBuffersIn->dwHeadersLength == 0 && *lpBuffersIn->lpcszHeader != '\0')
5573 {
5575 return FALSE;
5576 }
5577
5578 headerlen = MultiByteToWideChar(CP_ACP,0,lpBuffersIn->lpcszHeader,
5579 lpBuffersIn->dwHeadersLength,0,0);
5580 header = malloc(headerlen * sizeof(WCHAR));
5581 if (!(BuffersInW.lpcszHeader = header))
5582 {
5584 return FALSE;
5585 }
5587 lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
5588 header, headerlen);
5589 }
5590 else
5591 BuffersInW.lpcszHeader = NULL;
5592 BuffersInW.dwHeadersTotal = lpBuffersIn->dwHeadersTotal;
5593 BuffersInW.lpvBuffer = lpBuffersIn->lpvBuffer;
5594 BuffersInW.dwBufferLength = lpBuffersIn->dwBufferLength;
5595 BuffersInW.dwBufferTotal = lpBuffersIn->dwBufferTotal;
5596 BuffersInW.Next = NULL;
5597 }
5598
5599 rc = HttpSendRequestExW(hRequest, lpBuffersIn ? &BuffersInW : NULL, NULL, dwFlags, dwContext);
5600
5601 free(header);
5602 return rc;
5603}
5604
5605/***********************************************************************
5606 * HttpSendRequestExW (WININET.@)
5607 *
5608 * Sends the specified request to the HTTP server and allows chunked
5609 * transfers
5610 *
5611 * RETURNS
5612 * Success: TRUE
5613 * Failure: FALSE, call GetLastError() for more information.
5614 */
5616 LPINTERNET_BUFFERSW lpBuffersIn,
5617 LPINTERNET_BUFFERSW lpBuffersOut,
5618 DWORD dwFlags, DWORD_PTR dwContext)
5619{
5622 appinfo_t *hIC;
5623 DWORD res;
5624
5625 TRACE("(%p, %p, %p, %08lx, %08Ix)\n", hRequest, lpBuffersIn,
5626 lpBuffersOut, dwFlags, dwContext);
5627
5628 request = (http_request_t*) get_handle_object( hRequest );
5629
5630 if (NULL == request || request->hdr.htype != WH_HHTTPREQ)
5631 {
5633 goto lend;
5634 }
5635
5636 session = request->session;
5637 assert(session->hdr.htype == WH_HHTTPSESSION);
5638 hIC = session->appInfo;
5639 assert(hIC->hdr.htype == WH_HINIT);
5640
5641 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
5642 {
5644
5646 if (lpBuffersIn)
5647 {
5648 DWORD size = 0;
5649
5650 if (lpBuffersIn->lpcszHeader)
5651 {
5652 if (lpBuffersIn->dwHeadersLength == ~0u)
5653 size = (lstrlenW( lpBuffersIn->lpcszHeader ) + 1) * sizeof(WCHAR);
5654 else
5655 size = lpBuffersIn->dwHeadersLength * sizeof(WCHAR);
5656
5657 task->headers = malloc(size);
5658 memcpy(task->headers, lpBuffersIn->lpcszHeader, size);
5659 }
5660 else task->headers = NULL;
5661
5662 task->headers_len = size / sizeof(WCHAR);
5663 task->optional = lpBuffersIn->lpvBuffer;
5664 task->optional_len = lpBuffersIn->dwBufferLength;
5665 task->content_len = lpBuffersIn->dwBufferTotal;
5666 }
5667 else
5668 {
5669 task->headers = NULL;
5670 task->headers_len = 0;
5671 task->optional = NULL;
5672 task->optional_len = 0;
5673 task->content_len = 0;
5674 }
5675
5676 task->end_request = FALSE;
5677
5678 INTERNET_AsyncCall(&task->hdr);
5680 }
5681 else
5682 {
5683 if (lpBuffersIn)
5684 res = HTTP_HttpSendRequestW(request, lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
5685 lpBuffersIn->lpvBuffer, lpBuffersIn->dwBufferLength,
5686 lpBuffersIn->dwBufferTotal, FALSE);
5687 else
5689 }
5690
5691lend:
5692 if ( request )
5694
5695 TRACE("<---\n");
5697 return res == ERROR_SUCCESS;
5698}
5699
5700/***********************************************************************
5701 * HttpSendRequestW (WININET.@)
5702 *
5703 * Sends the specified request to the HTTP server
5704 *
5705 * RETURNS
5706 * TRUE on success
5707 * FALSE on failure
5708 *
5709 */
5711 DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
5712{
5715 appinfo_t *hIC = NULL;
5717
5718 TRACE("%p, %s, %li, %p, %li)\n", hHttpRequest,
5719 debugstr_wn(lpszHeaders, dwHeaderLength), dwHeaderLength, lpOptional, dwOptionalLength);
5720
5721 request = (http_request_t*) get_handle_object( hHttpRequest );
5722 if (NULL == request || request->hdr.htype != WH_HHTTPREQ)
5723 {
5725 goto lend;
5726 }
5727
5728 session = request->session;
5729 if (NULL == session || session->hdr.htype != WH_HHTTPSESSION)
5730 {
5732 goto lend;
5733 }
5734
5735 hIC = session->appInfo;
5736 if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
5737 {
5739 goto lend;
5740 }
5741
5742 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
5743 {
5745
5747 if (lpszHeaders)
5748 {
5749 DWORD size;
5750
5751 if (dwHeaderLength == ~0u) size = (lstrlenW(lpszHeaders) + 1) * sizeof(WCHAR);
5752 else size = dwHeaderLength * sizeof(WCHAR);
5753
5754 task->headers = malloc(size);
5755 memcpy(task->headers, lpszHeaders, size);
5756 }
5757 else
5758 task->headers = NULL;
5759 task->headers_len = dwHeaderLength;
5760 task->optional = lpOptional;
5761 task->optional_len = dwOptionalLength;
5762 task->content_len = dwOptionalLength;
5763 task->end_request = TRUE;
5764
5765 INTERNET_AsyncCall(&task->hdr);
5767 }
5768 else
5769 {
5770 res = HTTP_HttpSendRequestW(request, lpszHeaders,
5771 dwHeaderLength, lpOptional, dwOptionalLength,
5772 dwOptionalLength, TRUE);
5773 }
5774lend:
5775 if( request )
5777
5779 return res == ERROR_SUCCESS;
5780}
5781
5782/***********************************************************************
5783 * HttpSendRequestA (WININET.@)
5784 *
5785 * Sends the specified request to the HTTP server
5786 *
5787 * RETURNS
5788 * TRUE on success
5789 * FALSE on failure
5790 *
5791 */
5792BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
5793 DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
5794{
5795 BOOL result;
5796 LPWSTR szHeaders=NULL;
5797 DWORD nLen=dwHeaderLength;
5798 if(lpszHeaders!=NULL)
5799 {
5800 if (dwHeaderLength == 0 && *lpszHeaders != '\0')
5801 {
5803 return FALSE;
5804 }
5805
5806 nLen=MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,NULL,0);
5807 szHeaders = malloc(nLen * sizeof(WCHAR));
5808 MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,szHeaders,nLen);
5809 }
5810 result = HttpSendRequestW(hHttpRequest, szHeaders, nLen, lpOptional, dwOptionalLength);
5811 free(szHeaders);
5812 return result;
5813}
5814
5815/***********************************************************************
5816 * HTTPSESSION_Destroy (internal)
5817 *
5818 * Deallocate session handle
5819 *
5820 */
5822{
5824
5825 TRACE("%p\n", session);
5826
5827 WININET_Release(&session->appInfo->hdr);
5828
5829 free(session->hostName);
5830 free(session->password);
5831 free(session->userName);
5832}
5833
5835{
5836
5837 switch(option) {
5839 TRACE("INTERNET_OPTION_HANDLE_TYPE\n");
5840
5841 if (*size < sizeof(ULONG))
5843
5844 *size = sizeof(DWORD);
5846 return ERROR_SUCCESS;
5847 }
5848
5849 return INET_QueryOption(hdr, option, buffer, size, unicode);
5850}
5851
5853{
5855
5856 switch(option) {
5858 {
5859 free(ses->userName);
5860 if (!(ses->userName = wcsdup(buffer))) return ERROR_OUTOFMEMORY;
5861 return ERROR_SUCCESS;
5862 }
5864 {
5865 free(ses->password);
5866 if (!(ses->password = wcsdup(buffer))) return ERROR_OUTOFMEMORY;
5867 return ERROR_SUCCESS;
5868 }
5870 {
5871 free(ses->appInfo->proxyUsername);
5872 if (!(ses->appInfo->proxyUsername = wcsdup(buffer))) return ERROR_OUTOFMEMORY;
5873 return ERROR_SUCCESS;
5874 }
5876 {
5877 free(ses->appInfo->proxyPassword);
5878 if (!(ses->appInfo->proxyPassword = wcsdup(buffer))) return ERROR_OUTOFMEMORY;
5879 return ERROR_SUCCESS;
5880 }
5881 default: break;
5882 }
5883
5884 return INET_SetOption(hdr, option, buffer, size);
5885}
5886
5889 NULL,
5892 NULL,
5893 NULL,
5894 NULL,
5895 NULL,
5896 NULL
5897};
5898
5899
5900/***********************************************************************
5901 * HTTP_Connect (internal)
5902 *
5903 * Create http session handle
5904 *
5905 * RETURNS
5906 * HINTERNET a session handle on success
5907 * NULL on failure
5908 *
5909 */
5911 INTERNET_PORT serverPort, LPCWSTR lpszUserName,
5913 DWORD dwInternalFlags, HINTERNET *ret)
5914{
5916
5917 TRACE("-->\n");
5918
5919 if (!lpszServerName || !lpszServerName[0])
5921
5922 assert( hIC->hdr.htype == WH_HINIT );
5923
5925 if (!session)
5926 return ERROR_OUTOFMEMORY;
5927
5928 /*
5929 * According to my tests. The name is not resolved until a request is sent
5930 */
5931
5932 session->hdr.htype = WH_HHTTPSESSION;
5933 session->hdr.dwFlags = dwFlags;
5934 session->hdr.dwContext = dwContext;
5935 session->hdr.dwInternalFlags |= dwInternalFlags;
5936 session->hdr.decoding = hIC->hdr.decoding;
5937
5938 WININET_AddRef( &hIC->hdr );
5939 session->appInfo = hIC;
5940 list_add_head( &hIC->hdr.children, &session->hdr.entry );
5941
5942 session->hostName = wcsdup(lpszServerName);
5943 if (lpszUserName && lpszUserName[0])
5944 session->userName = wcsdup(lpszUserName);
5945 session->password = wcsdup(lpszPassword);
5946 session->hostPort = serverPort;
5947 session->hdr.connect_timeout = hIC->hdr.connect_timeout;
5948 session->hdr.send_timeout = hIC->hdr.send_timeout;
5949 session->hdr.receive_timeout = hIC->hdr.receive_timeout;
5950
5951 /* Don't send a handle created callback if this handle was created with InternetOpenUrl */
5952 if (!(session->hdr.dwInternalFlags & INET_OPENURL))
5953 {
5954 INTERNET_SendCallback(&hIC->hdr, dwContext,
5956 sizeof(HINTERNET));
5957 }
5958
5959/*
5960 * an INTERNET_STATUS_REQUEST_COMPLETE is NOT sent here as per my tests on
5961 * windows
5962 */
5963
5964 TRACE("%p --> %p\n", hIC, session);
5965
5966 *ret = session->hdr.hInternet;
5967 return ERROR_SUCCESS;
5968}
5969
5970/***********************************************************************
5971 * HTTP_clear_response_headers (internal)
5972 *
5973 * clear out any old response headers
5974 */
5976{
5977 DWORD i;
5978
5979 EnterCriticalSection( &request->headers_section );
5980
5981 for( i=0; i<request->nCustHeaders; i++)
5982 {
5983 if( !request->custHeaders[i].lpszField )
5984 continue;
5985 if( !request->custHeaders[i].lpszValue )
5986 continue;
5987 if ( request->custHeaders[i].wFlags & HDR_ISREQUEST )
5988 continue;
5990 i--;
5991 }
5992
5993 LeaveCriticalSection( &request->headers_section );
5994}
5995
5996/***********************************************************************
5997 * HTTP_GetResponseHeaders (internal)
5998 *
5999 * Read server response
6000 *
6001 * RETURNS
6002 *
6003 * TRUE on success
6004 * FALSE on error
6005 */
6007{
6008 INT cbreaks = 0;
6010 DWORD buflen = MAX_REPLY_LEN;
6011 INT rc = 0;
6012 char bufferA[MAX_REPLY_LEN];
6013 LPWSTR status_code = NULL, status_text = NULL;
6015 BOOL codeHundred = FALSE;
6016
6017 TRACE("-->\n");
6018
6020 goto lend;
6021
6022 /* clear old response headers (eg. from a redirect response) */
6024
6025 NETCON_set_timeout( request->netconn, FALSE, request->hdr.receive_timeout );
6026 do {
6027 /*
6028 * We should first receive 'HTTP/1.x nnn OK' where nnn is the status code.
6029 */
6030 buflen = MAX_REPLY_LEN;
6031 if ((res = read_line(request, bufferA, &buflen)))
6032 goto lend;
6033
6034 if (!buflen) goto lend;
6035
6036 rc += buflen;
6037 MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
6038 /* check is this a status code line? */
6039 if (!wcsncmp(buffer, L"HTTP/1.0", 4))
6040 {
6041 /* split the version from the status code */
6042 status_code = wcschr( buffer, ' ' );
6043 if( !status_code )
6044 goto lend;
6045 *status_code++=0;
6046
6047 /* split the status code from the status text */
6048 status_text = wcschr( status_code, ' ' );
6049 if( status_text )
6050 *status_text++=0;
6051
6052 request->status_code = wcstol(status_code, NULL, 10);
6053
6054 TRACE("version [%s] status code [%s] status text [%s]\n",
6056
6057 codeHundred = request->status_code == HTTP_STATUS_CONTINUE;
6058 }
6059 else if (!codeHundred)
6060 {
6061 WARN("No status line at head of response (%s)\n", debugstr_w(buffer));
6062
6064 free(request->statusText);
6065
6066 request->status_code = HTTP_STATUS_OK;
6067 request->version = wcsdup(L"HTTP/1.0");
6068 request->statusText = wcsdup(L"OK");
6069
6070 goto lend;
6071 }
6072 } while (codeHundred);
6073
6074 /* Add status code */
6077
6079 free(request->statusText);
6080
6082 request->statusText = wcsdup(status_text ? status_text : L"");
6083
6084 /* Restore the spaces */
6085 *(status_code-1) = ' ';
6086 if (status_text)
6087 *(status_text-1) = ' ';
6088
6089 /* Parse each response line */
6090 do
6091 {
6092 buflen = MAX_REPLY_LEN;
6093 if (!read_line(request, bufferA, &buflen) && buflen)
6094 {
6095 LPWSTR * pFieldAndValue;
6096
6097 TRACE("got line %s, now interpreting\n", debugstr_a(bufferA));
6098
6099 if (!bufferA[0]) break;
6100 MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
6101
6102 pFieldAndValue = HTTP_InterpretHttpHeader(buffer);
6103 if (pFieldAndValue)
6104 {
6105 HTTP_ProcessHeader(request, pFieldAndValue[0], pFieldAndValue[1],
6107 HTTP_FreeTokens(pFieldAndValue);
6108 }
6109 }
6110 else
6111 {
6112 cbreaks++;
6113 if (cbreaks >= 2)
6114 break;
6115 }
6116 }while(1);
6117
6119
6120lend:
6121
6122 *len = rc;
6123 TRACE("<--\n");
6124 return res;
6125}
6126
6127/***********************************************************************
6128 * HTTP_InterpretHttpHeader (internal)
6129 *
6130 * Parse server response
6131 *
6132 * RETURNS
6133 *
6134 * Pointer to array of field, value, NULL on success.
6135 * NULL on error.
6136 */
6138{
6139 LPWSTR * pTokenPair;
6140 LPWSTR pszColon;
6141 INT len;
6142
6143 pTokenPair = calloc(3, sizeof(*pTokenPair));
6144
6145 pszColon = wcschr(buffer, ':');
6146 /* must have two tokens */
6147 if (!pszColon)
6148 {
6149 HTTP_FreeTokens(pTokenPair);
6150 if (buffer[0])
6151 TRACE("No ':' in line: %s\n", debugstr_w(buffer));
6152 return NULL;
6153 }
6154
6155 pTokenPair[0] = malloc((pszColon - buffer + 1) * sizeof(WCHAR));
6156 if (!pTokenPair[0])
6157 {
6158 HTTP_FreeTokens(pTokenPair);
6159 return NULL;
6160 }
6161 memcpy(pTokenPair[0], buffer, (pszColon - buffer) * sizeof(WCHAR));
6162 pTokenPair[0][pszColon - buffer] = '\0';
6163
6164 /* skip colon */
6165 pszColon++;
6166 len = lstrlenW(pszColon);
6167 pTokenPair[1] = malloc((len + 1) * sizeof(WCHAR));
6168 if (!pTokenPair[1])
6169 {
6170 HTTP_FreeTokens(pTokenPair);
6171 return NULL;
6172 }
6173 memcpy(pTokenPair[1], pszColon, (len + 1) * sizeof(WCHAR));
6174
6175 strip_spaces(pTokenPair[0]);
6176 strip_spaces(pTokenPair[1]);
6177
6178 TRACE("field(%s) Value(%s)\n", debugstr_w(pTokenPair[0]), debugstr_w(pTokenPair[1]));
6179 return pTokenPair;
6180}
6181
6182/***********************************************************************
6183 * HTTP_ProcessHeader (internal)
6184 *
6185 * Stuff header into header tables according to <dwModifier>
6186 *
6187 */
6188
6189#define COALESCEFLAGS (HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA|HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON)
6190
6192{
6193 LPHTTPHEADERW lphttpHdr = NULL;
6194 INT index;
6195 BOOL request_only = !!(dwModifier & HTTP_ADDHDR_FLAG_REQ);
6197
6198 TRACE("--> %s: %s - 0x%08lx\n", debugstr_w(field), debugstr_w(value), dwModifier);
6199
6200 EnterCriticalSection( &request->headers_section );
6201
6202 /* REPLACE wins out over ADD */
6203 if (dwModifier & HTTP_ADDREQ_FLAG_REPLACE)
6204 dwModifier &= ~HTTP_ADDREQ_FLAG_ADD;
6205
6206 if (dwModifier & HTTP_ADDREQ_FLAG_ADD)
6207 index = -1;
6208 else
6209 index = HTTP_GetCustomHeaderIndex(request, field, 0, request_only);
6210
6211 if (index >= 0)
6212 {
6213 if (dwModifier & HTTP_ADDREQ_FLAG_ADD_IF_NEW)
6214 {
6215 LeaveCriticalSection( &request->headers_section );
6217 }
6218 lphttpHdr = &request->custHeaders[index];
6219 }
6220 else if (value)
6221 {
6223
6224 hdr.lpszField = (LPWSTR)field;
6225 hdr.lpszValue = (LPWSTR)value;
6226 hdr.wFlags = hdr.wCount = 0;
6227
6228 if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
6229 hdr.wFlags |= HDR_ISREQUEST;
6230
6232 LeaveCriticalSection( &request->headers_section );
6233 return res;
6234 }
6235 /* no value to delete */
6236 else
6237 {
6238 LeaveCriticalSection( &request->headers_section );
6239 return ERROR_SUCCESS;
6240 }
6241
6242 if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
6243 lphttpHdr->wFlags |= HDR_ISREQUEST;
6244 else
6245 lphttpHdr->wFlags &= ~HDR_ISREQUEST;
6246
6247 if (dwModifier & HTTP_ADDREQ_FLAG_REPLACE)
6248 {
6250
6251 if (value && value[0])
6252 {
6254
6255 hdr.lpszField = (LPWSTR)field;
6256 hdr.lpszValue = (LPWSTR)value;
6257 hdr.wFlags = hdr.wCount = 0;
6258
6259 if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
6260 hdr.wFlags |= HDR_ISREQUEST;
6261
6263 LeaveCriticalSection( &request->headers_section );
6264 return res;
6265 }
6266
6267 LeaveCriticalSection( &request->headers_section );
6268 return ERROR_SUCCESS;
6269 }
6270 else if (dwModifier & COALESCEFLAGS)
6271 {
6272 LPWSTR lpsztmp;
6273 WCHAR ch = 0;
6274 INT len = 0;
6275 INT origlen = lstrlenW(lphttpHdr->lpszValue);
6276 INT valuelen = lstrlenW(value);
6277
6278 if (dwModifier & HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA)
6279 {
6280 ch = ',';
6281 lphttpHdr->wFlags |= HDR_COMMADELIMITED;
6282 }
6283 else if (dwModifier & HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON)
6284 {
6285 ch = ';';
6286 lphttpHdr->wFlags |= HDR_COMMADELIMITED;
6287 }
6288
6289 len = origlen + valuelen + ((ch > 0) ? 2 : 0);
6290
6291 lpsztmp = realloc(lphttpHdr->lpszValue, (len + 1) * sizeof(WCHAR));
6292 if (lpsztmp)
6293 {
6294 lphttpHdr->lpszValue = lpsztmp;
6295 /* FIXME: Increment lphttpHdr->wCount. Perhaps lpszValue should be an array */
6296 if (ch > 0)
6297 {
6298 lphttpHdr->lpszValue[origlen] = ch;
6299 origlen++;
6300 lphttpHdr->lpszValue[origlen] = ' ';
6301 origlen++;
6302 }
6303
6304 memcpy(&lphttpHdr->lpszValue[origlen], value, valuelen*sizeof(WCHAR));
6305 lphttpHdr->lpszValue[len] = '\0';
6307 }
6308 else
6309 {
6310 WARN("realloc (%d bytes) failed\n",len+1);
6312 }
6313 }
6314 TRACE("<-- %ld\n", res);
6315 LeaveCriticalSection( &request->headers_section );
6316 return res;
6317}
6318
6319/***********************************************************************
6320 * HTTP_GetCustomHeaderIndex (internal)
6321 *
6322 * Return index of custom header from header array
6323 * Headers section must be held
6324 */
6326 int requested_index, BOOL request_only)
6327{
6328 DWORD index;
6329
6330 TRACE("%s, %d, %d\n", debugstr_w(lpszField), requested_index, request_only);
6331
6332 for (index = 0; index < request->nCustHeaders; index++)
6333 {
6334 if (wcsicmp(request->custHeaders[index].lpszField, lpszField))
6335 continue;
6336
6337 if (request_only && !(request->custHeaders[index].wFlags & HDR_ISREQUEST))
6338 continue;
6339
6340 if (!request_only && (request->custHeaders[index].wFlags & HDR_ISREQUEST))
6341 continue;
6342
6343 if (requested_index == 0)
6344 break;
6345 requested_index --;
6346 }
6347
6348 if (index >= request->nCustHeaders)
6349 index = -1;
6350
6351 TRACE("Return: %ld\n", index);
6352 return index;
6353}
6354
6355
6356/***********************************************************************
6357 * HTTP_InsertCustomHeader (internal)
6358 *
6359 * Insert header into array
6360 * Headers section must be held
6361 */
6363{
6364 INT count;
6365 LPHTTPHEADERW lph = NULL;
6366
6367 TRACE("--> %s: %s\n", debugstr_w(lpHdr->lpszField), debugstr_w(lpHdr->lpszValue));
6368 count = request->nCustHeaders + 1;
6369 lph = realloc(request->custHeaders, sizeof(HTTPHEADERW) * count);
6370
6371 if (!lph)
6372 return ERROR_OUTOFMEMORY;
6373
6374 request->custHeaders = lph;
6375 request->custHeaders[count-1].lpszField = wcsdup(lpHdr->lpszField);
6376 request->custHeaders[count-1].lpszValue = wcsdup(lpHdr->lpszValue);
6377 request->custHeaders[count-1].wFlags = lpHdr->wFlags;
6378 request->custHeaders[count-1].wCount= lpHdr->wCount;
6379 request->nCustHeaders++;
6380
6381 return ERROR_SUCCESS;
6382}
6383
6384
6385/***********************************************************************
6386 * HTTP_DeleteCustomHeader (internal)
6387 *
6388 * Delete header from array
6389 * If this function is called, the index may change.
6390 * Headers section must be held
6391 */
6393{
6394 if( request->nCustHeaders <= 0 )
6395 return FALSE;
6396 if( index >= request->nCustHeaders )
6397 return FALSE;
6398 request->nCustHeaders--;
6399
6400 free(request->custHeaders[index].lpszField);
6401 free(request->custHeaders[index].lpszValue);
6402
6403 memmove( &request->custHeaders[index], &request->custHeaders[index+1],
6404 (request->nCustHeaders - index)* sizeof(HTTPHEADERW) );
6405 memset( &request->custHeaders[request->nCustHeaders], 0, sizeof(HTTPHEADERW) );
6406
6407 return TRUE;
6408}
6409
6410
6411/***********************************************************************
6412 * IsHostInProxyBypassList (WININET.@)
6413 */
6415{
6416 FIXME("STUB: scheme=%d host=%s length=%ld\n", scheme, szHost, length);
6417 return FALSE;
6418}
HRESULT WINAPI DECLSPEC_HOTPATCH SetThreadDescription(_In_ HANDLE hThread, _In_ PCWSTR lpThreadDescription)
#define read
Definition: acwin.h:97
static int avail
Definition: adh-main.c:39
struct outqueuenode * head
Definition: adnsresfilter.c:66
static int state
Definition: maze.c:121
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
void user(int argc, const char *argv[])
Definition: cmds.c:1350
#define ARRAY_SIZE(A)
Definition: main.h:20
#define U(x)
Definition: wordpad.c:45
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
static HANDLE thread
Definition: service.c:33
static UCHAR password[]
Definition: bcrypt.c:494
Definition: list.h:39
#define IDS_CERT_ISSUER
Definition: cryptres.h:170
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define ERROR_IO_PENDING
Definition: dderror.h:15
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
DWORD task
Definition: delayimp.cpp:484
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
Definition: cert.c:369
VOID WINAPI CertFreeCertificateChain(PCCERT_CHAIN_CONTEXT pChainContext)
Definition: chain.c:2956
PCCERT_CHAIN_CONTEXT WINAPI CertDuplicateCertificateChain(PCCERT_CHAIN_CONTEXT pChainContext)
Definition: chain.c:2944
static WCHAR available[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2402
static WCHAR issuer[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1972
DWORD WINAPI CertNameToStrA(DWORD encoding_type, PCERT_NAME_BLOB name_blob, DWORD str_type, LPSTR str, DWORD str_len)
Definition: str.c:250
static WCHAR * strdupAtoW(const char *str)
Definition: main.c:61
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define FILE_BEGIN
Definition: compat.h:761
#define INVALID_SET_FILE_POINTER
Definition: compat.h:732
#define wcsnicmp
Definition: compat.h:14
#define CP_ACP
Definition: compat.h:109
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:55
#define __TRY
Definition: compat.h:80
#define FreeLibrary(x)
Definition: compat.h:748
#define TRACE_ON(x)
Definition: compat.h:75
#define ERROR_NOT_SUPPORTED
Definition: compat.h:100
#define MAX_PATH
Definition: compat.h:34
#define CreateFileW
Definition: compat.h:741
#define __ENDTRY
Definition: compat.h:82
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define FILE_SHARE_READ
Definition: compat.h:136
#define __EXCEPT_PAGE_FAULT
Definition: compat.h:81
#define wcsicmp
Definition: compat.h:15
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
int inflate(z_streamp strm, int flush)
Definition: inflate.c:1257
int inflateEnd(z_streamp strm)
Definition: inflate.c:1910
void FAR * voidpf
Definition: zlib.h:42
#define Z_STREAM_END
Definition: zlib.h:115
unsigned int uInt
Definition: zlib.h:38
#define Z_OK
Definition: zlib.h:114
static const WCHAR version[]
Definition: asmname.c:66
HINTERNET connection
Definition: port.c:65
static DOUBLE day(DOUBLE time)
Definition: date.c:75
BOOL WINAPI SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
Definition: fileinfo.c:177
BOOL WINAPI WriteFile(_In_ HANDLE hFile, _In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer, _In_ DWORD nNumberOfBytesToWrite, _Out_opt_ LPDWORD lpNumberOfBytesWritten, _Inout_opt_ LPOVERLAPPED lpOverlapped)
Definition: rw.c:25
BOOL WINAPI GetModuleHandleExW(IN DWORD dwFlags, IN LPCWSTR lpwModuleName OPTIONAL, OUT HMODULE *phModule)
Definition: loader.c:866
VOID WINAPI FreeLibraryAndExitThread(HMODULE hLibModule, DWORD dwExitCode)
Definition: loader.c:507
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:139
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:183
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:153
BOOL WINAPI InitializeCriticalSectionEx(OUT LPCRITICAL_SECTION lpCriticalSection, IN DWORD dwSpinCount, IN DWORD flags)
Definition: sync.c:107
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:3946
HRESULT WINAPI UrlEscapeW(const WCHAR *url, WCHAR *escaped, DWORD *escaped_len, DWORD flags)
Definition: path.c:3328
HRESULT WINAPI UrlCanonicalizeW(const WCHAR *src_url, WCHAR *canonicalized, DWORD *canonicalized_len, DWORD flags)
Definition: path.c:4128
BOOL WINAPI StrToInt64ExW(const WCHAR *str, DWORD flags, LONGLONG *ret)
Definition: string.c:919
INT WINAPI DECLSPEC_HOTPATCH LoadStringA(HINSTANCE instance, UINT resource_id, LPSTR buffer, INT buflen)
Definition: string.c:1307
ULONGLONG WINAPI DECLSPEC_HOTPATCH GetTickCount64(void)
Definition: sync.c:192
unsigned char ch[4][2]
Definition: console.c:118
#define assert(_expr)
Definition: assert.h:32
_ACRTIMP __msvcrt_ulong __cdecl wcstoul(const wchar_t *, wchar_t **, int)
Definition: wcs.c:2917
_ACRTIMP __msvcrt_long __cdecl wcstol(const wchar_t *, wchar_t **, int)
Definition: wcs.c:2752
_ACRTIMP size_t __cdecl wcsspn(const wchar_t *, const wchar_t *)
Definition: wcs.c:513
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1977
_ACRTIMP size_t __cdecl wcscspn(const wchar_t *, const wchar_t *)
Definition: wcs.c:503
_ACRTIMP int __cdecl wcsncmp(const wchar_t *, const wchar_t *, size_t)
Definition: wcs.c:523
#define ERANGE
Definition: errno.h:55
#define errno
Definition: errno.h:120
#define ULONG_MAX
Definition: limits.h:31
#define UINT_MAX
Definition: limits.h:27
_ACRTIMP int __cdecl _scprintf(const char *,...) __WINE_CRT_PRINTF_ATTR(1
_ACRTIMP char *__cdecl strchr(const char *, int)
Definition: string.c:3291
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1597
static wchar_t * wcsdup(const wchar_t *str)
Definition: string.h:94
USHORT port
Definition: uri.c:210
unsigned char
Definition: typeof.h:29
static const WCHAR month[12][4]
Definition: session.c:2528
static WCHAR * build_response_header(http_request_t *request, BOOL use_cr)
Definition: http.c:605
static void async_read_file_proc(task_header_t *hdr)
Definition: http.c:3153
static WCHAR * get_redirect_url(http_request_t *request)
Definition: http.c:4173
static void HTTP_ProcessExpires(http_request_t *request)
Definition: http.c:4778
static BOOL netconn_end_of_data(data_stream_t *stream, http_request_t *req)
Definition: http.c:2682
BOOL WINAPI HttpAddRequestHeadersW(HINTERNET hHttpRequest, LPCWSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
Definition: http.c:1280
static void destroy_data_stream(data_stream_t *stream)
Definition: http.c:333
static BOOL process_host_port(server_t *server)
Definition: http.c:168
static BOOL HTTP_ParseDate(LPCWSTR value, FILETIME *ft)
Definition: http.c:4750
static LPWSTR * HTTP_InterpretHttpHeader(LPCWSTR buffer)
Definition: http.c:6137
static WCHAR ** convert_accept_types(const char **accept_types)
Definition: http.c:1342
static const data_stream_vtbl_t chunked_stream_vtbl
Definition: http.c:2934
static BOOL retrieve_cached_authorization(LPWSTR host, LPWSTR scheme, SEC_WINNT_AUTH_IDENTITY_W *nt_auth_identity)
Definition: http.c:837
static DWORD str_to_buffer(const WCHAR *str, void *buffer, DWORD *size, BOOL unicode)
Definition: http.c:1977
static void wininet_zfree(voidpf opaque, voidpf address)
Definition: http.c:465
static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders, DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength, DWORD dwContentLength, BOOL bEndRequest)
Definition: http.c:5006
static BOOL is_basic_auth_value(LPCWSTR pszAuthValue, LPWSTR *pszRealm)
Definition: http.c:710
BOOL WINAPI HttpEndRequestW(HINTERNET hRequest, LPINTERNET_BUFFERSW lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
Definition: http.c:5498
static const signed char HTTP_Base64Dec[]
Definition: http.c:1492
static const object_vtbl_t HTTPREQVtbl
Definition: http.c:3431
static void HTTP_FixURL(http_request_t *request)
Definition: http.c:516
static DWORD drain_content(http_request_t *, BOOL)
Definition: http.c:3127
static struct list authorizationCache
Definition: http.c:109
static void AsyncHttpSendRequestProc(task_header_t *hdr)
Definition: http.c:5364
static void AsyncHttpEndRequestProc(task_header_t *hdr)
Definition: http.c:5478
static DWORD netconn_read(data_stream_t *stream, http_request_t *req, BYTE *buf, DWORD size, DWORD *read, BOOL allow_blocking)
Definition: http.c:2688
static void HTTPREQ_Destroy(object_header_t *hdr)
Definition: http.c:1838
BOOL WINAPI HttpEndRequestA(HINTERNET hRequest, LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
Definition: http.c:5458
static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
Definition: http.c:2048
static void http_process_keep_alive(http_request_t *req)
Definition: http.c:4885
static void destroy_authinfo(struct HttpAuthInfo *authinfo)
Definition: http.c:746
static DWORD HTTP_HttpEndRequestW(http_request_t *request, DWORD dwFlags, DWORD_PTR dwContext)
Definition: http.c:5378
#define HTTP_ADDHDR_FLAG_REQ
Definition: http.c:66
static DWORD HTTP_HttpAddRequestHeadersW(http_request_t *request, LPCWSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
Definition: http.c:1201
static WCHAR * encode_auth_data(const WCHAR *scheme, const char *data, UINT data_len)
Definition: http.c:1557
static struct list connection_pool
Definition: http.c:140
struct _authorizationData authorizationData
static WCHAR * get_host_header(http_request_t *req)
Definition: http.c:295
static DWORD HTTPREQ_ReadFile(object_header_t *hdr, void *buf, DWORD size, DWORD *ret_read, DWORD flags, DWORD_PTR context)
Definition: http.c:3262
static void remove_header(http_request_t *request, const WCHAR *str, BOOL from_request)
Definition: http.c:347
static void HTTP_ProcessLastModified(http_request_t *request)
Definition: http.c:4866
static void reset_data_stream(http_request_t *req)
Definition: http.c:338
static BOOL HTTP_ShouldBypassProxy(appinfo_t *lpwai, LPCWSTR server)
Definition: http.c:1705
static DWORD init_gzip_stream(http_request_t *req, BOOL is_gzip)
Definition: http.c:470
static DWORD read_more_data(http_request_t *req, int maxlen)
Definition: http.c:2542
static DWORD WINAPI collect_connections_proc(void *arg)
Definition: http.c:259
BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest, LPCSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
Definition: http.c:1312
static DWORD HTTP_HandleRedirect(http_request_t *request, WCHAR *url)
Definition: http.c:4240
static const LPCWSTR header_lookup[]
Definition: http.c:3615
static void commit_cache_entry(http_request_t *req)
Definition: http.c:2419
static CRITICAL_SECTION_DEBUG critsect_debug
Definition: http.c:112
static WORD HTTP_ParseMonth(LPCWSTR month)
Definition: http.c:4406
static char * build_ascii_request(const WCHAR *str, void *data, DWORD data_len, DWORD *out_len)
Definition: http.c:4975
static BOOL gzip_end_of_data(data_stream_t *stream, http_request_t *req)
Definition: http.c:366
static DWORD HTTP_ProcessHeader(http_request_t *req, LPCWSTR field, LPCWSTR value, DWORD dwModifier)
Definition: http.c:6191
static const data_stream_vtbl_t gzip_stream_vtbl
Definition: http.c:453
#define COLLECT_TIME
Definition: http.c:68
static void HTTPSESSION_Destroy(object_header_t *hdr)
Definition: http.c:5821
static DWORD HTTP_ResolveName(http_request_t *request)
Definition: http.c:1772
static DWORD open_http_connection(http_request_t *request, BOOL *reusing)
Definition: http.c:4900
static DWORD HTTP_InsertCustomHeader(http_request_t *req, LPHTTPHEADERW lpHdr)
Definition: http.c:6362
static INT HTTP_GetCustomHeaderIndex(http_request_t *req, LPCWSTR lpszField, INT index, BOOL Request)
static void HTTP_FreeTokens(LPWSTR *token_array)
Definition: http.c:509
static void strip_spaces(LPWSTR start)
Definition: http.c:691
static void HTTP_ProcessCookies(http_request_t *request)
Definition: http.c:658
static BOOL HTTP_DomainMatches(LPCWSTR server, substr_t domain)
Definition: http.c:1663
BOOL WINAPI IsHostInProxyBypassList(INTERNET_SCHEME scheme, LPCSTR szHost, DWORD length)
Definition: http.c:6414
static void chunked_destroy(data_stream_t *stream)
Definition: http.c:2928
static BOOL HTTP_DealWithProxy(appinfo_t *hIC, http_session_t *session, http_request_t *request)
Definition: http.c:1731
HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession, LPCSTR lpszVerb, LPCSTR lpszObjectName, LPCSTR lpszVersion, LPCSTR lpszReferrer, LPCSTR *lpszAcceptTypes, DWORD dwFlags, DWORD_PTR dwContext)
Definition: http.c:1393
static voidpf wininet_zalloc(voidpf opaque, uInt items, uInt size)
Definition: http.c:460
static void cache_authorization(LPWSTR host, LPWSTR scheme, SEC_WINNT_AUTH_IDENTITY_W *nt_auth_identity)
Definition: http.c:874
static DWORD read_req_file(http_request_t *req, BYTE *buffer, DWORD size, DWORD *read, BOOL allow_blocking)
Definition: http.c:3056
BOOL WINAPI HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders, DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength)
Definition: http.c:5710
static DWORD HTTP_GetResponseHeaders(http_request_t *req, INT *len)
Definition: http.c:6006
static WCHAR * build_request_header(http_request_t *request, const WCHAR *verb, const WCHAR *path, const WCHAR *version, BOOL use_cr)
Definition: http.c:548
static DWORD HTTP_HttpOpenRequestW(http_session_t *session, LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion, LPCWSTR lpszReferrer, LPCWSTR *lpszAcceptTypes, DWORD dwFlags, DWORD_PTR dwContext, HINTERNET *ret)
Definition: http.c:3454
static LPHTTPHEADERW HTTP_GetHeader(http_request_t *req, LPCWSTR head)
Definition: http.c:285
static DWORD HTTP_HttpQueryInfoW(http_request_t *, DWORD, LPVOID, LPDWORD, LPDWORD)
Definition: http.c:3692
BOOL WINAPI HttpQueryInfoA(HINTERNET hHttpRequest, DWORD dwInfoLevel, LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
Definition: http.c:4115
static void free_accept_types(WCHAR **accept_types)
Definition: http.c:1329
static BOOL HTTP_ParseRfc850Date(LPCWSTR value, FILETIME *ft)
Definition: http.c:4651
static void http_release_netconn(http_request_t *req, BOOL reuse)
Definition: http.c:1878
static void HTTP_InsertCookies(http_request_t *request)
Definition: http.c:4374
struct _basicAuthorizationData basicAuthorizationData
static WCHAR * build_proxy_path_url(http_request_t *req)
Definition: http.c:1640
static DWORD async_read(http_request_t *req, void *buf, DWORD size, DWORD read_pos, DWORD *ret_read)
Definition: http.c:3204
static DWORD chunked_read(data_stream_t *stream, http_request_t *req, BYTE *buf, DWORD size, DWORD *read, BOOL allow_blocking)
Definition: http.c:2767
void server_release(server_t *server)
Definition: http.c:148
static DWORD gzip_read(data_stream_t *stream, http_request_t *req, BYTE *buf, DWORD size, DWORD *read, BOOL allow_blocking)
Definition: http.c:373
static BOOL chunked_end_of_data(data_stream_t *stream, http_request_t *req)
Definition: http.c:2754
static BOOL HTTP_ParseRfc1123Date(LPCWSTR value, FILETIME *ft)
Definition: http.c:4556
static BOOL HTTP_DoAuthorization(http_request_t *request, LPCWSTR pszAuthValue, struct HttpAuthInfo **ppAuthInfo, LPWSTR domain_and_username, LPWSTR password, LPWSTR host)
Definition: http.c:957
static BOOL HTTP_DeleteCustomHeader(http_request_t *req, DWORD index)
Definition: http.c:6392
DWORD HTTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName, INTERNET_PORT serverPort, LPCWSTR lpszUserName, LPCWSTR lpszPassword, DWORD dwFlags, DWORD_PTR dwContext, DWORD dwInternalFlags, HINTERNET *ret)
Definition: http.c:5910
BOOL WINAPI HttpQueryInfoW(HINTERNET hHttpRequest, DWORD dwInfoLevel, LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
Definition: http.c:3967
static DWORD HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written)
Definition: http.c:3342
static void HTTP_ReceiveRequestData(http_request_t *req)
Definition: http.c:3029
BOOL WINAPI HttpSendRequestExW(HINTERNET hRequest, LPINTERNET_BUFFERSW lpBuffersIn, LPINTERNET_BUFFERSW lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
Definition: http.c:5615
BOOL collect_connections(collect_type_t collect_type)
Definition: http.c:229
static char next_chunked_data_char(chunked_stream_t *stream)
Definition: http.c:2746
static void HTTP_clear_response_headers(http_request_t *request)
Definition: http.c:5975
static BOOL HTTP_KeepAlive(http_request_t *request)
Definition: http.c:1951
static DWORD HTTPSESSION_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
Definition: http.c:5834
static void set_content_length_header(http_request_t *request, DWORD len, DWORD flags)
Definition: http.c:4988
static const object_vtbl_t HTTPSESSIONVtbl
Definition: http.c:5887
static DWORD HTTPREQ_Read(http_request_t *req, void *buffer, DWORD size, DWORD *read, BOOL allow_blocking)
Definition: http.c:3086
BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders, DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength)
Definition: http.c:5792
static void HTTPREQ_CloseConnection(object_header_t *hdr)
Definition: http.c:1970
static WORD HTTP_ParseWkday(LPCWSTR day)
Definition: http.c:4388
static void create_cache_entry(http_request_t *req)
Definition: http.c:2442
static BOOL HTTP_ParseTime(SYSTEMTIME *st, LPCWSTR *str)
Definition: http.c:4429
#define FE(x)
static BOOL has_keep_alive(const WCHAR *version, const WCHAR *connection)
Definition: http.c:1945
static DWORD HTTPREQ_SetFilePointer(object_header_t *hdr, LONG lDistanceToMove, DWORD dwMoveContext)
Definition: http.c:3221
static DWORD refill_read_buffer(http_request_t *req, BOOL allow_blocking, DWORD *read_bytes)
Definition: http.c:2656
#define COALESCEFLAGS
Definition: http.c:6189
static DWORD HTTPSESSION_SetOption(object_header_t *hdr, DWORD option, void *buffer, DWORD size)
Definition: http.c:5852
static UINT HTTP_EncodeBase64(LPCSTR bin, unsigned int len, LPWSTR base64)
Definition: http.c:1451
static const data_stream_vtbl_t netconn_stream_vtbl
Definition: http.c:2739
static BOOL HTTP_InsertAuthorization(http_request_t *request, struct HttpAuthInfo *pAuthInfo, LPCWSTR header)
Definition: http.c:1577
static void netconn_destroy(data_stream_t *stream)
Definition: http.c:2735
server_t * get_server(substr_t name, INTERNET_PORT port, BOOL is_https, BOOL do_create)
Definition: http.c:192
static BOOL HTTP_ParseDateAsAsctime(LPCWSTR value, FILETIME *ft)
Definition: http.c:4480
static DWORD HTTPREQ_QueryDataAvailable(object_header_t *hdr, DWORD *available, DWORD flags, DWORD_PTR ctx)
Definition: http.c:3358
static DWORD HTTPREQ_SetOption(object_header_t *hdr, DWORD option, void *buffer, DWORD size)
Definition: http.c:2365
void free_authorization_cache(void)
Definition: http.c:926
static CRITICAL_SECTION connection_pool_cs
Definition: http.c:131
static DWORD gzip_drain_content(data_stream_t *stream, http_request_t *req, BOOL allow_blocking)
Definition: http.c:436
static DWORD get_security_cert_struct(http_request_t *req, INTERNET_CERTIFICATE_INFOA *info)
Definition: http.c:2016
static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data, UINT auth_data_len)
Definition: http.c:797
static LPWSTR HTTP_build_req(LPCWSTR *list, int len)
Definition: http.c:4356
static DWORD chunked_drain_content(data_stream_t *stream, http_request_t *req, BOOL allow_blocking)
Definition: http.c:2910
static struct list basicAuthorizationCache
Definition: http.c:108
static DWORD HTTPREQ_LockRequestFile(object_header_t *hdr, req_file_t **ret)
Definition: http.c:3416
static WORD HTTP_ParseWeekday(LPCWSTR day)
Definition: http.c:4633
static void send_request_complete(http_request_t *req, DWORD_PTR result, DWORD error)
Definition: http.c:3018
static DWORD set_content_length(http_request_t *request)
Definition: http.c:2942
static CRITICAL_SECTION_DEBUG connection_pool_debug
Definition: http.c:132
static BOOL end_of_read_data(http_request_t *req)
Definition: http.c:2622
static DWORD read_http_stream(http_request_t *req, BYTE *buf, DWORD size, DWORD *read, BOOL allow_blocking)
Definition: http.c:2627
BOOL WINAPI HttpSendRequestExA(HINTERNET hRequest, LPINTERNET_BUFFERSA lpBuffersIn, LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
Definition: http.c:5554
static BOOL collector_running
Definition: http.c:141
static UINT retrieve_cached_basic_authorization(http_request_t *req, const WCHAR *host, const WCHAR *realm, char **auth_data)
Definition: http.c:760
HINTERNET WINAPI HttpOpenRequestW(HINTERNET hHttpSession, LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion, LPCWSTR lpszReferrer, LPCWSTR *lpszAcceptTypes, DWORD dwFlags, DWORD_PTR dwContext)
Definition: http.c:3569
static BOOL has_token(const WCHAR *str, const WCHAR *token)
Definition: http.c:1929
static void remove_data(http_request_t *req, int count)
Definition: http.c:2566
static WCHAR * compose_request_url(http_request_t *req)
Definition: http.c:1798
static UINT HTTP_DecodeBase64(LPCWSTR base64, LPSTR bin)
Definition: http.c:1507
static void gzip_destroy(data_stream_t *stream)
Definition: http.c:442
void server_addref(server_t *server)
Definition: http.c:143
static DWORD netconn_drain_content(data_stream_t *stream, http_request_t *req, BOOL allow_blocking)
Definition: http.c:2711
static CRITICAL_SECTION authcache_cs
Definition: http.c:111
BOOL WININET_Release(object_header_t *info)
Definition: internet.c:244
DWORD INTERNET_AsyncCall(task_header_t *task)
Definition: internet.c:4534
object_header_t * WININET_AddRef(object_header_t *info)
Definition: internet.c:202
BOOL WINAPI InternetCrackUrlW(const WCHAR *lpszUrl, DWORD dwUrlLength, DWORD dwFlags, URL_COMPONENTSW *lpUC)
Definition: internet.c:2052
DWORD create_req_file(const WCHAR *file_name, req_file_t **ret)
Definition: internet.c:4607
DWORD INTERNET_GetLastError(void)
Definition: internet.c:4477
BOOL WINAPI InternetTimeToSystemTimeW(LPCWSTR string, SYSTEMTIME *time, DWORD reserved)
Definition: internet.c:3979
BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags, LPWSTR lpszUrl, LPDWORD lpdwUrlLength)
Definition: internet.c:5050
DWORD INET_SetOption(object_header_t *hdr, DWORD option, void *buf, DWORD size)
Definition: internet.c:3309
void req_file_release(req_file_t *req_file)
Definition: internet.c:4634
WCHAR * INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto)
Definition: internet.c:511
void * alloc_async_task(object_header_t *hdr, async_task_proc_t proc, size_t size)
Definition: internet.c:4513
object_header_t * get_handle_object(HINTERNET hinternet)
Definition: internet.c:209
DWORD INET_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
Definition: internet.c:3159
BOOL WINAPI InternetCombineUrlW(LPCWSTR lpszBaseUrl, LPCWSTR lpszRelativeUrl, LPWSTR lpszBuffer, LPDWORD lpdwBufferLength, DWORD dwFlags)
Definition: internet.c:4766
void * alloc_object(object_header_t *parent, const object_vtbl_t *vtbl, size_t size)
Definition: internet.c:124
HMODULE WININET_hModule
Definition: internet.c:71
#define IDS_CERT_SIGNATURE
Definition: resource.h:48
#define IDS_CERT_HIGH
Definition: resource.h:51
#define IDS_CERT_SUBJECT
Definition: resource.h:43
#define IDS_CERT_LOW
Definition: resource.h:52
#define IDS_CERT_ENCRYPTION
Definition: resource.h:49
#define IDS_CERT_BITS
Definition: resource.h:53
#define IDS_CERT_EXPIRATION
Definition: resource.h:46
#define IDS_CERT_PRIVACY
Definition: resource.h:50
#define IDS_CERT_PROTOCOL
Definition: resource.h:47
#define IDS_CERT_EFFECTIVE
Definition: resource.h:45
BOOL WINAPI GetUrlCacheEntryInfoW(LPCWSTR lpszUrl, LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo, LPDWORD lpdwCacheEntryInfoBufferSize)
Definition: urlcache.c:2005
BOOL WINAPI CreateUrlCacheEntryW(LPCWSTR lpszUrlName, DWORD dwExpectedFileSize, LPCWSTR lpszFileExtension, LPWSTR lpszFileName, DWORD dwReserved)
Definition: urlcache.c:2808
BOOL WINAPI CommitUrlCacheEntryW(LPCWSTR lpszUrlName, LPCWSTR lpszLocalFileName, FILETIME ExpireTime, FILETIME LastModifiedTime, DWORD CacheEntryType, LPWSTR lpHeaderInfo, DWORD dwHeaderSize, LPCWSTR lpszFileExtension, LPCWSTR lpszOriginalUrl)
Definition: urlcache.c:3078
#define check(expected, result)
Definition: dplayx.c:43
return ret
Definition: mutex.c:147
#define L(x)
Definition: resources.c:13
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
time_t now
Definition: finger.c:65
int proxy
Definition: main.c:67
GLuint start
Definition: gl.h:1545
GLint level
Definition: gl.h:1546
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble t
Definition: gl.h:2047
GLdouble n
Definition: glext.h:7729
GLuint buffer
Definition: glext.h:5915
GLuint res
Definition: glext.h:9613
GLuint address
Definition: glext.h:9393
GLsizeiptr size
Definition: glext.h:5919
GLuint index
Definition: glext.h:6031
GLbitfield flags
Definition: glext.h:7161
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint in
Definition: glext.h:9616
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
const GLint * first
Definition: glext.h:5794
GLuint GLfloat * val
Definition: glext.h:7180
GLuint64EXT * result
Definition: glext.h:11304
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
unsigned int UINT
Definition: sysinfo.c:13
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
const char cursor[]
Definition: icontest.c:13
VOID INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInfo, DWORD dwStatusInfoLength)
DWORD create_netconn(server_t *, DWORD, BOOL, DWORD, netconn_t **)
static req_file_t * req_file_addref(req_file_t *req_file)
Definition: internet.h:417
static substr_t substr(const WCHAR *str, size_t len)
Definition: internet.h:169
collect_type_t
Definition: internet.h:58
@ COLLECT_TIMEOUT
Definition: internet.h:59
@ COLLECT_CLEANUP
Definition: internet.h:61
static WCHAR * strndupAtoW(const char *str, int len_a, DWORD *len_w)
Definition: internet.h:112
BOOL is_valid_netconn(netconn_t *)
#define INTERNET_HANDLE_IN_USE
Definition: internet.h:236
#define READ_BUFFER_SIZE
Definition: internet.h:309
void free_netconn(netconn_t *)
DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags, int *sent)
#define INET_OPENURL
Definition: internet.h:209
DWORD NETCON_secure_connect(netconn_t *, server_t *)
int NETCON_GetCipherStrength(netconn_t *)
DWORD NETCON_recv(netconn_t *, void *, size_t, BOOL, int *)
@ WH_HHTTPSESSION
Definition: internet.h:203
@ WH_HHTTPREQ
Definition: internet.h:206
@ WH_HINIT
Definition: internet.h:200
static substr_t substrz(const WCHAR *str)
Definition: internet.h:175
LPCVOID NETCON_GetCert(netconn_t *connection)
void close_netconn(netconn_t *)
#define HDR_COMMADELIMITED
Definition: internet.h:283
BOOL NETCON_is_alive(netconn_t *)
DWORD NETCON_set_timeout(netconn_t *connection, BOOL send, DWORD value)
BOOL GetAddress(const WCHAR *, INTERNET_PORT, SOCKADDR *, int *, char *)
Definition: utility.c:47
#define HDR_ISREQUEST
Definition: internet.h:282
#define S_OK
Definition: intsafe.h:52
char hdr[14]
Definition: iptest.cpp:33
uint32_t entry
Definition: isohybrid.c:63
#define b
Definition: ke_i.h:79
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
INT WINAPI GetTimeFormatA(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCSTR lpFormat, LPSTR lpTimeStr, INT cchOut)
Definition: lcformat.c:1052
INT WINAPI GetDateFormatA(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCSTR lpFormat, LPSTR lpDateStr, INT cchOut)
Definition: lcformat.c:944
if(dx< 0)
Definition: linetemp.h:194
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
int * LPINT
Definition: minwindef.h:151
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define memchr(s, c, n)
Definition: mkisofs.h:875
#define CREATE_ALWAYS
Definition: disk.h:72
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static PVOID ptr
Definition: dispmode.c:27
static const WCHAR url[]
Definition: encode.c:1384
static LPCWSTR szVersion
Definition: asmcache.c:748
static struct image bin
const WCHAR * combined_url
Definition: protocol.c:433
static LPCWSTR file_name
Definition: protocol.c:152
DWORD exp
Definition: msg.c:18625
#define min(a, b)
Definition: monoChain.cc:55
static CookieInternal * cookies
Definition: msctf.cpp:37
LONG SECURITY_STATUS
Definition: ncrypt.h:31
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
_Out_ LPWSTR lpBuffer
Definition: netsh.h:68
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define BOOL
Definition: nt_native.h:43
#define DWORD
Definition: nt_native.h:44
#define GENERIC_WRITE
Definition: nt_native.h:90
#define LOCALE_USER_DEFAULT
#define LOCALE_INVARIANT
#define LOCALE_SYSTEM_DEFAULT
NTSTATUS NTAPI NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime)
Definition: time.c:563
static TCHAR * items[]
Definition: page1.c:45
static BOOL read_bytes(parse_buffer *buf, LPVOID data, DWORD size)
Definition: parsing.c:148
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
char CHAR
Definition: pedump.c:57
#define URL_ESCAPE_SPACES_ONLY
Definition: shlwapi.h:530
#define STIF_DEFAULT
Definition: shlwapi.h:1068
#define SecIsValidHandle(x)
Definition: sspi.h:63
#define SECPKG_CRED_OUTBOUND
Definition: sspi.h:291
#define SECBUFFER_TOKEN
Definition: sspi.h:161
#define SECURITY_NETWORK_DREP
Definition: sspi.h:474
#define ISC_REQ_DELEGATE
Definition: sspi.h:362
#define ISC_REQ_MUTUAL_AUTH
Definition: sspi.h:363
#define SecInvalidateHandle(x)
Definition: sspi.h:58
#define ISC_REQ_CONNECTION
Definition: sspi.h:373
#define ISC_REQ_USE_DCE_STYLE
Definition: sspi.h:371
_In_ DWORD dwInfoLevel
Definition: winsvc.h:428
#define err(...)
#define equal(x, y)
Definition: reader.cc:56
static DWORD secure_proxy_connect(struct request *request)
Definition: request.c:1397
#define MAX_REPLY_LEN
Definition: request.c:2622
#define calloc
Definition: rosglue.h:14
const WCHAR * str
DWORD scheme
#define SEC_WINNT_AUTH_IDENTITY_UNICODE
Definition: rpcdce.h:310
#define iswspace(_c)
Definition: ctype.h:669
#define CP_UTF8
Definition: nls.h:20
#define inflateInit2(strm, windowBits)
Definition: zlib.h:1817
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:236
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:242
#define LIST_FOR_EACH(cursor, list)
Definition: list.h:226
#define memset(x, y, z)
Definition: compat.h:39
vector< Header * > headers
Definition: sdkparse.cpp:39
#define TRACE(s)
Definition: solgame.cpp:4
SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
Definition: sspi.c:699
LPWSTR lpszValue
Definition: internet.h:289
WORD wCount
Definition: internet.h:291
LPWSTR lpszField
Definition: internet.h:288
WORD wFlags
Definition: internet.h:290
ULONG max_token
Definition: http.c:77
void * auth_data
Definition: http.c:78
TimeStamp exp
Definition: http.c:75
ULONG attr
Definition: http.c:76
unsigned int auth_data_len
Definition: http.c:79
LPWSTR scheme
Definition: http.c:72
CtxtHandle ctx
Definition: http.c:74
BOOL finished
Definition: http.c:80
CredHandle cred
Definition: http.c:73
DWORD_PTR dwResult
Definition: wininet.h:155
DWORD dwUrlPathLength
Definition: wininet.h:223
LPWSTR lpszHostName
Definition: wininet.h:215
DWORD dwUserNameLength
Definition: wininet.h:219
DWORD dwHostNameLength
Definition: wininet.h:216
INTERNET_SCHEME nScheme
Definition: wininet.h:214
LPWSTR lpszScheme
Definition: wininet.h:212
LPWSTR lpszUserName
Definition: wininet.h:218
LPWSTR lpszUrlPath
Definition: wininet.h:222
INTERNET_PORT nPort
Definition: wininet.h:217
DWORD dwSchemeLength
Definition: wininet.h:213
DWORD dwHighDateTime
Definition: mapidefs.h:66
DWORD dwLowDateTime
Definition: mapidefs.h:65
DWORD dwHeadersLength
Definition: wininet.h:262
LPCSTR lpcszHeader
Definition: wininet.h:261
DWORD dwBufferLength
Definition: wininet.h:265
DWORD dwBufferTotal
Definition: wininet.h:266
LPVOID lpvBuffer
Definition: wininet.h:264
DWORD dwHeadersTotal
Definition: wininet.h:263
DWORD dwHeadersTotal
Definition: wininet.h:276
DWORD dwBufferLength
Definition: wininet.h:278
struct _INTERNET_BUFFERSW * Next
Definition: wininet.h:273
DWORD dwBufferTotal
Definition: wininet.h:279
LPCWSTR lpcszHeader
Definition: wininet.h:274
DWORD dwHeadersLength
Definition: wininet.h:275
LPVOID lpvBuffer
Definition: wininet.h:277
DWORD dwStructSize
Definition: wininet.h:272
Definition: wininet.h:2127
unsigned short * Domain
Definition: rpcdce.h:225
unsigned short * User
Definition: rpcdce.h:223
unsigned short * Password
Definition: rpcdce.h:227
WORD wMilliseconds
Definition: minwinbase.h:263
WORD wSecond
Definition: minwinbase.h:262
WORD wMinute
Definition: minwinbase.h:261
WORD wDayOfWeek
Definition: minwinbase.h:258
ULONG cBuffers
Definition: sspi.h:182
ULONG ulVersion
Definition: sspi.h:181
ULONG cbMaxToken
Definition: sspi.h:117
struct list entry
Definition: http.c:96
UINT domain_len
Definition: http.c:101
LPWSTR password
Definition: http.c:104
LPWSTR domain
Definition: http.c:100
LPWSTR host
Definition: http.c:98
LPWSTR scheme
Definition: http.c:99
LPWSTR user
Definition: http.c:102
UINT password_len
Definition: http.c:105
struct list entry
Definition: http.c:86
WH_TYPE htype
Definition: internet.h:240
ULONG connect_timeout
Definition: internet.h:243
HINTERNET hInternet
Definition: internet.h:242
DWORD dwInternalFlags
Definition: internet.h:253
ULONG receive_timeout
Definition: internet.h:245
struct list children
Definition: internet.h:258
DWORD_PTR dwContext
Definition: internet.h:250
ULONG send_timeout
Definition: internet.h:244
LPWSTR proxy
Definition: internet.h:265
LPWSTR proxyBypass
Definition: internet.h:266
LPWSTR agent
Definition: internet.h:264
LPWSTR proxyPassword
Definition: internet.h:268
object_header_t hdr
Definition: internet.h:263
LPWSTR proxyUsername
Definition: internet.h:267
DWORD scheme
CredHandle cred
CtxtHandle ctx
DWORD buf_pos
Definition: http.c:319
DWORD buf_size
Definition: http.c:318
data_stream_t data_stream
Definition: http.c:315
BYTE buf[READ_BUFFER_SIZE]
Definition: http.c:317
@ CHUNKED_STREAM_STATE_END_OF_STREAM
Definition: http.c:328
@ CHUNKED_STREAM_STATE_DISCARD_EOL_AFTER_DATA
Definition: http.c:326
@ CHUNKED_STREAM_STATE_READING_CHUNK
Definition: http.c:325
@ CHUNKED_STREAM_STATE_DISCARD_EOL_AT_END
Definition: http.c:327
@ CHUNKED_STREAM_STATE_DISCARD_EOL_AFTER_SIZE
Definition: http.c:324
@ CHUNKED_STREAM_STATE_READING_CHUNK_SIZE
Definition: http.c:323
enum chunked_stream_t::@748 state
DWORD chunk_size
Definition: http.c:320
Definition: http.c:7783
const data_stream_vtbl_t * vtbl
Definition: internet.h:300
DWORD(* drain_content)(data_stream_t *, http_request_t *, BOOL)
Definition: http.c:310
BOOL(* end_of_data)(data_stream_t *, http_request_t *)
Definition: http.c:308
void(* destroy)(data_stream_t *)
Definition: http.c:311
DWORD(* read)(data_stream_t *, http_request_t *, BYTE *, DWORD, DWORD *, BOOL)
Definition: http.c:309
Definition: cookie.c:42
task_header_t hdr
Definition: http.c:5473
Definition: parser.c:44
z_stream zstream
Definition: http.c:359
BOOL end_of_data
Definition: http.c:363
DWORD buf_pos
Definition: http.c:362
BYTE buf[READ_BUFFER_SIZE]
Definition: http.c:360
data_stream_t stream
Definition: http.c:357
data_stream_t * parent_stream
Definition: http.c:358
DWORD buf_size
Definition: http.c:361
Definition: txthost.c:37
server_t * server
Definition: internet.h:315
DWORD security_flags
Definition: internet.h:320
CRITICAL_SECTION read_section
Definition: internet.h:340
ULONGLONG cache_size
Definition: internet.h:334
data_stream_t * data_stream
Definition: internet.h:348
netconn_stream_t netconn_stream
Definition: internet.h:349
DWORD read_pos
Definition: internet.h:344
http_session_t * session
Definition: internet.h:314
FILETIME expires
Definition: internet.h:336
BYTE read_buf[READ_BUFFER_SIZE]
Definition: internet.h:346
FILETIME last_modified
Definition: internet.h:332
BOOL read_gzip
Definition: internet.h:343
LPWSTR version
Definition: internet.h:321
HANDLE hCacheFile
Definition: internet.h:333
object_header_t hdr
Definition: internet.h:313
req_file_t * req_file
Definition: internet.h:335
netconn_t * netconn
Definition: internet.h:319
ULONGLONG contentLength
Definition: internet.h:341
server_t * proxy
Definition: internet.h:316
DWORD status_code
Definition: internet.h:322
CRITICAL_SECTION headers_section
Definition: internet.h:328
DWORD read_size
Definition: internet.h:345
HTTPHEADERW * custHeaders
Definition: internet.h:329
ULONGLONG content_pos
Definition: internet.h:342
LPWSTR path
Definition: internet.h:317
LPWSTR verb
Definition: internet.h:318
appinfo_t * appInfo
Definition: internet.h:275
object_header_t hdr
Definition: internet.h:274
LPWSTR password
Definition: internet.h:278
LPWSTR userName
Definition: internet.h:277
Definition: list.h:15
Definition: name.c:39
ULONGLONG content_length
Definition: internet.h:305
ULONGLONG content_read
Definition: internet.h:306
data_stream_t data_stream
Definition: internet.h:304
BOOL secure
Definition: internet.h:69
DWORD security_flags
Definition: internet.h:80
DWORD64 keep_until
Definition: internet.h:84
BOOL keep_alive
Definition: internet.h:83
server_t * server
Definition: internet.h:73
struct list pool_entry
Definition: internet.h:85
ULONGLONG keep_until
Definition: getopt.h:109
DWORD * ret_read
Definition: http.c:3150
DWORD size
Definition: http.c:3148
task_header_t hdr
Definition: http.c:3146
void * buf
Definition: http.c:3147
DWORD read_pos
Definition: http.c:3149
WCHAR * file_name
Definition: internet.h:216
WCHAR * url
Definition: internet.h:217
BOOL is_committed
Definition: internet.h:218
HANDLE file_handle
Definition: internet.h:215
Definition: tftpd.h:86
DWORD content_read
DWORD read_size
WCHAR * version
char path[256]
Definition: tftpd.h:94
struct object_header hdr
WCHAR * verb
DWORD security_flags
WCHAR * password
DWORD read_pos
char read_buf[8192]
struct netconn * netconn
DWORD content_length
DWORD content_len
Definition: http.c:5355
void * optional
Definition: http.c:5353
WCHAR * headers
Definition: http.c:5351
task_header_t hdr
Definition: http.c:5350
DWORD optional_len
Definition: http.c:5354
DWORD headers_len
Definition: http.c:5352
const WCHAR * canon_host_port
Definition: internet.h:44
WCHAR * name
Definition: internet.h:35
const CERT_CHAIN_CONTEXT * cert_chain
Definition: internet.h:49
DWORD security_flags
Definition: internet.h:48
WCHAR * scheme_host_port
Definition: internet.h:42
BOOL is_https
Definition: internet.h:37
struct list conn_pool
Definition: internet.h:52
INTERNET_PORT port
Definition: internet.h:36
struct object_header hdr
Definition: parse.h:23
Definition: tools.h:99
Definition: cmds.c:130
uInt avail_in
Definition: zlib.h:60
z_const Bytef * next_in
Definition: zlib.h:59
alloc_func zalloc
Definition: zlib.h:70
uInt avail_out
Definition: zlib.h:64
Bytef * next_out
Definition: zlib.h:63
z_const char * msg
Definition: zlib.h:67
free_func zfree
Definition: zlib.h:71
#define max(a, b)
Definition: svc.c:63
PSYMCRYPT_PARALLEL_HASH_OPERATION next
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:726
#define LIST_INIT(head)
Definition: queue.h:197
#define LIST_ENTRY(type)
Definition: queue.h:175
int read_line()
#define DWORD_PTR
Definition: treelist.c:76
const char * LPCSTR
Definition: typedefs.h:52
const uint16_t * LPCWSTR
Definition: typedefs.h:57
uint32_t DWORD_PTR
Definition: typedefs.h:65
uint16_t * LPWSTR
Definition: typedefs.h:56
int64_t LONGLONG
Definition: typedefs.h:68
uint32_t * LPDWORD
Definition: typedefs.h:59
uint64_t DWORD64
Definition: typedefs.h:67
char * LPSTR
Definition: typedefs.h:51
int32_t INT
Definition: typedefs.h:58
uint64_t ULONGLONG
Definition: typedefs.h:67
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST Request
LONGLONG QuadPart
Definition: typedefs.h:114
struct _LARGE_INTEGER::@2753 u
Definition: pdh_main.c:64
static WCHAR * strndupW(LPCWSTR str, int len)
Definition: urlmon_main.h:236
static rfbScreenInfoPtr server
Definition: vnc.c:74
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
_In_ size_t cnt
Definition: wcstombs.cpp:43
#define FILE_END
Definition: winbase.h:117
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
HANDLE WINAPI GetCurrentThread(void)
Definition: proc.c:1197
BOOL WINAPI TryEnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define FILE_CURRENT
Definition: winbase.h:116
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
_In_opt_ LPSTR _In_opt_ LPSTR lpszPassword
Definition: winbase.h:2442
const CERT_CHAIN_CONTEXT * PCCERT_CHAIN_CONTEXT
Definition: wincrypt.h:1047
#define CERT_SIMPLE_NAME_STR
Definition: wincrypt.h:3642
#define CERT_NAME_STR_CRLF_FLAG
Definition: wincrypt.h:3648
const CERT_CONTEXT * PCCERT_CONTEXT
Definition: wincrypt.h:494
#define WINAPI
Definition: msvc.h:6
#define swprintf
Definition: winemm.h:209
#define WSAEISCONN
Definition: winerror.h:2872
#define SEC_E_OK
Definition: winerror.h:3450
#define ERROR_NO_DATA
Definition: winerror.h:406
#define WSAEWOULDBLOCK
Definition: winerror.h:2851
#define WSAECONNABORTED
Definition: winerror.h:2869
#define ERROR_NEGATIVE_SEEK
Definition: winerror.h:325
#define E_POINTER
Definition: winerror.h:3480
#define SEC_I_CONTINUE_NEEDED
Definition: winerror.h:4324
#define HTTP_STATUS_OK
Definition: winhttp.h:301
WORD INTERNET_PORT
Definition: winhttp.h:43
#define HTTP_STATUS_NO_CONTENT
Definition: winhttp.h:305
#define HTTP_STATUS_PROXY_AUTH_REQ
Definition: winhttp.h:324
_In_ _In_opt_ _Out_writes_bytes_to_opt_ lpdwBufferLength _Inout_ LPDWORD lpdwBufferLength
Definition: winhttp.h:1018
#define ICU_ENCODE_SPACES_ONLY
Definition: winhttp.h:355
#define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
Definition: winhttp.h:344
#define HTTP_STATUS_REDIRECT_KEEP_VERB
Definition: winhttp.h:315
#define INTERNET_SCHEME_HTTP
Definition: winhttp.h:47
#define HTTP_STATUS_DENIED
Definition: winhttp.h:318
#define HTTP_STATUS_CONTINUE
Definition: winhttp.h:299
#define HTTP_STATUS_NOT_MODIFIED
Definition: winhttp.h:313
#define INTERNET_DEFAULT_HTTP_PORT
Definition: winhttp.h:41
#define INTERNET_SCHEME_HTTPS
Definition: winhttp.h:48
#define HTTP_STATUS_REDIRECT
Definition: winhttp.h:311
#define HTTP_STATUS_MOVED
Definition: winhttp.h:310
#define HTTP_STATUS_REDIRECT_METHOD
Definition: winhttp.h:312
#define SECURITY_FLAG_IGNORE_CERT_CN_INVALID
Definition: winhttp.h:345
#define INTERNET_DEFAULT_HTTPS_PORT
Definition: winhttp.h:42
DWORD set_cookie(substr_t domain, substr_t path, substr_t name, substr_t data, DWORD flags)
Definition: cookie.c:912
DWORD get_cookie_header(const WCHAR *host, const WCHAR *path, WCHAR **ret)
Definition: cookie.c:646
#define HTTP_ADDREQ_FLAG_REPLACE
Definition: wininet.h:1711
#define IRF_NO_WAIT
Definition: wininet.h:625
#define INTERNET_STATUS_RECEIVING_RESPONSE
Definition: wininet.h:889
#define INTERNET_FLAG_PRAGMA_NOCACHE
Definition: wininet.h:85
#define INTERNET_ERROR_MASK_COMBINED_SEC_CERT
Definition: wininet.h:125
#define INTERNET_FLAG_NO_AUTO_REDIRECT
Definition: wininet.h:73
#define INTERNET_OPTION_SECURITY_FLAGS
Definition: wininet.h:725
#define INTERNET_FLAG_DONT_CACHE
Definition: wininet.h:67
#define INTERNET_OPTION_PROXY_PASSWORD
Definition: wininet.h:738
#define HTTP_QUERY_SET_COOKIE
Definition: wininet.h:1566
#define INTERNET_OPTION_CACHE_TIMESTAMPS
Definition: wininet.h:761
#define HTTP_QUERY_AGE
Definition: wininet.h:1571
#define HTTP_QUERY_PROXY_CONNECTION
Definition: wininet.h:1592
#define HTTP_QUERY_LAST_MODIFIED
Definition: wininet.h:1534
#define INTERNET_HANDLE_TYPE_HTTP_REQUEST
Definition: wininet.h:814
#define INTERNET_STATUS_CONNECTION_CLOSED
Definition: wininet.h:894
#define HTTP_QUERY_UNLESS_MODIFIED_SINCE
Definition: wininet.h:1593
#define HTTP_QUERY_PROXY_AUTHENTICATE
Definition: wininet.h:1564
#define ERROR_INTERNET_INVALID_URL
Definition: wininet.h:1994
#define INTERNET_OPTION_PROXY_USERNAME
Definition: wininet.h:737
#define ERROR_INTERNET_OPERATION_CANCELLED
Definition: wininet.h:2006
#define HTTP_QUERY_TITLE
Definition: wininet.h:1561
#define HTTP_QUERY_FLAG_SYSTEMTIME
Definition: wininet.h:1605
#define HTTP_QUERY_ACCEPT
Definition: wininet.h:1547
#define INTERNET_FLAG_ASYNC
Definition: wininet.h:64
#define HTTP_QUERY_RAW_HEADERS_CRLF
Definition: wininet.h:1545
#define INTERNET_FLAG_NO_COOKIES
Definition: wininet.h:75
#define INTERNET_STATUS_REQUEST_SENT
Definition: wininet.h:888
#define INTERNET_FLAG_KEEP_CONNECTION
Definition: wininet.h:72
#define HTTP_QUERY_DATE
Definition: wininet.h:1532
#define HTTP_QUERY_STATUS_TEXT
Definition: wininet.h:1543
#define INTERNET_OPTION_USER_AGENT
Definition: wininet.h:735
#define HTTP_QUERY_FLAG_COALESCE
Definition: wininet.h:1607
#define HTTP_QUERY_DERIVED_FROM
Definition: wininet.h:1537
#define HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON
Definition: wininet.h:1709
#define HTTP_QUERY_CONTENT_MD5
Definition: wininet.h:1575
#define HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA
Definition: wininet.h:1708
#define ERROR_INTERNET_ITEM_NOT_FOUND
Definition: wininet.h:2017
#define HTTP_QUERY_PUBLIC
Definition: wininet.h:1531
#define IDSI_FLAG_KEEP_ALIVE
Definition: wininet.h:386
#define INTERNET_OPTION_PASSWORD
Definition: wininet.h:723
#define IDSI_FLAG_PROXY
Definition: wininet.h:388
#define HTTP_QUERY_IF_MODIFIED_SINCE
Definition: wininet.h:1555
#define HTTP_QUERY_ETAG
Definition: wininet.h:1577
#define HTTP_QUERY_MODIFIER_FLAGS_MASK
Definition: wininet.h:1608
#define HTTP_QUERY_CONTENT_BASE
Definition: wininet.h:1573
#define HTTP_QUERY_CONTENT_ID
Definition: wininet.h:1526
#define HTTP_QUERY_USER_AGENT
Definition: wininet.h:1562
#define INTERNET_STATUS_SENDING_REQUEST
Definition: wininet.h:887
#define HTTP_QUERY_IF_RANGE
Definition: wininet.h:1581
#define INTERNET_OPTION_DATAFILE_NAME
Definition: wininet.h:727
#define HTTP_QUERY_ACCEPT_ENCODING
Definition: wininet.h:1549
#define HTTP_QUERY_CONNECTION
Definition: wininet.h:1546
#define HTTP_QUERY_VERSION
Definition: wininet.h:1541
#define HTTP_QUERY_HEADER_MASK
Definition: wininet.h:1613
#define INTERNET_OPTION_CONNECT_TIMEOUT
Definition: wininet.h:701
#define HTTP_QUERY_IF_NONE_MATCH
Definition: wininet.h:1580
#define ERROR_INTERNET_CONNECTION_ABORTED
Definition: wininet.h:2019
#define HTTP_QUERY_FLAG_NUMBER
Definition: wininet.h:1606
#define ERROR_INTERNET_OPTION_NOT_SETTABLE
Definition: wininet.h:2000
#define HTTP_QUERY_FORWARDED
Definition: wininet.h:1553
#define INTERNET_FLAG_NEED_FILE
Definition: wininet.h:88
#define INTERNET_STATUS_RESOLVING_NAME
Definition: wininet.h:883
#define INTERNET_FLAG_NO_CACHE_WRITE
Definition: wininet.h:66
#define HTTP_QUERY_ORIG_URI
Definition: wininet.h:1557
#define NORMAL_CACHE_ENTRY
Definition: wininet.h:2087
#define INTERNET_FLAG_SECURE
Definition: wininet.h:71
#define HTTP_ADDREQ_FLAG_ADD
Definition: wininet.h:1707
#define HTTP_QUERY_UPGRADE
Definition: wininet.h:1587
#define HTTP_QUERY_ACCEPT_CHARSET
Definition: wininet.h:1548
#define HTTP_QUERY_CONTENT_LOCATION
Definition: wininet.h:1574
#define INTERNET_OPTION_URL
Definition: wininet.h:728
#define HTTP_QUERY_ACCEPT_RANGES
Definition: wininet.h:1565
#define HTTP_QUERY_CONTENT_TYPE
Definition: wininet.h:1524
#define HTTP_QUERY_CONTENT_DESCRIPTION
Definition: wininet.h:1527
#define INTERNET_REQFLAG_NO_HEADERS
Definition: wininet.h:58
#define INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT
Definition: wininet.h:795
#define INTERNET_STATUS_RESPONSE_RECEIVED
Definition: wininet.h:890
#define ERROR_INTERNET_DECODING_FAILED
Definition: wininet.h:2083
#define HTTP_QUERY_VARY
Definition: wininet.h:1588
INTERNET_SCHEME
Definition: wininet.h:135
#define INTERNET_STATUS_REDIRECT
Definition: wininet.h:899
#define HTTP_QUERY_COOKIE
Definition: wininet.h:1567
#define INTERNET_STATUS_REQUEST_COMPLETE
Definition: wininet.h:898
#define INTERNET_STATUS_CONNECTING_TO_SERVER
Definition: wininet.h:885
#define HTTP_QUERY_AUTHORIZATION
Definition: wininet.h:1551
#define HTTP_QUERY_FROM
Definition: wininet.h:1554
#define IDSI_FLAG_SECURE
Definition: wininet.h:387
#define HTTP_QUERY_ALLOW
Definition: wininet.h:1530
#define ERROR_INTERNET_INCORRECT_HANDLE_STATE
Definition: wininet.h:2008
#define HTTP_QUERY_IF_UNMODIFIED_SINCE
Definition: wininet.h:1582
#define ERROR_INTERNET_INVALID_OPERATION
Definition: wininet.h:2005
#define HTTP_QUERY_REFERER
Definition: wininet.h:1558
#define HTTP_QUERY_TRANSFER_ENCODING
Definition: wininet.h:1586
#define HTTP_QUERY_HOST
Definition: wininet.h:1578
#define INTERNET_INVALID_PORT_NUMBER
Definition: wininet.h:36
#define HTTP_QUERY_LOCATION
Definition: wininet.h:1556
#define INTERNET_STATUS_HANDLE_CREATED
Definition: wininet.h:895
#define HTTP_QUERY_PRAGMA
Definition: wininet.h:1540
#define INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
Definition: wininet.h:80
#define HTTP_QUERY_COST
Definition: wininet.h:1538
#define HTTP_QUERY_STATUS_CODE
Definition: wininet.h:1542
#define HTTP_QUERY_IF_MATCH
Definition: wininet.h:1579
#define HTTP_QUERY_CACHE_CONTROL
Definition: wininet.h:1572
#define HTTP_QUERY_RAW_HEADERS
Definition: wininet.h:1544
#define HTTP_QUERY_VIA
Definition: wininet.h:1589
#define HTTP_QUERY_CONTENT_ENCODING
Definition: wininet.h:1552
#define INTERNET_OPTION_ERROR_MASK
Definition: wininet.h:755
#define INTERNET_FLAG_IGNORE_CERT_CN_INVALID
Definition: wininet.h:81
#define HTTP_QUERY_CONTENT_TRANSFER_ENCODING
Definition: wininet.h:1525
#define HTTP_QUERY_REQUEST_METHOD
Definition: wininet.h:1568
#define HTTP_QUERY_CUSTOM
Definition: wininet.h:1603
#define ERROR_HTTP_INVALID_SERVER_RESPONSE
Definition: wininet.h:2060
#define INTERNET_HANDLE_TYPE_CONNECT_HTTP
Definition: wininet.h:805
#define HTTP_QUERY_RETRY_AFTER
Definition: wininet.h:1559
#define HTTP_QUERY_SERVER
Definition: wininet.h:1560
#define INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT
Definition: wininet.h:726
#define INTERNET_COOKIE_HTTPONLY
Definition: wininet.h:1828
#define HTTP_QUERY_LINK
Definition: wininet.h:1539
#define ERROR_HTTP_INVALID_QUERY_REQUEST
Definition: wininet.h:2062
#define HTTP_QUERY_CONTENT_DISPOSITION
Definition: wininet.h:1570
#define HTTP_ADDREQ_FLAG_ADD_IF_NEW
Definition: wininet.h:1706
#define ERROR_INTERNET_NAME_NOT_RESOLVED
Definition: wininet.h:1996
#define ERROR_HTTP_INVALID_HEADER
Definition: wininet.h:2061
#define SECURITY_SET_MASK
Definition: wininet.h:836
#define INTERNET_STATUS_CONNECTED_TO_SERVER
Definition: wininet.h:886
#define INTERNET_STATUS_NAME_RESOLVED
Definition: wininet.h:884
#define INTERNET_OPTION_HANDLE_TYPE
Definition: wininet.h:710
#define HTTP_QUERY_CONTENT_LANGUAGE
Definition: wininet.h:1529
#define HTTP_QUERY_PROXY_AUTHORIZATION
Definition: wininet.h:1584
#define HTTP_QUERY_REFRESH
Definition: wininet.h:1569
#define INTERNET_OPTION_SECURITY_CERTIFICATE
Definition: wininet.h:729
#define HTTP_QUERY_WWW_AUTHENTICATE
Definition: wininet.h:1563
#define HTTP_QUERY_MESSAGE_ID
Definition: wininet.h:1535
#define ERROR_INTERNET_INCORRECT_HANDLE_TYPE
Definition: wininet.h:2007
#define HTTP_QUERY_ACCEPT_LANGUAGE
Definition: wininet.h:1550
#define HTTP_QUERY_FLAG_REQUEST_HEADERS
Definition: wininet.h:1604
#define HTTP_QUERY_URI
Definition: wininet.h:1536
#define HTTP_QUERY_RANGE
Definition: wininet.h:1585
#define HTTP_QUERY_EXPIRES
Definition: wininet.h:1533
#define INTERNET_STATUS_CLOSING_CONNECTION
Definition: wininet.h:893
#define HTTP_QUERY_CONTENT_RANGE
Definition: wininet.h:1576
#define INTERNET_OPTION_USERNAME
Definition: wininet.h:722
#define INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO
Definition: wininet.h:759
struct _INTERNET_DIAGNOSTIC_SOCKET_INFO INTERNET_DIAGNOSTIC_SOCKET_INFO
struct _INTERNET_BUFFERSW * LPINTERNET_BUFFERSW
#define HTTP_QUERY_WARNING
Definition: wininet.h:1590
#define INTERNET_REQFLAG_VIA_PROXY
Definition: wininet.h:57
#define ERROR_HTTP_HEADER_NOT_FOUND
Definition: wininet.h:2058
#define HTTP_QUERY_MAX_FORWARDS
Definition: wininet.h:1583
#define HTTP_QUERY_CONTENT_LENGTH
Definition: wininet.h:1528
#define ERROR_INTERNET_INTERNAL_ERROR
Definition: wininet.h:1993
#define INTERNET_FLAG_NO_AUTH
Definition: wininet.h:76
#define INTERNET_OPTION_REQUEST_FLAGS
Definition: wininet.h:718
#define IRF_ASYNC
Definition: wininet.h:622
#define HTTP_QUERY_MIME_VERSION
Definition: wininet.h:1523
#define INTERNET_CERTIFICATE_INFOA
Definition: wininet_test.h:53
#define NORM_IGNORECASE
Definition: winnls.h:191
#define CSTR_EQUAL
Definition: winnls.h:508
#define RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
Definition: winnt_old.h:1160
#define snprintf
Definition: wintirpc.h:48
SECURITY_STATUS WINAPI AcquireCredentialsHandleW(SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialsUse, PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
Definition: wrapper.c:105
SECURITY_STATUS WINAPI InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
Definition: wrapper.c:301
SECURITY_STATUS WINAPI DeleteSecurityContext(PCtxtHandle phContext)
Definition: wrapper.c:450
SECURITY_STATUS WINAPI QuerySecurityPackageInfoW(SEC_WCHAR *pszPackageName, PSecPkgInfoW *ppPackageInfo)
Definition: wrapper.c:750
SECURITY_STATUS WINAPI FreeCredentialsHandle(PCredHandle phCredential)
Definition: wrapper.c:151
unsigned char BYTE
Definition: xxhash.c:193