2 * Wininet - Http Implementation
4 * Copyright 1999 Corel Corporation
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <sys/types.h>
26 #ifdef HAVE_SYS_SOCKET_H
27 # include <sys/socket.h>
41 #define NO_SHLWAPI_STREAM
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(wininet
);
49 #define HTTPHEADER " HTTP/1.0"
50 #define HTTPHOSTHEADER "\r\nHost: "
51 #define MAXHOSTNAME 100
52 #define MAX_FIELD_VALUE_LEN 256
53 #define MAX_FIELD_LEN 256
56 #define HTTP_REFERER "Referer"
57 #define HTTP_ACCEPT "Accept"
59 #define HTTP_ADDHDR_FLAG_ADD 0x20000000
60 #define HTTP_ADDHDR_FLAG_ADD_IF_NEW 0x10000000
61 #define HTTP_ADDHDR_FLAG_COALESCE 0x40000000
62 #define HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA 0x40000000
63 #define HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON 0x01000000
64 #define HTTP_ADDHDR_FLAG_REPLACE 0x80000000
65 #define HTTP_ADDHDR_FLAG_REQ 0x02000000
68 BOOL
HTTP_OpenConnection(LPWININETHTTPREQA lpwhr
);
69 int HTTP_WriteDataToStream(LPWININETHTTPREQA lpwhr
,
70 void *Buffer
, int BytesToWrite
);
71 int HTTP_ReadDataFromStream(LPWININETHTTPREQA lpwhr
,
72 void *Buffer
, int BytesToRead
);
73 BOOL
HTTP_GetResponseHeaders(LPWININETHTTPREQA lpwhr
);
74 BOOL
HTTP_ProcessHeader(LPWININETHTTPREQA lpwhr
, LPCSTR field
, LPCSTR value
, DWORD dwModifier
);
75 void HTTP_CloseConnection(LPWININETHTTPREQA lpwhr
);
76 BOOL
HTTP_InterpretHttpHeader(LPSTR buffer
, LPSTR field
, INT fieldlen
, LPSTR value
, INT valuelen
);
77 INT
HTTP_GetStdHeaderIndex(LPCSTR lpszField
);
78 INT
HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr
, LPHTTPHEADERA lpHdr
);
79 INT
HTTP_GetCustomHeaderIndex(LPWININETHTTPREQA lpwhr
, LPCSTR lpszField
);
81 inline static LPSTR
HTTP_strdup( LPCSTR str
)
83 LPSTR ret
= HeapAlloc( GetProcessHeap(), 0, strlen(str
) + 1 );
84 if (ret
) strcpy( ret
, str
);
88 /***********************************************************************
89 * HttpAddRequestHeadersA (WININET.@)
91 * Adds one or more HTTP header to the request handler
98 BOOL WINAPI
HttpAddRequestHeadersA(HINTERNET hHttpRequest
,
99 LPCSTR lpszHeader
, DWORD dwHeaderLength
, DWORD dwModifier
)
104 CHAR value
[MAX_FIELD_VALUE_LEN
], field
[MAX_FIELD_LEN
];
105 BOOL bSuccess
= FALSE
;
106 LPWININETHTTPREQA lpwhr
= (LPWININETHTTPREQA
) hHttpRequest
;
108 if (NULL
== lpwhr
|| lpwhr
->hdr
.htype
!= WH_HHTTPREQ
)
110 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
114 buffer
= HTTP_strdup(lpszHeader
);
121 while (*lpszEnd
!= '\0')
123 if (*lpszEnd
== '\r' && *(lpszEnd
+ 1) == '\n')
128 if (*lpszEnd
== '\0')
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
);
136 lpszStart
= lpszEnd
+ 2; /* Jump over \0\n */
140 HeapFree(GetProcessHeap(), 0, buffer
);
145 /***********************************************************************
146 * HttpOpenRequestA (WININET.@)
148 * Open a HTTP request handle
151 * HINTERNET a HTTP request handle on success
155 HINTERNET WINAPI
HttpOpenRequestA(HINTERNET hHttpSession
,
156 LPCSTR lpszVerb
, LPCSTR lpszObjectName
, LPCSTR lpszVersion
,
157 LPCSTR lpszReferrer
, LPCSTR
*lpszAcceptTypes
,
158 DWORD dwFlags
, DWORD dwContext
)
160 LPWININETHTTPSESSIONA lpwhs
= (LPWININETHTTPSESSIONA
) hHttpSession
;
161 LPWININETAPPINFOA hIC
= NULL
;
165 if (NULL
== lpwhs
|| lpwhs
->hdr
.htype
!= WH_HHTTPSESSION
)
167 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
171 hIC
= (LPWININETAPPINFOA
) lpwhs
->hdr
.lpwhparent
;
173 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
175 WORKREQUEST workRequest
;
177 workRequest
.asyncall
= HTTPOPENREQUESTA
;
178 workRequest
.HFTPSESSION
= (DWORD
)hHttpSession
;
179 workRequest
.LPSZVERB
= (DWORD
)HTTP_strdup(lpszVerb
);
180 workRequest
.LPSZOBJECTNAME
= (DWORD
)HTTP_strdup(lpszObjectName
);
181 workRequest
.LPSZVERSION
= (DWORD
)HTTP_strdup(lpszVersion
);
182 workRequest
.LPSZREFERRER
= (DWORD
)HTTP_strdup(lpszReferrer
);
183 workRequest
.LPSZACCEPTTYPES
= (DWORD
)lpszAcceptTypes
;
184 workRequest
.DWFLAGS
= dwFlags
;
185 workRequest
.DWCONTEXT
= dwContext
;
187 return (HINTERNET
)INTERNET_AsyncCall(&workRequest
);
191 return HTTP_HttpOpenRequestA(hHttpSession
, lpszVerb
, lpszObjectName
,
192 lpszVersion
, lpszReferrer
, lpszAcceptTypes
, dwFlags
, dwContext
);
197 /***********************************************************************
198 * HTTP_HttpOpenRequestA (internal)
200 * Open a HTTP request handle
203 * HINTERNET a HTTP request handle on success
207 HINTERNET WINAPI
HTTP_HttpOpenRequestA(HINTERNET hHttpSession
,
208 LPCSTR lpszVerb
, LPCSTR lpszObjectName
, LPCSTR lpszVersion
,
209 LPCSTR lpszReferrer
, LPCSTR
*lpszAcceptTypes
,
210 DWORD dwFlags
, DWORD dwContext
)
212 LPWININETHTTPSESSIONA lpwhs
= (LPWININETHTTPSESSIONA
) hHttpSession
;
213 LPWININETAPPINFOA hIC
= NULL
;
214 LPWININETHTTPREQA lpwhr
;
218 if (NULL
== lpwhs
|| lpwhs
->hdr
.htype
!= WH_HHTTPSESSION
)
220 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
224 hIC
= (LPWININETAPPINFOA
) lpwhs
->hdr
.lpwhparent
;
226 lpwhr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WININETHTTPREQA
));
229 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
230 return (HINTERNET
) NULL
;
233 lpwhr
->hdr
.htype
= WH_HHTTPREQ
;
234 lpwhr
->hdr
.lpwhparent
= hHttpSession
;
235 lpwhr
->hdr
.dwFlags
= dwFlags
;
236 lpwhr
->hdr
.dwContext
= dwContext
;
237 lpwhr
->nSocketFD
= -1;
239 if (NULL
!= lpszObjectName
&& strlen(lpszObjectName
)) {
241 UrlEscapeA(lpszObjectName
, NULL
, &needed
, URL_ESCAPE_SPACES_ONLY
);
242 lpwhr
->lpszPath
= HeapAlloc(GetProcessHeap(), 0, needed
);
243 UrlEscapeA(lpszObjectName
, lpwhr
->lpszPath
, &needed
,
244 URL_ESCAPE_SPACES_ONLY
);
247 if (NULL
!= lpszReferrer
&& strlen(lpszReferrer
))
248 HTTP_ProcessHeader(lpwhr
, HTTP_REFERER
, lpszReferrer
, HTTP_ADDHDR_FLAG_COALESCE
);
251 if (NULL
!= lpszAcceptTypes
&& strlen(*lpszAcceptTypes
))
252 HTTP_ProcessHeader(lpwhr
, HTTP_ACCEPT
, *lpszAcceptTypes
, HTTP_ADDHDR_FLAG_COALESCE
);
254 if (NULL
== lpszVerb
)
255 lpwhr
->lpszVerb
= HTTP_strdup("GET");
256 else if (strlen(lpszVerb
))
257 lpwhr
->lpszVerb
= HTTP_strdup(lpszVerb
);
259 if (NULL
!= lpszReferrer
)
261 char buf
[MAXHOSTNAME
];
262 URL_COMPONENTSA UrlComponents
;
264 UrlComponents
.lpszExtraInfo
= NULL
;
265 UrlComponents
.lpszPassword
= NULL
;
266 UrlComponents
.lpszScheme
= NULL
;
267 UrlComponents
.lpszUrlPath
= NULL
;
268 UrlComponents
.lpszUserName
= NULL
;
269 UrlComponents
.lpszHostName
= buf
;
270 UrlComponents
.dwHostNameLength
= MAXHOSTNAME
;
272 InternetCrackUrlA(lpszReferrer
, 0, 0, &UrlComponents
);
273 if (strlen(UrlComponents
.lpszHostName
))
274 lpwhr
->lpszHostName
= HTTP_strdup(UrlComponents
.lpszHostName
);
276 lpwhr
->lpszHostName
= HTTP_strdup(lpwhs
->lpszServerName
);
279 if (hIC
->lpfnStatusCB
)
281 INTERNET_ASYNC_RESULT iar
;
283 iar
.dwResult
= (DWORD
)lpwhr
;
284 iar
.dwError
= ERROR_SUCCESS
;
286 hIC
->lpfnStatusCB(hHttpSession
, dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
287 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
290 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
292 INTERNET_ASYNC_RESULT iar
;
294 iar
.dwResult
= (DWORD
)lpwhr
;
295 iar
.dwError
= lpwhr
? ERROR_SUCCESS
: INTERNET_GetLastError();
296 hIC
->lpfnStatusCB(hHttpSession
, dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
297 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
300 return (HINTERNET
) lpwhr
;
304 /***********************************************************************
305 * HttpQueryInfoA (WININET.@)
307 * Queries for information about an HTTP request
314 BOOL WINAPI
HttpQueryInfoA(HINTERNET hHttpRequest
, DWORD dwInfoLevel
,
315 LPVOID lpBuffer
, LPDWORD lpdwBufferLength
, LPDWORD lpdwIndex
)
317 LPHTTPHEADERA lphttpHdr
= NULL
;
318 BOOL bSuccess
= FALSE
;
319 LPWININETHTTPREQA lpwhr
= (LPWININETHTTPREQA
) hHttpRequest
;
321 TRACE("(0x%08lx)--> %ld\n", dwInfoLevel
, dwInfoLevel
);
323 if (NULL
== lpwhr
|| lpwhr
->hdr
.htype
!= WH_HHTTPREQ
)
325 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
329 /* Find requested header structure */
330 if ((dwInfoLevel
& ~HTTP_QUERY_MODIFIER_FLAGS_MASK
) == HTTP_QUERY_CUSTOM
)
332 INT index
= HTTP_GetCustomHeaderIndex(lpwhr
, (LPSTR
)lpBuffer
);
337 lphttpHdr
= &lpwhr
->pCustHeaders
[index
];
341 INT index
= dwInfoLevel
& ~HTTP_QUERY_MODIFIER_FLAGS_MASK
;
343 if (index
== HTTP_QUERY_RAW_HEADERS_CRLF
|| index
== HTTP_QUERY_RAW_HEADERS
)
345 INT i
, delim
, size
= 0, cnt
= 0;
347 delim
= index
== HTTP_QUERY_RAW_HEADERS_CRLF
? 2 : 1;
349 /* Calculate length of custom reuqest headers */
350 for (i
= 0; i
< lpwhr
->nCustHeaders
; i
++)
352 if ((~lpwhr
->pCustHeaders
[i
].wFlags
& HDR_ISREQUEST
) && lpwhr
->pCustHeaders
[i
].lpszField
&&
353 lpwhr
->pCustHeaders
[i
].lpszValue
)
355 size
+= strlen(lpwhr
->pCustHeaders
[i
].lpszField
) +
356 strlen(lpwhr
->pCustHeaders
[i
].lpszValue
) + delim
+ 2;
360 /* Calculate the length of stadard request headers */
361 for (i
= 0; i
<= HTTP_QUERY_MAX
; i
++)
363 if ((~lpwhr
->StdHeaders
[i
].wFlags
& HDR_ISREQUEST
) && lpwhr
->StdHeaders
[i
].lpszField
&&
364 lpwhr
->StdHeaders
[i
].lpszValue
)
366 size
+= strlen(lpwhr
->StdHeaders
[i
].lpszField
) +
367 strlen(lpwhr
->StdHeaders
[i
].lpszValue
) + delim
+ 2;
373 if (size
+ 1 > *lpdwBufferLength
)
375 *lpdwBufferLength
= size
+ 1;
376 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER
);
380 /* Append standard request heades */
381 for (i
= 0; i
<= HTTP_QUERY_MAX
; i
++)
383 if ((~lpwhr
->StdHeaders
[i
].wFlags
& HDR_ISREQUEST
) &&
384 lpwhr
->StdHeaders
[i
].lpszField
&&
385 lpwhr
->StdHeaders
[i
].lpszValue
)
387 cnt
+= sprintf(lpBuffer
+ cnt
, "%s: %s%s", lpwhr
->StdHeaders
[i
].lpszField
, lpwhr
->StdHeaders
[i
].lpszValue
,
388 index
== HTTP_QUERY_RAW_HEADERS_CRLF
? "\r\n" : "\0");
392 /* Append custom request heades */
393 for (i
= 0; i
< lpwhr
->nCustHeaders
; i
++)
395 if ((~lpwhr
->pCustHeaders
[i
].wFlags
& HDR_ISREQUEST
) &&
396 lpwhr
->pCustHeaders
[i
].lpszField
&&
397 lpwhr
->pCustHeaders
[i
].lpszValue
)
399 cnt
+= sprintf(lpBuffer
+ cnt
, "%s: %s%s",
400 lpwhr
->pCustHeaders
[i
].lpszField
, lpwhr
->pCustHeaders
[i
].lpszValue
,
401 index
== HTTP_QUERY_RAW_HEADERS_CRLF
? "\r\n" : "\0");
405 strcpy(lpBuffer
+ cnt
, index
== HTTP_QUERY_RAW_HEADERS_CRLF
? "\r\n" : "");
407 *lpdwBufferLength
= cnt
+ delim
;
411 else if (index
>= 0 && index
<= HTTP_QUERY_MAX
&& lpwhr
->StdHeaders
[index
].lpszValue
)
413 lphttpHdr
= &lpwhr
->StdHeaders
[index
];
419 /* Ensure header satisifies requested attributes */
420 if ((dwInfoLevel
& HTTP_QUERY_FLAG_REQUEST_HEADERS
) &&
421 (~lphttpHdr
->wFlags
& HDR_ISREQUEST
))
424 /* coalesce value to reuqested type */
425 if (dwInfoLevel
& HTTP_QUERY_FLAG_NUMBER
)
427 *(int *)lpBuffer
= atoi(lphttpHdr
->lpszValue
);
430 else if (dwInfoLevel
& HTTP_QUERY_FLAG_SYSTEMTIME
)
436 tmpTime
= ConvertTimeString(lphttpHdr
->lpszValue
);
438 tmpTM
= *gmtime(&tmpTime
);
439 STHook
= (SYSTEMTIME
*) lpBuffer
;
443 STHook
->wDay
= tmpTM
.tm_mday
;
444 STHook
->wHour
= tmpTM
.tm_hour
;
445 STHook
->wMilliseconds
= 0;
446 STHook
->wMinute
= tmpTM
.tm_min
;
447 STHook
->wDayOfWeek
= tmpTM
.tm_wday
;
448 STHook
->wMonth
= tmpTM
.tm_mon
+ 1;
449 STHook
->wSecond
= tmpTM
.tm_sec
;
450 STHook
->wYear
= tmpTM
.tm_year
;
454 else if (dwInfoLevel
& HTTP_QUERY_FLAG_COALESCE
)
456 if (*lpdwIndex
>= lphttpHdr
->wCount
)
458 INTERNET_SetLastError(ERROR_HTTP_HEADER_NOT_FOUND
);
462 //! Copy strncpy(lpBuffer, lphttpHdr[*lpdwIndex], len);
468 INT len
= strlen(lphttpHdr
->lpszValue
);
470 if (len
+ 1 > *lpdwBufferLength
)
472 *lpdwBufferLength
= len
+ 1;
473 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER
);
477 strncpy(lpBuffer
, lphttpHdr
->lpszValue
, len
);
478 *lpdwBufferLength
= len
;
483 TRACE("%d <--\n", bSuccess
);
488 /***********************************************************************
489 * HttpSendRequestExA (WININET.@)
491 * Sends the specified request to the HTTP server and allows chunked
494 BOOL WINAPI
HttpSendRequestExA(HINTERNET hRequest
,
495 LPINTERNET_BUFFERSA lpBuffersIn
,
496 LPINTERNET_BUFFERSA lpBuffersOut
,
497 DWORD dwFlags
, DWORD dwContext
)
499 FIXME("(%p, %p, %p, %08lx, %08lx): stub\n", hRequest
, lpBuffersIn
,
500 lpBuffersOut
, dwFlags
, dwContext
);
504 /***********************************************************************
505 * HttpSendRequestA (WININET.@)
507 * Sends the specified request to the HTTP server
514 BOOL WINAPI
HttpSendRequestA(HINTERNET hHttpRequest
, LPCSTR lpszHeaders
,
515 DWORD dwHeaderLength
, LPVOID lpOptional
,DWORD dwOptionalLength
)
517 LPWININETHTTPREQA lpwhr
= (LPWININETHTTPREQA
) hHttpRequest
;
518 LPWININETHTTPSESSIONA lpwhs
= NULL
;
519 LPWININETAPPINFOA hIC
= NULL
;
521 TRACE("0x%08lx\n", (unsigned long)hHttpRequest
);
523 if (NULL
== lpwhr
|| lpwhr
->hdr
.htype
!= WH_HHTTPREQ
)
525 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
529 lpwhs
= (LPWININETHTTPSESSIONA
) lpwhr
->hdr
.lpwhparent
;
530 if (NULL
== lpwhs
|| lpwhs
->hdr
.htype
!= WH_HHTTPSESSION
)
532 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
536 hIC
= (LPWININETAPPINFOA
) lpwhs
->hdr
.lpwhparent
;
537 if (NULL
== hIC
|| hIC
->hdr
.htype
!= WH_HINIT
)
539 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
543 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
545 WORKREQUEST workRequest
;
547 workRequest
.asyncall
= HTTPSENDREQUESTA
;
548 workRequest
.HFTPSESSION
= (DWORD
)hHttpRequest
;
549 workRequest
.LPSZHEADER
= (DWORD
)HTTP_strdup(lpszHeaders
);
550 workRequest
.DWHEADERLENGTH
= dwHeaderLength
;
551 workRequest
.LPOPTIONAL
= (DWORD
)lpOptional
;
552 workRequest
.DWOPTIONALLENGTH
= dwOptionalLength
;
554 return INTERNET_AsyncCall(&workRequest
);
558 return HTTP_HttpSendRequestA(hHttpRequest
, lpszHeaders
,
559 dwHeaderLength
, lpOptional
, dwOptionalLength
);
564 /***********************************************************************
565 * HTTP_HttpSendRequestA (internal)
567 * Sends the specified request to the HTTP server
574 BOOL WINAPI
HTTP_HttpSendRequestA(HINTERNET hHttpRequest
, LPCSTR lpszHeaders
,
575 DWORD dwHeaderLength
, LPVOID lpOptional
,DWORD dwOptionalLength
)
579 BOOL bSuccess
= FALSE
;
580 LPSTR requestString
= NULL
;
581 INT requestStringLen
;
582 INT headerLength
= 0;
583 LPWININETHTTPREQA lpwhr
= (LPWININETHTTPREQA
) hHttpRequest
;
584 LPWININETHTTPSESSIONA lpwhs
= NULL
;
585 LPWININETAPPINFOA hIC
= NULL
;
587 TRACE("0x%08lx\n", (ULONG
)hHttpRequest
);
589 /* Verify our tree of internet handles */
590 if (NULL
== lpwhr
|| lpwhr
->hdr
.htype
!= WH_HHTTPREQ
)
592 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
596 lpwhs
= (LPWININETHTTPSESSIONA
) lpwhr
->hdr
.lpwhparent
;
597 if (NULL
== lpwhs
|| lpwhs
->hdr
.htype
!= WH_HHTTPSESSION
)
599 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
603 hIC
= (LPWININETAPPINFOA
) lpwhs
->hdr
.lpwhparent
;
604 if (NULL
== hIC
|| hIC
->hdr
.htype
!= WH_HINIT
)
606 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
610 /* Clear any error information */
611 INTERNET_SetLastError(0);
613 /* We must have a verb */
614 if (NULL
== lpwhr
->lpszVerb
)
619 /* If we don't have a path we set it to root */
620 if (NULL
== lpwhr
->lpszPath
)
621 lpwhr
->lpszPath
= HTTP_strdup("/");
623 if(lpwhr
->lpszPath
[0] != '/') /* not an absolute path ?? --> fix it !! */
625 char *fixurl
= HeapAlloc(GetProcessHeap(), 0, strlen(lpwhr
->lpszPath
) + 2);
627 strcpy(fixurl
+ 1, lpwhr
->lpszPath
);
628 HeapFree( GetProcessHeap(), 0, lpwhr
->lpszPath
);
629 lpwhr
->lpszPath
= fixurl
;
632 /* Calculate length of request string */
634 strlen(lpwhr
->lpszVerb
) +
635 strlen(lpwhr
->lpszPath
) +
636 (lpwhr
->lpszHostName
? (strlen(HTTPHOSTHEADER
) + strlen(lpwhr
->lpszHostName
)) : 0) +
640 /* Add length of passed headers */
643 headerLength
= -1 == dwHeaderLength
? strlen(lpszHeaders
) : dwHeaderLength
;
644 requestStringLen
+= headerLength
+ 2; /* \r\n */
647 /* Calculate length of custom request headers */
648 for (i
= 0; i
< lpwhr
->nCustHeaders
; i
++)
650 if (lpwhr
->pCustHeaders
[i
].wFlags
& HDR_ISREQUEST
)
652 requestStringLen
+= strlen(lpwhr
->pCustHeaders
[i
].lpszField
) +
653 strlen(lpwhr
->pCustHeaders
[i
].lpszValue
) + 4; /*: \r\n */
657 /* Calculate the length of standard request headers */
658 for (i
= 0; i
<= HTTP_QUERY_MAX
; i
++)
660 if (lpwhr
->StdHeaders
[i
].wFlags
& HDR_ISREQUEST
)
662 requestStringLen
+= strlen(lpwhr
->StdHeaders
[i
].lpszField
) +
663 strlen(lpwhr
->StdHeaders
[i
].lpszValue
) + 4; /*: \r\n */
667 /* Allocate string to hold entire request */
668 requestString
= HeapAlloc(GetProcessHeap(), 0, requestStringLen
+ 1);
669 if (NULL
== requestString
)
671 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
675 /* Build request string */
676 cnt
= sprintf(requestString
, "%s %s%s%s",
679 lpwhr
->lpszHostName
? (HTTPHEADER HTTPHOSTHEADER
) : HTTPHEADER
,
680 lpwhr
->lpszHostName
? lpwhr
->lpszHostName
: "");
682 /* Append standard request headers */
683 for (i
= 0; i
<= HTTP_QUERY_MAX
; i
++)
685 if (lpwhr
->StdHeaders
[i
].wFlags
& HDR_ISREQUEST
)
687 cnt
+= sprintf(requestString
+ cnt
, "\r\n%s: %s",
688 lpwhr
->StdHeaders
[i
].lpszField
, lpwhr
->StdHeaders
[i
].lpszValue
);
692 /* Append custom request heades */
693 for (i
= 0; i
< lpwhr
->nCustHeaders
; i
++)
695 if (lpwhr
->pCustHeaders
[i
].wFlags
& HDR_ISREQUEST
)
697 cnt
+= sprintf(requestString
+ cnt
, "\r\n%s: %s",
698 lpwhr
->pCustHeaders
[i
].lpszField
, lpwhr
->pCustHeaders
[i
].lpszValue
);
702 /* Append passed request headers */
705 strcpy(requestString
+ cnt
, "\r\n");
707 strcpy(requestString
+ cnt
, lpszHeaders
);
711 /* Set termination string for request */
712 strcpy(requestString
+ cnt
, "\r\n\r\n");
714 if (hIC
->lpfnStatusCB
)
715 hIC
->lpfnStatusCB(hHttpRequest
, lpwhr
->hdr
.dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
717 TRACE("(%s) len(%d)\n", requestString
, requestStringLen
);
718 /* Send the request and store the results */
719 if (!HTTP_OpenConnection(lpwhr
))
722 cnt
= INTERNET_WriteDataToStream(lpwhr
->nSocketFD
, requestString
, requestStringLen
);
727 if (HTTP_GetResponseHeaders(lpwhr
))
733 HeapFree(GetProcessHeap(), 0, requestString
);
735 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
737 INTERNET_ASYNC_RESULT iar
;
739 iar
.dwResult
= (DWORD
)bSuccess
;
740 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
741 hIC
->lpfnStatusCB(hHttpRequest
, lpwhr
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
742 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
750 /***********************************************************************
751 * HTTP_Connect (internal)
753 * Create http session handle
756 * HINTERNET a session handle on success
760 HINTERNET
HTTP_Connect(HINTERNET hInternet
, LPCSTR lpszServerName
,
761 INTERNET_PORT nServerPort
, LPCSTR lpszUserName
,
762 LPCSTR lpszPassword
, DWORD dwFlags
, DWORD dwContext
)
764 BOOL bSuccess
= FALSE
;
765 LPWININETAPPINFOA hIC
= NULL
;
766 LPWININETHTTPSESSIONA lpwhs
= NULL
;
770 if (((LPWININETHANDLEHEADER
)hInternet
)->htype
!= WH_HINIT
)
773 hIC
= (LPWININETAPPINFOA
) hInternet
;
775 lpwhs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WININETHTTPSESSIONA
));
778 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
782 if (hIC
->lpfnStatusCB
)
783 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_RESOLVING_NAME
,
784 (LPVOID
)lpszServerName
, strlen(lpszServerName
));
786 if (nServerPort
== INTERNET_INVALID_PORT_NUMBER
)
787 nServerPort
= INTERNET_DEFAULT_HTTP_PORT
;
789 if (!GetAddress(lpszServerName
, nServerPort
, &lpwhs
->phostent
, &lpwhs
->socketAddress
))
791 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED
);
795 if (hIC
->lpfnStatusCB
)
796 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_NAME_RESOLVED
,
797 (LPVOID
)lpszServerName
, strlen(lpszServerName
));
799 lpwhs
->hdr
.htype
= WH_HHTTPSESSION
;
800 lpwhs
->hdr
.lpwhparent
= (LPWININETHANDLEHEADER
)hInternet
;
801 lpwhs
->hdr
.dwFlags
= dwFlags
;
802 lpwhs
->hdr
.dwContext
= dwContext
;
803 if (NULL
!= lpszServerName
)
804 lpwhs
->lpszServerName
= HTTP_strdup(lpszServerName
);
805 if (NULL
!= lpszUserName
)
806 lpwhs
->lpszUserName
= HTTP_strdup(lpszUserName
);
807 lpwhs
->nServerPort
= nServerPort
;
809 if (hIC
->lpfnStatusCB
)
811 INTERNET_ASYNC_RESULT iar
;
813 iar
.dwResult
= (DWORD
)lpwhs
;
814 iar
.dwError
= ERROR_SUCCESS
;
816 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
817 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
823 if (!bSuccess
&& lpwhs
)
825 HeapFree(GetProcessHeap(), 0, lpwhs
);
829 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
831 INTERNET_ASYNC_RESULT iar
;
833 iar
.dwResult
= (DWORD
)lpwhs
;
834 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
835 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
836 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
839 return (HINTERNET
)lpwhs
;
843 /***********************************************************************
844 * HTTP_OpenConnection (internal)
846 * Connect to a web server
853 BOOL
HTTP_OpenConnection(LPWININETHTTPREQA lpwhr
)
855 BOOL bSuccess
= FALSE
;
857 LPWININETHTTPSESSIONA lpwhs
;
861 if (NULL
== lpwhr
|| lpwhr
->hdr
.htype
!= WH_HHTTPREQ
)
863 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
867 lpwhs
= (LPWININETHTTPSESSIONA
)lpwhr
->hdr
.lpwhparent
;
869 lpwhr
->nSocketFD
= socket(lpwhs
->phostent
->h_addrtype
,SOCK_STREAM
,0);
870 if (lpwhr
->nSocketFD
== -1)
872 WARN("Socket creation failed\n");
876 result
= connect(lpwhr
->nSocketFD
, (struct sockaddr
*)&lpwhs
->socketAddress
,
877 sizeof(lpwhs
->socketAddress
));
881 WARN("Unable to connect to host (%s)\n", strerror(errno
));
888 TRACE(": %d\n", bSuccess
);
893 /***********************************************************************
894 * HTTP_GetResponseHeaders (internal)
896 * Read server response
903 BOOL
HTTP_GetResponseHeaders(LPWININETHTTPREQA lpwhr
)
906 CHAR buffer
[MAX_REPLY_LEN
];
907 DWORD buflen
= MAX_REPLY_LEN
;
908 BOOL bSuccess
= FALSE
;
909 CHAR value
[MAX_FIELD_VALUE_LEN
], field
[MAX_FIELD_LEN
];
913 if (lpwhr
->nSocketFD
== -1)
917 * We should first receive 'HTTP/1.x nnn' where nnn is the status code.
919 if (!INTERNET_GetNextLine(lpwhr
->nSocketFD
, buffer
, &buflen
))
922 if (strncmp(buffer
, "HTTP", 4) != 0)
926 HTTP_ProcessHeader(lpwhr
, "Status", buffer
+9, (HTTP_ADDREQ_FLAG_ADD
| HTTP_ADDREQ_FLAG_REPLACE
));
928 /* Parse each response line */
931 buflen
= MAX_REPLY_LEN
;
932 if (INTERNET_GetNextLine(lpwhr
->nSocketFD
, buffer
, &buflen
))
934 if (!HTTP_InterpretHttpHeader(buffer
, field
, MAX_FIELD_LEN
, value
, MAX_FIELD_VALUE_LEN
))
937 HTTP_ProcessHeader(lpwhr
, field
, value
, (HTTP_ADDREQ_FLAG_ADD
| HTTP_ADDREQ_FLAG_REPLACE
));
955 /***********************************************************************
956 * HTTP_InterpretHttpHeader (internal)
958 * Parse server response
965 INT
stripSpaces(LPCSTR lpszSrc
, LPSTR lpszStart
, INT
*len
)
972 while (*lpszSrc
== ' ' && *lpszSrc
!= '\0')
976 while(*lpsztmp
!= '\0')
979 srclen
= lpsztmp
- lpszSrc
+ 1;
984 *len
= min(*len
, srclen
);
985 strncpy(lpszStart
, lpszSrc
, *len
);
986 lpszStart
[*len
] = '\0';
992 BOOL
HTTP_InterpretHttpHeader(LPSTR buffer
, LPSTR field
, INT fieldlen
, LPSTR value
, INT valuelen
)
995 BOOL bSuccess
= FALSE
;
1002 pd
= strchr(buffer
, ':');
1006 if (stripSpaces(buffer
, field
, &fieldlen
) > 0)
1008 if (stripSpaces(pd
+1, value
, &valuelen
) > 0)
1013 TRACE("%d: field(%s) Value(%s)\n", bSuccess
, field
, value
);
1018 /***********************************************************************
1019 * HTTP_GetStdHeaderIndex (internal)
1021 * Lookup field index in standard http header array
1023 * FIXME: This should be stuffed into a hash table
1025 INT
HTTP_GetStdHeaderIndex(LPCSTR lpszField
)
1029 if (!strcasecmp(lpszField
, "Content-Length"))
1030 index
= HTTP_QUERY_CONTENT_LENGTH
;
1031 else if (!strcasecmp(lpszField
,"Status"))
1032 index
= HTTP_QUERY_STATUS_CODE
;
1033 else if (!strcasecmp(lpszField
,"Content-Type"))
1034 index
= HTTP_QUERY_CONTENT_TYPE
;
1035 else if (!strcasecmp(lpszField
,"Last-Modified"))
1036 index
= HTTP_QUERY_LAST_MODIFIED
;
1037 else if (!strcasecmp(lpszField
,"Location"))
1038 index
= HTTP_QUERY_LOCATION
;
1039 else if (!strcasecmp(lpszField
,"Accept"))
1040 index
= HTTP_QUERY_ACCEPT
;
1041 else if (!strcasecmp(lpszField
,"Referer"))
1042 index
= HTTP_QUERY_REFERER
;
1043 else if (!strcasecmp(lpszField
,"Content-Transfer-Encoding"))
1044 index
= HTTP_QUERY_CONTENT_TRANSFER_ENCODING
;
1045 else if (!strcasecmp(lpszField
,"Date"))
1046 index
= HTTP_QUERY_DATE
;
1047 else if (!strcasecmp(lpszField
,"Server"))
1048 index
= HTTP_QUERY_SERVER
;
1049 else if (!strcasecmp(lpszField
,"Connection"))
1050 index
= HTTP_QUERY_CONNECTION
;
1051 else if (!strcasecmp(lpszField
,"ETag"))
1052 index
= HTTP_QUERY_ETAG
;
1053 else if (!strcasecmp(lpszField
,"Accept-Ranges"))
1054 index
= HTTP_QUERY_ACCEPT_RANGES
;
1055 else if (!strcasecmp(lpszField
,"Expires"))
1056 index
= HTTP_QUERY_EXPIRES
;
1057 else if (!strcasecmp(lpszField
,"Mime-Version"))
1058 index
= HTTP_QUERY_MIME_VERSION
;
1059 else if (!strcasecmp(lpszField
,"Pragma"))
1060 index
= HTTP_QUERY_PRAGMA
;
1061 else if (!strcasecmp(lpszField
,"Cache-Control"))
1062 index
= HTTP_QUERY_CACHE_CONTROL
;
1063 else if (!strcasecmp(lpszField
,"Content-Length"))
1064 index
= HTTP_QUERY_CONTENT_LENGTH
;
1065 else if (!strcasecmp(lpszField
,"User-Agent"))
1066 index
= HTTP_QUERY_USER_AGENT
;
1069 FIXME("Couldn't find %s in standard header table\n", lpszField
);
1076 /***********************************************************************
1077 * HTTP_ProcessHeader (internal)
1079 * Stuff header into header tables according to <dwModifier>
1083 #define COALESCEFLASG (HTTP_ADDHDR_FLAG_COALESCE|HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA|HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
1085 BOOL
HTTP_ProcessHeader(LPWININETHTTPREQA lpwhr
, LPCSTR field
, LPCSTR value
, DWORD dwModifier
)
1087 LPHTTPHEADERA lphttpHdr
= NULL
;
1088 BOOL bSuccess
= FALSE
;
1091 TRACE("%s:%s - 0x%08x\n", field
, value
, (unsigned int)dwModifier
);
1093 /* Adjust modifier flags */
1094 if (dwModifier
& COALESCEFLASG
)
1095 dwModifier
|= HTTP_ADDHDR_FLAG_ADD
;
1097 /* Try to get index into standard header array */
1098 index
= HTTP_GetStdHeaderIndex(field
);
1101 lphttpHdr
= &lpwhr
->StdHeaders
[index
];
1103 else /* Find or create new custom header */
1105 index
= HTTP_GetCustomHeaderIndex(lpwhr
, field
);
1108 if (dwModifier
& HTTP_ADDHDR_FLAG_ADD_IF_NEW
)
1112 lphttpHdr
= &lpwhr
->pCustHeaders
[index
];
1118 hdr
.lpszField
= (LPSTR
)field
;
1119 hdr
.lpszValue
= (LPSTR
)value
;
1120 hdr
.wFlags
= hdr
.wCount
= 0;
1122 if (dwModifier
& HTTP_ADDHDR_FLAG_REQ
)
1123 hdr
.wFlags
|= HDR_ISREQUEST
;
1125 index
= HTTP_InsertCustomHeader(lpwhr
, &hdr
);
1130 if (dwModifier
& HTTP_ADDHDR_FLAG_REQ
)
1131 lphttpHdr
->wFlags
|= HDR_ISREQUEST
;
1133 lphttpHdr
->wFlags
&= ~HDR_ISREQUEST
;
1135 if (!lphttpHdr
->lpszValue
&& (dwModifier
& (HTTP_ADDHDR_FLAG_ADD
|HTTP_ADDHDR_FLAG_ADD_IF_NEW
)))
1139 if (!lpwhr
->StdHeaders
[index
].lpszField
)
1141 lphttpHdr
->lpszField
= HTTP_strdup(field
);
1143 if (dwModifier
& HTTP_ADDHDR_FLAG_REQ
)
1144 lphttpHdr
->wFlags
|= HDR_ISREQUEST
;
1147 slen
= strlen(value
) + 1;
1148 lphttpHdr
->lpszValue
= HeapAlloc(GetProcessHeap(), 0, slen
);
1149 if (lphttpHdr
->lpszValue
)
1151 memcpy(lphttpHdr
->lpszValue
, value
, slen
);
1156 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1159 else if (lphttpHdr
->lpszValue
)
1161 if (dwModifier
& HTTP_ADDHDR_FLAG_REPLACE
)
1166 len
= strlen(value
);
1170 //! if custom header delete from array
1171 HeapFree(GetProcessHeap(), 0, lphttpHdr
->lpszValue
);
1172 lphttpHdr
->lpszValue
= NULL
;
1177 lpsztmp
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, lphttpHdr
->lpszValue
, len
+1);
1180 lphttpHdr
->lpszValue
= lpsztmp
;
1181 strcpy(lpsztmp
, value
);
1186 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1190 else if (dwModifier
& COALESCEFLASG
)
1195 INT origlen
= strlen(lphttpHdr
->lpszValue
);
1196 INT valuelen
= strlen(value
);
1198 if (dwModifier
& HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA
)
1201 lphttpHdr
->wFlags
|= HDR_COMMADELIMITED
;
1203 else if (dwModifier
& HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON
)
1206 lphttpHdr
->wFlags
|= HDR_COMMADELIMITED
;
1209 len
= origlen
+ valuelen
+ (ch
> 0) ? 1 : 0;
1211 lpsztmp
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, lphttpHdr
->lpszValue
, len
+1);
1214 /* FIXME: Increment lphttpHdr->wCount. Perhaps lpszValue should be an array */
1217 lphttpHdr
->lpszValue
[origlen
] = ch
;
1221 memcpy(&lphttpHdr
->lpszValue
[origlen
], value
, valuelen
);
1222 lphttpHdr
->lpszValue
[len
] = '\0';
1227 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1236 /***********************************************************************
1237 * HTTP_CloseConnection (internal)
1239 * Close socket connection
1242 VOID
HTTP_CloseConnection(LPWININETHTTPREQA lpwhr
)
1244 if (lpwhr
->nSocketFD
!= -1)
1246 close(lpwhr
->nSocketFD
);
1247 lpwhr
->nSocketFD
= -1;
1252 /***********************************************************************
1253 * HTTP_CloseHTTPRequestHandle (internal)
1255 * Deallocate request handle
1258 void HTTP_CloseHTTPRequestHandle(LPWININETHTTPREQA lpwhr
)
1264 if (lpwhr
->nSocketFD
!= -1)
1265 HTTP_CloseConnection(lpwhr
);
1267 if (lpwhr
->lpszPath
)
1268 HeapFree(GetProcessHeap(), 0, lpwhr
->lpszPath
);
1269 if (lpwhr
->lpszVerb
)
1270 HeapFree(GetProcessHeap(), 0, lpwhr
->lpszVerb
);
1271 if (lpwhr
->lpszHostName
)
1272 HeapFree(GetProcessHeap(), 0, lpwhr
->lpszHostName
);
1274 for (i
= 0; i
<= HTTP_QUERY_MAX
; i
++)
1276 if (lpwhr
->StdHeaders
[i
].lpszField
)
1277 HeapFree(GetProcessHeap(), 0, lpwhr
->StdHeaders
[i
].lpszField
);
1278 if (lpwhr
->StdHeaders
[i
].lpszValue
)
1279 HeapFree(GetProcessHeap(), 0, lpwhr
->StdHeaders
[i
].lpszValue
);
1282 for (i
= 0; i
< lpwhr
->nCustHeaders
; i
++)
1284 if (lpwhr
->pCustHeaders
[i
].lpszField
)
1285 HeapFree(GetProcessHeap(), 0, lpwhr
->pCustHeaders
[i
].lpszField
);
1286 if (lpwhr
->pCustHeaders
[i
].lpszValue
)
1287 HeapFree(GetProcessHeap(), 0, lpwhr
->pCustHeaders
[i
].lpszValue
);
1290 HeapFree(GetProcessHeap(), 0, lpwhr
->pCustHeaders
);
1291 HeapFree(GetProcessHeap(), 0, lpwhr
);
1295 /***********************************************************************
1296 * HTTP_CloseHTTPSessionHandle (internal)
1298 * Deallocate session handle
1301 void HTTP_CloseHTTPSessionHandle(LPWININETHTTPSESSIONA lpwhs
)
1305 if (lpwhs
->lpszServerName
)
1306 HeapFree(GetProcessHeap(), 0, lpwhs
->lpszServerName
);
1307 if (lpwhs
->lpszUserName
)
1308 HeapFree(GetProcessHeap(), 0, lpwhs
->lpszUserName
);
1309 HeapFree(GetProcessHeap(), 0, lpwhs
);
1313 /***********************************************************************
1314 * HTTP_GetCustomHeaderIndex (internal)
1316 * Return index of custom header from header array
1319 INT
HTTP_GetCustomHeaderIndex(LPWININETHTTPREQA lpwhr
, LPCSTR lpszField
)
1323 TRACE("%s\n", lpszField
);
1325 for (index
= 0; index
< lpwhr
->nCustHeaders
; index
++)
1327 if (!strcasecmp(lpwhr
->pCustHeaders
[index
].lpszField
, lpszField
))
1332 if (index
>= lpwhr
->nCustHeaders
)
1335 TRACE("Return: %d\n", index
);
1340 /***********************************************************************
1341 * HTTP_InsertCustomHeader (internal)
1343 * Insert header into array
1346 INT
HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr
, LPHTTPHEADERA lpHdr
)
1349 LPHTTPHEADERA lph
= NULL
;
1351 TRACE("%s: %s\n", lpHdr
->lpszField
, lpHdr
->lpszValue
);
1352 count
= lpwhr
->nCustHeaders
+ 1;
1354 lph
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, lpwhr
->pCustHeaders
, sizeof(HTTPHEADERA
) * count
);
1356 lph
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(HTTPHEADERA
) * count
);
1360 lpwhr
->pCustHeaders
= lph
;
1361 lpwhr
->pCustHeaders
[count
-1].lpszField
= HTTP_strdup(lpHdr
->lpszField
);
1362 lpwhr
->pCustHeaders
[count
-1].lpszValue
= HTTP_strdup(lpHdr
->lpszValue
);
1363 lpwhr
->pCustHeaders
[count
-1].wFlags
= lpHdr
->wFlags
;
1364 lpwhr
->pCustHeaders
[count
-1].wCount
= lpHdr
->wCount
;
1365 lpwhr
->nCustHeaders
++;
1369 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1373 TRACE("%d <--\n", count
-1);
1378 /***********************************************************************
1379 * HTTP_DeleteCustomHeader (internal)
1381 * Delete header from array
1384 BOOL
HTTP_DeleteCustomHeader(INT index
)