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

Last change on this file since 6640 was 6640, checked in by bird, 24 years ago

Added Missing $Id:$ keyword.

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