blob: a189ec7bd2f0b5f3c422a62723c69157a85727c0 [file] [log] [blame]
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00001/*
Ulrich Czekallac2757242000-06-11 20:04:44 +00002 * Wininet - Http Implementation
3 *
4 * Copyright 1999 Corel Corporation
Aric Stewartff9b9d42002-06-21 23:59:49 +00005 * Copyright 2002 CodeWeavers Inc.
David Hammerton852c7ae2003-06-20 23:26:56 +00006 * Copyright 2002 TransGaming Technologies Inc.
Francois Gougetad5ff7c2004-02-09 22:07:42 +00007 * Copyright 2004 Mike McCormack for CodeWeavers
Ulrich Czekallac2757242000-06-11 20:04:44 +00008 *
9 * Ulrich Czekalla
Aric Stewartff9b9d42002-06-21 23:59:49 +000010 * Aric Stewart
David Hammerton852c7ae2003-06-20 23:26:56 +000011 * David Hammerton
Ulrich Czekallac2757242000-06-11 20:04:44 +000012 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000013 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Ulrich Czekallac2757242000-06-11 20:04:44 +000026 */
27
Patrik Stridvall4710be22000-06-23 15:47:14 +000028#include "config.h"
29
Ulrich Czekallac2757242000-06-11 20:04:44 +000030#include <sys/types.h>
Patrik Stridvall4710be22000-06-23 15:47:14 +000031#ifdef HAVE_SYS_SOCKET_H
32# include <sys/socket.h>
33#endif
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000034#include <stdarg.h>
Ulrich Czekallac2757242000-06-11 20:04:44 +000035#include <stdio.h>
36#include <stdlib.h>
Patrik Stridvalld016f812002-08-17 00:43:16 +000037#ifdef HAVE_UNISTD_H
38# include <unistd.h>
39#endif
Ulrich Czekallac2757242000-06-11 20:04:44 +000040#include <errno.h>
Jon Griffiths4ab15582001-01-22 02:17:29 +000041#include <string.h>
Chris Morganb9807b42001-02-15 21:24:07 +000042#include <time.h>
Ulrich Czekallac2757242000-06-11 20:04:44 +000043
Guy Albertelliaafec982001-11-06 22:31:19 +000044#include "windef.h"
45#include "winbase.h"
46#include "wininet.h"
47#include "winreg.h"
48#include "winerror.h"
Jon Griffiths603f20f2001-12-11 00:30:17 +000049#define NO_SHLWAPI_STREAM
Guy Albertelliaafec982001-11-06 22:31:19 +000050#include "shlwapi.h"
51
Ulrich Czekallac2757242000-06-11 20:04:44 +000052#include "internet.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000053#include "wine/debug.h"
Alberto Massarid476a5a2002-11-12 02:13:04 +000054#include "wine/unicode.h"
Ulrich Czekallac2757242000-06-11 20:04:44 +000055
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000056WINE_DEFAULT_DEBUG_CHANNEL(wininet);
Ulrich Czekallac2757242000-06-11 20:04:44 +000057
Francois Gouget6a6c85c2004-04-19 20:12:14 +000058static const WCHAR g_szHttp[] = {' ','H','T','T','P','/','1','.','0',0 };
59static const WCHAR g_szHost[] = {'\r','\n','H','o','s','t',':',' ',0 };
60static const WCHAR g_szReferer[] = {'R','e','f','e','r','e','r',0};
61static const WCHAR g_szAccept[] = {'A','c','c','e','p','t',0};
62static const WCHAR g_szUserAgent[] = {'U','s','e','r','-','A','g','e','n','t',0};
Mike McCormacka4e902c2004-03-30 04:36:09 +000063
64
65#define HTTPHEADER g_szHttp
66#define HTTPHOSTHEADER g_szHost
Ulrich Czekallac2757242000-06-11 20:04:44 +000067#define MAXHOSTNAME 100
68#define MAX_FIELD_VALUE_LEN 256
69#define MAX_FIELD_LEN 256
70
Mike McCormacka4e902c2004-03-30 04:36:09 +000071#define HTTP_REFERER g_szReferer
72#define HTTP_ACCEPT g_szAccept
73#define HTTP_USERAGENT g_szUserAgent
Ulrich Czekallac2757242000-06-11 20:04:44 +000074
75#define HTTP_ADDHDR_FLAG_ADD 0x20000000
76#define HTTP_ADDHDR_FLAG_ADD_IF_NEW 0x10000000
77#define HTTP_ADDHDR_FLAG_COALESCE 0x40000000
78#define HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA 0x40000000
79#define HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON 0x01000000
80#define HTTP_ADDHDR_FLAG_REPLACE 0x80000000
81#define HTTP_ADDHDR_FLAG_REQ 0x02000000
82
83
Mike McCormacka4e902c2004-03-30 04:36:09 +000084BOOL HTTP_OpenConnection(LPWININETHTTPREQW lpwhr);
85int HTTP_WriteDataToStream(LPWININETHTTPREQW lpwhr,
Ulrich Czekallac2757242000-06-11 20:04:44 +000086 void *Buffer, int BytesToWrite);
Mike McCormacka4e902c2004-03-30 04:36:09 +000087int HTTP_ReadDataFromStream(LPWININETHTTPREQW lpwhr,
Ulrich Czekallac2757242000-06-11 20:04:44 +000088 void *Buffer, int BytesToRead);
Mike McCormacka4e902c2004-03-30 04:36:09 +000089BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr);
90BOOL HTTP_ProcessHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field, LPCWSTR value, DWORD dwModifier);
91void HTTP_CloseConnection(LPWININETHTTPREQW lpwhr);
92BOOL HTTP_InterpretHttpHeader(LPWSTR buffer, LPWSTR field, INT fieldlen, LPWSTR value, INT valuelen);
93INT HTTP_GetStdHeaderIndex(LPCWSTR lpszField);
94BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQW lpwhr, LPHTTPHEADERW lpHdr);
95INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQW lpwhr, LPCWSTR lpszField);
96BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQW lpwhr, INT index);
Ulrich Czekallac2757242000-06-11 20:04:44 +000097
98/***********************************************************************
Mike McCormacka4e902c2004-03-30 04:36:09 +000099 * HttpAddRequestHeadersW (WININET.@)
Ulrich Czekallac2757242000-06-11 20:04:44 +0000100 *
101 * Adds one or more HTTP header to the request handler
102 *
103 * RETURNS
104 * TRUE on success
105 * FALSE on failure
106 *
107 */
Mike McCormacka4e902c2004-03-30 04:36:09 +0000108BOOL WINAPI HttpAddRequestHeadersW(HINTERNET hHttpRequest,
109 LPCWSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
Ulrich Czekallac2757242000-06-11 20:04:44 +0000110{
Mike McCormacka4e902c2004-03-30 04:36:09 +0000111 LPWSTR lpszStart;
112 LPWSTR lpszEnd;
113 LPWSTR buffer;
114 WCHAR value[MAX_FIELD_VALUE_LEN], field[MAX_FIELD_LEN];
Ulrich Czekallac2757242000-06-11 20:04:44 +0000115 BOOL bSuccess = FALSE;
Mike McCormacka4e902c2004-03-30 04:36:09 +0000116 LPWININETHTTPREQW lpwhr;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000117
Mike McCormacka4e902c2004-03-30 04:36:09 +0000118 TRACE("%p, %s, %li, %li\n", hHttpRequest, debugstr_w(lpszHeader), dwHeaderLength,
David Hammerton852c7ae2003-06-20 23:26:56 +0000119 dwModifier);
120
Mike McCormacka4e902c2004-03-30 04:36:09 +0000121 lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hHttpRequest );
Aric Stewartff9b9d42002-06-21 23:59:49 +0000122
Ulrich Czekallac2757242000-06-11 20:04:44 +0000123 if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
124 {
125 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
126 return FALSE;
127 }
128
Uwe Bonnes1cd00da2003-02-25 03:57:59 +0000129 if (!lpszHeader)
130 return TRUE;
David Hammerton852c7ae2003-06-20 23:26:56 +0000131
Mike McCormacka4e902c2004-03-30 04:36:09 +0000132 TRACE("copying header: %s\n", debugstr_w(lpszHeader));
133 buffer = WININET_strdupW(lpszHeader);
Ulrich Czekallac2757242000-06-11 20:04:44 +0000134 lpszStart = buffer;
135
136 do
137 {
138 lpszEnd = lpszStart;
139
140 while (*lpszEnd != '\0')
141 {
142 if (*lpszEnd == '\r' && *(lpszEnd + 1) == '\n')
143 break;
144 lpszEnd++;
145 }
146
147 if (*lpszEnd == '\0')
148 break;
149
150 *lpszEnd = '\0';
151
Mike McCormacka4e902c2004-03-30 04:36:09 +0000152 TRACE("interpreting header %s\n", debugstr_w(lpszStart));
Ulrich Czekallac2757242000-06-11 20:04:44 +0000153 if (HTTP_InterpretHttpHeader(lpszStart, field, MAX_FIELD_LEN, value, MAX_FIELD_VALUE_LEN))
154 bSuccess = HTTP_ProcessHeader(lpwhr, field, value, dwModifier | HTTP_ADDHDR_FLAG_REQ);
155
156 lpszStart = lpszEnd + 2; /* Jump over \0\n */
157
158 } while (bSuccess);
159
160 HeapFree(GetProcessHeap(), 0, buffer);
161 return bSuccess;
162}
163
Chris Morgana8b32162002-09-27 22:05:23 +0000164/***********************************************************************
Mike McCormacka4e902c2004-03-30 04:36:09 +0000165 * HttpAddRequestHeadersA (WININET.@)
166 *
167 * Adds one or more HTTP header to the request handler
168 *
169 * RETURNS
170 * TRUE on success
171 * FALSE on failure
172 *
173 */
174BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest,
175 LPCSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
176{
177 DWORD len;
178 LPWSTR hdr;
179 BOOL r;
180
181 TRACE("%p, %s, %li, %li\n", hHttpRequest, debugstr_a(lpszHeader), dwHeaderLength,
182 dwModifier);
183
184 len = MultiByteToWideChar( CP_ACP, 0, lpszHeader, dwHeaderLength, NULL, 0 );
185 hdr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
186 MultiByteToWideChar( CP_ACP, 0, lpszHeader, dwHeaderLength, hdr, len );
187 if( dwHeaderLength != -1 )
188 dwHeaderLength = len;
189
190 r = HttpAddRequestHeadersW( hHttpRequest, hdr, dwHeaderLength, dwModifier );
191
192 HeapFree( GetProcessHeap(), 0, hdr );
193
194 return r;
195}
196
197/***********************************************************************
Chris Morgana8b32162002-09-27 22:05:23 +0000198 * HttpEndRequestA (WININET.@)
199 *
200 * Ends an HTTP request that was started by HttpSendRequestEx
201 *
202 * RETURNS
203 * TRUE if successful
204 * FALSE on failure
205 *
206 */
207BOOL WINAPI HttpEndRequestA(HINTERNET hRequest, LPINTERNET_BUFFERSA lpBuffersOut,
208 DWORD dwFlags, DWORD dwContext)
209{
210 FIXME("stub\n");
211 return FALSE;
212}
213
214/***********************************************************************
215 * HttpEndRequestW (WININET.@)
216 *
217 * Ends an HTTP request that was started by HttpSendRequestEx
218 *
219 * RETURNS
220 * TRUE if successful
221 * FALSE on failure
222 *
223 */
224BOOL WINAPI HttpEndRequestW(HINTERNET hRequest, LPINTERNET_BUFFERSW lpBuffersOut,
225 DWORD dwFlags, DWORD dwContext)
226{
227 FIXME("stub\n");
228 return FALSE;
229}
Ulrich Czekallac2757242000-06-11 20:04:44 +0000230
231/***********************************************************************
Mike McCormacka4e902c2004-03-30 04:36:09 +0000232 * HttpOpenRequestW (WININET.@)
Ulrich Czekallac2757242000-06-11 20:04:44 +0000233 *
234 * Open a HTTP request handle
235 *
236 * RETURNS
237 * HINTERNET a HTTP request handle on success
238 * NULL on failure
239 *
240 */
Mike McCormacka4e902c2004-03-30 04:36:09 +0000241HINTERNET WINAPI HttpOpenRequestW(HINTERNET hHttpSession,
242 LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
243 LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
Ulrich Czekallac2757242000-06-11 20:04:44 +0000244 DWORD dwFlags, DWORD dwContext)
245{
Mike McCormacka4e902c2004-03-30 04:36:09 +0000246 LPWININETHTTPSESSIONW lpwhs;
Mike McCormack09d2d472004-03-25 05:29:47 +0000247 LPWININETAPPINFOW hIC = NULL;
Mike McCormack7cc70c02004-02-07 01:03:41 +0000248 HINTERNET handle = NULL;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000249
David Hammerton852c7ae2003-06-20 23:26:56 +0000250 TRACE("(%p, %s, %s, %s, %s, %p, %08lx, %08lx)\n", hHttpSession,
Mike McCormacka4e902c2004-03-30 04:36:09 +0000251 debugstr_w(lpszVerb), debugstr_w(lpszObjectName),
252 debugstr_w(lpszVersion), debugstr_w(lpszReferrer), lpszAcceptTypes,
David Hammerton852c7ae2003-06-20 23:26:56 +0000253 dwFlags, dwContext);
Alberto Massaribc8bd722002-12-06 23:20:31 +0000254 if(lpszAcceptTypes!=NULL)
255 {
256 int i;
257 for(i=0;lpszAcceptTypes[i]!=NULL;i++)
Mike McCormacka4e902c2004-03-30 04:36:09 +0000258 TRACE("\taccept type: %s\n",debugstr_w(lpszAcceptTypes[i]));
Alberto Massaribc8bd722002-12-06 23:20:31 +0000259 }
Ulrich Czekallac2757242000-06-11 20:04:44 +0000260
Mike McCormacka4e902c2004-03-30 04:36:09 +0000261 lpwhs = (LPWININETHTTPSESSIONW) WININET_GetObject( hHttpSession );
Ulrich Czekallac2757242000-06-11 20:04:44 +0000262 if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
263 {
264 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
Mike McCormack7cc70c02004-02-07 01:03:41 +0000265 return NULL;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000266 }
Mike McCormack09d2d472004-03-25 05:29:47 +0000267 hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000268
Aric Stewartff9b9d42002-06-21 23:59:49 +0000269 /*
270 * My tests seem to show that the windows version does not
271 * become asynchronous until after this point. And anyhow
272 * if this call was asynchronous then how would you get the
273 * necessary HINTERNET pointer returned by this function.
274 *
275 * I am leaving this here just in case I am wrong
276 *
277 * if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
278 */
279 if (0)
Ulrich Czekallac2757242000-06-11 20:04:44 +0000280 {
281 WORKREQUEST workRequest;
Mike McCormacka4e902c2004-03-30 04:36:09 +0000282 struct WORKREQ_HTTPOPENREQUESTW *req;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000283
Mike McCormacka4e902c2004-03-30 04:36:09 +0000284 workRequest.asyncall = HTTPOPENREQUESTW;
Mike McCormackb8921a22003-09-25 20:25:22 +0000285 workRequest.handle = hHttpSession;
Mike McCormacka4e902c2004-03-30 04:36:09 +0000286 req = &workRequest.u.HttpOpenRequestW;
287 req->lpszVerb = WININET_strdupW(lpszVerb);
288 req->lpszObjectName = WININET_strdupW(lpszObjectName);
Aric Stewartff9b9d42002-06-21 23:59:49 +0000289 if (lpszVersion)
Mike McCormacka4e902c2004-03-30 04:36:09 +0000290 req->lpszVersion = WININET_strdupW(lpszVersion);
Aric Stewartff9b9d42002-06-21 23:59:49 +0000291 else
Mike McCormackb8921a22003-09-25 20:25:22 +0000292 req->lpszVersion = 0;
Aric Stewartff9b9d42002-06-21 23:59:49 +0000293 if (lpszReferrer)
Mike McCormacka4e902c2004-03-30 04:36:09 +0000294 req->lpszReferrer = WININET_strdupW(lpszReferrer);
Aric Stewartff9b9d42002-06-21 23:59:49 +0000295 else
Mike McCormackb8921a22003-09-25 20:25:22 +0000296 req->lpszReferrer = 0;
297 req->lpszAcceptTypes = lpszAcceptTypes;
298 req->dwFlags = dwFlags;
299 req->dwContext = dwContext;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000300
Aric Stewartff9b9d42002-06-21 23:59:49 +0000301 INTERNET_AsyncCall(&workRequest);
Ulrich Czekallac2757242000-06-11 20:04:44 +0000302 }
303 else
304 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000305 handle = HTTP_HttpOpenRequestW(hHttpSession, lpszVerb, lpszObjectName,
David Hammerton852c7ae2003-06-20 23:26:56 +0000306 lpszVersion, lpszReferrer, lpszAcceptTypes,
307 dwFlags, dwContext);
Ulrich Czekallac2757242000-06-11 20:04:44 +0000308 }
Mike McCormack7cc70c02004-02-07 01:03:41 +0000309 TRACE("returning %p\n", handle);
310 return handle;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000311}
312
David Hammerton852c7ae2003-06-20 23:26:56 +0000313
Alberto Massarid476a5a2002-11-12 02:13:04 +0000314/***********************************************************************
Mike McCormacka4e902c2004-03-30 04:36:09 +0000315 * HttpOpenRequestA (WININET.@)
Alberto Massarid476a5a2002-11-12 02:13:04 +0000316 *
317 * Open a HTTP request handle
318 *
319 * RETURNS
320 * HINTERNET a HTTP request handle on success
321 * NULL on failure
322 *
323 */
Mike McCormacka4e902c2004-03-30 04:36:09 +0000324HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession,
325 LPCSTR lpszVerb, LPCSTR lpszObjectName, LPCSTR lpszVersion,
326 LPCSTR lpszReferrer , LPCSTR *lpszAcceptTypes,
Alberto Massarid476a5a2002-11-12 02:13:04 +0000327 DWORD dwFlags, DWORD dwContext)
328{
Mike McCormacka4e902c2004-03-30 04:36:09 +0000329 LPWSTR szVerb = NULL, szObjectName = NULL;
330 LPWSTR szVersion = NULL, szReferrer = NULL, *szAcceptTypes = NULL;
David Hammerton852c7ae2003-06-20 23:26:56 +0000331 INT len;
332 INT acceptTypesCount;
333 HINTERNET rc = FALSE;
334 TRACE("(%p, %s, %s, %s, %s, %p, %08lx, %08lx)\n", hHttpSession,
Mike McCormacka4e902c2004-03-30 04:36:09 +0000335 debugstr_a(lpszVerb), debugstr_a(lpszObjectName),
336 debugstr_a(lpszVersion), debugstr_a(lpszReferrer), lpszAcceptTypes,
David Hammerton852c7ae2003-06-20 23:26:56 +0000337 dwFlags, dwContext);
Alberto Massaribc8bd722002-12-06 23:20:31 +0000338
David Hammerton852c7ae2003-06-20 23:26:56 +0000339 if (lpszVerb)
340 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000341 len = MultiByteToWideChar(CP_ACP, 0, lpszVerb, -1, NULL, 0 );
342 szVerb = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR) );
Mike McCormack43629c92003-08-15 03:47:30 +0000343 if ( !szVerb )
David Hammerton852c7ae2003-06-20 23:26:56 +0000344 goto end;
Mike McCormacka4e902c2004-03-30 04:36:09 +0000345 MultiByteToWideChar(CP_ACP, 0, lpszVerb, -1, szVerb, len);
David Hammerton852c7ae2003-06-20 23:26:56 +0000346 }
347
348 if (lpszObjectName)
349 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000350 len = MultiByteToWideChar(CP_ACP, 0, lpszObjectName, -1, NULL, 0 );
351 szObjectName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR) );
Mike McCormack43629c92003-08-15 03:47:30 +0000352 if ( !szObjectName )
David Hammerton852c7ae2003-06-20 23:26:56 +0000353 goto end;
Mike McCormacka4e902c2004-03-30 04:36:09 +0000354 MultiByteToWideChar(CP_ACP, 0, lpszObjectName, -1, szObjectName, len );
David Hammerton852c7ae2003-06-20 23:26:56 +0000355 }
356
357 if (lpszVersion)
358 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000359 len = MultiByteToWideChar(CP_ACP, 0, lpszVersion, -1, NULL, 0 );
360 szVersion = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
Mike McCormack43629c92003-08-15 03:47:30 +0000361 if ( !szVersion )
David Hammerton852c7ae2003-06-20 23:26:56 +0000362 goto end;
Mike McCormacka4e902c2004-03-30 04:36:09 +0000363 MultiByteToWideChar(CP_ACP, 0, lpszVersion, -1, szVersion, len );
David Hammerton852c7ae2003-06-20 23:26:56 +0000364 }
365
366 if (lpszReferrer)
367 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000368 len = MultiByteToWideChar(CP_ACP, 0, lpszReferrer, -1, NULL, 0 );
369 szReferrer = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
Mike McCormack43629c92003-08-15 03:47:30 +0000370 if ( !szReferrer )
David Hammerton852c7ae2003-06-20 23:26:56 +0000371 goto end;
Mike McCormacka4e902c2004-03-30 04:36:09 +0000372 MultiByteToWideChar(CP_ACP, 0, lpszReferrer, -1, szReferrer, len );
David Hammerton852c7ae2003-06-20 23:26:56 +0000373 }
374
375 acceptTypesCount = 0;
376 if (lpszAcceptTypes)
377 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000378 /* find out how many there are */
379 while (lpszAcceptTypes[acceptTypesCount])
380 acceptTypesCount++;
381 szAcceptTypes = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *) * (acceptTypesCount+1));
David Hammerton852c7ae2003-06-20 23:26:56 +0000382 acceptTypesCount = 0;
383 while (lpszAcceptTypes[acceptTypesCount])
384 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000385 len = MultiByteToWideChar(CP_ACP, 0, lpszAcceptTypes[acceptTypesCount],
386 -1, NULL, 0 );
387 szAcceptTypes[acceptTypesCount] = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
Mike McCormack43629c92003-08-15 03:47:30 +0000388 if (!szAcceptTypes[acceptTypesCount] )
David Hammerton852c7ae2003-06-20 23:26:56 +0000389 goto end;
Mike McCormacka4e902c2004-03-30 04:36:09 +0000390 MultiByteToWideChar(CP_ACP, 0, lpszAcceptTypes[acceptTypesCount],
391 -1, szAcceptTypes[acceptTypesCount], len );
David Hammerton852c7ae2003-06-20 23:26:56 +0000392 acceptTypesCount++;
393 }
Mike McCormacka4e902c2004-03-30 04:36:09 +0000394 szAcceptTypes[acceptTypesCount] = NULL;
David Hammerton852c7ae2003-06-20 23:26:56 +0000395 }
396 else szAcceptTypes = 0;
397
Mike McCormacka4e902c2004-03-30 04:36:09 +0000398 rc = HttpOpenRequestW(hHttpSession, szVerb, szObjectName,
399 szVersion, szReferrer,
400 (LPCWSTR*)szAcceptTypes, dwFlags, dwContext);
David Hammerton852c7ae2003-06-20 23:26:56 +0000401
402end:
403 if (szAcceptTypes)
404 {
405 acceptTypesCount = 0;
406 while (szAcceptTypes[acceptTypesCount])
407 {
408 HeapFree(GetProcessHeap(), 0, szAcceptTypes[acceptTypesCount]);
409 acceptTypesCount++;
410 }
411 HeapFree(GetProcessHeap(), 0, szAcceptTypes);
412 }
413 if (szReferrer) HeapFree(GetProcessHeap(), 0, szReferrer);
414 if (szVersion) HeapFree(GetProcessHeap(), 0, szVersion);
415 if (szObjectName) HeapFree(GetProcessHeap(), 0, szObjectName);
416 if (szVerb) HeapFree(GetProcessHeap(), 0, szVerb);
417
418 return rc;
Alberto Massarid476a5a2002-11-12 02:13:04 +0000419}
Ulrich Czekallac2757242000-06-11 20:04:44 +0000420
421/***********************************************************************
Mike McCormacka1c16d22003-07-22 03:17:52 +0000422 * HTTP_Base64
423 */
Mike McCormack09d2d472004-03-25 05:29:47 +0000424static UINT HTTP_Base64( LPCWSTR bin, LPWSTR base64 )
Mike McCormacka1c16d22003-07-22 03:17:52 +0000425{
426 UINT n = 0, x;
427 static LPSTR HTTP_Base64Enc =
428 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
429
430 while( bin[0] )
431 {
432 /* first 6 bits, all from bin[0] */
433 base64[n++] = HTTP_Base64Enc[(bin[0] & 0xfc) >> 2];
434 x = (bin[0] & 3) << 4;
435
436 /* next 6 bits, 2 from bin[0] and 4 from bin[1] */
437 if( !bin[1] )
438 {
439 base64[n++] = HTTP_Base64Enc[x];
440 base64[n++] = '=';
441 base64[n++] = '=';
442 break;
443 }
444 base64[n++] = HTTP_Base64Enc[ x | ( (bin[1]&0xf0) >> 4 ) ];
445 x = ( bin[1] & 0x0f ) << 2;
446
447 /* next 6 bits 4 from bin[1] and 2 from bin[2] */
448 if( !bin[2] )
449 {
450 base64[n++] = HTTP_Base64Enc[x];
451 base64[n++] = '=';
452 break;
453 }
454 base64[n++] = HTTP_Base64Enc[ x | ( (bin[2]&0xc0 ) >> 6 ) ];
455
456 /* last 6 bits, all from bin [2] */
457 base64[n++] = HTTP_Base64Enc[ bin[2] & 0x3f ];
458 bin += 3;
459 }
460 base64[n] = 0;
461 return n;
462}
463
464/***********************************************************************
465 * HTTP_EncodeBasicAuth
466 *
467 * Encode the basic authentication string for HTTP 1.1
468 */
Mike McCormack09d2d472004-03-25 05:29:47 +0000469static LPWSTR HTTP_EncodeBasicAuth( LPCWSTR username, LPCWSTR password)
Mike McCormacka1c16d22003-07-22 03:17:52 +0000470{
471 UINT len;
Mike McCormack09d2d472004-03-25 05:29:47 +0000472 LPWSTR in, out;
Francois Gouget6a6c85c2004-04-19 20:12:14 +0000473 static const WCHAR szBasic[] = {'B','a','s','i','c',' ',0};
474 static const WCHAR szColon[] = {':',0};
Mike McCormacka1c16d22003-07-22 03:17:52 +0000475
Mike McCormack09d2d472004-03-25 05:29:47 +0000476 len = lstrlenW( username ) + 1 + lstrlenW ( password ) + 1;
477 in = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
Mike McCormacka1c16d22003-07-22 03:17:52 +0000478 if( !in )
479 return NULL;
480
Mike McCormack09d2d472004-03-25 05:29:47 +0000481 len = lstrlenW(szBasic) +
482 (lstrlenW( username ) + 1 + lstrlenW ( password ))*2 + 1 + 1;
Mike McCormacka4e902c2004-03-30 04:36:09 +0000483 out = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
Mike McCormacka1c16d22003-07-22 03:17:52 +0000484 if( out )
485 {
Mike McCormack09d2d472004-03-25 05:29:47 +0000486 lstrcpyW( in, username );
487 lstrcatW( in, szColon );
488 lstrcatW( in, password );
489 lstrcpyW( out, szBasic );
490 HTTP_Base64( in, &out[strlenW(out)] );
Mike McCormacka1c16d22003-07-22 03:17:52 +0000491 }
492 HeapFree( GetProcessHeap(), 0, in );
493
494 return out;
495}
496
497/***********************************************************************
498 * HTTP_InsertProxyAuthorization
499 *
500 * Insert the basic authorization field in the request header
501 */
Mike McCormacka4e902c2004-03-30 04:36:09 +0000502BOOL HTTP_InsertProxyAuthorization( LPWININETHTTPREQW lpwhr,
Mike McCormack09d2d472004-03-25 05:29:47 +0000503 LPCWSTR username, LPCWSTR password )
Mike McCormacka1c16d22003-07-22 03:17:52 +0000504{
Mike McCormacka4e902c2004-03-30 04:36:09 +0000505 HTTPHEADERW hdr;
506 INT index;
Francois Gouget6a6c85c2004-04-19 20:12:14 +0000507 static const WCHAR szProxyAuthorization[] = {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000508 'P','r','o','x','y','-','A','u','t','h','o','r','i','z','a','t','i','o','n',0 };
Mike McCormack09d2d472004-03-25 05:29:47 +0000509
Mike McCormacka4e902c2004-03-30 04:36:09 +0000510 hdr.lpszValue = HTTP_EncodeBasicAuth( username, password );
Alexandre Julliard286fe0a2004-04-13 00:19:58 +0000511 hdr.lpszField = (WCHAR *)szProxyAuthorization;
Mike McCormacka1c16d22003-07-22 03:17:52 +0000512 hdr.wFlags = HDR_ISREQUEST;
513 hdr.wCount = 0;
514 if( !hdr.lpszValue )
515 return FALSE;
516
517 TRACE("Inserting %s = %s\n",
Mike McCormacka4e902c2004-03-30 04:36:09 +0000518 debugstr_w( hdr.lpszField ), debugstr_w( hdr.lpszValue ) );
Mike McCormacka1c16d22003-07-22 03:17:52 +0000519
520 /* remove the old proxy authorization header */
521 index = HTTP_GetCustomHeaderIndex( lpwhr, hdr.lpszField );
522 if( index >=0 )
523 HTTP_DeleteCustomHeader( lpwhr, index );
524
525 HTTP_InsertCustomHeader(lpwhr, &hdr);
526 HeapFree( GetProcessHeap(), 0, hdr.lpszValue );
527
528 return TRUE;
529}
530
531/***********************************************************************
532 * HTTP_DealWithProxy
533 */
Mike McCormack09d2d472004-03-25 05:29:47 +0000534static BOOL HTTP_DealWithProxy( LPWININETAPPINFOW hIC,
Mike McCormacka4e902c2004-03-30 04:36:09 +0000535 LPWININETHTTPSESSIONW lpwhs, LPWININETHTTPREQW lpwhr)
Mike McCormacka1c16d22003-07-22 03:17:52 +0000536{
Mike McCormacka4e902c2004-03-30 04:36:09 +0000537 WCHAR buf[MAXHOSTNAME];
538 WCHAR proxy[MAXHOSTNAME + 15]; /* 15 == "http://" + sizeof(port#) + ":/\0" */
539 WCHAR* url, szNul[] = { 0 };
540 URL_COMPONENTSW UrlComponents;
Mike McCormack34622992004-04-12 23:13:53 +0000541 const WCHAR szHttp[] = { 'h','t','t','p',':','/','/',0 }, szSlash[] = { '/',0 } ;
542 const WCHAR szFormat1[] = { 'h','t','t','p',':','/','/','%','s',':','%','d',0 };
543 const WCHAR szFormat2[] = { 'h','t','t','p',':','/','/','%','s',':','%','d',0 };
Mike McCormacka4e902c2004-03-30 04:36:09 +0000544 int len;
Mike McCormacka1c16d22003-07-22 03:17:52 +0000545
546 memset( &UrlComponents, 0, sizeof UrlComponents );
547 UrlComponents.dwStructSize = sizeof UrlComponents;
548 UrlComponents.lpszHostName = buf;
549 UrlComponents.dwHostNameLength = MAXHOSTNAME;
550
Mike McCormacka4e902c2004-03-30 04:36:09 +0000551 if( CSTR_EQUAL != CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
552 buf,strlenW(szHttp),szHttp,strlenW(szHttp)) )
553 sprintfW(proxy, szFormat1, hIC->lpszProxy);
Uwe Bonnes599c4522003-12-15 19:47:31 +0000554 else
Mike McCormacka4e902c2004-03-30 04:36:09 +0000555 strcpyW(proxy,buf);
556 if( !InternetCrackUrlW(proxy, 0, 0, &UrlComponents) )
Mike McCormacka1c16d22003-07-22 03:17:52 +0000557 return FALSE;
558 if( UrlComponents.dwHostNameLength == 0 )
559 return FALSE;
560
561 if( !lpwhr->lpszPath )
562 lpwhr->lpszPath = szNul;
563 TRACE("server='%s' path='%s'\n",
Mike McCormacka4e902c2004-03-30 04:36:09 +0000564 debugstr_w(lpwhs->lpszServerName), debugstr_w(lpwhr->lpszPath));
Mike McCormacka1c16d22003-07-22 03:17:52 +0000565 /* for constant 15 see above */
Mike McCormacka4e902c2004-03-30 04:36:09 +0000566 len = strlenW(lpwhs->lpszServerName) + strlenW(lpwhr->lpszPath) + 15;
567 url = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
Mike McCormacka1c16d22003-07-22 03:17:52 +0000568
569 if(UrlComponents.nPort == INTERNET_INVALID_PORT_NUMBER)
570 UrlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT;
571
Mike McCormacka4e902c2004-03-30 04:36:09 +0000572 sprintfW(url, szFormat2, lpwhs->lpszServerName, lpwhs->nServerPort);
573
Mike McCormacka1c16d22003-07-22 03:17:52 +0000574 if( lpwhr->lpszPath[0] != '/' )
Mike McCormacka4e902c2004-03-30 04:36:09 +0000575 strcatW( url, szSlash );
576 strcatW(url, lpwhr->lpszPath);
Mike McCormacka1c16d22003-07-22 03:17:52 +0000577 if(lpwhr->lpszPath != szNul)
578 HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath);
579 lpwhr->lpszPath = url;
580 /* FIXME: Do I have to free lpwhs->lpszServerName here ? */
Mike McCormacka4e902c2004-03-30 04:36:09 +0000581 lpwhs->lpszServerName = WININET_strdupW(UrlComponents.lpszHostName);
Mike McCormacka1c16d22003-07-22 03:17:52 +0000582 lpwhs->nServerPort = UrlComponents.nPort;
583
584 return TRUE;
585}
586
587/***********************************************************************
Mike McCormacka4e902c2004-03-30 04:36:09 +0000588 * HTTP_HttpOpenRequestW (internal)
Ulrich Czekallac2757242000-06-11 20:04:44 +0000589 *
590 * Open a HTTP request handle
591 *
592 * RETURNS
593 * HINTERNET a HTTP request handle on success
594 * NULL on failure
595 *
596 */
Mike McCormacka4e902c2004-03-30 04:36:09 +0000597HINTERNET WINAPI HTTP_HttpOpenRequestW(HINTERNET hHttpSession,
598 LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
599 LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
Ulrich Czekallac2757242000-06-11 20:04:44 +0000600 DWORD dwFlags, DWORD dwContext)
601{
Mike McCormacka4e902c2004-03-30 04:36:09 +0000602 LPWININETHTTPSESSIONW lpwhs;
Mike McCormack09d2d472004-03-25 05:29:47 +0000603 LPWININETAPPINFOW hIC = NULL;
Mike McCormacka4e902c2004-03-30 04:36:09 +0000604 LPWININETHTTPREQW lpwhr;
605 LPWSTR lpszCookies;
606 LPWSTR lpszUrl = NULL;
David Hammerton852c7ae2003-06-20 23:26:56 +0000607 DWORD nCookieSize;
Mike McCormack7cc70c02004-02-07 01:03:41 +0000608 HINTERNET handle;
Francois Gouget6a6c85c2004-04-19 20:12:14 +0000609 static const WCHAR szUrlForm[] = {'h','t','t','p',':','/','/','%','s',0};
Mike McCormacka4e902c2004-03-30 04:36:09 +0000610 DWORD len;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000611
Aric Stewartff9b9d42002-06-21 23:59:49 +0000612 TRACE("--> \n");
Ulrich Czekallac2757242000-06-11 20:04:44 +0000613
Mike McCormacka4e902c2004-03-30 04:36:09 +0000614 lpwhs = (LPWININETHTTPSESSIONW) WININET_GetObject( hHttpSession );
Ulrich Czekallac2757242000-06-11 20:04:44 +0000615 if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
616 {
617 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
Mike McCormack7cc70c02004-02-07 01:03:41 +0000618 return NULL;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000619 }
620
Mike McCormack09d2d472004-03-25 05:29:47 +0000621 hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000622
Mike McCormacka4e902c2004-03-30 04:36:09 +0000623 lpwhr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETHTTPREQW));
Ulrich Czekallac2757242000-06-11 20:04:44 +0000624 if (NULL == lpwhr)
625 {
626 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
Mike McCormack7cc70c02004-02-07 01:03:41 +0000627 return NULL;
628 }
629 handle = WININET_AllocHandle( &lpwhr->hdr );
630 if (NULL == handle)
631 {
632 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
633 HeapFree( GetProcessHeap(), 0, lpwhr );
634 return NULL;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000635 }
636
637 lpwhr->hdr.htype = WH_HHTTPREQ;
Mike McCormack7cc70c02004-02-07 01:03:41 +0000638 lpwhr->hdr.lpwhparent = &lpwhs->hdr;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000639 lpwhr->hdr.dwFlags = dwFlags;
640 lpwhr->hdr.dwContext = dwContext;
David Hammerton852c7ae2003-06-20 23:26:56 +0000641 NETCON_init(&lpwhr->netConnection, dwFlags & INTERNET_FLAG_SECURE);
Ulrich Czekallac2757242000-06-11 20:04:44 +0000642
Mike McCormacka4e902c2004-03-30 04:36:09 +0000643 if (NULL != lpszObjectName && strlenW(lpszObjectName)) {
Aric Stewartff9b9d42002-06-21 23:59:49 +0000644 HRESULT rc;
Mike McCormacka4e902c2004-03-30 04:36:09 +0000645
646 len = 0;
647 rc = UrlEscapeW(lpszObjectName, NULL, &len, URL_ESCAPE_SPACES_ONLY);
Aric Stewartff9b9d42002-06-21 23:59:49 +0000648 if (rc != E_POINTER)
Mike McCormacka4e902c2004-03-30 04:36:09 +0000649 len = strlenW(lpszObjectName)+1;
650 lpwhr->lpszPath = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
651 rc = UrlEscapeW(lpszObjectName, lpwhr->lpszPath, &len,
Huw D M Davies0aebee92001-01-21 21:09:00 +0000652 URL_ESCAPE_SPACES_ONLY);
Aric Stewartff9b9d42002-06-21 23:59:49 +0000653 if (rc)
654 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000655 ERR("Unable to escape string!(%s) (%ld)\n",debugstr_w(lpszObjectName),rc);
656 strcpyW(lpwhr->lpszPath,lpszObjectName);
Aric Stewartff9b9d42002-06-21 23:59:49 +0000657 }
Huw D M Davies0aebee92001-01-21 21:09:00 +0000658 }
Ulrich Czekallac2757242000-06-11 20:04:44 +0000659
Mike McCormacka4e902c2004-03-30 04:36:09 +0000660 if (NULL != lpszReferrer && strlenW(lpszReferrer))
David Hammerton852c7ae2003-06-20 23:26:56 +0000661 HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpszReferrer, HTTP_ADDHDR_FLAG_COALESCE);
Alberto Massaribc8bd722002-12-06 23:20:31 +0000662
663 if(lpszAcceptTypes!=NULL)
664 {
665 int i;
666 for(i=0;lpszAcceptTypes[i]!=NULL;i++)
667 HTTP_ProcessHeader(lpwhr, HTTP_ACCEPT, lpszAcceptTypes[i], HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA|HTTP_ADDHDR_FLAG_REQ|HTTP_ADDHDR_FLAG_ADD_IF_NEW);
668 }
Ulrich Czekallac2757242000-06-11 20:04:44 +0000669
670 if (NULL == lpszVerb)
Ulrich Czekallac2757242000-06-11 20:04:44 +0000671 {
Francois Gouget6a6c85c2004-04-19 20:12:14 +0000672 static const WCHAR szGet[] = {'G','E','T',0};
Mike McCormacka4e902c2004-03-30 04:36:09 +0000673 lpwhr->lpszVerb = WININET_strdupW(szGet);
674 }
675 else if (strlenW(lpszVerb))
676 lpwhr->lpszVerb = WININET_strdupW(lpszVerb);
677
678 if (NULL != lpszReferrer && strlenW(lpszReferrer))
679 {
680 WCHAR buf[MAXHOSTNAME];
681 URL_COMPONENTSW UrlComponents;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000682
Mike McCormacka1c16d22003-07-22 03:17:52 +0000683 memset( &UrlComponents, 0, sizeof UrlComponents );
684 UrlComponents.dwStructSize = sizeof UrlComponents;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000685 UrlComponents.lpszHostName = buf;
686 UrlComponents.dwHostNameLength = MAXHOSTNAME;
687
Mike McCormacka4e902c2004-03-30 04:36:09 +0000688 InternetCrackUrlW(lpszReferrer, 0, 0, &UrlComponents);
689 if (strlenW(UrlComponents.lpszHostName))
690 lpwhr->lpszHostName = WININET_strdupW(UrlComponents.lpszHostName);
Andreas Mohr34965562000-08-26 20:31:48 +0000691 } else {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000692 lpwhr->lpszHostName = WININET_strdupW(lpwhs->lpszServerName);
Ulrich Czekallac2757242000-06-11 20:04:44 +0000693 }
Mike McCormacka1c16d22003-07-22 03:17:52 +0000694 if (NULL != hIC->lpszProxy && hIC->lpszProxy[0] != 0)
695 HTTP_DealWithProxy( hIC, lpwhs, lpwhr );
Ulrich Czekallac2757242000-06-11 20:04:44 +0000696
David Hammerton852c7ae2003-06-20 23:26:56 +0000697 if (hIC->lpszAgent)
698 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000699 WCHAR *agent_header;
Francois Gouget6a6c85c2004-04-19 20:12:14 +0000700 static const WCHAR user_agent[] = {'U','s','e','r','-','A','g','e','n','t',':',' ','%','s','\r','\n',0 };
Mike McCormack09d2d472004-03-25 05:29:47 +0000701
Mike McCormacka4e902c2004-03-30 04:36:09 +0000702 len = strlenW(hIC->lpszAgent) + strlenW(user_agent);
703 agent_header = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
704 sprintfW(agent_header, user_agent, hIC->lpszAgent );
Mike McCormack09d2d472004-03-25 05:29:47 +0000705
Mike McCormacka4e902c2004-03-30 04:36:09 +0000706 HttpAddRequestHeadersW(handle, agent_header, strlenW(agent_header),
David Hammerton852c7ae2003-06-20 23:26:56 +0000707 HTTP_ADDREQ_FLAG_ADD);
708 HeapFree(GetProcessHeap(), 0, agent_header);
709 }
710
Mike McCormacka4e902c2004-03-30 04:36:09 +0000711 len = strlenW(lpwhr->lpszHostName) + strlenW(szUrlForm);
712 lpszUrl = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
713 sprintfW( lpszUrl, szUrlForm, lpwhr->lpszHostName );
714
715 if (InternetGetCookieW(lpszUrl, NULL, NULL, &nCookieSize))
David Hammerton852c7ae2003-06-20 23:26:56 +0000716 {
717 int cnt = 0;
Francois Gouget6a6c85c2004-04-19 20:12:14 +0000718 static const WCHAR szCookie[] = {'C','o','o','k','i','e',':',' ',0};
719 static const WCHAR szcrlf[] = {'\r','\n',0};
David Hammerton852c7ae2003-06-20 23:26:56 +0000720
Mike McCormacka4e902c2004-03-30 04:36:09 +0000721 lpszCookies = HeapAlloc(GetProcessHeap(), 0, (nCookieSize + 1 + 8)*sizeof(WCHAR));
David Hammerton852c7ae2003-06-20 23:26:56 +0000722
Mike McCormacka4e902c2004-03-30 04:36:09 +0000723 cnt += sprintfW(lpszCookies, szCookie);
724 InternetGetCookieW(lpszUrl, NULL, lpszCookies + cnt, &nCookieSize);
725 strcatW(lpszCookies, szcrlf);
David Hammerton852c7ae2003-06-20 23:26:56 +0000726
Mike McCormacka4e902c2004-03-30 04:36:09 +0000727 HttpAddRequestHeadersW(handle, lpszCookies, strlenW(lpszCookies),
David Hammerton852c7ae2003-06-20 23:26:56 +0000728 HTTP_ADDREQ_FLAG_ADD);
729 HeapFree(GetProcessHeap(), 0, lpszCookies);
730 }
731 HeapFree(GetProcessHeap(), 0, lpszUrl);
732
733
734
Ulrich Czekallac2757242000-06-11 20:04:44 +0000735 if (hIC->lpfnStatusCB)
736 {
737 INTERNET_ASYNC_RESULT iar;
738
Lionel Ulmera29b4c72004-02-09 20:55:58 +0000739 iar.dwResult = (DWORD)handle;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000740 iar.dwError = ERROR_SUCCESS;
741
Aric Stewartff9b9d42002-06-21 23:59:49 +0000742 SendAsyncCallback(hIC, hHttpSession, dwContext,
743 INTERNET_STATUS_HANDLE_CREATED, &iar,
744 sizeof(INTERNET_ASYNC_RESULT));
Ulrich Czekallac2757242000-06-11 20:04:44 +0000745 }
746
Aric Stewartff9b9d42002-06-21 23:59:49 +0000747 /*
748 * A STATUS_REQUEST_COMPLETE is NOT sent here as per my tests on windows
749 */
750
751 /*
752 * According to my tests. The name is not resolved until a request is Opened
753 */
754 SendAsyncCallback(hIC, hHttpSession, dwContext,
755 INTERNET_STATUS_RESOLVING_NAME,
756 lpwhs->lpszServerName,
Mike McCormacka4e902c2004-03-30 04:36:09 +0000757 strlenW(lpwhs->lpszServerName)+1);
Aric Stewartff9b9d42002-06-21 23:59:49 +0000758 if (!GetAddress(lpwhs->lpszServerName, lpwhs->nServerPort,
759 &lpwhs->phostent, &lpwhs->socketAddress))
Ulrich Czekallac2757242000-06-11 20:04:44 +0000760 {
Aric Stewartff9b9d42002-06-21 23:59:49 +0000761 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
Mike McCormack7cc70c02004-02-07 01:03:41 +0000762 return NULL;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000763 }
764
Aric Stewartff9b9d42002-06-21 23:59:49 +0000765 SendAsyncCallback(hIC, hHttpSession, lpwhr->hdr.dwContext,
766 INTERNET_STATUS_NAME_RESOLVED,
767 &(lpwhs->socketAddress),
768 sizeof(struct sockaddr_in));
769
Mike McCormack7cc70c02004-02-07 01:03:41 +0000770 TRACE("<-- %p\n", handle);
771 return handle;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000772}
773
774
775/***********************************************************************
Mike McCormack1baf39f2004-03-30 20:37:49 +0000776 * HttpQueryInfoW (WININET.@)
Ulrich Czekallac2757242000-06-11 20:04:44 +0000777 *
778 * Queries for information about an HTTP request
779 *
780 * RETURNS
781 * TRUE on success
782 * FALSE on failure
783 *
784 */
Mike McCormacka4e902c2004-03-30 04:36:09 +0000785BOOL WINAPI HttpQueryInfoW(HINTERNET hHttpRequest, DWORD dwInfoLevel,
Ulrich Czekallac2757242000-06-11 20:04:44 +0000786 LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
787{
Mike McCormacka4e902c2004-03-30 04:36:09 +0000788 LPHTTPHEADERW lphttpHdr = NULL;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000789 BOOL bSuccess = FALSE;
Mike McCormacka4e902c2004-03-30 04:36:09 +0000790 LPWININETHTTPREQW lpwhr;
Francois Gouget6a6c85c2004-04-19 20:12:14 +0000791 static const WCHAR szFmt[] = { '%','s',':',' ','%','s','%','s',0 };
792 static const WCHAR szcrlf[] = { '\r','\n',0 };
793 static const WCHAR sznul[] = { 0 };
Vincent BĂ©ron9a624912002-05-31 23:06:46 +0000794
Lionel Ulmer1d5e6b62004-02-09 22:01:49 +0000795 if (TRACE_ON(wininet)) {
796#define FE(x) { x, #x }
797 static const wininet_flag_info query_flags[] = {
798 FE(HTTP_QUERY_MIME_VERSION),
799 FE(HTTP_QUERY_CONTENT_TYPE),
800 FE(HTTP_QUERY_CONTENT_TRANSFER_ENCODING),
801 FE(HTTP_QUERY_CONTENT_ID),
802 FE(HTTP_QUERY_CONTENT_DESCRIPTION),
803 FE(HTTP_QUERY_CONTENT_LENGTH),
804 FE(HTTP_QUERY_CONTENT_LANGUAGE),
805 FE(HTTP_QUERY_ALLOW),
806 FE(HTTP_QUERY_PUBLIC),
807 FE(HTTP_QUERY_DATE),
808 FE(HTTP_QUERY_EXPIRES),
809 FE(HTTP_QUERY_LAST_MODIFIED),
810 FE(HTTP_QUERY_MESSAGE_ID),
811 FE(HTTP_QUERY_URI),
812 FE(HTTP_QUERY_DERIVED_FROM),
813 FE(HTTP_QUERY_COST),
814 FE(HTTP_QUERY_LINK),
815 FE(HTTP_QUERY_PRAGMA),
816 FE(HTTP_QUERY_VERSION),
817 FE(HTTP_QUERY_STATUS_CODE),
818 FE(HTTP_QUERY_STATUS_TEXT),
819 FE(HTTP_QUERY_RAW_HEADERS),
820 FE(HTTP_QUERY_RAW_HEADERS_CRLF),
821 FE(HTTP_QUERY_CONNECTION),
822 FE(HTTP_QUERY_ACCEPT),
823 FE(HTTP_QUERY_ACCEPT_CHARSET),
824 FE(HTTP_QUERY_ACCEPT_ENCODING),
825 FE(HTTP_QUERY_ACCEPT_LANGUAGE),
826 FE(HTTP_QUERY_AUTHORIZATION),
827 FE(HTTP_QUERY_CONTENT_ENCODING),
828 FE(HTTP_QUERY_FORWARDED),
829 FE(HTTP_QUERY_FROM),
830 FE(HTTP_QUERY_IF_MODIFIED_SINCE),
831 FE(HTTP_QUERY_LOCATION),
832 FE(HTTP_QUERY_ORIG_URI),
833 FE(HTTP_QUERY_REFERER),
834 FE(HTTP_QUERY_RETRY_AFTER),
835 FE(HTTP_QUERY_SERVER),
836 FE(HTTP_QUERY_TITLE),
837 FE(HTTP_QUERY_USER_AGENT),
838 FE(HTTP_QUERY_WWW_AUTHENTICATE),
839 FE(HTTP_QUERY_PROXY_AUTHENTICATE),
840 FE(HTTP_QUERY_ACCEPT_RANGES),
841 FE(HTTP_QUERY_SET_COOKIE),
842 FE(HTTP_QUERY_COOKIE),
843 FE(HTTP_QUERY_REQUEST_METHOD),
844 FE(HTTP_QUERY_REFRESH),
845 FE(HTTP_QUERY_CONTENT_DISPOSITION),
846 FE(HTTP_QUERY_AGE),
847 FE(HTTP_QUERY_CACHE_CONTROL),
848 FE(HTTP_QUERY_CONTENT_BASE),
849 FE(HTTP_QUERY_CONTENT_LOCATION),
850 FE(HTTP_QUERY_CONTENT_MD5),
851 FE(HTTP_QUERY_CONTENT_RANGE),
852 FE(HTTP_QUERY_ETAG),
853 FE(HTTP_QUERY_HOST),
854 FE(HTTP_QUERY_IF_MATCH),
855 FE(HTTP_QUERY_IF_NONE_MATCH),
856 FE(HTTP_QUERY_IF_RANGE),
857 FE(HTTP_QUERY_IF_UNMODIFIED_SINCE),
858 FE(HTTP_QUERY_MAX_FORWARDS),
859 FE(HTTP_QUERY_PROXY_AUTHORIZATION),
860 FE(HTTP_QUERY_RANGE),
861 FE(HTTP_QUERY_TRANSFER_ENCODING),
862 FE(HTTP_QUERY_UPGRADE),
863 FE(HTTP_QUERY_VARY),
864 FE(HTTP_QUERY_VIA),
865 FE(HTTP_QUERY_WARNING),
866 FE(HTTP_QUERY_CUSTOM)
867 };
868 static const wininet_flag_info modifier_flags[] = {
869 FE(HTTP_QUERY_FLAG_REQUEST_HEADERS),
870 FE(HTTP_QUERY_FLAG_SYSTEMTIME),
871 FE(HTTP_QUERY_FLAG_NUMBER),
872 FE(HTTP_QUERY_FLAG_COALESCE)
873 };
874#undef FE
875 DWORD info_mod = dwInfoLevel & HTTP_QUERY_MODIFIER_FLAGS_MASK;
876 DWORD info = dwInfoLevel & HTTP_QUERY_HEADER_MASK;
877 int i;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000878
Lionel Ulmer1d5e6b62004-02-09 22:01:49 +0000879 TRACE("(%p, 0x%08lx)--> %ld\n", hHttpRequest, dwInfoLevel, dwInfoLevel);
880 TRACE(" Attribute:");
881 for (i = 0; i < (sizeof(query_flags) / sizeof(query_flags[0])); i++) {
882 if (query_flags[i].val == info) {
883 DPRINTF(" %s", query_flags[i].name);
884 break;
885 }
886 }
887 if (i == (sizeof(query_flags) / sizeof(query_flags[0]))) {
888 DPRINTF(" Unknown (%08lx)", info);
889 }
890
891 DPRINTF(" Modifier:");
892 for (i = 0; i < (sizeof(modifier_flags) / sizeof(modifier_flags[0])); i++) {
893 if (modifier_flags[i].val & info_mod) {
894 DPRINTF(" %s", modifier_flags[i].name);
895 info_mod &= ~ modifier_flags[i].val;
896 }
897 }
898
899 if (info_mod) {
900 DPRINTF(" Unknown (%08lx)", info_mod);
901 }
902 DPRINTF("\n");
903 }
904
Mike McCormacka4e902c2004-03-30 04:36:09 +0000905 lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hHttpRequest );
Ulrich Czekallac2757242000-06-11 20:04:44 +0000906 if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
907 {
908 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
Lionel Ulmer1d5e6b62004-02-09 22:01:49 +0000909 goto lend;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000910 }
911
912 /* Find requested header structure */
913 if ((dwInfoLevel & ~HTTP_QUERY_MODIFIER_FLAGS_MASK) == HTTP_QUERY_CUSTOM)
914 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000915 INT index = HTTP_GetCustomHeaderIndex(lpwhr, (LPWSTR)lpBuffer);
Ulrich Czekallac2757242000-06-11 20:04:44 +0000916
917 if (index < 0)
918 goto lend;
919
920 lphttpHdr = &lpwhr->pCustHeaders[index];
921 }
922 else
923 {
924 INT index = dwInfoLevel & ~HTTP_QUERY_MODIFIER_FLAGS_MASK;
925
926 if (index == HTTP_QUERY_RAW_HEADERS_CRLF || index == HTTP_QUERY_RAW_HEADERS)
927 {
928 INT i, delim, size = 0, cnt = 0;
929
930 delim = index == HTTP_QUERY_RAW_HEADERS_CRLF ? 2 : 1;
931
932 /* Calculate length of custom reuqest headers */
933 for (i = 0; i < lpwhr->nCustHeaders; i++)
934 {
935 if ((~lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST) && lpwhr->pCustHeaders[i].lpszField &&
936 lpwhr->pCustHeaders[i].lpszValue)
937 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000938 size += strlenW(lpwhr->pCustHeaders[i].lpszField) +
939 strlenW(lpwhr->pCustHeaders[i].lpszValue) + delim + 2;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000940 }
941 }
942
943 /* Calculate the length of stadard request headers */
944 for (i = 0; i <= HTTP_QUERY_MAX; i++)
945 {
Vincent BĂ©ron9a624912002-05-31 23:06:46 +0000946 if ((~lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST) && lpwhr->StdHeaders[i].lpszField &&
Ulrich Czekallac2757242000-06-11 20:04:44 +0000947 lpwhr->StdHeaders[i].lpszValue)
948 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000949 size += strlenW(lpwhr->StdHeaders[i].lpszField) +
950 strlenW(lpwhr->StdHeaders[i].lpszValue) + delim + 2;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000951 }
952 }
Ulrich Czekallac2757242000-06-11 20:04:44 +0000953 size += delim;
954
Alexandre Julliarda2bf4d02004-03-31 20:09:54 +0000955 if (size + 1 > *lpdwBufferLength/sizeof(WCHAR))
Ulrich Czekallac2757242000-06-11 20:04:44 +0000956 {
Alexandre Julliarda2bf4d02004-03-31 20:09:54 +0000957 *lpdwBufferLength = (size + 1) * sizeof(WCHAR);
Ulrich Czekallac2757242000-06-11 20:04:44 +0000958 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
959 goto lend;
960 }
961
962 /* Append standard request heades */
963 for (i = 0; i <= HTTP_QUERY_MAX; i++)
964 {
965 if ((~lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST) &&
966 lpwhr->StdHeaders[i].lpszField &&
967 lpwhr->StdHeaders[i].lpszValue)
968 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000969 cnt += sprintfW((WCHAR*)lpBuffer + cnt, szFmt,
970 lpwhr->StdHeaders[i].lpszField, lpwhr->StdHeaders[i].lpszValue,
971 index == HTTP_QUERY_RAW_HEADERS_CRLF ? szcrlf : sznul );
Ulrich Czekallac2757242000-06-11 20:04:44 +0000972 }
973 }
974
975 /* Append custom request heades */
976 for (i = 0; i < lpwhr->nCustHeaders; i++)
977 {
978 if ((~lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST) &&
979 lpwhr->pCustHeaders[i].lpszField &&
980 lpwhr->pCustHeaders[i].lpszValue)
981 {
Mike McCormacka4e902c2004-03-30 04:36:09 +0000982 cnt += sprintfW((WCHAR*)lpBuffer + cnt, szFmt,
Ulrich Czekallac2757242000-06-11 20:04:44 +0000983 lpwhr->pCustHeaders[i].lpszField, lpwhr->pCustHeaders[i].lpszValue,
Mike McCormacka4e902c2004-03-30 04:36:09 +0000984 index == HTTP_QUERY_RAW_HEADERS_CRLF ? szcrlf : sznul);
Ulrich Czekallac2757242000-06-11 20:04:44 +0000985 }
986 }
987
Mike McCormacka4e902c2004-03-30 04:36:09 +0000988 strcpyW((WCHAR*)lpBuffer + cnt, index == HTTP_QUERY_RAW_HEADERS_CRLF ? szcrlf : sznul);
Ulrich Czekallac2757242000-06-11 20:04:44 +0000989
Alexandre Julliarda2bf4d02004-03-31 20:09:54 +0000990 *lpdwBufferLength = (cnt + delim) * sizeof(WCHAR);
991 bSuccess = TRUE;
992 goto lend;
Ulrich Czekallac2757242000-06-11 20:04:44 +0000993 }
994 else if (index >= 0 && index <= HTTP_QUERY_MAX && lpwhr->StdHeaders[index].lpszValue)
Vincent BĂ©ron9a624912002-05-31 23:06:46 +0000995 {
Ulrich Czekallac2757242000-06-11 20:04:44 +0000996 lphttpHdr = &lpwhr->StdHeaders[index];
997 }
998 else
999 goto lend;
1000 }
1001
1002 /* Ensure header satisifies requested attributes */
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00001003 if ((dwInfoLevel & HTTP_QUERY_FLAG_REQUEST_HEADERS) &&
Ulrich Czekallac2757242000-06-11 20:04:44 +00001004 (~lphttpHdr->wFlags & HDR_ISREQUEST))
1005 goto lend;
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00001006
Ulrich Czekallac2757242000-06-11 20:04:44 +00001007 /* coalesce value to reuqested type */
1008 if (dwInfoLevel & HTTP_QUERY_FLAG_NUMBER)
1009 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001010 *(int *)lpBuffer = atoiW(lphttpHdr->lpszValue);
Lionel Ulmer1d5e6b62004-02-09 22:01:49 +00001011 bSuccess = TRUE;
1012
1013 TRACE(" returning number : %d\n", *(int *)lpBuffer);
Ulrich Czekallac2757242000-06-11 20:04:44 +00001014 }
1015 else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME)
1016 {
1017 time_t tmpTime;
1018 struct tm tmpTM;
1019 SYSTEMTIME *STHook;
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00001020
Ulrich Czekallac2757242000-06-11 20:04:44 +00001021 tmpTime = ConvertTimeString(lphttpHdr->lpszValue);
1022
1023 tmpTM = *gmtime(&tmpTime);
1024 STHook = (SYSTEMTIME *) lpBuffer;
1025 if(STHook==NULL)
1026 goto lend;
1027
Lionel Ulmer1d5e6b62004-02-09 22:01:49 +00001028 STHook->wDay = tmpTM.tm_mday;
1029 STHook->wHour = tmpTM.tm_hour;
1030 STHook->wMilliseconds = 0;
1031 STHook->wMinute = tmpTM.tm_min;
1032 STHook->wDayOfWeek = tmpTM.tm_wday;
1033 STHook->wMonth = tmpTM.tm_mon + 1;
1034 STHook->wSecond = tmpTM.tm_sec;
1035 STHook->wYear = tmpTM.tm_year;
1036
1037 bSuccess = TRUE;
1038
1039 TRACE(" returning time : %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n",
1040 STHook->wYear, STHook->wMonth, STHook->wDay, STHook->wDayOfWeek,
1041 STHook->wHour, STHook->wMinute, STHook->wSecond, STHook->wMilliseconds);
Ulrich Czekallac2757242000-06-11 20:04:44 +00001042 }
1043 else if (dwInfoLevel & HTTP_QUERY_FLAG_COALESCE)
1044 {
1045 if (*lpdwIndex >= lphttpHdr->wCount)
1046 {
1047 INTERNET_SetLastError(ERROR_HTTP_HEADER_NOT_FOUND);
1048 }
1049 else
1050 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001051 /* Copy strncpyW(lpBuffer, lphttpHdr[*lpdwIndex], len); */
Ulrich Czekallac2757242000-06-11 20:04:44 +00001052 (*lpdwIndex)++;
1053 }
1054 }
1055 else
1056 {
Alexandre Julliarda2bf4d02004-03-31 20:09:54 +00001057 INT len = (strlenW(lphttpHdr->lpszValue) + 1) * sizeof(WCHAR);
Ulrich Czekallac2757242000-06-11 20:04:44 +00001058
Alexandre Julliarda2bf4d02004-03-31 20:09:54 +00001059 if (len > *lpdwBufferLength)
Ulrich Czekallac2757242000-06-11 20:04:44 +00001060 {
Alexandre Julliarda2bf4d02004-03-31 20:09:54 +00001061 *lpdwBufferLength = len;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001062 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1063 goto lend;
1064 }
1065
Alexandre Julliarda2bf4d02004-03-31 20:09:54 +00001066 memcpy(lpBuffer, lphttpHdr->lpszValue, len);
1067 *lpdwBufferLength = len - sizeof(WCHAR);
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00001068 bSuccess = TRUE;
Lionel Ulmer1d5e6b62004-02-09 22:01:49 +00001069
Mike McCormacka4e902c2004-03-30 04:36:09 +00001070 TRACE(" returning string : '%s'\n", debugstr_w(lpBuffer));
Ulrich Czekallac2757242000-06-11 20:04:44 +00001071 }
1072
1073lend:
1074 TRACE("%d <--\n", bSuccess);
1075 return bSuccess;
1076}
1077
Alberto Massarid476a5a2002-11-12 02:13:04 +00001078/***********************************************************************
Mike McCormacka4e902c2004-03-30 04:36:09 +00001079 * HttpQueryInfoA (WININET.@)
Alberto Massarid476a5a2002-11-12 02:13:04 +00001080 *
1081 * Queries for information about an HTTP request
1082 *
1083 * RETURNS
1084 * TRUE on success
1085 * FALSE on failure
1086 *
1087 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001088BOOL WINAPI HttpQueryInfoA(HINTERNET hHttpRequest, DWORD dwInfoLevel,
Alberto Massarid476a5a2002-11-12 02:13:04 +00001089 LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
1090{
1091 BOOL result;
Mike McCormack1baf39f2004-03-30 20:37:49 +00001092 DWORD len;
1093 WCHAR* bufferW;
1094
Alberto Massarid476a5a2002-11-12 02:13:04 +00001095 if((dwInfoLevel & HTTP_QUERY_FLAG_NUMBER) ||
1096 (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME))
1097 {
Mike McCormack1baf39f2004-03-30 20:37:49 +00001098 return HttpQueryInfoW( hHttpRequest, dwInfoLevel, lpBuffer,
1099 lpdwBufferLength, lpdwIndex );
Alberto Massarid476a5a2002-11-12 02:13:04 +00001100 }
Mike McCormack1baf39f2004-03-30 20:37:49 +00001101
1102 len = (*lpdwBufferLength)*sizeof(WCHAR);
1103 bufferW = HeapAlloc( GetProcessHeap(), 0, len );
1104 result = HttpQueryInfoW( hHttpRequest, dwInfoLevel, bufferW,
1105 &len, lpdwIndex );
1106 if( result )
Alberto Massarid476a5a2002-11-12 02:13:04 +00001107 {
Mike McCormack1baf39f2004-03-30 20:37:49 +00001108 len = WideCharToMultiByte( CP_ACP,0, bufferW, len / sizeof(WCHAR),
1109 lpBuffer, *lpdwBufferLength, NULL, NULL );
1110 *lpdwBufferLength = len * sizeof(WCHAR);
Alberto Massarid476a5a2002-11-12 02:13:04 +00001111 }
Mike McCormack1baf39f2004-03-30 20:37:49 +00001112 HeapFree(GetProcessHeap(), 0, bufferW );
1113
Alberto Massarid476a5a2002-11-12 02:13:04 +00001114 return result;
1115}
Huw D M Daviesf9b6d7b2000-10-28 00:30:23 +00001116
1117/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00001118 * HttpSendRequestExA (WININET.@)
Huw D M Daviesf9b6d7b2000-10-28 00:30:23 +00001119 *
1120 * Sends the specified request to the HTTP server and allows chunked
1121 * transfers
1122 */
1123BOOL WINAPI HttpSendRequestExA(HINTERNET hRequest,
1124 LPINTERNET_BUFFERSA lpBuffersIn,
1125 LPINTERNET_BUFFERSA lpBuffersOut,
1126 DWORD dwFlags, DWORD dwContext)
1127{
1128 FIXME("(%p, %p, %p, %08lx, %08lx): stub\n", hRequest, lpBuffersIn,
1129 lpBuffersOut, dwFlags, dwContext);
1130 return FALSE;
1131}
1132
Ulrich Czekallac2757242000-06-11 20:04:44 +00001133/***********************************************************************
Patrik Stridvall8b216b32001-06-19 18:20:47 +00001134 * HttpSendRequestA (WININET.@)
Ulrich Czekallac2757242000-06-11 20:04:44 +00001135 *
1136 * Sends the specified request to the HTTP server
1137 *
1138 * RETURNS
1139 * TRUE on success
1140 * FALSE on failure
1141 *
1142 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001143BOOL WINAPI HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders,
Ulrich Czekallac2757242000-06-11 20:04:44 +00001144 DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00001145{
Mike McCormacka4e902c2004-03-30 04:36:09 +00001146 LPWININETHTTPREQW lpwhr;
1147 LPWININETHTTPSESSIONW lpwhs = NULL;
Mike McCormack09d2d472004-03-25 05:29:47 +00001148 LPWININETAPPINFOW hIC = NULL;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001149
Mike McCormack7cc70c02004-02-07 01:03:41 +00001150 TRACE("%p, %p (%s), %li, %p, %li)\n", hHttpRequest,
Mike McCormacka4e902c2004-03-30 04:36:09 +00001151 lpszHeaders, debugstr_w(lpszHeaders), dwHeaderLength, lpOptional, dwOptionalLength);
Ulrich Czekallac2757242000-06-11 20:04:44 +00001152
Mike McCormacka4e902c2004-03-30 04:36:09 +00001153 lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hHttpRequest );
Ulrich Czekallac2757242000-06-11 20:04:44 +00001154 if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
1155 {
1156 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1157 return FALSE;
1158 }
1159
Mike McCormacka4e902c2004-03-30 04:36:09 +00001160 lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001161 if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
1162 {
1163 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1164 return FALSE;
1165 }
1166
Mike McCormack09d2d472004-03-25 05:29:47 +00001167 hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001168 if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
1169 {
1170 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1171 return FALSE;
1172 }
1173
1174 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1175 {
1176 WORKREQUEST workRequest;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001177 struct WORKREQ_HTTPSENDREQUESTW *req;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001178
Mike McCormacka4e902c2004-03-30 04:36:09 +00001179 workRequest.asyncall = HTTPSENDREQUESTW;
Mike McCormackb8921a22003-09-25 20:25:22 +00001180 workRequest.handle = hHttpRequest;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001181 req = &workRequest.u.HttpSendRequestW;
Aric Stewartff9b9d42002-06-21 23:59:49 +00001182 if (lpszHeaders)
Mike McCormacka4e902c2004-03-30 04:36:09 +00001183 req->lpszHeader = WININET_strdupW(lpszHeaders);
Aric Stewartff9b9d42002-06-21 23:59:49 +00001184 else
Mike McCormackb8921a22003-09-25 20:25:22 +00001185 req->lpszHeader = 0;
1186 req->dwHeaderLength = dwHeaderLength;
1187 req->lpOptional = lpOptional;
1188 req->dwOptionalLength = dwOptionalLength;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001189
Aric Stewartff9b9d42002-06-21 23:59:49 +00001190 INTERNET_AsyncCall(&workRequest);
1191 /*
Alberto Massaribc8bd722002-12-06 23:20:31 +00001192 * This is from windows.
Aric Stewartff9b9d42002-06-21 23:59:49 +00001193 */
Alberto Massaribc8bd722002-12-06 23:20:31 +00001194 SetLastError(ERROR_IO_PENDING);
Aric Stewartff9b9d42002-06-21 23:59:49 +00001195 return 0;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001196 }
1197 else
1198 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001199 return HTTP_HttpSendRequestW(hHttpRequest, lpszHeaders,
Ulrich Czekallac2757242000-06-11 20:04:44 +00001200 dwHeaderLength, lpOptional, dwOptionalLength);
1201 }
1202}
1203
Alberto Massarid476a5a2002-11-12 02:13:04 +00001204/***********************************************************************
1205 * HttpSendRequestW (WININET.@)
1206 *
1207 * Sends the specified request to the HTTP server
1208 *
1209 * RETURNS
1210 * TRUE on success
1211 * FALSE on failure
1212 *
1213 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001214BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
Alberto Massarid476a5a2002-11-12 02:13:04 +00001215 DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
1216{
1217 BOOL result;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001218 LPWSTR szHeaders=NULL;
Alberto Massarid476a5a2002-11-12 02:13:04 +00001219 DWORD nLen=dwHeaderLength;
1220 if(lpszHeaders!=NULL)
1221 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001222 nLen=MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,NULL,0);
1223 szHeaders=HeapAlloc(GetProcessHeap(),0,nLen*sizeof(WCHAR));
1224 MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,szHeaders,nLen);
Alberto Massarid476a5a2002-11-12 02:13:04 +00001225 }
Mike McCormacka4e902c2004-03-30 04:36:09 +00001226 result=HttpSendRequestW(hHttpRequest, szHeaders, nLen, lpOptional, dwOptionalLength);
Alberto Massarid476a5a2002-11-12 02:13:04 +00001227 if(szHeaders!=NULL)
Mike McCormack43629c92003-08-15 03:47:30 +00001228 HeapFree(GetProcessHeap(),0,szHeaders);
Alberto Massarid476a5a2002-11-12 02:13:04 +00001229 return result;
1230}
Ulrich Czekallac2757242000-06-11 20:04:44 +00001231
1232/***********************************************************************
Alberto Massaribc8bd722002-12-06 23:20:31 +00001233 * HTTP_HandleRedirect (internal)
1234 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001235static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl, LPCWSTR lpszHeaders,
Alberto Massaribc8bd722002-12-06 23:20:31 +00001236 DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength)
1237{
Mike McCormacka4e902c2004-03-30 04:36:09 +00001238 LPWININETHTTPSESSIONW lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent;
Mike McCormack09d2d472004-03-25 05:29:47 +00001239 LPWININETAPPINFOW hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001240 WCHAR path[2048];
Mike McCormack7cc70c02004-02-07 01:03:41 +00001241 HINTERNET handle;
1242
Alberto Massaribc8bd722002-12-06 23:20:31 +00001243 if(lpszUrl[0]=='/')
1244 {
1245 /* if it's an absolute path, keep the same session info */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001246 strcpyW(path,lpszUrl);
Alberto Massaribc8bd722002-12-06 23:20:31 +00001247 }
Mike McCormacka1c16d22003-07-22 03:17:52 +00001248 else if (NULL != hIC->lpszProxy && hIC->lpszProxy[0] != 0)
1249 {
1250 TRACE("Redirect through proxy\n");
Mike McCormacka4e902c2004-03-30 04:36:09 +00001251 strcpyW(path,lpszUrl);
Mike McCormacka1c16d22003-07-22 03:17:52 +00001252 }
Alberto Massaribc8bd722002-12-06 23:20:31 +00001253 else
1254 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001255 URL_COMPONENTSW urlComponents;
1256 WCHAR protocol[32], hostName[MAXHOSTNAME], userName[1024];
1257 WCHAR password[1024], extra[1024];
1258 urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
Alberto Massaribc8bd722002-12-06 23:20:31 +00001259 urlComponents.lpszScheme = protocol;
1260 urlComponents.dwSchemeLength = 32;
1261 urlComponents.lpszHostName = hostName;
1262 urlComponents.dwHostNameLength = MAXHOSTNAME;
1263 urlComponents.lpszUserName = userName;
1264 urlComponents.dwUserNameLength = 1024;
1265 urlComponents.lpszPassword = password;
1266 urlComponents.dwPasswordLength = 1024;
1267 urlComponents.lpszUrlPath = path;
1268 urlComponents.dwUrlPathLength = 2048;
1269 urlComponents.lpszExtraInfo = extra;
1270 urlComponents.dwExtraInfoLength = 1024;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001271 if(!InternetCrackUrlW(lpszUrl, strlenW(lpszUrl), 0, &urlComponents))
Alberto Massaribc8bd722002-12-06 23:20:31 +00001272 return FALSE;
1273
1274 if (urlComponents.nPort == INTERNET_INVALID_PORT_NUMBER)
1275 urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT;
1276
Mike McCormacka1c16d22003-07-22 03:17:52 +00001277#if 0
1278 /*
1279 * This upsets redirects to binary files on sourceforge.net
1280 * and gives an html page instead of the target file
1281 * Examination of the HTTP request sent by native wininet.dll
1282 * reveals that it doesn't send a referrer in that case.
1283 * Maybe there's a flag that enables this, or maybe a referrer
1284 * shouldn't be added in case of a redirect.
1285 */
1286
1287 /* consider the current host as the referrer */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001288 if (NULL != lpwhs->lpszServerName && strlenW(lpwhs->lpszServerName))
Mike McCormacka1c16d22003-07-22 03:17:52 +00001289 HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpwhs->lpszServerName,
1290 HTTP_ADDHDR_FLAG_REQ|HTTP_ADDREQ_FLAG_REPLACE|
1291 HTTP_ADDHDR_FLAG_ADD_IF_NEW);
1292#endif
Alberto Massaribc8bd722002-12-06 23:20:31 +00001293
1294 if (NULL != lpwhs->lpszServerName)
1295 HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName);
Mike McCormacka4e902c2004-03-30 04:36:09 +00001296 lpwhs->lpszServerName = WININET_strdupW(hostName);
Alberto Massaribc8bd722002-12-06 23:20:31 +00001297 if (NULL != lpwhs->lpszUserName)
1298 HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName);
Mike McCormacka4e902c2004-03-30 04:36:09 +00001299 lpwhs->lpszUserName = WININET_strdupW(userName);
Alberto Massaribc8bd722002-12-06 23:20:31 +00001300 lpwhs->nServerPort = urlComponents.nPort;
1301
1302 if (NULL != lpwhr->lpszHostName)
1303 HeapFree(GetProcessHeap(), 0, lpwhr->lpszHostName);
Mike McCormacka4e902c2004-03-30 04:36:09 +00001304 lpwhr->lpszHostName=WININET_strdupW(hostName);
Alberto Massaribc8bd722002-12-06 23:20:31 +00001305
1306 SendAsyncCallback(hIC, lpwhs, lpwhr->hdr.dwContext,
1307 INTERNET_STATUS_RESOLVING_NAME,
1308 lpwhs->lpszServerName,
Mike McCormacka4e902c2004-03-30 04:36:09 +00001309 strlenW(lpwhs->lpszServerName)+1);
Alberto Massaribc8bd722002-12-06 23:20:31 +00001310
1311 if (!GetAddress(lpwhs->lpszServerName, lpwhs->nServerPort,
1312 &lpwhs->phostent, &lpwhs->socketAddress))
1313 {
1314 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
1315 return FALSE;
1316 }
1317
1318 SendAsyncCallback(hIC, lpwhs, lpwhr->hdr.dwContext,
1319 INTERNET_STATUS_NAME_RESOLVED,
1320 &(lpwhs->socketAddress),
1321 sizeof(struct sockaddr_in));
1322
1323 }
1324
1325 if(lpwhr->lpszPath)
1326 HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath);
1327 lpwhr->lpszPath=NULL;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001328 if (strlenW(path))
Alberto Massaribc8bd722002-12-06 23:20:31 +00001329 {
1330 DWORD needed = 0;
1331 HRESULT rc;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001332
1333 rc = UrlEscapeW(path, NULL, &needed, URL_ESCAPE_SPACES_ONLY);
Alberto Massaribc8bd722002-12-06 23:20:31 +00001334 if (rc != E_POINTER)
Mike McCormacka4e902c2004-03-30 04:36:09 +00001335 needed = strlenW(path)+1;
1336 lpwhr->lpszPath = HeapAlloc(GetProcessHeap(), 0, needed*sizeof(WCHAR));
1337 rc = UrlEscapeW(path, lpwhr->lpszPath, &needed,
Alberto Massaribc8bd722002-12-06 23:20:31 +00001338 URL_ESCAPE_SPACES_ONLY);
1339 if (rc)
1340 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001341 ERR("Unable to escape string!(%s) (%ld)\n",debugstr_w(path),rc);
1342 strcpyW(lpwhr->lpszPath,path);
Alberto Massaribc8bd722002-12-06 23:20:31 +00001343 }
1344 }
1345
Mike McCormack7cc70c02004-02-07 01:03:41 +00001346 handle = WININET_FindHandle( &lpwhr->hdr );
Mike McCormacka4e902c2004-03-30 04:36:09 +00001347 return HttpSendRequestW(handle, lpszHeaders, dwHeaderLength, lpOptional, dwOptionalLength);
Alberto Massaribc8bd722002-12-06 23:20:31 +00001348}
1349
1350/***********************************************************************
Mike McCormacka4e902c2004-03-30 04:36:09 +00001351 * HTTP_HttpSendRequestW (internal)
Ulrich Czekallac2757242000-06-11 20:04:44 +00001352 *
1353 * Sends the specified request to the HTTP server
1354 *
1355 * RETURNS
1356 * TRUE on success
1357 * FALSE on failure
1358 *
1359 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001360BOOL WINAPI HTTP_HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders,
Ulrich Czekallac2757242000-06-11 20:04:44 +00001361 DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
1362{
1363 INT cnt;
1364 INT i;
1365 BOOL bSuccess = FALSE;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001366 LPWSTR requestString = NULL;
1367 LPWSTR lpszHeaders_r_n = NULL; /* lpszHeaders with atleast one pair of \r\n at the end */
Ulrich Czekallac2757242000-06-11 20:04:44 +00001368 INT requestStringLen;
Aric Stewartff9b9d42002-06-21 23:59:49 +00001369 INT responseLen;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001370 INT headerLength = 0;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001371 LPWININETHTTPREQW lpwhr;
1372 LPWININETHTTPSESSIONW lpwhs = NULL;
Mike McCormack09d2d472004-03-25 05:29:47 +00001373 LPWININETAPPINFOW hIC = NULL;
David Hammerton852c7ae2003-06-20 23:26:56 +00001374 BOOL loop_next = FALSE;
1375 int CustHeaderIndex;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001376
Aric Stewartff9b9d42002-06-21 23:59:49 +00001377 TRACE("--> 0x%08lx\n", (ULONG)hHttpRequest);
Ulrich Czekallac2757242000-06-11 20:04:44 +00001378
1379 /* Verify our tree of internet handles */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001380 lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hHttpRequest );
Ulrich Czekallac2757242000-06-11 20:04:44 +00001381 if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
1382 {
1383 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1384 return FALSE;
1385 }
1386
Mike McCormacka4e902c2004-03-30 04:36:09 +00001387 lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001388 if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
1389 {
1390 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1391 return FALSE;
1392 }
1393
Mike McCormack09d2d472004-03-25 05:29:47 +00001394 hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001395 if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
1396 {
1397 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1398 return FALSE;
1399 }
1400
1401 /* Clear any error information */
1402 INTERNET_SetLastError(0);
1403
Aric Stewartff9b9d42002-06-21 23:59:49 +00001404
Ulrich Czekallac2757242000-06-11 20:04:44 +00001405 /* We must have a verb */
1406 if (NULL == lpwhr->lpszVerb)
1407 {
1408 goto lend;
1409 }
1410
David Hammerton6226f3f2003-08-05 18:31:02 +00001411 /* if we are using optional stuff, we must add the fixed header of that option length */
1412 if (lpOptional && dwOptionalLength)
1413 {
1414 char contentLengthStr[sizeof("Content-Length: ") + 20 /* int */ + 2 /* \n\r */];
1415 sprintf(contentLengthStr, "Content-Length: %li\r\n", dwOptionalLength);
1416 HttpAddRequestHeadersA(hHttpRequest, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_ADD);
1417 }
1418
David Hammerton852c7ae2003-06-20 23:26:56 +00001419 do
Nikolas Zimmermann76598822001-10-04 18:12:41 +00001420 {
Francois Gouget6a6c85c2004-04-19 20:12:14 +00001421 static const WCHAR szSlash[] = { '/',0 };
1422 static const WCHAR szSpace[] = { ' ',0 };
1423 static const WCHAR szHttp[] = { 'h','t','t','p',':','/','/', 0 };
1424 static const WCHAR szcrlf[] = {'\r','\n', 0};
1425 static const WCHAR sztwocrlf[] = {'\r','\n','\r','\n', 0};
1426 static const WCHAR szSetCookie[] = {'S','e','t','-','C','o','o','k','i','e',0 };
Mike McCormacka4e902c2004-03-30 04:36:09 +00001427
1428 TRACE("Going to url %s %s\n", debugstr_w(lpwhr->lpszHostName), debugstr_w(lpwhr->lpszPath));
David Hammerton852c7ae2003-06-20 23:26:56 +00001429 loop_next = FALSE;
Nikolas Zimmermann76598822001-10-04 18:12:41 +00001430
David Hammerton852c7ae2003-06-20 23:26:56 +00001431 /* If we don't have a path we set it to root */
1432 if (NULL == lpwhr->lpszPath)
Mike McCormacka4e902c2004-03-30 04:36:09 +00001433 lpwhr->lpszPath = WININET_strdupW(szSlash);
1434
1435 if(CSTR_EQUAL != CompareStringW( LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
1436 lpwhr->lpszPath, strlenW(szHttp), szHttp, strlenW(szHttp) )
David Hammerton852c7ae2003-06-20 23:26:56 +00001437 && lpwhr->lpszPath[0] != '/') /* not an absolute path ?? --> fix it !! */
1438 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001439 WCHAR *fixurl = HeapAlloc(GetProcessHeap(), 0,
1440 (strlenW(lpwhr->lpszPath) + 2)*sizeof(WCHAR));
David Hammerton852c7ae2003-06-20 23:26:56 +00001441 *fixurl = '/';
Mike McCormacka4e902c2004-03-30 04:36:09 +00001442 strcpyW(fixurl + 1, lpwhr->lpszPath);
David Hammerton852c7ae2003-06-20 23:26:56 +00001443 HeapFree( GetProcessHeap(), 0, lpwhr->lpszPath );
1444 lpwhr->lpszPath = fixurl;
1445 }
Ulrich Czekallac2757242000-06-11 20:04:44 +00001446
David Hammerton852c7ae2003-06-20 23:26:56 +00001447 /* Calculate length of request string */
1448 requestStringLen =
Mike McCormacka4e902c2004-03-30 04:36:09 +00001449 strlenW(lpwhr->lpszVerb) +
1450 strlenW(lpwhr->lpszPath) +
1451 strlenW(HTTPHEADER) +
David Hammerton852c7ae2003-06-20 23:26:56 +00001452 5; /* " \r\n\r\n" */
1453
Jeremy Shaw3cd1cfe2003-12-11 04:25:41 +00001454 /* add "\r\n" to end of lpszHeaders if needed */
1455 if (lpszHeaders)
1456 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001457 int len = strlenW(lpszHeaders);
Jeremy Shaw3cd1cfe2003-12-11 04:25:41 +00001458
1459 /* Check if the string is terminated with \r\n, but not if
1460 * the string is less that 2 characters long, because then
1461 * we would be looking at memory before the beginning of
1462 * the string. Besides, if it is less than 2 characters
1463 * long, then clearly, its not terminated with \r\n.
1464 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001465 if ((len > 2) && (memcmp(lpszHeaders + (len - 2), szcrlf, sizeof szcrlf) == 0))
Jeremy Shaw3cd1cfe2003-12-11 04:25:41 +00001466 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001467 lpszHeaders_r_n = WININET_strdupW(lpszHeaders);
Jeremy Shaw3cd1cfe2003-12-11 04:25:41 +00001468 }
1469 else
1470 {
1471 TRACE("Adding \r\n to lpszHeaders.\n");
Mike McCormacka4e902c2004-03-30 04:36:09 +00001472 lpszHeaders_r_n = HeapAlloc( GetProcessHeap(), 0,
1473 (len + 3)*sizeof(WCHAR) );
1474 strcpyW( lpszHeaders_r_n, lpszHeaders );
1475 strcatW( lpszHeaders_r_n, szcrlf );
Jeremy Shaw3cd1cfe2003-12-11 04:25:41 +00001476 }
1477 }
1478
David Hammerton852c7ae2003-06-20 23:26:56 +00001479 /* Add length of passed headers */
1480 if (lpszHeaders)
1481 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001482 headerLength = -1 == dwHeaderLength ? strlenW(lpszHeaders_r_n) : dwHeaderLength;
David Hammerton852c7ae2003-06-20 23:26:56 +00001483 requestStringLen += headerLength + 2; /* \r\n */
1484 }
1485
Mike McCormacka1c16d22003-07-22 03:17:52 +00001486
1487 /* if there isa proxy username and password, add it to the headers */
1488 if( hIC && (hIC->lpszProxyUsername || hIC->lpszProxyPassword ) )
1489 {
1490 HTTP_InsertProxyAuthorization( lpwhr, hIC->lpszProxyUsername, hIC->lpszProxyPassword );
1491 }
1492
David Hammerton852c7ae2003-06-20 23:26:56 +00001493 /* Calculate length of custom request headers */
1494 for (i = 0; i < lpwhr->nCustHeaders; i++)
1495 {
Ulrich Czekallac2757242000-06-11 20:04:44 +00001496 if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
1497 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001498 requestStringLen += strlenW(lpwhr->pCustHeaders[i].lpszField) +
1499 strlenW(lpwhr->pCustHeaders[i].lpszValue) + 4; /*: \r\n */
Ulrich Czekallac2757242000-06-11 20:04:44 +00001500 }
David Hammerton852c7ae2003-06-20 23:26:56 +00001501 }
Ulrich Czekallac2757242000-06-11 20:04:44 +00001502
David Hammerton852c7ae2003-06-20 23:26:56 +00001503 /* Calculate the length of standard request headers */
1504 for (i = 0; i <= HTTP_QUERY_MAX; i++)
1505 {
1506 if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST)
1507 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001508 requestStringLen += strlenW(lpwhr->StdHeaders[i].lpszField) +
1509 strlenW(lpwhr->StdHeaders[i].lpszValue) + 4; /*: \r\n */
David Hammerton852c7ae2003-06-20 23:26:56 +00001510 }
1511 }
Ulrich Czekallac2757242000-06-11 20:04:44 +00001512
David Hammerton852c7ae2003-06-20 23:26:56 +00001513 if (lpwhr->lpszHostName)
Mike McCormacka4e902c2004-03-30 04:36:09 +00001514 requestStringLen += (strlenW(HTTPHOSTHEADER) + strlenW(lpwhr->lpszHostName));
Ulrich Czekallac2757242000-06-11 20:04:44 +00001515
David Hammerton6226f3f2003-08-05 18:31:02 +00001516 /* if there is optional data to send, add the length */
1517 if (lpOptional)
1518 {
1519 requestStringLen += dwOptionalLength;
1520 }
Ulrich Czekallac2757242000-06-11 20:04:44 +00001521
David Hammerton852c7ae2003-06-20 23:26:56 +00001522 /* Allocate string to hold entire request */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001523 requestString = HeapAlloc(GetProcessHeap(), 0, (requestStringLen + 1)*sizeof(WCHAR));
David Hammerton852c7ae2003-06-20 23:26:56 +00001524 if (NULL == requestString)
1525 {
1526 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1527 goto lend;
1528 }
Ulrich Czekallac2757242000-06-11 20:04:44 +00001529
David Hammerton852c7ae2003-06-20 23:26:56 +00001530 /* Build request string */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001531 strcpyW(requestString, lpwhr->lpszVerb);
1532 strcatW(requestString, szSpace);
1533 strcatW(requestString, lpwhr->lpszPath);
1534 strcatW(requestString, HTTPHEADER );
1535 cnt = strlenW(requestString);
Ulrich Czekallac2757242000-06-11 20:04:44 +00001536
David Hammerton852c7ae2003-06-20 23:26:56 +00001537 /* Append standard request headers */
1538 for (i = 0; i <= HTTP_QUERY_MAX; i++)
1539 {
1540 if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST)
1541 {
Francois Gouget6a6c85c2004-04-19 20:12:14 +00001542 static const WCHAR szFmt[] = { '\r','\n','%','s',':',' ','%','s', 0};
Mike McCormacka4e902c2004-03-30 04:36:09 +00001543 cnt += sprintfW(requestString + cnt, szFmt,
David Hammerton852c7ae2003-06-20 23:26:56 +00001544 lpwhr->StdHeaders[i].lpszField, lpwhr->StdHeaders[i].lpszValue);
Mike McCormacka4e902c2004-03-30 04:36:09 +00001545 TRACE("Adding header %s (%s)\n",
1546 debugstr_w(lpwhr->StdHeaders[i].lpszField),
1547 debugstr_w(lpwhr->StdHeaders[i].lpszValue));
David Hammerton852c7ae2003-06-20 23:26:56 +00001548 }
1549 }
Ulrich Czekallac2757242000-06-11 20:04:44 +00001550
David Hammerton852c7ae2003-06-20 23:26:56 +00001551 /* Append custom request heades */
1552 for (i = 0; i < lpwhr->nCustHeaders; i++)
1553 {
1554 if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
1555 {
Francois Gouget6a6c85c2004-04-19 20:12:14 +00001556 static const WCHAR szFmt[] = { '\r','\n','%','s',':',' ','%','s', 0};
Mike McCormacka4e902c2004-03-30 04:36:09 +00001557 cnt += sprintfW(requestString + cnt, szFmt,
David Hammerton852c7ae2003-06-20 23:26:56 +00001558 lpwhr->pCustHeaders[i].lpszField, lpwhr->pCustHeaders[i].lpszValue);
Mike McCormacka4e902c2004-03-30 04:36:09 +00001559 TRACE("Adding custom header %s (%s)\n",
1560 debugstr_w(lpwhr->pCustHeaders[i].lpszField),
1561 debugstr_w(lpwhr->pCustHeaders[i].lpszValue));
David Hammerton852c7ae2003-06-20 23:26:56 +00001562 }
1563 }
Ulrich Czekallac2757242000-06-11 20:04:44 +00001564
David Hammerton852c7ae2003-06-20 23:26:56 +00001565 if (lpwhr->lpszHostName)
Mike McCormacka4e902c2004-03-30 04:36:09 +00001566 {
Francois Gouget6a6c85c2004-04-19 20:12:14 +00001567 static const WCHAR szFmt[] = { '%','s','%','s',0 };
Mike McCormacka4e902c2004-03-30 04:36:09 +00001568 cnt += sprintfW(requestString + cnt, szFmt, HTTPHOSTHEADER, lpwhr->lpszHostName);
1569 }
Ulrich Czekallac2757242000-06-11 20:04:44 +00001570
David Hammerton852c7ae2003-06-20 23:26:56 +00001571 /* Append passed request headers */
Jeremy Shaw3cd1cfe2003-12-11 04:25:41 +00001572 if (lpszHeaders_r_n)
David Hammerton852c7ae2003-06-20 23:26:56 +00001573 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001574 strcpyW(requestString + cnt, szcrlf);
David Hammerton852c7ae2003-06-20 23:26:56 +00001575 cnt += 2;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001576 strcpyW(requestString + cnt, lpszHeaders_r_n);
David Hammerton852c7ae2003-06-20 23:26:56 +00001577 cnt += headerLength;
Jeremy Shaw3cd1cfe2003-12-11 04:25:41 +00001578 /* only add \r\n if not already present */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001579 if (memcmp((requestString + cnt) - 2, szcrlf, sizeof szcrlf) != 0)
Jeremy Shaw3cd1cfe2003-12-11 04:25:41 +00001580 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001581 strcpyW(requestString + cnt, szcrlf);
Jeremy Shaw3cd1cfe2003-12-11 04:25:41 +00001582 cnt += 2;
1583 }
David Hammerton852c7ae2003-06-20 23:26:56 +00001584 }
Aric Stewartff9b9d42002-06-21 23:59:49 +00001585
David Hammerton6226f3f2003-08-05 18:31:02 +00001586 /* Set (header) termination string for request */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001587 if (memcmp((requestString + cnt) - 4, sztwocrlf, sizeof sztwocrlf) != 0)
David Hammerton6226f3f2003-08-05 18:31:02 +00001588 { /* only add it if the request string doesn't already
1589 have the thing.. (could happen if the custom header
1590 added it */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001591 strcpyW(requestString + cnt, szcrlf);
David Hammerton6226f3f2003-08-05 18:31:02 +00001592 cnt += 2;
1593 }
1594 else
1595 requestStringLen -= 2;
1596
1597 /* if optional data, append it */
1598 if (lpOptional)
1599 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001600 memcpy(requestString + cnt, lpOptional, dwOptionalLength*sizeof(WCHAR));
David Hammerton6226f3f2003-08-05 18:31:02 +00001601 cnt += dwOptionalLength;
1602 /* we also have to decrease the expected string length by two,
1603 * since we won't be adding on those following \r\n's */
Jeremy Shaw3cd1cfe2003-12-11 04:25:41 +00001604 requestStringLen -= 2;
David Hammerton6226f3f2003-08-05 18:31:02 +00001605 }
1606 else
1607 { /* if there is no optional data, add on another \r\n just to be safe */
1608 /* termination for request */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001609 strcpyW(requestString + cnt, szcrlf);
David Hammerton6226f3f2003-08-05 18:31:02 +00001610 cnt += 2;
1611 }
Aric Stewartff9b9d42002-06-21 23:59:49 +00001612
Mike McCormacka4e902c2004-03-30 04:36:09 +00001613 TRACE("(%s) len(%d)\n", debugstr_w(requestString), requestStringLen);
David Hammerton852c7ae2003-06-20 23:26:56 +00001614 /* Send the request and store the results */
1615 if (!HTTP_OpenConnection(lpwhr))
1616 goto lend;
Aric Stewartff9b9d42002-06-21 23:59:49 +00001617
David Hammerton852c7ae2003-06-20 23:26:56 +00001618 SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
1619 INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
Ulrich Czekallac2757242000-06-11 20:04:44 +00001620
Mike McCormacka4e902c2004-03-30 04:36:09 +00001621 /* send the request as ASCII */
1622 {
1623 int ascii_len;
1624 char *ascii_req;
1625
1626 ascii_len = WideCharToMultiByte( CP_ACP, 0, requestString,
1627 requestStringLen, NULL, 0, NULL, NULL );
1628 ascii_req = HeapAlloc( GetProcessHeap(), 0, ascii_len );
1629 WideCharToMultiByte( CP_ACP, 0, requestString, requestStringLen,
1630 ascii_req, ascii_len, NULL, NULL );
1631 NETCON_send(&lpwhr->netConnection, ascii_req, ascii_len, 0, &cnt);
1632 HeapFree( GetProcessHeap(), 0, ascii_req );
1633 }
Ulrich Czekallac2757242000-06-11 20:04:44 +00001634
David Hammerton852c7ae2003-06-20 23:26:56 +00001635
1636 SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
1637 INTERNET_STATUS_REQUEST_SENT,
1638 &requestStringLen,sizeof(DWORD));
1639
1640 SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
1641 INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
1642
1643 if (cnt < 0)
1644 goto lend;
1645
1646 responseLen = HTTP_GetResponseHeaders(lpwhr);
1647 if (responseLen)
Ulrich Czekallac2757242000-06-11 20:04:44 +00001648 bSuccess = TRUE;
1649
David Hammerton852c7ae2003-06-20 23:26:56 +00001650 SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
1651 INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen,
1652 sizeof(DWORD));
1653
1654 /* process headers here. Is this right? */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001655 CustHeaderIndex = HTTP_GetCustomHeaderIndex(lpwhr, szSetCookie);
David Hammerton852c7ae2003-06-20 23:26:56 +00001656 if (CustHeaderIndex >= 0)
1657 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001658 LPHTTPHEADERW setCookieHeader;
1659 int nPosStart = 0, nPosEnd = 0, len;
Francois Gouget6a6c85c2004-04-19 20:12:14 +00001660 static const WCHAR szFmt[] = { 'h','t','t','p',':','/','/','%','s','/',0};
David Hammerton852c7ae2003-06-20 23:26:56 +00001661
1662 setCookieHeader = &lpwhr->pCustHeaders[CustHeaderIndex];
1663
1664 while (setCookieHeader->lpszValue[nPosEnd] != '\0')
1665 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001666 LPWSTR buf_cookie, cookie_name, cookie_data;
1667 LPWSTR buf_url;
1668 LPWSTR domain = NULL;
David Hammerton852c7ae2003-06-20 23:26:56 +00001669 int nEqualPos = 0;
1670 while (setCookieHeader->lpszValue[nPosEnd] != ';' && setCookieHeader->lpszValue[nPosEnd] != ',' &&
1671 setCookieHeader->lpszValue[nPosEnd] != '\0')
1672 {
1673 nPosEnd++;
1674 }
1675 if (setCookieHeader->lpszValue[nPosEnd] == ';')
1676 {
1677 /* fixme: not case sensitive, strcasestr is gnu only */
1678 int nDomainPosEnd = 0;
1679 int nDomainPosStart = 0, nDomainLength = 0;
Francois Gouget6a6c85c2004-04-19 20:12:14 +00001680 static const WCHAR szDomain[] = {'d','o','m','a','i','n','=',0};
Mike McCormacka4e902c2004-03-30 04:36:09 +00001681 LPWSTR lpszDomain = strstrW(&setCookieHeader->lpszValue[nPosEnd], szDomain);
David Hammerton852c7ae2003-06-20 23:26:56 +00001682 if (lpszDomain)
1683 { /* they have specified their own domain, lets use it */
1684 while (lpszDomain[nDomainPosEnd] != ';' && lpszDomain[nDomainPosEnd] != ',' &&
1685 lpszDomain[nDomainPosEnd] != '\0')
1686 {
1687 nDomainPosEnd++;
1688 }
Mike McCormacka4e902c2004-03-30 04:36:09 +00001689 nDomainPosStart = strlenW(szDomain);
David Hammerton852c7ae2003-06-20 23:26:56 +00001690 nDomainLength = (nDomainPosEnd - nDomainPosStart) + 1;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001691 domain = HeapAlloc(GetProcessHeap(), 0, (nDomainLength + 1)*sizeof(WCHAR));
1692 strncpyW(domain, &lpszDomain[nDomainPosStart], nDomainLength);
David Hammerton852c7ae2003-06-20 23:26:56 +00001693 domain[nDomainLength] = '\0';
1694 }
1695 }
1696 if (setCookieHeader->lpszValue[nPosEnd] == '\0') break;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001697 buf_cookie = HeapAlloc(GetProcessHeap(), 0, ((nPosEnd - nPosStart) + 1)*sizeof(WCHAR));
1698 strncpyW(buf_cookie, &setCookieHeader->lpszValue[nPosStart], (nPosEnd - nPosStart));
David Hammerton852c7ae2003-06-20 23:26:56 +00001699 buf_cookie[(nPosEnd - nPosStart)] = '\0';
Mike McCormacka4e902c2004-03-30 04:36:09 +00001700 TRACE("%s\n", debugstr_w(buf_cookie));
David Hammerton852c7ae2003-06-20 23:26:56 +00001701 while (buf_cookie[nEqualPos] != '=' && buf_cookie[nEqualPos] != '\0')
1702 {
1703 nEqualPos++;
1704 }
1705 if (buf_cookie[nEqualPos] == '\0' || buf_cookie[nEqualPos + 1] == '\0')
1706 {
1707 HeapFree(GetProcessHeap(), 0, buf_cookie);
1708 break;
1709 }
1710
Mike McCormacka4e902c2004-03-30 04:36:09 +00001711 cookie_name = HeapAlloc(GetProcessHeap(), 0, (nEqualPos + 1)*sizeof(WCHAR));
1712 strncpyW(cookie_name, buf_cookie, nEqualPos);
David Hammerton852c7ae2003-06-20 23:26:56 +00001713 cookie_name[nEqualPos] = '\0';
1714 cookie_data = &buf_cookie[nEqualPos + 1];
1715
1716
Mike McCormacka4e902c2004-03-30 04:36:09 +00001717 len = strlenW((domain ? domain : lpwhr->lpszHostName)) + strlenW(lpwhr->lpszPath) + 9;
1718 buf_url = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
1719 sprintfW(buf_url, szFmt, (domain ? domain : lpwhr->lpszHostName)); /* FIXME PATH!!! */
1720 InternetSetCookieW(buf_url, cookie_name, cookie_data);
David Hammerton852c7ae2003-06-20 23:26:56 +00001721
1722 HeapFree(GetProcessHeap(), 0, buf_url);
1723 HeapFree(GetProcessHeap(), 0, buf_cookie);
1724 HeapFree(GetProcessHeap(), 0, cookie_name);
1725 if (domain) HeapFree(GetProcessHeap(), 0, domain);
1726 nPosStart = nPosEnd;
1727 }
1728 }
David Hammerton852c7ae2003-06-20 23:26:56 +00001729 }
1730 while (loop_next);
Aric Stewartff9b9d42002-06-21 23:59:49 +00001731
Ulrich Czekallac2757242000-06-11 20:04:44 +00001732lend:
1733
1734 if (requestString)
1735 HeapFree(GetProcessHeap(), 0, requestString);
1736
Jeremy Shaw3cd1cfe2003-12-11 04:25:41 +00001737 if (lpszHeaders)
1738 HeapFree(GetProcessHeap(), 0, lpszHeaders_r_n);
1739
Alberto Massaribc8bd722002-12-06 23:20:31 +00001740 /* TODO: send notification for P3P header */
1741
1742 if(!(hIC->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && bSuccess)
1743 {
1744 DWORD dwCode,dwCodeLength=sizeof(DWORD),dwIndex=0;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001745 if(HttpQueryInfoW(hHttpRequest,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,&dwCode,&dwCodeLength,&dwIndex) &&
Alberto Massaribc8bd722002-12-06 23:20:31 +00001746 (dwCode==302 || dwCode==301))
1747 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001748 WCHAR szNewLocation[2048];
Alberto Massaribc8bd722002-12-06 23:20:31 +00001749 DWORD dwBufferSize=2048;
1750 dwIndex=0;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001751 if(HttpQueryInfoW(hHttpRequest,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,&dwIndex))
Alberto Massaribc8bd722002-12-06 23:20:31 +00001752 {
1753 SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
1754 INTERNET_STATUS_REDIRECT, szNewLocation,
1755 dwBufferSize);
1756 return HTTP_HandleRedirect(lpwhr, szNewLocation, lpszHeaders,
1757 dwHeaderLength, lpOptional, dwOptionalLength);
1758 }
1759 }
1760 }
Aric Stewartff9b9d42002-06-21 23:59:49 +00001761
1762 if (hIC->lpfnStatusCB)
Ulrich Czekallac2757242000-06-11 20:04:44 +00001763 {
1764 INTERNET_ASYNC_RESULT iar;
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00001765
Ulrich Czekallac2757242000-06-11 20:04:44 +00001766 iar.dwResult = (DWORD)bSuccess;
1767 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
Aric Stewartff9b9d42002-06-21 23:59:49 +00001768
1769 SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
1770 INTERNET_STATUS_REQUEST_COMPLETE, &iar,
1771 sizeof(INTERNET_ASYNC_RESULT));
Ulrich Czekallac2757242000-06-11 20:04:44 +00001772 }
1773
1774 TRACE("<--\n");
1775 return bSuccess;
1776}
1777
1778
1779/***********************************************************************
1780 * HTTP_Connect (internal)
1781 *
1782 * Create http session handle
1783 *
1784 * RETURNS
1785 * HINTERNET a session handle on success
1786 * NULL on failure
1787 *
1788 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001789HINTERNET HTTP_Connect(HINTERNET hInternet, LPCWSTR lpszServerName,
1790 INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
1791 LPCWSTR lpszPassword, DWORD dwFlags, DWORD dwContext)
Ulrich Czekallac2757242000-06-11 20:04:44 +00001792{
1793 BOOL bSuccess = FALSE;
Mike McCormack09d2d472004-03-25 05:29:47 +00001794 LPWININETAPPINFOW hIC = NULL;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001795 LPWININETHTTPSESSIONW lpwhs = NULL;
Mike McCormack7cc70c02004-02-07 01:03:41 +00001796 HINTERNET handle = NULL;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001797
Aric Stewartff9b9d42002-06-21 23:59:49 +00001798 TRACE("-->\n");
Ulrich Czekallac2757242000-06-11 20:04:44 +00001799
Mike McCormack09d2d472004-03-25 05:29:47 +00001800 hIC = (LPWININETAPPINFOW) WININET_GetObject( hInternet );
Mike McCormack7cc70c02004-02-07 01:03:41 +00001801 if( (hIC == NULL) || (hIC->hdr.htype != WH_HINIT) )
Ulrich Czekallac2757242000-06-11 20:04:44 +00001802 goto lerror;
1803
Aric Stewartff9b9d42002-06-21 23:59:49 +00001804 hIC->hdr.dwContext = dwContext;
Dominik Strasser94c02fe2003-04-14 21:32:36 +00001805
Mike McCormacka4e902c2004-03-30 04:36:09 +00001806 lpwhs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETHTTPSESSIONW));
Ulrich Czekallac2757242000-06-11 20:04:44 +00001807 if (NULL == lpwhs)
1808 {
1809 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1810 goto lerror;
1811 }
1812
Mike McCormack7cc70c02004-02-07 01:03:41 +00001813 handle = WININET_AllocHandle( &lpwhs->hdr );
1814 if (NULL == handle)
1815 {
1816 ERR("Failed to alloc handle\n");
1817 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1818 goto lerror;
1819 }
1820
Aric Stewartff9b9d42002-06-21 23:59:49 +00001821 /*
1822 * According to my tests. The name is not resolved until a request is sent
1823 */
Ulrich Czekallac2757242000-06-11 20:04:44 +00001824
1825 if (nServerPort == INTERNET_INVALID_PORT_NUMBER)
1826 nServerPort = INTERNET_DEFAULT_HTTP_PORT;
1827
Ulrich Czekallac2757242000-06-11 20:04:44 +00001828 lpwhs->hdr.htype = WH_HHTTPSESSION;
Mike McCormack7cc70c02004-02-07 01:03:41 +00001829 lpwhs->hdr.lpwhparent = &hIC->hdr;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001830 lpwhs->hdr.dwFlags = dwFlags;
1831 lpwhs->hdr.dwContext = dwContext;
Dominik Strasser94c02fe2003-04-14 21:32:36 +00001832 if(hIC->lpszProxy && hIC->dwAccessType == INTERNET_OPEN_TYPE_PROXY) {
Mike McCormack09d2d472004-03-25 05:29:47 +00001833 if(strchrW(hIC->lpszProxy, ' '))
Dominik Strasser94c02fe2003-04-14 21:32:36 +00001834 FIXME("Several proxies not implemented.\n");
1835 if(hIC->lpszProxyBypass)
1836 FIXME("Proxy bypass is ignored.\n");
1837 }
Ulrich Czekallac2757242000-06-11 20:04:44 +00001838 if (NULL != lpszServerName)
Mike McCormacka4e902c2004-03-30 04:36:09 +00001839 lpwhs->lpszServerName = WININET_strdupW(lpszServerName);
Ulrich Czekallac2757242000-06-11 20:04:44 +00001840 if (NULL != lpszUserName)
Mike McCormacka4e902c2004-03-30 04:36:09 +00001841 lpwhs->lpszUserName = WININET_strdupW(lpszUserName);
Ulrich Czekallac2757242000-06-11 20:04:44 +00001842 lpwhs->nServerPort = nServerPort;
1843
1844 if (hIC->lpfnStatusCB)
1845 {
1846 INTERNET_ASYNC_RESULT iar;
1847
Lionel Ulmera29b4c72004-02-09 20:55:58 +00001848 iar.dwResult = (DWORD)handle;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001849 iar.dwError = ERROR_SUCCESS;
1850
Aric Stewartff9b9d42002-06-21 23:59:49 +00001851 SendAsyncCallback(hIC, hInternet, dwContext,
1852 INTERNET_STATUS_HANDLE_CREATED, &iar,
1853 sizeof(INTERNET_ASYNC_RESULT));
Ulrich Czekallac2757242000-06-11 20:04:44 +00001854 }
1855
1856 bSuccess = TRUE;
1857
1858lerror:
1859 if (!bSuccess && lpwhs)
1860 {
1861 HeapFree(GetProcessHeap(), 0, lpwhs);
Mike McCormack7cc70c02004-02-07 01:03:41 +00001862 WININET_FreeHandle( handle );
Ulrich Czekallac2757242000-06-11 20:04:44 +00001863 lpwhs = NULL;
1864 }
1865
Aric Stewartff9b9d42002-06-21 23:59:49 +00001866/*
1867 * a INTERNET_STATUS_REQUEST_COMPLETE is NOT sent here as per my tests on
1868 * windows
1869 */
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00001870
Mike McCormack7cc70c02004-02-07 01:03:41 +00001871 TRACE("%p --> %p\n", hInternet, handle);
1872 return handle;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001873}
1874
1875
1876/***********************************************************************
1877 * HTTP_OpenConnection (internal)
1878 *
1879 * Connect to a web server
1880 *
1881 * RETURNS
1882 *
1883 * TRUE on success
1884 * FALSE on failure
1885 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001886BOOL HTTP_OpenConnection(LPWININETHTTPREQW lpwhr)
Ulrich Czekallac2757242000-06-11 20:04:44 +00001887{
1888 BOOL bSuccess = FALSE;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001889 LPWININETHTTPSESSIONW lpwhs;
Mike McCormack09d2d472004-03-25 05:29:47 +00001890 LPWININETAPPINFOW hIC = NULL;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001891
Aric Stewartff9b9d42002-06-21 23:59:49 +00001892 TRACE("-->\n");
1893
Ulrich Czekallac2757242000-06-11 20:04:44 +00001894
1895 if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
1896 {
1897 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
1898 goto lend;
1899 }
1900
Mike McCormacka4e902c2004-03-30 04:36:09 +00001901 lpwhs = (LPWININETHTTPSESSIONW)lpwhr->hdr.lpwhparent;
Ulrich Czekallac2757242000-06-11 20:04:44 +00001902
Mike McCormack09d2d472004-03-25 05:29:47 +00001903 hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
Aric Stewartff9b9d42002-06-21 23:59:49 +00001904 SendAsyncCallback(hIC, lpwhr, lpwhr->hdr.dwContext,
1905 INTERNET_STATUS_CONNECTING_TO_SERVER,
1906 &(lpwhs->socketAddress),
1907 sizeof(struct sockaddr_in));
1908
David Hammerton852c7ae2003-06-20 23:26:56 +00001909 if (!NETCON_create(&lpwhr->netConnection, lpwhs->phostent->h_addrtype,
1910 SOCK_STREAM, 0))
Ulrich Czekallac2757242000-06-11 20:04:44 +00001911 {
1912 WARN("Socket creation failed\n");
1913 goto lend;
1914 }
1915
David Hammerton852c7ae2003-06-20 23:26:56 +00001916 if (!NETCON_connect(&lpwhr->netConnection, (struct sockaddr *)&lpwhs->socketAddress,
1917 sizeof(lpwhs->socketAddress)))
Ulrich Czekallac2757242000-06-11 20:04:44 +00001918 {
Andreas Mohr34965562000-08-26 20:31:48 +00001919 WARN("Unable to connect to host (%s)\n", strerror(errno));
Ulrich Czekallac2757242000-06-11 20:04:44 +00001920 goto lend;
1921 }
1922
Aric Stewartff9b9d42002-06-21 23:59:49 +00001923 SendAsyncCallback(hIC, lpwhr, lpwhr->hdr.dwContext,
1924 INTERNET_STATUS_CONNECTED_TO_SERVER,
1925 &(lpwhs->socketAddress),
1926 sizeof(struct sockaddr_in));
1927
Ulrich Czekallac2757242000-06-11 20:04:44 +00001928 bSuccess = TRUE;
1929
1930lend:
Aric Stewartff9b9d42002-06-21 23:59:49 +00001931 TRACE("%d <--\n", bSuccess);
Ulrich Czekallac2757242000-06-11 20:04:44 +00001932 return bSuccess;
1933}
1934
1935
1936/***********************************************************************
1937 * HTTP_GetResponseHeaders (internal)
1938 *
1939 * Read server response
1940 *
1941 * RETURNS
1942 *
1943 * TRUE on success
1944 * FALSE on error
1945 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00001946BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr)
Ulrich Czekallac2757242000-06-11 20:04:44 +00001947{
1948 INT cbreaks = 0;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001949 WCHAR buffer[MAX_REPLY_LEN];
Ulrich Czekallac2757242000-06-11 20:04:44 +00001950 DWORD buflen = MAX_REPLY_LEN;
1951 BOOL bSuccess = FALSE;
Aric Stewartff9b9d42002-06-21 23:59:49 +00001952 INT rc = 0;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001953 WCHAR value[MAX_FIELD_VALUE_LEN], field[MAX_FIELD_LEN];
Francois Gouget6a6c85c2004-04-19 20:12:14 +00001954 static const WCHAR szStatus[] = {'S','t','a','t','u','s',0};
1955 static const WCHAR szHttp[] = { 'H','T','T','P',0 };
Mike McCormacka4e902c2004-03-30 04:36:09 +00001956 char bufferA[MAX_REPLY_LEN];
Ulrich Czekallac2757242000-06-11 20:04:44 +00001957
Aric Stewartff9b9d42002-06-21 23:59:49 +00001958 TRACE("-->\n");
Ulrich Czekallac2757242000-06-11 20:04:44 +00001959
David Hammerton852c7ae2003-06-20 23:26:56 +00001960 if (!NETCON_connected(&lpwhr->netConnection))
Ulrich Czekallac2757242000-06-11 20:04:44 +00001961 goto lend;
1962
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00001963 /*
Aric Stewartff9b9d42002-06-21 23:59:49 +00001964 * HACK peek at the buffer
1965 */
David Hammerton852c7ae2003-06-20 23:26:56 +00001966 NETCON_recv(&lpwhr->netConnection, buffer, buflen, MSG_PEEK, &rc);
Aric Stewartff9b9d42002-06-21 23:59:49 +00001967
1968 /*
Ulrich Czekallac2757242000-06-11 20:04:44 +00001969 * We should first receive 'HTTP/1.x nnn' where nnn is the status code.
1970 */
Aric Stewartff9b9d42002-06-21 23:59:49 +00001971 buflen = MAX_REPLY_LEN;
David Hammerton852c7ae2003-06-20 23:26:56 +00001972 memset(buffer, 0, MAX_REPLY_LEN);
Mike McCormacka4e902c2004-03-30 04:36:09 +00001973 if (!NETCON_getNextLine(&lpwhr->netConnection, bufferA, &buflen))
Ulrich Czekallac2757242000-06-11 20:04:44 +00001974 goto lend;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001975 MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
Ulrich Czekallac2757242000-06-11 20:04:44 +00001976
Mike McCormacka4e902c2004-03-30 04:36:09 +00001977 if (strncmpW(buffer, szHttp, 4) != 0)
Ulrich Czekallac2757242000-06-11 20:04:44 +00001978 goto lend;
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00001979
Ulrich Czekallac2757242000-06-11 20:04:44 +00001980 buffer[12]='\0';
Mike McCormacka4e902c2004-03-30 04:36:09 +00001981 HTTP_ProcessHeader(lpwhr, szStatus, buffer+9, (HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE));
Ulrich Czekallac2757242000-06-11 20:04:44 +00001982
1983 /* Parse each response line */
1984 do
1985 {
1986 buflen = MAX_REPLY_LEN;
Mike McCormacka4e902c2004-03-30 04:36:09 +00001987 if (NETCON_getNextLine(&lpwhr->netConnection, bufferA, &buflen))
Ulrich Czekallac2757242000-06-11 20:04:44 +00001988 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00001989 TRACE("got line %s, now interpretting\n", debugstr_a(bufferA));
1990 MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
Ulrich Czekallac2757242000-06-11 20:04:44 +00001991 if (!HTTP_InterpretHttpHeader(buffer, field, MAX_FIELD_LEN, value, MAX_FIELD_VALUE_LEN))
1992 break;
1993
1994 HTTP_ProcessHeader(lpwhr, field, value, (HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE));
1995 }
1996 else
1997 {
1998 cbreaks++;
1999 if (cbreaks >= 2)
2000 break;
2001 }
2002 }while(1);
2003
2004 bSuccess = TRUE;
2005
2006lend:
2007
Aric Stewartff9b9d42002-06-21 23:59:49 +00002008 TRACE("<--\n");
2009 if (bSuccess)
2010 return rc;
2011 else
2012 return FALSE;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002013}
2014
2015
2016/***********************************************************************
2017 * HTTP_InterpretHttpHeader (internal)
2018 *
2019 * Parse server response
2020 *
2021 * RETURNS
2022 *
2023 * TRUE on success
2024 * FALSE on error
2025 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00002026INT stripSpaces(LPCWSTR lpszSrc, LPWSTR lpszStart, INT *len)
Ulrich Czekallac2757242000-06-11 20:04:44 +00002027{
Mike McCormacka4e902c2004-03-30 04:36:09 +00002028 LPCWSTR lpsztmp;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002029 INT srclen;
2030
2031 srclen = 0;
2032
2033 while (*lpszSrc == ' ' && *lpszSrc != '\0')
2034 lpszSrc++;
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00002035
Ulrich Czekallac2757242000-06-11 20:04:44 +00002036 lpsztmp = lpszSrc;
2037 while(*lpsztmp != '\0')
2038 {
2039 if (*lpsztmp != ' ')
2040 srclen = lpsztmp - lpszSrc + 1;
2041
2042 lpsztmp++;
2043 }
2044
2045 *len = min(*len, srclen);
Mike McCormacka4e902c2004-03-30 04:36:09 +00002046 strncpyW(lpszStart, lpszSrc, *len);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002047 lpszStart[*len] = '\0';
2048
2049 return *len;
2050}
2051
2052
Mike McCormacka4e902c2004-03-30 04:36:09 +00002053BOOL HTTP_InterpretHttpHeader(LPWSTR buffer, LPWSTR field, INT fieldlen, LPWSTR value, INT valuelen)
Ulrich Czekallac2757242000-06-11 20:04:44 +00002054{
Mike McCormacka4e902c2004-03-30 04:36:09 +00002055 WCHAR *pd;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002056 BOOL bSuccess = FALSE;
2057
2058 TRACE("\n");
2059
2060 *field = '\0';
2061 *value = '\0';
2062
Mike McCormacka4e902c2004-03-30 04:36:09 +00002063 pd = strchrW(buffer, ':');
Ulrich Czekallac2757242000-06-11 20:04:44 +00002064 if (pd)
2065 {
2066 *pd = '\0';
2067 if (stripSpaces(buffer, field, &fieldlen) > 0)
2068 {
2069 if (stripSpaces(pd+1, value, &valuelen) > 0)
2070 bSuccess = TRUE;
2071 }
2072 }
2073
Mike McCormacka4e902c2004-03-30 04:36:09 +00002074 TRACE("%d: field(%s) Value(%s)\n", bSuccess, debugstr_w(field), debugstr_w(value));
Ulrich Czekallac2757242000-06-11 20:04:44 +00002075 return bSuccess;
2076}
2077
2078
2079/***********************************************************************
2080 * HTTP_GetStdHeaderIndex (internal)
2081 *
John R. Sheets646d2a22000-07-23 13:34:43 +00002082 * Lookup field index in standard http header array
Ulrich Czekallac2757242000-06-11 20:04:44 +00002083 *
2084 * FIXME: This should be stuffed into a hash table
2085 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00002086INT HTTP_GetStdHeaderIndex(LPCWSTR lpszField)
Ulrich Czekallac2757242000-06-11 20:04:44 +00002087{
2088 INT index = -1;
Francois Gouget6a6c85c2004-04-19 20:12:14 +00002089 static const WCHAR szContentLength[] = {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002090 'C','o','n','t','e','n','t','-','L','e','n','g','t','h',0};
Francois Gouget6a6c85c2004-04-19 20:12:14 +00002091 static const WCHAR szStatus[] = {'S','t','a','t','u','s',0};
2092 static const WCHAR szContentType[] = {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002093 'C','o','n','t','e','n','t','-','T','y','p','e',0};
Francois Gouget6a6c85c2004-04-19 20:12:14 +00002094 static const WCHAR szLastModified[] = {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002095 'L','a','s','t','-','M','o','d','i','f','i','e','d',0};
Francois Gouget6a6c85c2004-04-19 20:12:14 +00002096 static const WCHAR szLocation[] = {'L','o','c','a','t','i','o','n',0};
2097 static const WCHAR szAccept[] = {'A','c','c','e','p','t',0};
2098 static const WCHAR szReferer[] = { 'R','e','f','e','r','e','r',0};
2099 static const WCHAR szContentTrans[] = { 'C','o','n','t','e','n','t','-',
Mike McCormacka4e902c2004-03-30 04:36:09 +00002100 'T','r','a','n','s','f','e','r','-','E','n','c','o','d','i','n','g',0};
Francois Gouget6a6c85c2004-04-19 20:12:14 +00002101 static const WCHAR szDate[] = { 'D','a','t','e',0};
2102 static const WCHAR szServer[] = { 'S','e','r','v','e','r',0};
2103 static const WCHAR szConnection[] = { 'C','o','n','n','e','c','t','i','o','n',0};
2104 static const WCHAR szETag[] = { 'E','T','a','g',0};
2105 static const WCHAR szAcceptRanges[] = {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002106 'A','c','c','e','p','t','-','R','a','n','g','e','s',0 };
Francois Gouget6a6c85c2004-04-19 20:12:14 +00002107 static const WCHAR szExpires[] = { 'E','x','p','i','r','e','s',0 };
2108 static const WCHAR szMimeVersion[] = {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002109 'M','i','m','e','-','V','e','r','s','i','o','n', 0};
Francois Gouget6a6c85c2004-04-19 20:12:14 +00002110 static const WCHAR szPragma[] = { 'P','r','a','g','m','a', 0};
2111 static const WCHAR szCacheControl[] = {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002112 'C','a','c','h','e','-','C','o','n','t','r','o','l',0};
Francois Gouget6a6c85c2004-04-19 20:12:14 +00002113 static const WCHAR szUserAgent[] = { 'U','s','e','r','-','A','g','e','n','t',0};
2114 static const WCHAR szProxyAuth[] = {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002115 'P','r','o','x','y','-',
2116 'A','u','t','h','e','n','t','i','c','a','t','e', 0};
Ulrich Czekallac2757242000-06-11 20:04:44 +00002117
Mike McCormacka4e902c2004-03-30 04:36:09 +00002118 if (!strcmpiW(lpszField, szContentLength))
Ulrich Czekallac2757242000-06-11 20:04:44 +00002119 index = HTTP_QUERY_CONTENT_LENGTH;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002120 else if (!strcmpiW(lpszField,szStatus))
Ulrich Czekallac2757242000-06-11 20:04:44 +00002121 index = HTTP_QUERY_STATUS_CODE;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002122 else if (!strcmpiW(lpszField,szContentType))
Ulrich Czekallac2757242000-06-11 20:04:44 +00002123 index = HTTP_QUERY_CONTENT_TYPE;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002124 else if (!strcmpiW(lpszField,szLastModified))
Ulrich Czekallac2757242000-06-11 20:04:44 +00002125 index = HTTP_QUERY_LAST_MODIFIED;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002126 else if (!strcmpiW(lpszField,szLocation))
Ulrich Czekallac2757242000-06-11 20:04:44 +00002127 index = HTTP_QUERY_LOCATION;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002128 else if (!strcmpiW(lpszField,szAccept))
Ulrich Czekallac2757242000-06-11 20:04:44 +00002129 index = HTTP_QUERY_ACCEPT;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002130 else if (!strcmpiW(lpszField,szReferer))
Ulrich Czekallac2757242000-06-11 20:04:44 +00002131 index = HTTP_QUERY_REFERER;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002132 else if (!strcmpiW(lpszField,szContentTrans))
Ulrich Czekallac2757242000-06-11 20:04:44 +00002133 index = HTTP_QUERY_CONTENT_TRANSFER_ENCODING;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002134 else if (!strcmpiW(lpszField,szDate))
John R. Sheets646d2a22000-07-23 13:34:43 +00002135 index = HTTP_QUERY_DATE;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002136 else if (!strcmpiW(lpszField,szServer))
John R. Sheets646d2a22000-07-23 13:34:43 +00002137 index = HTTP_QUERY_SERVER;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002138 else if (!strcmpiW(lpszField,szConnection))
John R. Sheets646d2a22000-07-23 13:34:43 +00002139 index = HTTP_QUERY_CONNECTION;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002140 else if (!strcmpiW(lpszField,szETag))
John R. Sheets646d2a22000-07-23 13:34:43 +00002141 index = HTTP_QUERY_ETAG;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002142 else if (!strcmpiW(lpszField,szAcceptRanges))
John R. Sheets646d2a22000-07-23 13:34:43 +00002143 index = HTTP_QUERY_ACCEPT_RANGES;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002144 else if (!strcmpiW(lpszField,szExpires))
John R. Sheets646d2a22000-07-23 13:34:43 +00002145 index = HTTP_QUERY_EXPIRES;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002146 else if (!strcmpiW(lpszField,szMimeVersion))
John R. Sheets66b4dd22000-08-03 22:16:39 +00002147 index = HTTP_QUERY_MIME_VERSION;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002148 else if (!strcmpiW(lpszField,szPragma))
Johan Dahlin664b9bb2001-12-17 20:50:53 +00002149 index = HTTP_QUERY_PRAGMA;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002150 else if (!strcmpiW(lpszField,szCacheControl))
Johan Dahlin664b9bb2001-12-17 20:50:53 +00002151 index = HTTP_QUERY_CACHE_CONTROL;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002152 else if (!strcmpiW(lpszField,szUserAgent))
Johan Dahlin664b9bb2001-12-17 20:50:53 +00002153 index = HTTP_QUERY_USER_AGENT;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002154 else if (!strcmpiW(lpszField,szProxyAuth))
Mike McCormacka1c16d22003-07-22 03:17:52 +00002155 index = HTTP_QUERY_PROXY_AUTHENTICATE;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002156 else
2157 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002158 TRACE("Couldn't find %s in standard header table\n", debugstr_w(lpszField));
Ulrich Czekallac2757242000-06-11 20:04:44 +00002159 }
2160
2161 return index;
2162}
2163
2164
2165/***********************************************************************
2166 * HTTP_ProcessHeader (internal)
2167 *
2168 * Stuff header into header tables according to <dwModifier>
2169 *
2170 */
2171
2172#define COALESCEFLASG (HTTP_ADDHDR_FLAG_COALESCE|HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA|HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
2173
Mike McCormacka4e902c2004-03-30 04:36:09 +00002174BOOL HTTP_ProcessHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field, LPCWSTR value, DWORD dwModifier)
Ulrich Czekallac2757242000-06-11 20:04:44 +00002175{
Mike McCormacka4e902c2004-03-30 04:36:09 +00002176 LPHTTPHEADERW lphttpHdr = NULL;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002177 BOOL bSuccess = FALSE;
2178 INT index;
2179
Mike McCormacka4e902c2004-03-30 04:36:09 +00002180 TRACE("--> %s: %s - 0x%08x\n", debugstr_w(field), debugstr_w(value), (unsigned int)dwModifier);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002181
2182 /* Adjust modifier flags */
2183 if (dwModifier & COALESCEFLASG)
2184 dwModifier |= HTTP_ADDHDR_FLAG_ADD;
2185
2186 /* Try to get index into standard header array */
2187 index = HTTP_GetStdHeaderIndex(field);
2188 if (index >= 0)
2189 {
2190 lphttpHdr = &lpwhr->StdHeaders[index];
2191 }
2192 else /* Find or create new custom header */
2193 {
Aric Stewartff9b9d42002-06-21 23:59:49 +00002194 index = HTTP_GetCustomHeaderIndex(lpwhr, field);
2195 if (index >= 0)
2196 {
2197 if (dwModifier & HTTP_ADDHDR_FLAG_ADD_IF_NEW)
2198 {
2199 return FALSE;
2200 }
2201 lphttpHdr = &lpwhr->pCustHeaders[index];
2202 }
2203 else
2204 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002205 HTTPHEADERW hdr;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002206
Mike McCormacka4e902c2004-03-30 04:36:09 +00002207 hdr.lpszField = (LPWSTR)field;
2208 hdr.lpszValue = (LPWSTR)value;
Aric Stewartff9b9d42002-06-21 23:59:49 +00002209 hdr.wFlags = hdr.wCount = 0;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002210
2211 if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
2212 hdr.wFlags |= HDR_ISREQUEST;
2213
Mike McCormacka1c16d22003-07-22 03:17:52 +00002214 return HTTP_InsertCustomHeader(lpwhr, &hdr);
Aric Stewartff9b9d42002-06-21 23:59:49 +00002215 }
Ulrich Czekallac2757242000-06-11 20:04:44 +00002216 }
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00002217
Ulrich Czekallac2757242000-06-11 20:04:44 +00002218 if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
2219 lphttpHdr->wFlags |= HDR_ISREQUEST;
2220 else
2221 lphttpHdr->wFlags &= ~HDR_ISREQUEST;
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00002222
Ulrich Czekallac2757242000-06-11 20:04:44 +00002223 if (!lphttpHdr->lpszValue && (dwModifier & (HTTP_ADDHDR_FLAG_ADD|HTTP_ADDHDR_FLAG_ADD_IF_NEW)))
2224 {
2225 INT slen;
2226
2227 if (!lpwhr->StdHeaders[index].lpszField)
2228 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002229 lphttpHdr->lpszField = WININET_strdupW(field);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002230
2231 if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
2232 lphttpHdr->wFlags |= HDR_ISREQUEST;
2233 }
2234
Mike McCormacka4e902c2004-03-30 04:36:09 +00002235 slen = strlenW(value) + 1;
2236 lphttpHdr->lpszValue = HeapAlloc(GetProcessHeap(), 0, slen*sizeof(WCHAR));
Ulrich Czekallac2757242000-06-11 20:04:44 +00002237 if (lphttpHdr->lpszValue)
2238 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002239 strcpyW(lphttpHdr->lpszValue, value);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002240 bSuccess = TRUE;
2241 }
2242 else
2243 {
2244 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
2245 }
2246 }
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00002247 else if (lphttpHdr->lpszValue)
Ulrich Czekallac2757242000-06-11 20:04:44 +00002248 {
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00002249 if (dwModifier & HTTP_ADDHDR_FLAG_REPLACE)
Ulrich Czekallac2757242000-06-11 20:04:44 +00002250 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002251 LPWSTR lpsztmp;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002252 INT len;
2253
Mike McCormacka4e902c2004-03-30 04:36:09 +00002254 len = strlenW(value);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002255
2256 if (len <= 0)
2257 {
Patrik Stridvallfc2be7e2002-04-29 18:48:56 +00002258 /* if custom header delete from array */
Ulrich Czekallac2757242000-06-11 20:04:44 +00002259 HeapFree(GetProcessHeap(), 0, lphttpHdr->lpszValue);
2260 lphttpHdr->lpszValue = NULL;
2261 bSuccess = TRUE;
2262 }
2263 else
2264 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002265 lpsztmp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lphttpHdr->lpszValue, (len+1)*sizeof(WCHAR));
Ulrich Czekallac2757242000-06-11 20:04:44 +00002266 if (lpsztmp)
2267 {
2268 lphttpHdr->lpszValue = lpsztmp;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002269 strcpyW(lpsztmp, value);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002270 bSuccess = TRUE;
2271 }
2272 else
2273 {
Alberto Massaribc8bd722002-12-06 23:20:31 +00002274 WARN("HeapReAlloc (%d bytes) failed\n",len+1);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002275 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
2276 }
2277 }
2278 }
2279 else if (dwModifier & COALESCEFLASG)
2280 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002281 LPWSTR lpsztmp;
2282 WCHAR ch = 0;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002283 INT len = 0;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002284 INT origlen = strlenW(lphttpHdr->lpszValue);
2285 INT valuelen = strlenW(value);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002286
2287 if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA)
2288 {
2289 ch = ',';
2290 lphttpHdr->wFlags |= HDR_COMMADELIMITED;
2291 }
2292 else if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
2293 {
2294 ch = ';';
2295 lphttpHdr->wFlags |= HDR_COMMADELIMITED;
2296 }
2297
Alberto Massaribc8bd722002-12-06 23:20:31 +00002298 len = origlen + valuelen + ((ch > 0) ? 1 : 0);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002299
Mike McCormacka4e902c2004-03-30 04:36:09 +00002300 lpsztmp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lphttpHdr->lpszValue, (len+1)*sizeof(WCHAR));
Ulrich Czekallac2757242000-06-11 20:04:44 +00002301 if (lpsztmp)
2302 {
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00002303 /* FIXME: Increment lphttpHdr->wCount. Perhaps lpszValue should be an array */
Ulrich Czekallac2757242000-06-11 20:04:44 +00002304 if (ch > 0)
2305 {
2306 lphttpHdr->lpszValue[origlen] = ch;
2307 origlen++;
2308 }
2309
Mike McCormacka4e902c2004-03-30 04:36:09 +00002310 memcpy(&lphttpHdr->lpszValue[origlen], value, valuelen*sizeof(WCHAR));
Ulrich Czekallac2757242000-06-11 20:04:44 +00002311 lphttpHdr->lpszValue[len] = '\0';
2312 bSuccess = TRUE;
2313 }
2314 else
2315 {
Alberto Massaribc8bd722002-12-06 23:20:31 +00002316 WARN("HeapReAlloc (%d bytes) failed\n",len+1);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002317 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
2318 }
2319 }
2320 }
Alberto Massaribc8bd722002-12-06 23:20:31 +00002321 TRACE("<-- %d\n",bSuccess);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002322 return bSuccess;
2323}
2324
2325
2326/***********************************************************************
2327 * HTTP_CloseConnection (internal)
2328 *
2329 * Close socket connection
2330 *
2331 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00002332VOID HTTP_CloseConnection(LPWININETHTTPREQW lpwhr)
Ulrich Czekallac2757242000-06-11 20:04:44 +00002333{
Aric Stewartff9b9d42002-06-21 23:59:49 +00002334
2335
Mike McCormacka4e902c2004-03-30 04:36:09 +00002336 LPWININETHTTPSESSIONW lpwhs = NULL;
Mike McCormack09d2d472004-03-25 05:29:47 +00002337 LPWININETAPPINFOW hIC = NULL;
Mike McCormack7cc70c02004-02-07 01:03:41 +00002338 HINTERNET handle;
Aric Stewartff9b9d42002-06-21 23:59:49 +00002339
2340 TRACE("%p\n",lpwhr);
2341
Mike McCormack7cc70c02004-02-07 01:03:41 +00002342 handle = WININET_FindHandle( &lpwhr->hdr );
Mike McCormacka4e902c2004-03-30 04:36:09 +00002343 lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent;
Mike McCormack09d2d472004-03-25 05:29:47 +00002344 hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
Aric Stewartff9b9d42002-06-21 23:59:49 +00002345
2346 SendAsyncCallback(hIC, lpwhr, lpwhr->hdr.dwContext,
2347 INTERNET_STATUS_CLOSING_CONNECTION, 0, 0);
2348
David Hammerton852c7ae2003-06-20 23:26:56 +00002349 if (NETCON_connected(&lpwhr->netConnection))
2350 {
2351 NETCON_close(&lpwhr->netConnection);
2352 }
Aric Stewartff9b9d42002-06-21 23:59:49 +00002353
2354 SendAsyncCallback(hIC, lpwhr, lpwhr->hdr.dwContext,
2355 INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002356}
2357
2358
2359/***********************************************************************
2360 * HTTP_CloseHTTPRequestHandle (internal)
2361 *
2362 * Deallocate request handle
2363 *
2364 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00002365void HTTP_CloseHTTPRequestHandle(LPWININETHTTPREQW lpwhr)
Ulrich Czekallac2757242000-06-11 20:04:44 +00002366{
2367 int i;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002368 LPWININETHTTPSESSIONW lpwhs = NULL;
Mike McCormack09d2d472004-03-25 05:29:47 +00002369 LPWININETAPPINFOW hIC = NULL;
Mike McCormack7cc70c02004-02-07 01:03:41 +00002370 HINTERNET handle;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002371
2372 TRACE("\n");
2373
David Hammerton852c7ae2003-06-20 23:26:56 +00002374 if (NETCON_connected(&lpwhr->netConnection))
Ulrich Czekallac2757242000-06-11 20:04:44 +00002375 HTTP_CloseConnection(lpwhr);
2376
Mike McCormack7cc70c02004-02-07 01:03:41 +00002377 handle = WININET_FindHandle( &lpwhr->hdr );
Mike McCormacka4e902c2004-03-30 04:36:09 +00002378 lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent;
Mike McCormack09d2d472004-03-25 05:29:47 +00002379 hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
Aric Stewartff9b9d42002-06-21 23:59:49 +00002380
Mike McCormack7cc70c02004-02-07 01:03:41 +00002381 SendAsyncCallback(hIC, handle, lpwhr->hdr.dwContext,
Aric Stewartff9b9d42002-06-21 23:59:49 +00002382 INTERNET_STATUS_HANDLE_CLOSING, lpwhr,
2383 sizeof(HINTERNET));
2384
Ulrich Czekallac2757242000-06-11 20:04:44 +00002385 if (lpwhr->lpszPath)
2386 HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath);
2387 if (lpwhr->lpszVerb)
2388 HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
2389 if (lpwhr->lpszHostName)
2390 HeapFree(GetProcessHeap(), 0, lpwhr->lpszHostName);
2391
2392 for (i = 0; i <= HTTP_QUERY_MAX; i++)
2393 {
2394 if (lpwhr->StdHeaders[i].lpszField)
2395 HeapFree(GetProcessHeap(), 0, lpwhr->StdHeaders[i].lpszField);
2396 if (lpwhr->StdHeaders[i].lpszValue)
2397 HeapFree(GetProcessHeap(), 0, lpwhr->StdHeaders[i].lpszValue);
2398 }
2399
2400 for (i = 0; i < lpwhr->nCustHeaders; i++)
2401 {
2402 if (lpwhr->pCustHeaders[i].lpszField)
2403 HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszField);
2404 if (lpwhr->pCustHeaders[i].lpszValue)
2405 HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszValue);
2406 }
2407
2408 HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders);
2409 HeapFree(GetProcessHeap(), 0, lpwhr);
2410}
2411
2412
2413/***********************************************************************
2414 * HTTP_CloseHTTPSessionHandle (internal)
2415 *
2416 * Deallocate session handle
2417 *
2418 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00002419void HTTP_CloseHTTPSessionHandle(LPWININETHTTPSESSIONW lpwhs)
Ulrich Czekallac2757242000-06-11 20:04:44 +00002420{
Mike McCormack09d2d472004-03-25 05:29:47 +00002421 LPWININETAPPINFOW hIC = NULL;
Mike McCormack7cc70c02004-02-07 01:03:41 +00002422 HINTERNET handle;
2423
David Hammerton852c7ae2003-06-20 23:26:56 +00002424 TRACE("%p\n", lpwhs);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002425
Mike McCormack09d2d472004-03-25 05:29:47 +00002426 hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
Aric Stewartff9b9d42002-06-21 23:59:49 +00002427
Mike McCormack7cc70c02004-02-07 01:03:41 +00002428 handle = WININET_FindHandle( &lpwhs->hdr );
2429 SendAsyncCallback(hIC, handle, lpwhs->hdr.dwContext,
Aric Stewartff9b9d42002-06-21 23:59:49 +00002430 INTERNET_STATUS_HANDLE_CLOSING, lpwhs,
2431 sizeof(HINTERNET));
2432
Ulrich Czekallac2757242000-06-11 20:04:44 +00002433 if (lpwhs->lpszServerName)
2434 HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName);
2435 if (lpwhs->lpszUserName)
2436 HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName);
2437 HeapFree(GetProcessHeap(), 0, lpwhs);
2438}
2439
2440
2441/***********************************************************************
2442 * HTTP_GetCustomHeaderIndex (internal)
2443 *
2444 * Return index of custom header from header array
2445 *
2446 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00002447INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQW lpwhr, LPCWSTR lpszField)
Ulrich Czekallac2757242000-06-11 20:04:44 +00002448{
2449 INT index;
2450
Mike McCormacka4e902c2004-03-30 04:36:09 +00002451 TRACE("%s\n", debugstr_w(lpszField));
Ulrich Czekallac2757242000-06-11 20:04:44 +00002452
2453 for (index = 0; index < lpwhr->nCustHeaders; index++)
2454 {
Mike McCormacka4e902c2004-03-30 04:36:09 +00002455 if (!strcmpiW(lpwhr->pCustHeaders[index].lpszField, lpszField))
Ulrich Czekallac2757242000-06-11 20:04:44 +00002456 break;
2457
2458 }
2459
2460 if (index >= lpwhr->nCustHeaders)
2461 index = -1;
2462
2463 TRACE("Return: %d\n", index);
2464 return index;
2465}
2466
2467
2468/***********************************************************************
2469 * HTTP_InsertCustomHeader (internal)
2470 *
2471 * Insert header into array
2472 *
2473 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00002474BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQW lpwhr, LPHTTPHEADERW lpHdr)
Ulrich Czekallac2757242000-06-11 20:04:44 +00002475{
2476 INT count;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002477 LPHTTPHEADERW lph = NULL;
Mike McCormacka1c16d22003-07-22 03:17:52 +00002478 BOOL r = FALSE;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002479
Mike McCormacka4e902c2004-03-30 04:36:09 +00002480 TRACE("--> %s: %s\n", debugstr_w(lpHdr->lpszField), debugstr_w(lpHdr->lpszValue));
Ulrich Czekallac2757242000-06-11 20:04:44 +00002481 count = lpwhr->nCustHeaders + 1;
2482 if (count > 1)
Mike McCormacka4e902c2004-03-30 04:36:09 +00002483 lph = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpwhr->pCustHeaders, sizeof(HTTPHEADERW) * count);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002484 else
Mike McCormacka4e902c2004-03-30 04:36:09 +00002485 lph = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HTTPHEADERW) * count);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002486
2487 if (NULL != lph)
2488 {
2489 lpwhr->pCustHeaders = lph;
Mike McCormacka4e902c2004-03-30 04:36:09 +00002490 lpwhr->pCustHeaders[count-1].lpszField = WININET_strdupW(lpHdr->lpszField);
2491 lpwhr->pCustHeaders[count-1].lpszValue = WININET_strdupW(lpHdr->lpszValue);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002492 lpwhr->pCustHeaders[count-1].wFlags = lpHdr->wFlags;
2493 lpwhr->pCustHeaders[count-1].wCount= lpHdr->wCount;
2494 lpwhr->nCustHeaders++;
Mike McCormacka1c16d22003-07-22 03:17:52 +00002495 r = TRUE;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002496 }
2497 else
2498 {
2499 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
Ulrich Czekallac2757242000-06-11 20:04:44 +00002500 }
2501
Mike McCormacka1c16d22003-07-22 03:17:52 +00002502 return r;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002503}
2504
2505
2506/***********************************************************************
2507 * HTTP_DeleteCustomHeader (internal)
2508 *
2509 * Delete header from array
Mike McCormacka1c16d22003-07-22 03:17:52 +00002510 * If this function is called, the indexs may change.
Ulrich Czekallac2757242000-06-11 20:04:44 +00002511 */
Mike McCormacka4e902c2004-03-30 04:36:09 +00002512BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQW lpwhr, INT index)
Ulrich Czekallac2757242000-06-11 20:04:44 +00002513{
Mike McCormacka1c16d22003-07-22 03:17:52 +00002514 if( lpwhr->nCustHeaders <= 0 )
2515 return FALSE;
2516 if( lpwhr->nCustHeaders >= index )
2517 return FALSE;
2518 lpwhr->nCustHeaders--;
2519
2520 memmove( &lpwhr->pCustHeaders[index], &lpwhr->pCustHeaders[index+1],
Mike McCormacka4e902c2004-03-30 04:36:09 +00002521 (lpwhr->nCustHeaders - index)* sizeof(HTTPHEADERW) );
2522 memset( &lpwhr->pCustHeaders[lpwhr->nCustHeaders], 0, sizeof(HTTPHEADERW) );
Mike McCormacka1c16d22003-07-22 03:17:52 +00002523
2524 return TRUE;
Ulrich Czekallac2757242000-06-11 20:04:44 +00002525}
Alberto Massarib09eef22002-11-13 04:08:26 +00002526
2527/***********************************************************************
2528 * IsHostInProxyBypassList (@)
2529 *
2530 * Undocumented
2531 *
2532 */
2533BOOL WINAPI IsHostInProxyBypassList(DWORD flags, LPCSTR szHost, DWORD length)
2534{
2535 FIXME("STUB: flags=%ld host=%s length=%ld\n",flags,szHost,length);
2536 return FALSE;
2537}