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

Last change on this file since 7290 was 7290, checked in by phaller, 24 years ago

.

File size: 38.6 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 requestStringLen += strlen(lpwhr->pCustHeaders[i].lpszField) +
640 strlen(lpwhr->pCustHeaders[i].lpszValue) + 4; /*: \r\n */
641 }
642 }
643
644 /* Calculate the length of standard request headers */
645 for (i = 0; i <= HTTP_QUERY_MAX; i++)
646 {
647 if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST)
648 {
649 requestStringLen += strlen(lpwhr->StdHeaders[i].lpszField) +
650 strlen(lpwhr->StdHeaders[i].lpszValue) + 4; /*: \r\n */
651 }
652 }
653
654 /* Allocate string to hold entire request */
655 requestString = HeapAlloc(GetProcessHeap(), 0, requestStringLen + 1);
656 if (NULL == requestString)
657 {
658 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
659 goto lend;
660 }
661
662 /* Build request string */
663 cnt = sprintf(requestString, "%s %s%s%s",
664 lpwhr->lpszVerb,
665 lpwhr->lpszPath,
666 lpwhr->lpszHostName ? (HTTPHEADER HTTPHOSTHEADER) : HTTPHEADER,
667 lpwhr->lpszHostName ? lpwhr->lpszHostName : "");
668
669 /* Append standard request headers */
670 for (i = 0; i <= HTTP_QUERY_MAX; i++)
671 {
672 if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST)
673 {
674 cnt += sprintf(requestString + cnt, "\r\n%s: %s",
675 lpwhr->StdHeaders[i].lpszField, lpwhr->StdHeaders[i].lpszValue);
676 }
677 }
678
679 /* Append custom request heades */
680 for (i = 0; i < lpwhr->nCustHeaders; i++)
681 {
682 if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
683 {
684 cnt += sprintf(requestString + cnt, "\r\n%s: %s",
685 lpwhr->pCustHeaders[i].lpszField, lpwhr->pCustHeaders[i].lpszValue);
686 }
687 }
688
689 /* Append passed request headers */
690 if (lpszHeaders)
691 {
692 strcpy(requestString + cnt, "\r\n");
693 cnt += 2;
694 strcpy(requestString + cnt, lpszHeaders);
695 cnt += headerLength;
696 }
697
698 /* Set termination string for request */
699 strcpy(requestString + cnt, "\r\n\r\n");
700
701 if (hIC->lpfnStatusCB)
702 hIC->lpfnStatusCB(hHttpRequest, lpwhr->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
703
704 TRACE("(%s) len(%d)\n", requestString, requestStringLen);
705 /* Send the request and store the results */
706 if (!HTTP_OpenConnection(lpwhr))
707 goto lend;
708
709 cnt = INTERNET_WriteDataToStream(lpwhr->nSocketFD, requestString, requestStringLen);
710
711 if (cnt < 0)
712 goto lend;
713
714 if (HTTP_GetResponseHeaders(lpwhr))
715 bSuccess = TRUE;
716
717lend:
718
719 if (requestString)
720 HeapFree(GetProcessHeap(), 0, requestString);
721
722 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
723 {
724 INTERNET_ASYNC_RESULT iar;
725
726 iar.dwResult = (DWORD)bSuccess;
727 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
728 hIC->lpfnStatusCB(hHttpRequest, lpwhr->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
729 &iar, sizeof(INTERNET_ASYNC_RESULT));
730 }
731
732 TRACE("<--\n");
733 return bSuccess;
734}
735
736
737/***********************************************************************
738 * HTTP_Connect (internal)
739 *
740 * Create http session handle
741 *
742 * RETURNS
743 * HINTERNET a session handle on success
744 * NULL on failure
745 *
746 */
747HINTERNET HTTP_Connect(HINTERNET hInternet, LPCSTR lpszServerName,
748 INTERNET_PORT nServerPort, LPCSTR lpszUserName,
749 LPCSTR lpszPassword, DWORD dwFlags, DWORD dwContext)
750{
751 BOOL bSuccess = FALSE;
752 LPWININETAPPINFOA hIC = NULL;
753 LPWININETHTTPSESSIONA lpwhs = NULL;
754
755 TRACE("\n");
756
757 if (((LPWININETHANDLEHEADER)hInternet)->htype != WH_HINIT)
758 goto lerror;
759
760 hIC = (LPWININETAPPINFOA) hInternet;
761
762 lpwhs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETHTTPSESSIONA));
763 if (NULL == lpwhs)
764 {
765 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
766 goto lerror;
767 }
768
769 if (hIC->lpfnStatusCB)
770 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_RESOLVING_NAME,
771 (LPVOID)lpszServerName, strlen(lpszServerName));
772
773 if (nServerPort == INTERNET_INVALID_PORT_NUMBER)
774 nServerPort = INTERNET_DEFAULT_HTTP_PORT;
775
776 if (!GetAddress(lpszServerName, nServerPort, &lpwhs->phostent, &lpwhs->socketAddress))
777 {
778 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
779 goto lerror;
780 }
781
782 if (hIC->lpfnStatusCB)
783 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_NAME_RESOLVED,
784 (LPVOID)lpszServerName, strlen(lpszServerName));
785
786 lpwhs->hdr.htype = WH_HHTTPSESSION;
787 lpwhs->hdr.lpwhparent = (LPWININETHANDLEHEADER)hInternet;
788 lpwhs->hdr.dwFlags = dwFlags;
789 lpwhs->hdr.dwContext = dwContext;
790 if (NULL != lpszServerName)
791 lpwhs->lpszServerName = strdup(lpszServerName);
792 if (NULL != lpszUserName)
793 lpwhs->lpszUserName = strdup(lpszUserName);
794 lpwhs->nServerPort = nServerPort;
795
796 if (hIC->lpfnStatusCB)
797 {
798 INTERNET_ASYNC_RESULT iar;
799
800 iar.dwResult = (DWORD)lpwhs;
801 iar.dwError = ERROR_SUCCESS;
802
803 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_HANDLE_CREATED,
804 &iar, sizeof(INTERNET_ASYNC_RESULT));
805 }
806
807 bSuccess = TRUE;
808
809lerror:
810 if (!bSuccess && lpwhs)
811 {
812 HeapFree(GetProcessHeap(), 0, lpwhs);
813 lpwhs = NULL;
814 }
815
816 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
817 {
818 INTERNET_ASYNC_RESULT iar;
819
820 iar.dwResult = (DWORD)lpwhs;
821 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
822 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
823 &iar, sizeof(INTERNET_ASYNC_RESULT));
824 }
825TRACE("<--\n");
826 return (HINTERNET)lpwhs;
827}
828
829
830/***********************************************************************
831 * HTTP_OpenConnection (internal)
832 *
833 * Connect to a web server
834 *
835 * RETURNS
836 *
837 * TRUE on success
838 * FALSE on failure
839 */
840BOOL HTTP_OpenConnection(LPWININETHTTPREQA lpwhr)
841{
842 BOOL bSuccess = FALSE;
843 INT result;
844 LPWININETHTTPSESSIONA lpwhs;
845
846 TRACE("\n");
847
848 if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
849 {
850 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
851 goto lend;
852 }
853
854 lpwhs = (LPWININETHTTPSESSIONA)lpwhr->hdr.lpwhparent;
855
856 lpwhr->nSocketFD = socket(lpwhs->phostent->h_addrtype,SOCK_STREAM,0);
857 if (INVALID_SOCKET == lpwhr->nSocketFD)
858 {
859 WARN("Socket creation failed\n");
860 goto lend;
861 }
862
863 result = connect(lpwhr->nSocketFD, (struct sockaddr *)&lpwhs->socketAddress,
864 sizeof(lpwhs->socketAddress));
865
866 if (SOCKET_ERROR == result)
867 {
868 WARN("Unable to connect to host (%s)\n", strerror(errno));
869 goto lend;
870 }
871
872 bSuccess = TRUE;
873
874lend:
875 TRACE(": %d\n", bSuccess);
876 return bSuccess;
877}
878
879
880/***********************************************************************
881 * HTTP_GetResponseHeaders (internal)
882 *
883 * Read server response
884 *
885 * RETURNS
886 *
887 * TRUE on success
888 * FALSE on error
889 */
890BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQA lpwhr)
891{
892 INT cbreaks = 0;
893 CHAR buffer[MAX_REPLY_LEN];
894 DWORD buflen = MAX_REPLY_LEN;
895 BOOL bSuccess = FALSE;
896 CHAR value[MAX_FIELD_VALUE_LEN], field[MAX_FIELD_LEN];
897
898 TRACE("\n");
899
900 if (INVALID_SOCKET == lpwhr->nSocketFD)
901 goto lend;
902
903 /*
904 * We should first receive 'HTTP/1.x nnn' where nnn is the status code.
905 */
906 if (!INTERNET_GetNextLine(lpwhr->nSocketFD, buffer, &buflen))
907 goto lend;
908
909 if (strncmp(buffer, "HTTP", 4) != 0)
910 goto lend;
911
912 buffer[12]='\0';
913 HTTP_ProcessHeader(lpwhr, "Status", buffer+9, (HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE));
914
915 /* Parse each response line */
916 do
917 {
918 buflen = MAX_REPLY_LEN;
919 if (INTERNET_GetNextLine(lpwhr->nSocketFD, buffer, &buflen))
920 {
921 if (!HTTP_InterpretHttpHeader(buffer, field, MAX_FIELD_LEN, value, MAX_FIELD_VALUE_LEN))
922 break;
923
924 HTTP_ProcessHeader(lpwhr, field, value, (HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE));
925 }
926 else
927 {
928 cbreaks++;
929 if (cbreaks >= 2)
930 break;
931 }
932 }while(1);
933
934 bSuccess = TRUE;
935
936lend:
937
938 return bSuccess;
939}
940
941
942/***********************************************************************
943 * HTTP_InterpretHttpHeader (internal)
944 *
945 * Parse server response
946 *
947 * RETURNS
948 *
949 * TRUE on success
950 * FALSE on error
951 */
952INT stripSpaces(LPCSTR lpszSrc, LPSTR lpszStart, INT *len)
953{
954 LPCSTR lpsztmp;
955 INT srclen;
956
957 srclen = 0;
958
959 while (*lpszSrc == ' ' && *lpszSrc != '\0')
960 lpszSrc++;
961
962 lpsztmp = lpszSrc;
963 while(*lpsztmp != '\0')
964 {
965 if (*lpsztmp != ' ')
966 srclen = lpsztmp - lpszSrc + 1;
967
968 lpsztmp++;
969 }
970
971 *len = min(*len, srclen);
972 strncpy(lpszStart, lpszSrc, *len);
973 lpszStart[*len] = '\0';
974
975 return *len;
976}
977
978
979BOOL HTTP_InterpretHttpHeader(LPSTR buffer, LPSTR field, INT fieldlen, LPSTR value, INT valuelen)
980{
981 CHAR *pd;
982 BOOL bSuccess = FALSE;
983
984 TRACE("\n");
985
986 *field = '\0';
987 *value = '\0';
988
989 pd = strchr(buffer, ':');
990 if (pd)
991 {
992 *pd = '\0';
993 if (stripSpaces(buffer, field, &fieldlen) > 0)
994 {
995 if (stripSpaces(pd+1, value, &valuelen) > 0)
996 bSuccess = TRUE;
997 }
998 }
999
1000 TRACE("%d: field(%s) Value(%s)\n", bSuccess, field, value);
1001 return bSuccess;
1002}
1003
1004
1005/***********************************************************************
1006 * HTTP_GetStdHeaderIndex (internal)
1007 *
1008 * Lookup field index in standard http header array
1009 *
1010 * FIXME: This should be stuffed into a hash table
1011 */
1012INT HTTP_GetStdHeaderIndex(LPCSTR lpszField)
1013{
1014 INT index = -1;
1015
1016 if (!strcasecmp(lpszField, "Content-Length"))
1017 index = HTTP_QUERY_CONTENT_LENGTH;
1018 else if (!strcasecmp(lpszField,"Status"))
1019 index = HTTP_QUERY_STATUS_CODE;
1020 else if (!strcasecmp(lpszField,"Content-Type"))
1021 index = HTTP_QUERY_CONTENT_TYPE;
1022 else if (!strcasecmp(lpszField,"Last-Modified"))
1023 index = HTTP_QUERY_LAST_MODIFIED;
1024 else if (!strcasecmp(lpszField,"Location"))
1025 index = HTTP_QUERY_LOCATION;
1026 else if (!strcasecmp(lpszField,"Accept"))
1027 index = HTTP_QUERY_ACCEPT;
1028 else if (!strcasecmp(lpszField,"Referer"))
1029 index = HTTP_QUERY_REFERER;
1030 else if (!strcasecmp(lpszField,"Content-Transfer-Encoding"))
1031 index = HTTP_QUERY_CONTENT_TRANSFER_ENCODING;
1032 else if (!strcasecmp(lpszField,"Date"))
1033 index = HTTP_QUERY_DATE;
1034 else if (!strcasecmp(lpszField,"Server"))
1035 index = HTTP_QUERY_SERVER;
1036 else if (!strcasecmp(lpszField,"Connection"))
1037 index = HTTP_QUERY_CONNECTION;
1038 else if (!strcasecmp(lpszField,"ETag"))
1039 index = HTTP_QUERY_ETAG;
1040 else if (!strcasecmp(lpszField,"Accept-Ranges"))
1041 index = HTTP_QUERY_ACCEPT_RANGES;
1042 else if (!strcasecmp(lpszField,"Expires"))
1043 index = HTTP_QUERY_EXPIRES;
1044 else if (!strcasecmp(lpszField,"Mime-Version"))
1045 index = HTTP_QUERY_MIME_VERSION;
1046 else
1047 {
1048 FIXME("Couldn't find %s in standard header table\n", lpszField);
1049 }
1050
1051 return index;
1052}
1053
1054
1055/***********************************************************************
1056 * HTTP_ProcessHeader (internal)
1057 *
1058 * Stuff header into header tables according to <dwModifier>
1059 *
1060 */
1061
1062#define COALESCEFLASG (HTTP_ADDHDR_FLAG_COALESCE|HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA|HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
1063
1064BOOL HTTP_ProcessHeader(LPWININETHTTPREQA lpwhr, LPCSTR field, LPCSTR value, DWORD dwModifier)
1065{
1066 LPHTTPHEADERA lphttpHdr = NULL;
1067 BOOL bSuccess = FALSE;
1068 INT index;
1069
1070 TRACE("%s:%s - 0x%08x\n", field, value, (unsigned int)dwModifier);
1071
1072 /* Adjust modifier flags */
1073 if (dwModifier & COALESCEFLASG)
1074 dwModifier |= HTTP_ADDHDR_FLAG_ADD;
1075
1076 /* Try to get index into standard header array */
1077 index = HTTP_GetStdHeaderIndex(field);
1078 if (index >= 0)
1079 {
1080 lphttpHdr = &lpwhr->StdHeaders[index];
1081 }
1082 else /* Find or create new custom header */
1083 {
1084 index = HTTP_GetCustomHeaderIndex(lpwhr, field);
1085 if (index >= 0)
1086 {
1087 if (dwModifier & HTTP_ADDHDR_FLAG_ADD_IF_NEW)
1088 {
1089 return FALSE;
1090 }
1091 lphttpHdr = &lpwhr->pCustHeaders[index];
1092 }
1093 else
1094 {
1095 HTTPHEADERA hdr;
1096
1097 hdr.lpszField = (LPSTR)field;
1098 hdr.lpszValue = (LPSTR)value;
1099 hdr.wFlags = hdr.wCount = 0;
1100
1101 if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
1102 hdr.wFlags |= HDR_ISREQUEST;
1103
1104 index = HTTP_InsertCustomHeader(lpwhr, &hdr);
1105 return index >= 0;
1106 }
1107 }
1108
1109 if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
1110 lphttpHdr->wFlags |= HDR_ISREQUEST;
1111 else
1112 lphttpHdr->wFlags &= ~HDR_ISREQUEST;
1113
1114 if (!lphttpHdr->lpszValue && (dwModifier & (HTTP_ADDHDR_FLAG_ADD|HTTP_ADDHDR_FLAG_ADD_IF_NEW)))
1115 {
1116 INT slen;
1117
1118 if (!lpwhr->StdHeaders[index].lpszField)
1119 {
1120 lphttpHdr->lpszField = strdup(field);
1121
1122 if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
1123 lphttpHdr->wFlags |= HDR_ISREQUEST;
1124 }
1125
1126 slen = strlen(value) + 1;
1127 lphttpHdr->lpszValue = HeapAlloc(GetProcessHeap(), 0, slen);
1128 if (lphttpHdr->lpszValue)
1129 {
1130 memcpy(lphttpHdr->lpszValue, value, slen);
1131 bSuccess = TRUE;
1132 }
1133 else
1134 {
1135 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1136 }
1137 }
1138 else if (lphttpHdr->lpszValue)
1139 {
1140 if (dwModifier & HTTP_ADDHDR_FLAG_REPLACE)
1141 {
1142 LPSTR lpsztmp;
1143 INT len;
1144
1145 len = strlen(value);
1146
1147 if (len <= 0)
1148 {
1149 //! if custom header delete from array
1150 HeapFree(GetProcessHeap(), 0, lphttpHdr->lpszValue);
1151 lphttpHdr->lpszValue = NULL;
1152 bSuccess = TRUE;
1153 }
1154 else
1155 {
1156 lpsztmp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lphttpHdr->lpszValue, len+1);
1157 if (lpsztmp)
1158 {
1159 lphttpHdr->lpszValue = lpsztmp;
1160 strcpy(lpsztmp, value);
1161 bSuccess = TRUE;
1162 }
1163 else
1164 {
1165 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1166 }
1167 }
1168 }
1169 else if (dwModifier & COALESCEFLASG)
1170 {
1171 LPSTR lpsztmp;
1172 CHAR ch = 0;
1173 INT len = 0;
1174 INT origlen = strlen(lphttpHdr->lpszValue);
1175 INT valuelen = strlen(value);
1176
1177 if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA)
1178 {
1179 ch = ',';
1180 lphttpHdr->wFlags |= HDR_COMMADELIMITED;
1181 }
1182 else if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
1183 {
1184 ch = ';';
1185 lphttpHdr->wFlags |= HDR_COMMADELIMITED;
1186 }
1187
1188 len = origlen + valuelen + (ch > 0) ? 1 : 0;
1189
1190 lpsztmp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lphttpHdr->lpszValue, len+1);
1191 if (lpsztmp)
1192 {
1193 /* FIXME: Increment lphttpHdr->wCount. Perhaps lpszValue should be an array */
1194 if (ch > 0)
1195 {
1196 lphttpHdr->lpszValue[origlen] = ch;
1197 origlen++;
1198 }
1199
1200 memcpy(&lphttpHdr->lpszValue[origlen], value, valuelen);
1201 lphttpHdr->lpszValue[len] = '\0';
1202 bSuccess = TRUE;
1203 }
1204 else
1205 {
1206 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1207 }
1208 }
1209 }
1210
1211 return bSuccess;
1212}
1213
1214
1215/***********************************************************************
1216 * HTTP_CloseConnection (internal)
1217 *
1218 * Close socket connection
1219 *
1220 */
1221VOID HTTP_CloseConnection(LPWININETHTTPREQA lpwhr)
1222{
1223 if (lpwhr->nSocketFD != INVALID_SOCKET)
1224 {
1225 close(lpwhr->nSocketFD);
1226 lpwhr->nSocketFD = INVALID_SOCKET;
1227 }
1228}
1229
1230
1231/***********************************************************************
1232 * HTTP_CloseHTTPRequestHandle (internal)
1233 *
1234 * Deallocate request handle
1235 *
1236 */
1237void HTTP_CloseHTTPRequestHandle(LPWININETHTTPREQA lpwhr)
1238{
1239 int i;
1240
1241 TRACE("\n");
1242
1243 if (lpwhr->nSocketFD != INVALID_SOCKET)
1244 HTTP_CloseConnection(lpwhr);
1245
1246 if (lpwhr->lpszPath)
1247 HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath);
1248 if (lpwhr->lpszVerb)
1249 HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
1250 if (lpwhr->lpszHostName)
1251 HeapFree(GetProcessHeap(), 0, lpwhr->lpszHostName);
1252
1253 for (i = 0; i <= HTTP_QUERY_MAX; i++)
1254 {
1255 if (lpwhr->StdHeaders[i].lpszField)
1256 HeapFree(GetProcessHeap(), 0, lpwhr->StdHeaders[i].lpszField);
1257 if (lpwhr->StdHeaders[i].lpszValue)
1258 HeapFree(GetProcessHeap(), 0, lpwhr->StdHeaders[i].lpszValue);
1259 }
1260
1261 for (i = 0; i < lpwhr->nCustHeaders; i++)
1262 {
1263 if (lpwhr->pCustHeaders[i].lpszField)
1264 HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszField);
1265 if (lpwhr->pCustHeaders[i].lpszValue)
1266 HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszValue);
1267 }
1268
1269 HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders);
1270 HeapFree(GetProcessHeap(), 0, lpwhr);
1271}
1272
1273
1274/***********************************************************************
1275 * HTTP_CloseHTTPSessionHandle (internal)
1276 *
1277 * Deallocate session handle
1278 *
1279 */
1280void HTTP_CloseHTTPSessionHandle(LPWININETHTTPSESSIONA lpwhs)
1281{
1282 TRACE("\n");
1283
1284 if (lpwhs->lpszServerName)
1285 HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName);
1286 if (lpwhs->lpszUserName)
1287 HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName);
1288 HeapFree(GetProcessHeap(), 0, lpwhs);
1289}
1290
1291
1292/***********************************************************************
1293 * HTTP_GetCustomHeaderIndex (internal)
1294 *
1295 * Return index of custom header from header array
1296 *
1297 */
1298INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQA lpwhr, LPCSTR lpszField)
1299{
1300 INT index;
1301
1302 TRACE("%s\n", lpszField);
1303
1304 for (index = 0; index < lpwhr->nCustHeaders; index++)
1305 {
1306 if (!strcasecmp(lpwhr->pCustHeaders[index].lpszField, lpszField))
1307 break;
1308
1309 }
1310
1311 if (index >= lpwhr->nCustHeaders)
1312 index = -1;
1313
1314 TRACE("Return: %d\n", index);
1315 return index;
1316}
1317
1318
1319/***********************************************************************
1320 * HTTP_InsertCustomHeader (internal)
1321 *
1322 * Insert header into array
1323 *
1324 */
1325INT HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr, LPHTTPHEADERA lpHdr)
1326{
1327 INT count;
1328 LPHTTPHEADERA lph = NULL;
1329
1330 TRACE("%s: %s\n", lpHdr->lpszField, lpHdr->lpszValue);
1331 count = lpwhr->nCustHeaders + 1;
1332 if (count > 1)
1333 lph = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpwhr->pCustHeaders, sizeof(HTTPHEADERA) * count);
1334 else
1335 lph = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HTTPHEADERA) * count);
1336
1337 if (NULL != lph)
1338 {
1339 lpwhr->pCustHeaders = lph;
1340 lpwhr->pCustHeaders[count-1].lpszField = strdup(lpHdr->lpszField);
1341 lpwhr->pCustHeaders[count-1].lpszValue = strdup(lpHdr->lpszValue);
1342 lpwhr->pCustHeaders[count-1].wFlags = lpHdr->wFlags;
1343 lpwhr->pCustHeaders[count-1].wCount= lpHdr->wCount;
1344 lpwhr->nCustHeaders++;
1345 }
1346 else
1347 {
1348 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1349 count = 0;
1350 }
1351
1352 TRACE("%d <--\n", count-1);
1353 return count - 1;
1354}
1355
1356
1357/***********************************************************************
1358 * HTTP_DeleteCustomHeader (internal)
1359 *
1360 * Delete header from array
1361 *
1362 */
1363BOOL HTTP_DeleteCustomHeader(INT index)
1364{
1365 TRACE("\n");
1366 return FALSE;
1367}
Note: See TracBrowser for help on using the repository browser.