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

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

JH: Resync with latest Wine + fixes/additions

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