source: trunk/src/wininet/http.c@ 10367

Last change on this file since 10367 was 7544, checked in by sandervl, 24 years ago

strlen crashes on NULL strings

File size: 39.1 KB
Line 
1/*
2 * Wininet - Http Implementation
3 *
4 * Copyright 1999 Corel Corporation
5 *
6 * Ulrich Czekalla
7 *
8 */
9
10#include "config.h"
11
12#include "windef.h"
13#include "winbase.h"
14#include "wininet.h"
15#include "debugtools.h"
16#include "winerror.h"
17#include <shlwapi.h>
18#include "winsock.h"
19
20#ifdef __WIN32OS2__
21#include <stdlib.h>
22#include <string.h>
23#define strcasecmp stricmp
24#else
25#include <sys/types.h>
26#ifdef HAVE_SYS_SOCKET_H
27# include <sys/socket.h>
28#endif
29#ifdef HAVE_NETDB_H
30# include <netdb.h>
31#endif
32#include <stdio.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <errno.h>
36#endif
37
38#include "internet.h"
39
40DEFAULT_DEBUG_CHANNEL(wininet);
41
42#define HTTPHEADER " HTTP/1.0"
43#define HTTPHOSTHEADER "\r\nHost: "
44#define MAXHOSTNAME 100
45#define MAX_FIELD_VALUE_LEN 256
46#define MAX_FIELD_LEN 256
47
48
49#define HTTP_REFERER "Referer"
50#define HTTP_ACCEPT "Accept"
51
52#define HTTP_ADDHDR_FLAG_ADD 0x20000000
53#define HTTP_ADDHDR_FLAG_ADD_IF_NEW 0x10000000
54#define HTTP_ADDHDR_FLAG_COALESCE 0x40000000
55#define HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA 0x40000000
56#define HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON 0x01000000
57#define HTTP_ADDHDR_FLAG_REPLACE 0x80000000
58#define HTTP_ADDHDR_FLAG_REQ 0x02000000
59
60
61BOOL HTTP_OpenConnection(LPWININETHTTPREQA lpwhr);
62int HTTP_WriteDataToStream(LPWININETHTTPREQA lpwhr,
63 void *Buffer, int BytesToWrite);
64int HTTP_ReadDataFromStream(LPWININETHTTPREQA lpwhr,
65 void *Buffer, int BytesToRead);
66BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQA lpwhr);
67BOOL HTTP_ProcessHeader(LPWININETHTTPREQA lpwhr, LPCSTR field, LPCSTR value, DWORD dwModifier);
68void HTTP_CloseConnection(LPWININETHTTPREQA lpwhr);
69BOOL HTTP_InterpretHttpHeader(LPSTR buffer, LPSTR field, INT fieldlen, LPSTR value, INT valuelen);
70INT HTTP_GetStdHeaderIndex(LPCSTR lpszField);
71INT HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr, LPHTTPHEADERA lpHdr);
72INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQA lpwhr, LPCSTR lpszField);
73
74
75/***********************************************************************
76 * HttpAddRequestHeadersA (WININET.68)
77 *
78 * Adds one or more HTTP header to the request handler
79 *
80 * RETURNS
81 * TRUE on success
82 * FALSE on failure
83 *
84 */
85INTERNETAPI BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest,
86 LPCSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
87{
88 LPSTR lpszStart;
89 LPSTR lpszEnd;
90 LPSTR buffer;
91 CHAR value[MAX_FIELD_VALUE_LEN], field[MAX_FIELD_LEN];
92 BOOL bSuccess = FALSE;
93 LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hHttpRequest;
94
95 if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
96 {
97 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
98 return FALSE;
99 }
100
101 buffer = strdup(lpszHeader);
102 lpszStart = buffer;
103
104 do
105 {
106 lpszEnd = lpszStart;
107
108 while (*lpszEnd != '\0')
109 {
110 if (*lpszEnd == '\r' && *(lpszEnd + 1) == '\n')
111 break;
112 lpszEnd++;
113 }
114
115 if (*lpszEnd == '\0')
116 break;
117
118 *lpszEnd = '\0';
119
120 if (HTTP_InterpretHttpHeader(lpszStart, field, MAX_FIELD_LEN, value, MAX_FIELD_VALUE_LEN))
121 bSuccess = HTTP_ProcessHeader(lpwhr, field, value, dwModifier | HTTP_ADDHDR_FLAG_REQ);
122
123 lpszStart = lpszEnd + 2; /* Jump over \0\n */
124
125 } while (bSuccess);
126
127 HeapFree(GetProcessHeap(), 0, buffer);
128 return bSuccess;
129}
130
131
132/***********************************************************************
133 * HttpOpenRequestA (WININET.72)
134 *
135 * Open a HTTP request handle
136 *
137 * RETURNS
138 * HINTERNET a HTTP request handle on success
139 * NULL on failure
140 *
141 */
142INTERNETAPI HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession,
143 LPCSTR lpszVerb, LPCSTR lpszObjectName, LPCSTR lpszVersion,
144 LPCSTR lpszReferrer , LPCSTR *lpszAcceptTypes,
145 DWORD dwFlags, DWORD dwContext)
146{
147 LPWININETHTTPSESSIONA lpwhs = (LPWININETHTTPSESSIONA) hHttpSession;
148 LPWININETAPPINFOA hIC = NULL;
149
150 TRACE("\n");
151
152 if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
153 {
154 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
155 return FALSE;
156 }
157
158 hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent;
159
160 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
161 {
162 WORKREQUEST workRequest;
163
164 workRequest.asyncall = HTTPOPENREQUESTA;
165 workRequest.HFTPSESSION = (DWORD)hHttpSession;
166 workRequest.LPSZVERB = (DWORD)strdup(lpszVerb);
167 workRequest.LPSZOBJECTNAME = (DWORD)strdup(lpszObjectName);
168 workRequest.LPSZVERSION = (DWORD)strdup(lpszVersion);
169 workRequest.LPSZREFERRER = (DWORD)strdup(lpszReferrer);
170 workRequest.LPSZACCEPTTYPES = (DWORD)lpszAcceptTypes;
171 workRequest.DWFLAGS = dwFlags;
172 workRequest.DWCONTEXT = dwContext;
173
174 return (HINTERNET)INTERNET_AsyncCall(&workRequest);
175 }
176 else
177 {
178 return HTTP_HttpOpenRequestA(hHttpSession, lpszVerb, lpszObjectName,
179 lpszVersion, lpszReferrer, lpszAcceptTypes, dwFlags, dwContext);
180 }
181}
182
183
184/***********************************************************************
185 * HTTP_HttpOpenRequestA (internal)
186 *
187 * Open a HTTP request handle
188 *
189 * RETURNS
190 * HINTERNET a HTTP request handle on success
191 * NULL on failure
192 *
193 */
194HINTERNET HTTP_HttpOpenRequestA(HINTERNET hHttpSession,
195 LPCSTR lpszVerb, LPCSTR lpszObjectName, LPCSTR lpszVersion,
196 LPCSTR lpszReferrer , LPCSTR *lpszAcceptTypes,
197 DWORD dwFlags, DWORD dwContext)
198{
199 LPWININETHTTPSESSIONA lpwhs = (LPWININETHTTPSESSIONA) hHttpSession;
200 LPWININETAPPINFOA hIC = NULL;
201 LPWININETHTTPREQA lpwhr;
202
203 TRACE("\n");
204
205 if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
206 {
207 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
208 return FALSE;
209 }
210
211 hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent;
212
213 lpwhr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETHTTPREQA));
214 if (NULL == lpwhr)
215 {
216 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
217 return (HINTERNET) NULL;
218 }
219
220 lpwhr->hdr.htype = WH_HHTTPREQ;
221 lpwhr->hdr.lpwhparent = hHttpSession;
222 lpwhr->hdr.dwFlags = dwFlags;
223 lpwhr->hdr.dwContext = dwContext;
224 lpwhr->nSocketFD = INVALID_SOCKET;
225
226 if (NULL != lpszObjectName && strlen(lpszObjectName)) {
227 DWORD needed = 0;
228 UrlEscapeA(lpszObjectName, NULL, &needed, URL_ESCAPE_SPACES_ONLY);
229 lpwhr->lpszPath = HeapAlloc(GetProcessHeap(), 0, needed);
230 UrlEscapeA(lpszObjectName, lpwhr->lpszPath, &needed,
231 URL_ESCAPE_SPACES_ONLY);
232 }
233
234 if (NULL != lpszReferrer && strlen(lpszReferrer))
235 HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpszReferrer, HTTP_ADDHDR_FLAG_COALESCE);
236
237 //! FIXME
238 if (NULL != lpszAcceptTypes && strlen(*lpszAcceptTypes))
239 HTTP_ProcessHeader(lpwhr, HTTP_ACCEPT, *lpszAcceptTypes, HTTP_ADDHDR_FLAG_COALESCE);
240
241 if (NULL == lpszVerb)
242 lpwhr->lpszVerb = strdup("GET");
243 else if (strlen(lpszVerb))
244 lpwhr->lpszVerb = strdup(lpszVerb);
245
246 if (NULL != lpszReferrer)
247 {
248 char buf[MAXHOSTNAME];
249 URL_COMPONENTSA UrlComponents;
250
251 UrlComponents.lpszExtraInfo = NULL;
252 UrlComponents.lpszPassword = NULL;
253 UrlComponents.lpszScheme = NULL;
254 UrlComponents.lpszUrlPath = NULL;
255 UrlComponents.lpszUserName = NULL;
256 UrlComponents.lpszHostName = buf;
257 UrlComponents.dwHostNameLength = MAXHOSTNAME;
258
259 InternetCrackUrlA(lpszReferrer, 0, 0, &UrlComponents);
260 if (strlen(UrlComponents.lpszHostName))
261 lpwhr->lpszHostName = strdup(UrlComponents.lpszHostName);
262 } else {
263 lpwhr->lpszHostName = strdup(lpwhs->lpszServerName);
264 }
265
266 if (hIC->lpfnStatusCB)
267 {
268 INTERNET_ASYNC_RESULT iar;
269
270 iar.dwResult = (DWORD)lpwhr;
271 iar.dwError = ERROR_SUCCESS;
272
273 hIC->lpfnStatusCB(hHttpSession, dwContext, INTERNET_STATUS_HANDLE_CREATED,
274 &iar, sizeof(INTERNET_ASYNC_RESULT));
275 }
276
277 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
278 {
279 INTERNET_ASYNC_RESULT iar;
280
281 iar.dwResult = (DWORD)lpwhr;
282 iar.dwError = lpwhr ? ERROR_SUCCESS : INTERNET_GetLastError();
283 hIC->lpfnStatusCB(hHttpSession, dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
284 &iar, sizeof(INTERNET_ASYNC_RESULT));
285 }
286
287 return (HINTERNET) lpwhr;
288}
289
290
291/***********************************************************************
292 * HttpQueryInfoA (WININET.74)
293 *
294 * Queries for information about an HTTP request
295 *
296 * RETURNS
297 * TRUE on success
298 * FALSE on failure
299 *
300 */
301BOOL WINAPI HttpQueryInfoA(HINTERNET hHttpRequest, DWORD dwInfoLevel,
302 LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
303{
304 LPHTTPHEADERA lphttpHdr = NULL;
305 BOOL bSuccess = FALSE;
306 LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hHttpRequest;
307
308 TRACE("(0x%08lx)--> %ld\n", dwInfoLevel, dwInfoLevel);
309
310 if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
311 {
312 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
313 return FALSE;
314 }
315
316 /* Find requested header structure */
317 if ((dwInfoLevel & ~HTTP_QUERY_MODIFIER_FLAGS_MASK) == HTTP_QUERY_CUSTOM)
318 {
319 INT index = HTTP_GetCustomHeaderIndex(lpwhr, (LPSTR)lpBuffer);
320
321 if (index < 0)
322 goto lend;
323
324 lphttpHdr = &lpwhr->pCustHeaders[index];
325 }
326 else
327 {
328 INT index = dwInfoLevel & ~HTTP_QUERY_MODIFIER_FLAGS_MASK;
329
330 if (index == HTTP_QUERY_RAW_HEADERS_CRLF || index == HTTP_QUERY_RAW_HEADERS)
331 {
332 INT i, delim, size = 0, cnt = 0;
333
334 delim = index == HTTP_QUERY_RAW_HEADERS_CRLF ? 2 : 1;
335
336 /* Calculate length of custom reuqest headers */
337 for (i = 0; i < lpwhr->nCustHeaders; i++)
338 {
339 if ((~lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST) && lpwhr->pCustHeaders[i].lpszField &&
340 lpwhr->pCustHeaders[i].lpszValue)
341 {
342 size += strlen(lpwhr->pCustHeaders[i].lpszField) +
343 strlen(lpwhr->pCustHeaders[i].lpszValue) + delim + 2;
344 }
345 }
346
347 /* Calculate the length of stadard request headers */
348 for (i = 0; i <= HTTP_QUERY_MAX; i++)
349 {
350 if ((~lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST) && lpwhr->StdHeaders[i].lpszField &&
351 lpwhr->StdHeaders[i].lpszValue)
352 {
353 size += strlen(lpwhr->StdHeaders[i].lpszField) +
354 strlen(lpwhr->StdHeaders[i].lpszValue) + delim + 2;
355 }
356 }
357
358 size += delim;
359
360 if (size + 1 > *lpdwBufferLength)
361 {
362 *lpdwBufferLength = size + 1;
363 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
364 goto lend;
365 }
366
367 /* Append standard request heades */
368 for (i = 0; i <= HTTP_QUERY_MAX; i++)
369 {
370 if ((~lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST) &&
371 lpwhr->StdHeaders[i].lpszField &&
372 lpwhr->StdHeaders[i].lpszValue)
373 {
374 cnt += sprintf((LPBYTE)lpBuffer + cnt, "%s: %s%s", lpwhr->StdHeaders[i].lpszField, lpwhr->StdHeaders[i].lpszValue,
375 index == HTTP_QUERY_RAW_HEADERS_CRLF ? "\r\n" : "\0");
376 }
377 }
378
379 /* Append custom request heades */
380 for (i = 0; i < lpwhr->nCustHeaders; i++)
381 {
382 if ((~lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST) &&
383 lpwhr->pCustHeaders[i].lpszField &&
384 lpwhr->pCustHeaders[i].lpszValue)
385 {
386 cnt += sprintf((LPBYTE)lpBuffer + cnt, "%s: %s%s",
387 lpwhr->pCustHeaders[i].lpszField, lpwhr->pCustHeaders[i].lpszValue,
388 index == HTTP_QUERY_RAW_HEADERS_CRLF ? "\r\n" : "\0");
389 }
390 }
391
392 strcpy((LPBYTE)lpBuffer + cnt, index == HTTP_QUERY_RAW_HEADERS_CRLF ? "\r\n" : "");
393
394 *lpdwBufferLength = cnt + delim;
395 bSuccess = TRUE;
396 goto lend;
397 }
398 else if (index >= 0 && index <= HTTP_QUERY_MAX && lpwhr->StdHeaders[index].lpszValue)
399 {
400 lphttpHdr = &lpwhr->StdHeaders[index];
401 }
402 else
403 goto lend;
404 }
405
406 /* Ensure header satisifies requested attributes */
407 if ((dwInfoLevel & HTTP_QUERY_FLAG_REQUEST_HEADERS) &&
408 (~lphttpHdr->wFlags & HDR_ISREQUEST))
409 goto lend;
410
411 /* coalesce value to reuqested type */
412 if (dwInfoLevel & HTTP_QUERY_FLAG_NUMBER)
413 {
414 *(int *)lpBuffer = atoi(lphttpHdr->lpszValue);
415 bSuccess = TRUE;
416 }
417 else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME)
418 {
419 time_t tmpTime;
420 struct tm tmpTM;
421 SYSTEMTIME *STHook;
422
423 tmpTime = ConvertTimeString(lphttpHdr->lpszValue);
424
425 tmpTM = *gmtime(&tmpTime);
426 STHook = (SYSTEMTIME *) lpBuffer;
427 if(STHook==NULL)
428 goto lend;
429
430 STHook->wDay = tmpTM.tm_mday;
431 STHook->wHour = tmpTM.tm_hour;
432 STHook->wMilliseconds = 0;
433 STHook->wMinute = tmpTM.tm_min;
434 STHook->wDayOfWeek = tmpTM.tm_wday;
435 STHook->wMonth = tmpTM.tm_mon + 1;
436 STHook->wSecond = tmpTM.tm_sec;
437 STHook->wYear = tmpTM.tm_year;
438
439 bSuccess = TRUE;
440 }
441 else if (dwInfoLevel & HTTP_QUERY_FLAG_COALESCE)
442 {
443 if (*lpdwIndex >= lphttpHdr->wCount)
444 {
445 INTERNET_SetLastError(ERROR_HTTP_HEADER_NOT_FOUND);
446 }
447 else
448 {
449 //! Copy strncpy(lpBuffer, lphttpHdr[*lpdwIndex], len);
450 (*lpdwIndex)++;
451 }
452 }
453 else
454 {
455 INT len = strlen(lphttpHdr->lpszValue);
456
457 if (len + 1 > *lpdwBufferLength)
458 {
459 *lpdwBufferLength = len + 1;
460 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
461 goto lend;
462 }
463
464 strncpy(lpBuffer, lphttpHdr->lpszValue, len);
465 *lpdwBufferLength = len;
466 bSuccess = TRUE;
467 }
468
469lend:
470 TRACE("%d <--\n", bSuccess);
471 return bSuccess;
472}
473
474
475/***********************************************************************
476 * HttpSendRequestExA (WININET)
477 *
478 * Sends the specified request to the HTTP server and allows chunked
479 * transfers
480 */
481BOOL WINAPI HttpSendRequestExA(HINTERNET hRequest,
482 LPINTERNET_BUFFERSA lpBuffersIn,
483 LPINTERNET_BUFFERSA lpBuffersOut,
484 DWORD dwFlags, DWORD dwContext)
485{
486 FIXME("(%p, %p, %p, %08lx, %08lx): stub\n", hRequest, lpBuffersIn,
487 lpBuffersOut, dwFlags, dwContext);
488 return FALSE;
489}
490
491/***********************************************************************
492 * HttpSendRequestA (WININET.76)
493 *
494 * Sends the specified request to the HTTP server
495 *
496 * RETURNS
497 * TRUE on success
498 * FALSE on failure
499 *
500 */
501BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
502 DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
503{
504 LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hHttpRequest;
505 LPWININETHTTPSESSIONA lpwhs = NULL;
506 LPWININETAPPINFOA hIC = NULL;
507
508 TRACE("0x%08lx\n", (unsigned long)hHttpRequest);
509
510 if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
511 {
512 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
513 return FALSE;
514 }
515
516 lpwhs = (LPWININETHTTPSESSIONA) lpwhr->hdr.lpwhparent;
517 if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
518 {
519 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
520 return FALSE;
521 }
522
523 hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent;
524 if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
525 {
526 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
527 return FALSE;
528 }
529
530 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
531 {
532 WORKREQUEST workRequest;
533
534 workRequest.asyncall = HTTPSENDREQUESTA;
535 workRequest.HFTPSESSION = (DWORD)hHttpRequest;
536 workRequest.LPSZHEADER = (DWORD)strdup(lpszHeaders);
537 workRequest.DWHEADERLENGTH = dwHeaderLength;
538 workRequest.LPOPTIONAL = (DWORD)lpOptional;
539 workRequest.DWOPTIONALLENGTH = dwOptionalLength;
540
541 return INTERNET_AsyncCall(&workRequest);
542 }
543 else
544 {
545 return HTTP_HttpSendRequestA(hHttpRequest, lpszHeaders,
546 dwHeaderLength, lpOptional, dwOptionalLength);
547 }
548}
549
550
551/***********************************************************************
552 * HTTP_HttpSendRequestA (internal)
553 *
554 * Sends the specified request to the HTTP server
555 *
556 * RETURNS
557 * TRUE on success
558 * FALSE on failure
559 *
560 */
561BOOL HTTP_HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
562 DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
563{
564 INT cnt;
565 INT i;
566 BOOL bSuccess = FALSE;
567 LPSTR requestString = NULL;
568 INT requestStringLen;
569 INT headerLength = 0;
570 LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hHttpRequest;
571 LPWININETHTTPSESSIONA lpwhs = NULL;
572 LPWININETAPPINFOA hIC = NULL;
573
574 TRACE("0x%08lx\n", (ULONG)hHttpRequest);
575
576 /* Verify our tree of internet handles */
577 if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
578 {
579 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
580 return FALSE;
581 }
582
583 lpwhs = (LPWININETHTTPSESSIONA) lpwhr->hdr.lpwhparent;
584 if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
585 {
586 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
587 return FALSE;
588 }
589
590 hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent;
591 if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
592 {
593 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
594 return FALSE;
595 }
596
597 /* Clear any error information */
598 INTERNET_SetLastError(0);
599
600 /* We must have a verb */
601 if (NULL == lpwhr->lpszVerb)
602 {
603 goto lend;
604 }
605
606 /* If we don't have a path we set it to root */
607 if (NULL == lpwhr->lpszPath)
608 lpwhr->lpszPath = strdup("/");
609
610 if(lpwhr->lpszPath[0] != '/') /* not an absolute path ?? --> fix it !! */
611 {
612 char *fixurl = HeapAlloc(GetProcessHeap(), 0, strlen(lpwhr->lpszPath) + 2);
613 *fixurl = '/';
614 strcpy(fixurl + 1, lpwhr->lpszPath);
615 HeapFree( GetProcessHeap(), 0, lpwhr->lpszPath );
616 lpwhr->lpszPath = fixurl;
617 }
618
619 /* Calculate length of request string */
620 requestStringLen =
621 strlen(lpwhr->lpszVerb) +
622 strlen(lpwhr->lpszPath) +
623 (lpwhr->lpszHostName ? (strlen(HTTPHOSTHEADER) + strlen(lpwhr->lpszHostName)) : 0) +
624 strlen(HTTPHEADER) +
625 5; /* " \r\n\r\n" */
626
627 /* Add length of passed headers */
628 if (lpszHeaders)
629 {
630 headerLength = -1 == dwHeaderLength ? strlen(lpszHeaders) : dwHeaderLength;
631 requestStringLen += headerLength + 2; /* \r\n */
632 }
633
634 /* Calculate length of custom request headers */
635 for (i = 0; i < lpwhr->nCustHeaders; i++)
636 {
637 if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
638 {
639#ifdef __WIN32OS2__
640 requestStringLen += (lpwhr->pCustHeaders[i].lpszField) ? strlen(lpwhr->pCustHeaders[i].lpszField) : 0 +
641 (lpwhr->pCustHeaders[i].lpszValue) ? strlen(lpwhr->pCustHeaders[i].lpszValue) : 0 + 4; /*: \r\n */
642#else
643 requestStringLen += strlen(lpwhr->pCustHeaders[i].lpszField) +
644 strlen(lpwhr->pCustHeaders[i].lpszValue) + 4; /*: \r\n */
645#endif
646 }
647 }
648
649 /* Calculate the length of standard request headers */
650 for (i = 0; i <= HTTP_QUERY_MAX; i++)
651 {
652 if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST)
653 {
654#ifdef __WIN32OS2__
655 requestStringLen += (lpwhr->StdHeaders[i].lpszField) ? strlen(lpwhr->StdHeaders[i].lpszField) : 0 +
656 (lpwhr->StdHeaders[i].lpszValue) ? strlen(lpwhr->StdHeaders[i].lpszValue) : 0 + 4; /*: \r\n */
657#else
658 requestStringLen += strlen(lpwhr->StdHeaders[i].lpszField) +
659 strlen(lpwhr->StdHeaders[i].lpszValue) + 4; /*: \r\n */
660#endif
661 }
662 }
663
664 /* Allocate string to hold entire request */
665 requestString = HeapAlloc(GetProcessHeap(), 0, requestStringLen + 1);
666 if (NULL == requestString)
667 {
668 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
669 goto lend;
670 }
671
672 /* Build request string */
673 cnt = sprintf(requestString, "%s %s%s%s",
674 lpwhr->lpszVerb,
675 lpwhr->lpszPath,
676 lpwhr->lpszHostName ? (HTTPHEADER HTTPHOSTHEADER) : HTTPHEADER,
677 lpwhr->lpszHostName ? lpwhr->lpszHostName : "");
678
679 /* Append standard request headers */
680 for (i = 0; i <= HTTP_QUERY_MAX; i++)
681 {
682 if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST)
683 {
684 cnt += sprintf(requestString + cnt, "\r\n%s: %s",
685 lpwhr->StdHeaders[i].lpszField, lpwhr->StdHeaders[i].lpszValue);
686 }
687 }
688
689 /* Append custom request heades */
690 for (i = 0; i < lpwhr->nCustHeaders; i++)
691 {
692 if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
693 {
694 cnt += sprintf(requestString + cnt, "\r\n%s: %s",
695 lpwhr->pCustHeaders[i].lpszField, lpwhr->pCustHeaders[i].lpszValue);
696 }
697 }
698
699 /* Append passed request headers */
700 if (lpszHeaders)
701 {
702 strcpy(requestString + cnt, "\r\n");
703 cnt += 2;
704 strcpy(requestString + cnt, lpszHeaders);
705 cnt += headerLength;
706 }
707
708 /* Set termination string for request */
709 strcpy(requestString + cnt, "\r\n\r\n");
710
711 if (hIC->lpfnStatusCB)
712 hIC->lpfnStatusCB(hHttpRequest, lpwhr->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
713
714 TRACE("(%s) len(%d)\n", requestString, requestStringLen);
715 /* Send the request and store the results */
716 if (!HTTP_OpenConnection(lpwhr))
717 goto lend;
718
719 cnt = INTERNET_WriteDataToStream(lpwhr->nSocketFD, requestString, requestStringLen);
720
721 if (cnt < 0)
722 goto lend;
723
724 if (HTTP_GetResponseHeaders(lpwhr))
725 bSuccess = TRUE;
726
727lend:
728
729 if (requestString)
730 HeapFree(GetProcessHeap(), 0, requestString);
731
732 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
733 {
734 INTERNET_ASYNC_RESULT iar;
735
736 iar.dwResult = (DWORD)bSuccess;
737 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
738 hIC->lpfnStatusCB(hHttpRequest, lpwhr->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
739 &iar, sizeof(INTERNET_ASYNC_RESULT));
740 }
741
742 TRACE("<--\n");
743 return bSuccess;
744}
745
746
747/***********************************************************************
748 * HTTP_Connect (internal)
749 *
750 * Create http session handle
751 *
752 * RETURNS
753 * HINTERNET a session handle on success
754 * NULL on failure
755 *
756 */
757HINTERNET HTTP_Connect(HINTERNET hInternet, LPCSTR lpszServerName,
758 INTERNET_PORT nServerPort, LPCSTR lpszUserName,
759 LPCSTR lpszPassword, DWORD dwFlags, DWORD dwContext)
760{
761 BOOL bSuccess = FALSE;
762 LPWININETAPPINFOA hIC = NULL;
763 LPWININETHTTPSESSIONA lpwhs = NULL;
764
765 TRACE("\n");
766
767 if (((LPWININETHANDLEHEADER)hInternet)->htype != WH_HINIT)
768 goto lerror;
769
770 hIC = (LPWININETAPPINFOA) hInternet;
771
772 lpwhs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETHTTPSESSIONA));
773 if (NULL == lpwhs)
774 {
775 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
776 goto lerror;
777 }
778
779 if (hIC->lpfnStatusCB)
780 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_RESOLVING_NAME,
781 (LPVOID)lpszServerName, strlen(lpszServerName));
782
783 if (nServerPort == INTERNET_INVALID_PORT_NUMBER)
784 nServerPort = INTERNET_DEFAULT_HTTP_PORT;
785
786 if (!GetAddress(lpszServerName, nServerPort, &lpwhs->phostent, &lpwhs->socketAddress))
787 {
788 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
789 goto lerror;
790 }
791
792 if (hIC->lpfnStatusCB)
793 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_NAME_RESOLVED,
794 (LPVOID)lpszServerName, strlen(lpszServerName));
795
796 lpwhs->hdr.htype = WH_HHTTPSESSION;
797 lpwhs->hdr.lpwhparent = (LPWININETHANDLEHEADER)hInternet;
798 lpwhs->hdr.dwFlags = dwFlags;
799 lpwhs->hdr.dwContext = dwContext;
800 if (NULL != lpszServerName)
801 lpwhs->lpszServerName = strdup(lpszServerName);
802 if (NULL != lpszUserName)
803 lpwhs->lpszUserName = strdup(lpszUserName);
804 lpwhs->nServerPort = nServerPort;
805
806 if (hIC->lpfnStatusCB)
807 {
808 INTERNET_ASYNC_RESULT iar;
809
810 iar.dwResult = (DWORD)lpwhs;
811 iar.dwError = ERROR_SUCCESS;
812
813 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_HANDLE_CREATED,
814 &iar, sizeof(INTERNET_ASYNC_RESULT));
815 }
816
817 bSuccess = TRUE;
818
819lerror:
820 if (!bSuccess && lpwhs)
821 {
822 HeapFree(GetProcessHeap(), 0, lpwhs);
823 lpwhs = NULL;
824 }
825
826 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
827 {
828 INTERNET_ASYNC_RESULT iar;
829
830 iar.dwResult = (DWORD)lpwhs;
831 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
832 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
833 &iar, sizeof(INTERNET_ASYNC_RESULT));
834 }
835TRACE("<--\n");
836 return (HINTERNET)lpwhs;
837}
838
839
840/***********************************************************************
841 * HTTP_OpenConnection (internal)
842 *
843 * Connect to a web server
844 *
845 * RETURNS
846 *
847 * TRUE on success
848 * FALSE on failure
849 */
850BOOL HTTP_OpenConnection(LPWININETHTTPREQA lpwhr)
851{
852 BOOL bSuccess = FALSE;
853 INT result;
854 LPWININETHTTPSESSIONA lpwhs;
855
856 TRACE("\n");
857
858 if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
859 {
860 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
861 goto lend;
862 }
863
864 lpwhs = (LPWININETHTTPSESSIONA)lpwhr->hdr.lpwhparent;
865
866 lpwhr->nSocketFD = socket(lpwhs->phostent->h_addrtype,SOCK_STREAM,0);
867 if (INVALID_SOCKET == lpwhr->nSocketFD)
868 {
869 WARN("Socket creation failed\n");
870 goto lend;
871 }
872
873 result = connect(lpwhr->nSocketFD, (struct sockaddr *)&lpwhs->socketAddress,
874 sizeof(lpwhs->socketAddress));
875
876 if (SOCKET_ERROR == result)
877 {
878 WARN("Unable to connect to host (%s)\n", strerror(errno));
879 goto lend;
880 }
881
882 bSuccess = TRUE;
883
884lend:
885 TRACE(": %d\n", bSuccess);
886 return bSuccess;
887}
888
889
890/***********************************************************************
891 * HTTP_GetResponseHeaders (internal)
892 *
893 * Read server response
894 *
895 * RETURNS
896 *
897 * TRUE on success
898 * FALSE on error
899 */
900BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQA lpwhr)
901{
902 INT cbreaks = 0;
903 CHAR buffer[MAX_REPLY_LEN];
904 DWORD buflen = MAX_REPLY_LEN;
905 BOOL bSuccess = FALSE;
906 CHAR value[MAX_FIELD_VALUE_LEN], field[MAX_FIELD_LEN];
907
908 TRACE("\n");
909
910 if (INVALID_SOCKET == lpwhr->nSocketFD)
911 goto lend;
912
913 /*
914 * We should first receive 'HTTP/1.x nnn' where nnn is the status code.
915 */
916 if (!INTERNET_GetNextLine(lpwhr->nSocketFD, buffer, &buflen))
917 goto lend;
918
919 if (strncmp(buffer, "HTTP", 4) != 0)
920 goto lend;
921
922 buffer[12]='\0';
923 HTTP_ProcessHeader(lpwhr, "Status", buffer+9, (HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE));
924
925 /* Parse each response line */
926 do
927 {
928 buflen = MAX_REPLY_LEN;
929 if (INTERNET_GetNextLine(lpwhr->nSocketFD, buffer, &buflen))
930 {
931 if (!HTTP_InterpretHttpHeader(buffer, field, MAX_FIELD_LEN, value, MAX_FIELD_VALUE_LEN))
932 break;
933
934 HTTP_ProcessHeader(lpwhr, field, value, (HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE));
935 }
936 else
937 {
938 cbreaks++;
939 if (cbreaks >= 2)
940 break;
941 }
942 }while(1);
943
944 bSuccess = TRUE;
945
946lend:
947
948 return bSuccess;
949}
950
951
952/***********************************************************************
953 * HTTP_InterpretHttpHeader (internal)
954 *
955 * Parse server response
956 *
957 * RETURNS
958 *
959 * TRUE on success
960 * FALSE on error
961 */
962INT stripSpaces(LPCSTR lpszSrc, LPSTR lpszStart, INT *len)
963{
964 LPCSTR lpsztmp;
965 INT srclen;
966
967 srclen = 0;
968
969 while (*lpszSrc == ' ' && *lpszSrc != '\0')
970 lpszSrc++;
971
972 lpsztmp = lpszSrc;
973 while(*lpsztmp != '\0')
974 {
975 if (*lpsztmp != ' ')
976 srclen = lpsztmp - lpszSrc + 1;
977
978 lpsztmp++;
979 }
980
981 *len = min(*len, srclen);
982 strncpy(lpszStart, lpszSrc, *len);
983 lpszStart[*len] = '\0';
984
985 return *len;
986}
987
988
989BOOL HTTP_InterpretHttpHeader(LPSTR buffer, LPSTR field, INT fieldlen, LPSTR value, INT valuelen)
990{
991 CHAR *pd;
992 BOOL bSuccess = FALSE;
993
994 TRACE("\n");
995
996 *field = '\0';
997 *value = '\0';
998
999 pd = strchr(buffer, ':');
1000 if (pd)
1001 {
1002 *pd = '\0';
1003 if (stripSpaces(buffer, field, &fieldlen) > 0)
1004 {
1005 if (stripSpaces(pd+1, value, &valuelen) > 0)
1006 bSuccess = TRUE;
1007 }
1008 }
1009
1010 TRACE("%d: field(%s) Value(%s)\n", bSuccess, field, value);
1011 return bSuccess;
1012}
1013
1014
1015/***********************************************************************
1016 * HTTP_GetStdHeaderIndex (internal)
1017 *
1018 * Lookup field index in standard http header array
1019 *
1020 * FIXME: This should be stuffed into a hash table
1021 */
1022INT HTTP_GetStdHeaderIndex(LPCSTR lpszField)
1023{
1024 INT index = -1;
1025
1026 if (!strcasecmp(lpszField, "Content-Length"))
1027 index = HTTP_QUERY_CONTENT_LENGTH;
1028 else if (!strcasecmp(lpszField,"Status"))
1029 index = HTTP_QUERY_STATUS_CODE;
1030 else if (!strcasecmp(lpszField,"Content-Type"))
1031 index = HTTP_QUERY_CONTENT_TYPE;
1032 else if (!strcasecmp(lpszField,"Last-Modified"))
1033 index = HTTP_QUERY_LAST_MODIFIED;
1034 else if (!strcasecmp(lpszField,"Location"))
1035 index = HTTP_QUERY_LOCATION;
1036 else if (!strcasecmp(lpszField,"Accept"))
1037 index = HTTP_QUERY_ACCEPT;
1038 else if (!strcasecmp(lpszField,"Referer"))
1039 index = HTTP_QUERY_REFERER;
1040 else if (!strcasecmp(lpszField,"Content-Transfer-Encoding"))
1041 index = HTTP_QUERY_CONTENT_TRANSFER_ENCODING;
1042 else if (!strcasecmp(lpszField,"Date"))
1043 index = HTTP_QUERY_DATE;
1044 else if (!strcasecmp(lpszField,"Server"))
1045 index = HTTP_QUERY_SERVER;
1046 else if (!strcasecmp(lpszField,"Connection"))
1047 index = HTTP_QUERY_CONNECTION;
1048 else if (!strcasecmp(lpszField,"ETag"))
1049 index = HTTP_QUERY_ETAG;
1050 else if (!strcasecmp(lpszField,"Accept-Ranges"))
1051 index = HTTP_QUERY_ACCEPT_RANGES;
1052 else if (!strcasecmp(lpszField,"Expires"))
1053 index = HTTP_QUERY_EXPIRES;
1054 else if (!strcasecmp(lpszField,"Mime-Version"))
1055 index = HTTP_QUERY_MIME_VERSION;
1056 else
1057 {
1058 FIXME("Couldn't find %s in standard header table\n", lpszField);
1059 }
1060
1061 return index;
1062}
1063
1064
1065/***********************************************************************
1066 * HTTP_ProcessHeader (internal)
1067 *
1068 * Stuff header into header tables according to <dwModifier>
1069 *
1070 */
1071
1072#define COALESCEFLASG (HTTP_ADDHDR_FLAG_COALESCE|HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA|HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
1073
1074BOOL HTTP_ProcessHeader(LPWININETHTTPREQA lpwhr, LPCSTR field, LPCSTR value, DWORD dwModifier)
1075{
1076 LPHTTPHEADERA lphttpHdr = NULL;
1077 BOOL bSuccess = FALSE;
1078 INT index;
1079
1080 TRACE("%s:%s - 0x%08x\n", field, value, (unsigned int)dwModifier);
1081
1082 /* Adjust modifier flags */
1083 if (dwModifier & COALESCEFLASG)
1084 dwModifier |= HTTP_ADDHDR_FLAG_ADD;
1085
1086 /* Try to get index into standard header array */
1087 index = HTTP_GetStdHeaderIndex(field);
1088 if (index >= 0)
1089 {
1090 lphttpHdr = &lpwhr->StdHeaders[index];
1091 }
1092 else /* Find or create new custom header */
1093 {
1094 index = HTTP_GetCustomHeaderIndex(lpwhr, field);
1095 if (index >= 0)
1096 {
1097 if (dwModifier & HTTP_ADDHDR_FLAG_ADD_IF_NEW)
1098 {
1099 return FALSE;
1100 }
1101 lphttpHdr = &lpwhr->pCustHeaders[index];
1102 }
1103 else
1104 {
1105 HTTPHEADERA hdr;
1106
1107 hdr.lpszField = (LPSTR)field;
1108 hdr.lpszValue = (LPSTR)value;
1109 hdr.wFlags = hdr.wCount = 0;
1110
1111 if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
1112 hdr.wFlags |= HDR_ISREQUEST;
1113
1114 index = HTTP_InsertCustomHeader(lpwhr, &hdr);
1115 return index >= 0;
1116 }
1117 }
1118
1119 if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
1120 lphttpHdr->wFlags |= HDR_ISREQUEST;
1121 else
1122 lphttpHdr->wFlags &= ~HDR_ISREQUEST;
1123
1124 if (!lphttpHdr->lpszValue && (dwModifier & (HTTP_ADDHDR_FLAG_ADD|HTTP_ADDHDR_FLAG_ADD_IF_NEW)))
1125 {
1126 INT slen;
1127
1128 if (!lpwhr->StdHeaders[index].lpszField)
1129 {
1130 lphttpHdr->lpszField = strdup(field);
1131
1132 if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
1133 lphttpHdr->wFlags |= HDR_ISREQUEST;
1134 }
1135
1136 slen = strlen(value) + 1;
1137 lphttpHdr->lpszValue = HeapAlloc(GetProcessHeap(), 0, slen);
1138 if (lphttpHdr->lpszValue)
1139 {
1140 memcpy(lphttpHdr->lpszValue, value, slen);
1141 bSuccess = TRUE;
1142 }
1143 else
1144 {
1145 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1146 }
1147 }
1148 else if (lphttpHdr->lpszValue)
1149 {
1150 if (dwModifier & HTTP_ADDHDR_FLAG_REPLACE)
1151 {
1152 LPSTR lpsztmp;
1153 INT len;
1154
1155 len = strlen(value);
1156
1157 if (len <= 0)
1158 {
1159 //! if custom header delete from array
1160 HeapFree(GetProcessHeap(), 0, lphttpHdr->lpszValue);
1161 lphttpHdr->lpszValue = NULL;
1162 bSuccess = TRUE;
1163 }
1164 else
1165 {
1166 lpsztmp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lphttpHdr->lpszValue, len+1);
1167 if (lpsztmp)
1168 {
1169 lphttpHdr->lpszValue = lpsztmp;
1170 strcpy(lpsztmp, value);
1171 bSuccess = TRUE;
1172 }
1173 else
1174 {
1175 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1176 }
1177 }
1178 }
1179 else if (dwModifier & COALESCEFLASG)
1180 {
1181 LPSTR lpsztmp;
1182 CHAR ch = 0;
1183 INT len = 0;
1184 INT origlen = strlen(lphttpHdr->lpszValue);
1185 INT valuelen = strlen(value);
1186
1187 if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA)
1188 {
1189 ch = ',';
1190 lphttpHdr->wFlags |= HDR_COMMADELIMITED;
1191 }
1192 else if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
1193 {
1194 ch = ';';
1195 lphttpHdr->wFlags |= HDR_COMMADELIMITED;
1196 }
1197
1198 len = origlen + valuelen + (ch > 0) ? 1 : 0;
1199
1200 lpsztmp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lphttpHdr->lpszValue, len+1);
1201 if (lpsztmp)
1202 {
1203 /* FIXME: Increment lphttpHdr->wCount. Perhaps lpszValue should be an array */
1204 if (ch > 0)
1205 {
1206 lphttpHdr->lpszValue[origlen] = ch;
1207 origlen++;
1208 }
1209
1210 memcpy(&lphttpHdr->lpszValue[origlen], value, valuelen);
1211 lphttpHdr->lpszValue[len] = '\0';
1212 bSuccess = TRUE;
1213 }
1214 else
1215 {
1216 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1217 }
1218 }
1219 }
1220
1221 return bSuccess;
1222}
1223
1224
1225/***********************************************************************
1226 * HTTP_CloseConnection (internal)
1227 *
1228 * Close socket connection
1229 *
1230 */
1231VOID HTTP_CloseConnection(LPWININETHTTPREQA lpwhr)
1232{
1233 if (lpwhr->nSocketFD != INVALID_SOCKET)
1234 {
1235 close(lpwhr->nSocketFD);
1236 lpwhr->nSocketFD = INVALID_SOCKET;
1237 }
1238}
1239
1240
1241/***********************************************************************
1242 * HTTP_CloseHTTPRequestHandle (internal)
1243 *
1244 * Deallocate request handle
1245 *
1246 */
1247void HTTP_CloseHTTPRequestHandle(LPWININETHTTPREQA lpwhr)
1248{
1249 int i;
1250
1251 TRACE("\n");
1252
1253 if (lpwhr->nSocketFD != INVALID_SOCKET)
1254 HTTP_CloseConnection(lpwhr);
1255
1256 if (lpwhr->lpszPath)
1257 HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath);
1258 if (lpwhr->lpszVerb)
1259 HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
1260 if (lpwhr->lpszHostName)
1261 HeapFree(GetProcessHeap(), 0, lpwhr->lpszHostName);
1262
1263 for (i = 0; i <= HTTP_QUERY_MAX; i++)
1264 {
1265 if (lpwhr->StdHeaders[i].lpszField)
1266 HeapFree(GetProcessHeap(), 0, lpwhr->StdHeaders[i].lpszField);
1267 if (lpwhr->StdHeaders[i].lpszValue)
1268 HeapFree(GetProcessHeap(), 0, lpwhr->StdHeaders[i].lpszValue);
1269 }
1270
1271 for (i = 0; i < lpwhr->nCustHeaders; i++)
1272 {
1273 if (lpwhr->pCustHeaders[i].lpszField)
1274 HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszField);
1275 if (lpwhr->pCustHeaders[i].lpszValue)
1276 HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszValue);
1277 }
1278
1279 HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders);
1280 HeapFree(GetProcessHeap(), 0, lpwhr);
1281}
1282
1283
1284/***********************************************************************
1285 * HTTP_CloseHTTPSessionHandle (internal)
1286 *
1287 * Deallocate session handle
1288 *
1289 */
1290void HTTP_CloseHTTPSessionHandle(LPWININETHTTPSESSIONA lpwhs)
1291{
1292 TRACE("\n");
1293
1294 if (lpwhs->lpszServerName)
1295 HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName);
1296 if (lpwhs->lpszUserName)
1297 HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName);
1298 HeapFree(GetProcessHeap(), 0, lpwhs);
1299}
1300
1301
1302/***********************************************************************
1303 * HTTP_GetCustomHeaderIndex (internal)
1304 *
1305 * Return index of custom header from header array
1306 *
1307 */
1308INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQA lpwhr, LPCSTR lpszField)
1309{
1310 INT index;
1311
1312 TRACE("%s\n", lpszField);
1313
1314 for (index = 0; index < lpwhr->nCustHeaders; index++)
1315 {
1316 if (!strcasecmp(lpwhr->pCustHeaders[index].lpszField, lpszField))
1317 break;
1318
1319 }
1320
1321 if (index >= lpwhr->nCustHeaders)
1322 index = -1;
1323
1324 TRACE("Return: %d\n", index);
1325 return index;
1326}
1327
1328
1329/***********************************************************************
1330 * HTTP_InsertCustomHeader (internal)
1331 *
1332 * Insert header into array
1333 *
1334 */
1335INT HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr, LPHTTPHEADERA lpHdr)
1336{
1337 INT count;
1338 LPHTTPHEADERA lph = NULL;
1339
1340 TRACE("%s: %s\n", lpHdr->lpszField, lpHdr->lpszValue);
1341 count = lpwhr->nCustHeaders + 1;
1342 if (count > 1)
1343 lph = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpwhr->pCustHeaders, sizeof(HTTPHEADERA) * count);
1344 else
1345 lph = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HTTPHEADERA) * count);
1346
1347 if (NULL != lph)
1348 {
1349 lpwhr->pCustHeaders = lph;
1350 lpwhr->pCustHeaders[count-1].lpszField = strdup(lpHdr->lpszField);
1351 lpwhr->pCustHeaders[count-1].lpszValue = strdup(lpHdr->lpszValue);
1352 lpwhr->pCustHeaders[count-1].wFlags = lpHdr->wFlags;
1353 lpwhr->pCustHeaders[count-1].wCount= lpHdr->wCount;
1354 lpwhr->nCustHeaders++;
1355 }
1356 else
1357 {
1358 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1359 count = 0;
1360 }
1361
1362 TRACE("%d <--\n", count-1);
1363 return count - 1;
1364}
1365
1366
1367/***********************************************************************
1368 * HTTP_DeleteCustomHeader (internal)
1369 *
1370 * Delete header from array
1371 *
1372 */
1373BOOL HTTP_DeleteCustomHeader(INT index)
1374{
1375 TRACE("\n");
1376 return FALSE;
1377}
Note: See TracBrowser for help on using the repository browser.