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

Last change on this file since 4842 was 4842, checked in by sandervl, 25 years ago

JH: Resync with latest Wine + fixes/additions

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