Merge of WineX's (LGPL licensed) wininet.dll code

Mike McCormack mike at codeweavers.com
Mon Jun 2 04:43:55 CDT 2003


Hi All,

This patch is based upon wininet.dll code from the WineX CVS.  The 
following work was done by David Hammerton on behalf of Transgamine.

This is mainly untested, so if somebody could try it out or review it, 
that would be great.

thanks,

Mike


ChangeLog:
david at transgaming.com for Transgaming
* implement support for https protocol
* fixes to the http protocol

-------------- next part --------------
Index: configure.ac
===================================================================
RCS file: /home/wine/wine/configure.ac,v
retrieving revision 1.160
diff -u -u -r1.160 configure.ac
--- configure.ac	21 May 2003 18:50:53 -0000	1.160
+++ configure.ac	2 Jun 2003 09:31:51 -0000
@@ -161,6 +161,9 @@
                       [AC_DEFINE(HAVE_LIBGIF,1)
                        GIFLIB="-lgif"])]))
 
+AC_CHECK_HEADERS(openssl/ssl.h,
+        AC_DEFINE(HAVE_OPENSSL,1,[Define if you have OpenSSL headers])
+)
 
 AC_SUBST(XLIB)
 AC_SUBST(XFILES)
@@ -890,6 +893,8 @@
   WINE_GET_SONAME(GL,glXQueryExtension,[$X_LIBS $X_EXTRA_LIBS])
   WINE_GET_SONAME(cups,cupsGetDefault)
   WINE_GET_SONAME(jack,jack_client_new)
+  WINE_GET_SONAME(ssl, SSL_library_init);
+  WINE_GET_SONAME(crypto, BIO_new_socket);
 fi
 
 
Index: dlls/wininet/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/wininet/Makefile.in,v
retrieving revision 1.20
diff -u -u -r1.20 Makefile.in
--- dlls/wininet/Makefile.in	14 Apr 2003 21:32:36 -0000	1.20
+++ dlls/wininet/Makefile.in	2 Jun 2003 09:31:51 -0000
@@ -11,9 +11,11 @@
 SYMBOLFILE = $(MODULE).tmp.o
 
 C_SRCS = \
+	cookie.c \
 	ftp.c \
 	http.c \
 	internet.c \
+	netconnection.c \
 	urlcache.c \
 	utility.c \
 	wininet_main.c
Index: dlls/wininet/http.c
===================================================================
RCS file: /home/wine/wine/dlls/wininet/http.c,v
retrieving revision 1.35
diff -u -u -r1.35 http.c
--- dlls/wininet/http.c	16 May 2003 20:12:03 -0000	1.35
+++ dlls/wininet/http.c	2 Jun 2003 09:31:52 -0000
@@ -3,9 +3,11 @@
  *
  * Copyright 1999 Corel Corporation
  * Copyright 2002 CodeWeavers Inc.
+ * Copyright 2002 TransGaming Technologies Inc.
  *
  * Ulrich Czekalla
  * Aric Stewart
+ * David Hammerton
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -62,20 +64,20 @@
 #define HTTP_ACCEPT     "Accept"
 #define HTTP_USERAGENT  "User-Agent"
 
-#define HTTP_ADDHDR_FLAG_ADD				0x20000000
-#define HTTP_ADDHDR_FLAG_ADD_IF_NEW			0x10000000
-#define HTTP_ADDHDR_FLAG_COALESCE			0x40000000
-#define HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA		0x40000000
-#define HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON	0x01000000
-#define HTTP_ADDHDR_FLAG_REPLACE			0x80000000
-#define HTTP_ADDHDR_FLAG_REQ				0x02000000
+#define HTTP_ADDHDR_FLAG_ADD                                0x20000000
+#define HTTP_ADDHDR_FLAG_ADD_IF_NEW                        0x10000000
+#define HTTP_ADDHDR_FLAG_COALESCE                        0x40000000
+#define HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA                0x40000000
+#define HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON        0x01000000
+#define HTTP_ADDHDR_FLAG_REPLACE                        0x80000000
+#define HTTP_ADDHDR_FLAG_REQ                                0x02000000
 
 
 BOOL HTTP_OpenConnection(LPWININETHTTPREQA lpwhr);
 int HTTP_WriteDataToStream(LPWININETHTTPREQA lpwhr,
-	void *Buffer, int BytesToWrite);
+        void *Buffer, int BytesToWrite);
 int HTTP_ReadDataFromStream(LPWININETHTTPREQA lpwhr,
-	void *Buffer, int BytesToRead);
+        void *Buffer, int BytesToRead);
 BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQA lpwhr);
 BOOL HTTP_ProcessHeader(LPWININETHTTPREQA lpwhr, LPCSTR field, LPCSTR value, DWORD dwModifier);
 void HTTP_CloseConnection(LPWININETHTTPREQA lpwhr);
@@ -102,7 +104,7 @@
  *
  */
 BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest,
-	LPCSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
+        LPCSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
 {
     LPSTR lpszStart;
     LPSTR lpszEnd;
@@ -111,7 +113,9 @@
     BOOL bSuccess = FALSE;
     LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hHttpRequest;
 
-    TRACE("\n");
+    TRACE("%p, %s, %li, %li\n", hHttpRequest, lpszHeader, dwHeaderLength,
+          dwModifier);
+
 
     if (NULL == lpwhr ||  lpwhr->hdr.htype != WH_HHTTPREQ)
     {
@@ -120,7 +124,9 @@
     }
 
     if (!lpszHeader) 
-      return TRUE;
+        return TRUE;
+
+    TRACE("copying header: %s\n", lpszHeader);
     buffer = HTTP_strdup(lpszHeader);
     lpszStart = buffer;
 
@@ -136,10 +142,11 @@
         }
 
         if (*lpszEnd == '\0')
-	    break;
+            break;
 
         *lpszEnd = '\0';
 
+        TRACE("interpreting header %s\n", debugstr_a(lpszStart));
         if (HTTP_InterpretHttpHeader(lpszStart, field, MAX_FIELD_LEN, value, MAX_FIELD_VALUE_LEN))
             bSuccess = HTTP_ProcessHeader(lpwhr, field, value, dwModifier | HTTP_ADDHDR_FLAG_REQ);
 
@@ -157,8 +164,8 @@
  * Ends an HTTP request that was started by HttpSendRequestEx
  *
  * RETURNS
- *    TRUE	if successful
- *    FALSE	on failure
+ *    TRUE        if successful
+ *    FALSE        on failure
  *
  */
 BOOL WINAPI HttpEndRequestA(HINTERNET hRequest, LPINTERNET_BUFFERSA lpBuffersOut, 
@@ -174,8 +181,8 @@
  * Ends an HTTP request that was started by HttpSendRequestEx
  *
  * RETURNS
- *    TRUE	if successful
- *    FALSE	on failure
+ *    TRUE        if successful
+ *    FALSE        on failure
  *
  */
 BOOL WINAPI HttpEndRequestW(HINTERNET hRequest, LPINTERNET_BUFFERSW lpBuffersOut, 
@@ -192,29 +199,32 @@
  *
  * RETURNS
  *    HINTERNET  a HTTP request handle on success
- *    NULL 	 on failure
+ *    NULL          on failure
  *
  */
 HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession,
-	LPCSTR lpszVerb, LPCSTR lpszObjectName, LPCSTR lpszVersion,
-	LPCSTR lpszReferrer , LPCSTR *lpszAcceptTypes,
-	DWORD dwFlags, DWORD dwContext)
+        LPCSTR lpszVerb, LPCSTR lpszObjectName, LPCSTR lpszVersion,
+        LPCSTR lpszReferrer , LPCSTR *lpszAcceptTypes,
+        DWORD dwFlags, DWORD dwContext)
 {
     LPWININETHTTPSESSIONA lpwhs = (LPWININETHTTPSESSIONA) hHttpSession;
     LPWININETAPPINFOA hIC = NULL;
 
-    TRACE("(%s, %s, %s, %s, %ld, %ld)\n", lpszVerb, lpszObjectName, lpszVersion, lpszReferrer, dwFlags, dwContext);
+    TRACE("(%p, %s, %s, %s, %s, %p, %08lx, %08lx)\n", hHttpSession,
+          debugstr_a(lpszVerb), lpszObjectName,
+          debugstr_a(lpszVersion), debugstr_a(lpszReferrer), lpszAcceptTypes,
+          dwFlags, dwContext);
     if(lpszAcceptTypes!=NULL)
     {
         int i;
         for(i=0;lpszAcceptTypes[i]!=NULL;i++)
             TRACE("\taccept type: %s\n",lpszAcceptTypes[i]);
     }    
-
+ 
     if (NULL == lpwhs ||  lpwhs->hdr.htype != WH_HHTTPSESSION)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
+        return FALSE;
     }
     hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent;
 
@@ -232,10 +242,10 @@
     {
         WORKREQUEST workRequest;
 
-	workRequest.asyncall = HTTPOPENREQUESTA;
-	workRequest.HFTPSESSION = (DWORD)hHttpSession;
-	workRequest.LPSZVERB = (DWORD)HTTP_strdup(lpszVerb);
-	workRequest.LPSZOBJECTNAME = (DWORD)HTTP_strdup(lpszObjectName);
+        workRequest.asyncall = HTTPOPENREQUESTA;
+        workRequest.HFTPSESSION = (DWORD)hHttpSession;
+        workRequest.LPSZVERB = (DWORD)HTTP_strdup(lpszVerb);
+        workRequest.LPSZOBJECTNAME = (DWORD)HTTP_strdup(lpszObjectName);
         if (lpszVersion)
             workRequest.LPSZVERSION = (DWORD)HTTP_strdup(lpszVersion);
         else
@@ -244,20 +254,25 @@
             workRequest.LPSZREFERRER = (DWORD)HTTP_strdup(lpszReferrer);
         else
             workRequest.LPSZREFERRER = 0;
-	workRequest.LPSZACCEPTTYPES = (DWORD)lpszAcceptTypes;
-	workRequest.DWFLAGS = dwFlags;
-	workRequest.DWCONTEXT = dwContext;
+        workRequest.LPSZACCEPTTYPES = (DWORD)lpszAcceptTypes;
+        workRequest.DWFLAGS = dwFlags;
+        workRequest.DWCONTEXT = dwContext;
 
         INTERNET_AsyncCall(&workRequest);
+        TRACE ("returning NULL\n");
         return NULL;
     }
     else
     {
-	return HTTP_HttpOpenRequestA(hHttpSession, lpszVerb, lpszObjectName,
-		lpszVersion, lpszReferrer, lpszAcceptTypes, dwFlags, dwContext);
+        HINTERNET rec = HTTP_HttpOpenRequestA(hHttpSession, lpszVerb, lpszObjectName,
+                                              lpszVersion, lpszReferrer, lpszAcceptTypes,
+                                              dwFlags, dwContext);
+        TRACE("returning %p\n", rec);
+        return rec;
     }
 }
 
+
 /***********************************************************************
  *           HttpOpenRequestW (WININET.@)
  *
@@ -267,27 +282,95 @@
  *    HINTERNET  a HTTP request handle on success
  *    NULL 	 on failure
  *
+ * FIXME: This should be the other way around (A should call W)
  */
 HINTERNET WINAPI HttpOpenRequestW(HINTERNET hHttpSession,
-	LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
-	LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
-	DWORD dwFlags, DWORD dwContext)
-{
-    char szVerb[20],
-         szObjectName[INTERNET_MAX_PATH_LENGTH];
-    TRACE("(%s, %s, %s, %s, %ld, %ld)\n", debugstr_w(lpszVerb), debugstr_w(lpszObjectName), debugstr_w(lpszVersion), debugstr_w(lpszReferrer), dwFlags, dwContext);
+        LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
+        LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
+        DWORD dwFlags, DWORD dwContext)
+{
+    CHAR *szVerb = NULL, *szObjectName = NULL;
+    CHAR *szVersion = NULL, *szReferrer = NULL, **szAcceptTypes = NULL;
+    INT len;
+    INT acceptTypesCount;
+    HINTERNET rc = FALSE;
+    TRACE("(%p, %s, %s, %s, %s, %p, %08lx, %08lx)\n", hHttpSession,
+          debugstr_w(lpszVerb), debugstr_w(lpszObjectName),
+          debugstr_w(lpszVersion), debugstr_w(lpszReferrer), lpszAcceptTypes,
+          dwFlags, dwContext);
 
-    if(lpszVerb!=NULL)
-        WideCharToMultiByte(CP_ACP,0,lpszVerb,-1,szVerb,20,NULL,NULL);
-    else
-        szVerb[0]=0;
-    if(lpszObjectName!=NULL)
-        WideCharToMultiByte(CP_ACP,0,lpszObjectName,-1,szObjectName,INTERNET_MAX_PATH_LENGTH,NULL,NULL);
-    else
-        szObjectName[0]=0;
-    TRACE("object name=%s\n",szObjectName);
-    FIXME("lpszVersion, lpszReferrer and lpszAcceptTypes ignored\n");
-    return HttpOpenRequestA(hHttpSession, szVerb[0]?szVerb:NULL, szObjectName, NULL, NULL, NULL, dwFlags, dwContext);
+    if (lpszVerb)
+    {
+        len = lstrlenW(lpszVerb)+1;
+        if (!(szVerb = (CHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(CHAR))))
+            goto end;
+        WideCharToMultiByte(CP_ACP, -1, lpszVerb, -1, szVerb, len, NULL, NULL);
+    }
+
+    if (lpszObjectName)
+    {
+        len = lstrlenW(lpszObjectName)+1;
+        if (!(szObjectName = (CHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(CHAR))))
+            goto end;
+        WideCharToMultiByte(CP_ACP, -1, lpszObjectName, -1, szObjectName, len, NULL, NULL);
+    }
+
+    if (lpszVersion)
+    {
+        len = lstrlenW(lpszVersion)+1;
+        if (!(szVersion = (CHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(CHAR))))
+            goto end;
+        WideCharToMultiByte(CP_ACP, -1, lpszVersion, -1, szVersion, len, NULL, NULL);
+    }
+
+    if (lpszReferrer)
+    {
+        len = lstrlenW(lpszReferrer)+1;
+        if (!(szReferrer = (CHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(CHAR))))
+            goto end;
+        WideCharToMultiByte(CP_ACP, -1, lpszReferrer, -1, szReferrer, len, NULL, NULL);
+    }
+
+    acceptTypesCount = 0;
+    if (lpszAcceptTypes)
+    {
+        while (lpszAcceptTypes[acceptTypesCount]) { acceptTypesCount++; } /* find out how many there are */
+        szAcceptTypes = HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR *) * acceptTypesCount);
+        acceptTypesCount = 0;
+        while (lpszAcceptTypes[acceptTypesCount])
+        {
+            len = lstrlenW(lpszAcceptTypes[acceptTypesCount])+1;
+            if (!(szAcceptTypes[acceptTypesCount] = (CHAR *) HeapAlloc(GetProcessHeap(),
+                                                                       0, len * sizeof(CHAR))))
+                goto end;
+            WideCharToMultiByte(CP_ACP, -1, lpszAcceptTypes[acceptTypesCount],
+                                -1, szAcceptTypes[acceptTypesCount], len, NULL, NULL);
+            acceptTypesCount++;
+        }
+    }
+    else szAcceptTypes = 0;
+
+    rc = HttpOpenRequestA(hHttpSession, (LPCSTR)szVerb, (LPCSTR)szObjectName,
+                          (LPCSTR)szVersion, (LPCSTR)szReferrer,
+                          (LPCSTR *)szAcceptTypes, dwFlags, dwContext);
+
+end:
+    if (szAcceptTypes)
+    {
+        acceptTypesCount = 0;
+        while (szAcceptTypes[acceptTypesCount])
+        {
+            HeapFree(GetProcessHeap(), 0, szAcceptTypes[acceptTypesCount]);
+            acceptTypesCount++;
+        }
+        HeapFree(GetProcessHeap(), 0, szAcceptTypes);
+    }
+    if (szReferrer) HeapFree(GetProcessHeap(), 0, szReferrer);
+    if (szVersion) HeapFree(GetProcessHeap(), 0, szVersion);
+    if (szObjectName) HeapFree(GetProcessHeap(), 0, szObjectName);
+    if (szVerb) HeapFree(GetProcessHeap(), 0, szVerb);
+
+    return rc;
 }
 
 /***********************************************************************
@@ -297,24 +380,27 @@
  *
  * RETURNS
  *    HINTERNET  a HTTP request handle on success
- *    NULL 	 on failure
+ *    NULL          on failure
  *
  */
 HINTERNET WINAPI HTTP_HttpOpenRequestA(HINTERNET hHttpSession,
-	LPCSTR lpszVerb, LPCSTR lpszObjectName, LPCSTR lpszVersion,
-	LPCSTR lpszReferrer , LPCSTR *lpszAcceptTypes,
-	DWORD dwFlags, DWORD dwContext)
+        LPCSTR lpszVerb, LPCSTR lpszObjectName, LPCSTR lpszVersion,
+        LPCSTR lpszReferrer , LPCSTR *lpszAcceptTypes,
+        DWORD dwFlags, DWORD dwContext)
 {
     LPWININETHTTPSESSIONA lpwhs = (LPWININETHTTPSESSIONA) hHttpSession;
     LPWININETAPPINFOA hIC = NULL;
     LPWININETHTTPREQA lpwhr;
+    LPSTR lpszCookies;
+    LPSTR lpszUrl = NULL;
+    DWORD nCookieSize;
 
     TRACE("--> \n");
 
     if (NULL == lpwhs ||  lpwhs->hdr.htype != WH_HHTTPSESSION)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
+        return FALSE;
     }
 
     hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent;
@@ -330,7 +416,7 @@
     lpwhr->hdr.lpwhparent = hHttpSession;
     lpwhr->hdr.dwFlags = dwFlags;
     lpwhr->hdr.dwContext = dwContext;
-    lpwhr->nSocketFD = -1;
+    NETCON_init(&lpwhr->netConnection, dwFlags & INTERNET_FLAG_SECURE);
 
     if (NULL != lpszObjectName && strlen(lpszObjectName)) {
         DWORD needed = 0;
@@ -348,11 +434,8 @@
         }
     }
 
-    if (NULL != hIC->lpszAgent && strlen(hIC->lpszAgent))
-        HTTP_ProcessHeader(lpwhr, HTTP_USERAGENT, hIC->lpszAgent, HTTP_ADDHDR_FLAG_REQ|HTTP_ADDREQ_FLAG_REPLACE|HTTP_ADDHDR_FLAG_ADD_IF_NEW);
-
     if (NULL != lpszReferrer && strlen(lpszReferrer))
-        HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpszReferrer, HTTP_ADDHDR_FLAG_REQ|HTTP_ADDREQ_FLAG_REPLACE|HTTP_ADDHDR_FLAG_ADD_IF_NEW);
+        HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpszReferrer, HTTP_ADDHDR_FLAG_COALESCE);
 
     if(lpszAcceptTypes!=NULL)
     {
@@ -366,7 +449,7 @@
     else if (strlen(lpszVerb))
         lpwhr->lpszVerb = HTTP_strdup(lpszVerb);
 
-    if (NULL != lpszReferrer)
+    if (NULL != lpszReferrer && strlen(lpszReferrer))
     {
         char buf[MAXHOSTNAME];
         URL_COMPONENTSA UrlComponents;
@@ -420,6 +503,36 @@
         lpwhr->lpszHostName = HTTP_strdup(lpwhs->lpszServerName);
     }
 
+    if (hIC->lpszAgent)
+    {
+        char *agent_header = HeapAlloc(GetProcessHeap(), 0, strlen(hIC->lpszAgent) + 1 + 14);
+        sprintf(agent_header, "User-Agent: %s\r\n", hIC->lpszAgent);
+        HttpAddRequestHeadersA((HINTERNET)lpwhr, agent_header, strlen(agent_header),
+                               HTTP_ADDREQ_FLAG_ADD);
+        HeapFree(GetProcessHeap(), 0, agent_header);
+    }
+
+    lpszUrl = HeapAlloc(GetProcessHeap(), 0, strlen(lpwhr->lpszHostName) + 1 + 7);
+    sprintf(lpszUrl, "http://%s", lpwhr->lpszHostName);
+    if (InternetGetCookieA(lpszUrl, NULL, NULL, &nCookieSize))
+    {
+        int cnt = 0;
+
+        lpszCookies = HeapAlloc(GetProcessHeap(), 0, nCookieSize + 1 + 8);
+
+        cnt += sprintf(lpszCookies, "Cookie: ");
+        InternetGetCookieA(lpszUrl, NULL, lpszCookies + cnt, &nCookieSize);
+        cnt += nCookieSize - 1;
+        sprintf(lpszCookies + cnt, "\r\n");
+
+        HttpAddRequestHeadersA((HINTERNET)lpwhr, lpszCookies, strlen(lpszCookies),
+                               HTTP_ADDREQ_FLAG_ADD);
+        HeapFree(GetProcessHeap(), 0, lpszCookies);
+    }
+    HeapFree(GetProcessHeap(), 0, lpszUrl);
+
+
+
     if (hIC->lpfnStatusCB)
     {
         INTERNET_ASYNC_RESULT iar;
@@ -443,7 +556,6 @@
                       INTERNET_STATUS_RESOLVING_NAME,
                       lpwhs->lpszServerName,
                       strlen(lpwhs->lpszServerName)+1);
-
     if (!GetAddress(lpwhs->lpszServerName, lpwhs->nServerPort,
                     &lpwhs->phostent, &lpwhs->socketAddress))
     {
@@ -472,7 +584,7 @@
  *
  */
 BOOL WINAPI HttpQueryInfoA(HINTERNET hHttpRequest, DWORD dwInfoLevel,
-	LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
+        LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
 {
     LPHTTPHEADERA lphttpHdr = NULL;
     BOOL bSuccess = FALSE;
@@ -510,11 +622,11 @@
            for (i = 0; i < lpwhr->nCustHeaders; i++)
            {
                if ((~lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST) && lpwhr->pCustHeaders[i].lpszField &&
-		   lpwhr->pCustHeaders[i].lpszValue)
-	       {
+                   lpwhr->pCustHeaders[i].lpszValue)
+               {
                   size += strlen(lpwhr->pCustHeaders[i].lpszField) +
                        strlen(lpwhr->pCustHeaders[i].lpszValue) + delim + 2;
-	       }
+               }
            }
 
            /* Calculate the length of stadard request headers */
@@ -540,8 +652,8 @@
            for (i = 0; i <= HTTP_QUERY_MAX; i++)
            {
                if ((~lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST) &&
-					   lpwhr->StdHeaders[i].lpszField &&
-					   lpwhr->StdHeaders[i].lpszValue)
+                                           lpwhr->StdHeaders[i].lpszField &&
+                                           lpwhr->StdHeaders[i].lpszValue)
                {
                    cnt += sprintf((char*)lpBuffer + cnt, "%s: %s%s", lpwhr->StdHeaders[i].lpszField, lpwhr->StdHeaders[i].lpszValue,
                           index == HTTP_QUERY_RAW_HEADERS_CRLF ? "\r\n" : "\0");
@@ -552,12 +664,12 @@
             for (i = 0; i < lpwhr->nCustHeaders; i++)
             {
                 if ((~lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST) &&
-						lpwhr->pCustHeaders[i].lpszField &&
-						lpwhr->pCustHeaders[i].lpszValue)
+                                                lpwhr->pCustHeaders[i].lpszField &&
+                                                lpwhr->pCustHeaders[i].lpszValue)
                 {
                    cnt += sprintf((char*)lpBuffer + cnt, "%s: %s%s",
                     lpwhr->pCustHeaders[i].lpszField, lpwhr->pCustHeaders[i].lpszValue,
-					index == HTTP_QUERY_RAW_HEADERS_CRLF ? "\r\n" : "\0");
+                                        index == HTTP_QUERY_RAW_HEADERS_CRLF ? "\r\n" : "\0");
                 }
             }
 
@@ -565,26 +677,26 @@
 
            *lpdwBufferLength = cnt + delim;
            bSuccess = TRUE;
-	        goto lend;
+                goto lend;
+        }
+        else if (index >= 0 && index <= HTTP_QUERY_MAX && lpwhr->StdHeaders[index].lpszValue)
+        {
+            lphttpHdr = &lpwhr->StdHeaders[index];
         }
-	else if (index >= 0 && index <= HTTP_QUERY_MAX && lpwhr->StdHeaders[index].lpszValue)
-	{
-	    lphttpHdr = &lpwhr->StdHeaders[index];
-	}
-	else
+        else
             goto lend;
     }
 
     /* Ensure header satisifies requested attributes */
     if ((dwInfoLevel & HTTP_QUERY_FLAG_REQUEST_HEADERS) &&
-	    (~lphttpHdr->wFlags & HDR_ISREQUEST))
-	goto lend;
+            (~lphttpHdr->wFlags & HDR_ISREQUEST))
+        goto lend;
 
     /* coalesce value to reuqested type */
     if (dwInfoLevel & HTTP_QUERY_FLAG_NUMBER)
     {
        *(int *)lpBuffer = atoi(lphttpHdr->lpszValue);
-	   bSuccess = TRUE;
+           bSuccess = TRUE;
     }
     else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME)
     {
@@ -599,28 +711,28 @@
         if(STHook==NULL)
             goto lend;
 
-	    STHook->wDay = tmpTM.tm_mday;
-	    STHook->wHour = tmpTM.tm_hour;
-	    STHook->wMilliseconds = 0;
-	    STHook->wMinute = tmpTM.tm_min;
-	    STHook->wDayOfWeek = tmpTM.tm_wday;
-	    STHook->wMonth = tmpTM.tm_mon + 1;
-	    STHook->wSecond = tmpTM.tm_sec;
-	    STHook->wYear = tmpTM.tm_year;
+            STHook->wDay = tmpTM.tm_mday;
+            STHook->wHour = tmpTM.tm_hour;
+            STHook->wMilliseconds = 0;
+            STHook->wMinute = tmpTM.tm_min;
+            STHook->wDayOfWeek = tmpTM.tm_wday;
+            STHook->wMonth = tmpTM.tm_mon + 1;
+            STHook->wSecond = tmpTM.tm_sec;
+            STHook->wYear = tmpTM.tm_year;
 
-	    bSuccess = TRUE;
+            bSuccess = TRUE;
     }
     else if (dwInfoLevel & HTTP_QUERY_FLAG_COALESCE)
     {
-	    if (*lpdwIndex >= lphttpHdr->wCount)
-		{
-	        INTERNET_SetLastError(ERROR_HTTP_HEADER_NOT_FOUND);
-		}
-	    else
-	    {
-	    /* Copy strncpy(lpBuffer, lphttpHdr[*lpdwIndex], len); */
+            if (*lpdwIndex >= lphttpHdr->wCount)
+                {
+                INTERNET_SetLastError(ERROR_HTTP_HEADER_NOT_FOUND);
+                }
+            else
+            {
+            /* Copy strncpy(lpBuffer, lphttpHdr[*lpdwIndex], len); */
             (*lpdwIndex)++;
-	    }
+            }
     }
     else
     {
@@ -655,7 +767,7 @@
  *
  */
 BOOL WINAPI HttpQueryInfoW(HINTERNET hHttpRequest, DWORD dwInfoLevel,
-	LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
+        LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
 {
     BOOL result;
     DWORD charLen=*lpdwBufferLength;
@@ -682,12 +794,12 @@
  * transfers
  */
 BOOL WINAPI HttpSendRequestExA(HINTERNET hRequest,
-			       LPINTERNET_BUFFERSA lpBuffersIn,
-			       LPINTERNET_BUFFERSA lpBuffersOut,
-			       DWORD dwFlags, DWORD dwContext)
+                               LPINTERNET_BUFFERSA lpBuffersIn,
+                               LPINTERNET_BUFFERSA lpBuffersOut,
+                               DWORD dwFlags, DWORD dwContext)
 {
   FIXME("(%p, %p, %p, %08lx, %08lx): stub\n", hRequest, lpBuffersIn,
-	lpBuffersOut, dwFlags, dwContext);
+        lpBuffersOut, dwFlags, dwContext);
   return FALSE;
 }
 
@@ -702,7 +814,7 @@
  *
  */
 BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
-	DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
+        DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
 {
     LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hHttpRequest;
     LPWININETHTTPSESSIONA lpwhs = NULL;
@@ -713,21 +825,21 @@
     if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
+        return FALSE;
     }
 
     lpwhs = (LPWININETHTTPSESSIONA) lpwhr->hdr.lpwhparent;
     if (NULL == lpwhs ||  lpwhs->hdr.htype != WH_HHTTPSESSION)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
+        return FALSE;
     }
 
     hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent;
     if (NULL == hIC ||  hIC->hdr.htype != WH_HINIT)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
+        return FALSE;
     }
 
     if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
@@ -753,8 +865,8 @@
     }
     else
     {
-	return HTTP_HttpSendRequestA(hHttpRequest, lpszHeaders,
-		dwHeaderLength, lpOptional, dwOptionalLength);
+        return HTTP_HttpSendRequestA(hHttpRequest, lpszHeaders,
+                dwHeaderLength, lpOptional, dwOptionalLength);
     }
 }
 
@@ -769,7 +881,7 @@
  *
  */
 BOOL WINAPI HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders,
-	DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
+        DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
 {
     BOOL result;
     char* szHeaders=NULL;
@@ -894,7 +1006,7 @@
  *
  */
 BOOL WINAPI HTTP_HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
-	DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
+        DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
 {
     INT cnt;
     INT i;
@@ -906,6 +1018,8 @@
     LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hHttpRequest;
     LPWININETHTTPSESSIONA lpwhs = NULL;
     LPWININETAPPINFOA hIC = NULL;
+    BOOL loop_next = FALSE;
+    int CustHeaderIndex;
 
     TRACE("--> 0x%08lx\n", (ULONG)hHttpRequest);
 
@@ -913,21 +1027,21 @@
     if (NULL == lpwhr ||  lpwhr->hdr.htype != WH_HHTTPREQ)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
+        return FALSE;
     }
 
     lpwhs = (LPWININETHTTPSESSIONA) lpwhr->hdr.lpwhparent;
     if (NULL == lpwhs ||  lpwhs->hdr.htype != WH_HHTTPSESSION)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
+        return FALSE;
     }
 
     hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent;
     if (NULL == hIC ||  hIC->hdr.htype != WH_HINIT)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
+        return FALSE;
     }
 
     /* Clear any error information */
@@ -937,134 +1051,275 @@
     /* We must have a verb */
     if (NULL == lpwhr->lpszVerb)
     {
-	    goto lend;
+            goto lend;
     }
 
-    /* If we don't have a path we set it to root */
-    if (NULL == lpwhr->lpszPath)
-        lpwhr->lpszPath = HTTP_strdup("/");
-
-    if(strncmp(lpwhr->lpszPath, "http://", sizeof("http://") -1) != 0
-    	&& lpwhr->lpszPath[0] != '/') /* not an absolute path ?? --> fix it !! */
+    do
     {
-        char *fixurl = HeapAlloc(GetProcessHeap(), 0, strlen(lpwhr->lpszPath) + 2);
-        *fixurl = '/';
-        strcpy(fixurl + 1, lpwhr->lpszPath);
-        HeapFree( GetProcessHeap(), 0, lpwhr->lpszPath );
-        lpwhr->lpszPath = fixurl;
-    }
+       TRACE("Going to url %s %s\n", debugstr_a(lpwhr->lpszHostName), debugstr_a(lpwhr->lpszPath));
+        loop_next = FALSE;
 
-    /* Calculate length of request string */
-    requestStringLen =
-        strlen(lpwhr->lpszVerb) +
-        strlen(lpwhr->lpszPath) +
-        (lpwhr->lpszHostName ? (strlen(HTTPHOSTHEADER) + strlen(lpwhr->lpszHostName)) : 0) +
-        strlen(HTTPHEADER) +
+        /* If we don't have a path we set it to root */
+        if (NULL == lpwhr->lpszPath)
+            lpwhr->lpszPath = HTTP_strdup("/");
+
+        if(strncmp(lpwhr->lpszPath, "http://", sizeof("http://") -1) != 0
+                && lpwhr->lpszPath[0] != '/') /* not an absolute path ?? --> fix it !! */
+        {
+            char *fixurl = HeapAlloc(GetProcessHeap(), 0, strlen(lpwhr->lpszPath) + 2);
+            *fixurl = '/';
+            strcpy(fixurl + 1, lpwhr->lpszPath);
+            HeapFree( GetProcessHeap(), 0, lpwhr->lpszPath );
+            lpwhr->lpszPath = fixurl;
+        }
+
+        /* Calculate length of request string */
+        requestStringLen =
+            strlen(lpwhr->lpszVerb) +
+            strlen(lpwhr->lpszPath) +
+            strlen(HTTPHEADER) +
         5; /* " \r\n\r\n" */
 
-    /* Add length of passed headers */
-    if (lpszHeaders)
-    {
-        headerLength = -1 == dwHeaderLength ?  strlen(lpszHeaders) : dwHeaderLength;
-        requestStringLen += headerLength +  2; /* \r\n */
-    }
+        /* Add length of passed headers */
+        if (lpszHeaders)
+        {
+            headerLength = -1 == dwHeaderLength ?  strlen(lpszHeaders) : dwHeaderLength;
+            requestStringLen += headerLength +  2; /* \r\n */
+        }
 
-    /* Calculate length of custom request headers */
-    for (i = 0; i < lpwhr->nCustHeaders; i++)
-    {
-	    if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
-	    {
+        /* Calculate length of custom request headers */
+        for (i = 0; i < lpwhr->nCustHeaders; i++)
+        {
+            if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
+            {
             requestStringLen += strlen(lpwhr->pCustHeaders[i].lpszField) +
                 strlen(lpwhr->pCustHeaders[i].lpszValue) + 4; /*: \r\n */
-	    }
-    }
+            }
+        }
 
-    /* Calculate the length of standard request headers */
-    for (i = 0; i <= HTTP_QUERY_MAX; i++)
-    {
-       if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST)
-       {
-          requestStringLen += strlen(lpwhr->StdHeaders[i].lpszField) +
-             strlen(lpwhr->StdHeaders[i].lpszValue) + 4; /*: \r\n */
-       }
-    }
+        /* Calculate the length of standard request headers */
+        for (i = 0; i <= HTTP_QUERY_MAX; i++)
+        {
+           if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST)
+           {
+              requestStringLen += strlen(lpwhr->StdHeaders[i].lpszField) +
+                 strlen(lpwhr->StdHeaders[i].lpszValue) + 4; /*: \r\n */
+           }
+        }
 
-    /* Allocate string to hold entire request */
-    requestString = HeapAlloc(GetProcessHeap(), 0, requestStringLen + 1);
-    if (NULL == requestString)
-    {
-        INTERNET_SetLastError(ERROR_OUTOFMEMORY);
-        goto lend;
-    }
+        if (lpwhr->lpszHostName)
+            requestStringLen += (strlen(HTTPHOSTHEADER) + strlen(lpwhr->lpszHostName));
 
-    /* Build request string */
-    cnt = sprintf(requestString, "%s %s%s%s",
-        lpwhr->lpszVerb,
-        lpwhr->lpszPath,
-        lpwhr->lpszHostName ? (HTTPHEADER HTTPHOSTHEADER) : HTTPHEADER,
-        lpwhr->lpszHostName ? lpwhr->lpszHostName : "");
 
-    /* Append standard request headers */
-    for (i = 0; i <= HTTP_QUERY_MAX; i++)
-    {
-       if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST)
-       {
-           cnt += sprintf(requestString + cnt, "\r\n%s: %s",
-               lpwhr->StdHeaders[i].lpszField, lpwhr->StdHeaders[i].lpszValue);
-           TRACE("Adding header %s (%s)\n",lpwhr->StdHeaders[i].lpszField,lpwhr->StdHeaders[i].lpszValue);
-       }
-    }
+        /* Allocate string to hold entire request */
+        requestString = HeapAlloc(GetProcessHeap(), 0, requestStringLen + 1);
+        if (NULL == requestString)
+        {
+            INTERNET_SetLastError(ERROR_OUTOFMEMORY);
+            goto lend;
+        }
 
-    /* Append custom request heades */
-    for (i = 0; i < lpwhr->nCustHeaders; i++)
-    {
-       if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
-       {
-           cnt += sprintf(requestString + cnt, "\r\n%s: %s",
-               lpwhr->pCustHeaders[i].lpszField, lpwhr->pCustHeaders[i].lpszValue);
-           TRACE("Adding custom header %s (%s)\n",lpwhr->pCustHeaders[i].lpszField,lpwhr->pCustHeaders[i].lpszValue);
-       }
-    }
+        /* Build request string */
+        cnt = sprintf(requestString, "%s %s%s",
+            lpwhr->lpszVerb,
+            lpwhr->lpszPath,
+            HTTPHEADER);
 
-    /* Append passed request headers */
-    if (lpszHeaders)
-    {
-        strcpy(requestString + cnt, "\r\n");
-        cnt += 2;
-        strcpy(requestString + cnt, lpszHeaders);
-        cnt += headerLength;
-    }
+        /* Append standard request headers */
+        for (i = 0; i <= HTTP_QUERY_MAX; i++)
+        {
+           if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST)
+           {
+               cnt += sprintf(requestString + cnt, "\r\n%s: %s",
+                   lpwhr->StdHeaders[i].lpszField, lpwhr->StdHeaders[i].lpszValue);
+               TRACE("Adding header %s (%s)\n",lpwhr->StdHeaders[i].lpszField,lpwhr->StdHeaders[i].lpszValue);
+           }
+        }
 
-    /* Set termination string for request */
-    strcpy(requestString + cnt, "\r\n\r\n");
+        /* Append custom request heades */
+        for (i = 0; i < lpwhr->nCustHeaders; i++)
+        {
+           if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
+           {
+               cnt += sprintf(requestString + cnt, "\r\n%s: %s",
+                   lpwhr->pCustHeaders[i].lpszField, lpwhr->pCustHeaders[i].lpszValue);
+               TRACE("Adding custom header %s (%s)\n",lpwhr->pCustHeaders[i].lpszField,lpwhr->pCustHeaders[i].lpszValue);
+           }
+        }
 
-    TRACE("(%s) len(%d)\n", requestString, requestStringLen);
-    /* Send the request and store the results */
-    if (!HTTP_OpenConnection(lpwhr))
-        goto lend;
+        if (lpwhr->lpszHostName)
+            cnt += sprintf(requestString + cnt, "%s%s", HTTPHOSTHEADER, lpwhr->lpszHostName);
+
+        /* Append passed request headers */
+        if (lpszHeaders)
+        {
+            strcpy(requestString + cnt, "\r\n");
+            cnt += 2;
+            strcpy(requestString + cnt, lpszHeaders);
+            cnt += headerLength;
+        }
+
+        /* Set termination string for request */
+        strcpy(requestString + cnt, "\r\n\r\n");
 
-    SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
-                      INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
+        TRACE("(%s) len(%d)\n", requestString, requestStringLen);
+        /* Send the request and store the results */
+        if (!HTTP_OpenConnection(lpwhr))
+            goto lend;
 
-    cnt = send(lpwhr->nSocketFD, requestString, requestStringLen, 0);
+        SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
+                          INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
 
-    SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
-                      INTERNET_STATUS_REQUEST_SENT,
-                      &requestStringLen,sizeof(DWORD));
+        NETCON_send(&lpwhr->netConnection, requestString, requestStringLen,
+                    0, &cnt);
 
-    SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
-                      INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
 
-    if (cnt < 0)
-        goto lend;
+        SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
+                          INTERNET_STATUS_REQUEST_SENT,
+                          &requestStringLen,sizeof(DWORD));
+
+        SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
+                          INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
+
+        if (cnt < 0)
+            goto lend;
+
+        responseLen = HTTP_GetResponseHeaders(lpwhr);
+        if (responseLen)
+            bSuccess = TRUE;
+
+        SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
+                          INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen,
+                          sizeof(DWORD));
+
+        /* process headers here. Is this right? */
+        CustHeaderIndex = HTTP_GetCustomHeaderIndex(lpwhr, "Set-Cookie");
+        if (CustHeaderIndex >= 0)
+        {
+            LPHTTPHEADERA setCookieHeader;
+            int nPosStart = 0, nPosEnd = 0;
 
-    responseLen = HTTP_GetResponseHeaders(lpwhr);
-    if (responseLen)
-	    bSuccess = TRUE;
-
-    SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
-                      INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen,
-                      sizeof(DWORD));
+            setCookieHeader = &lpwhr->pCustHeaders[CustHeaderIndex];
+
+            while (setCookieHeader->lpszValue[nPosEnd] != '\0')
+            {
+                LPSTR buf_cookie, cookie_name, cookie_data;
+                LPSTR buf_url;
+                LPSTR domain = NULL;
+                int nEqualPos = 0;
+                while (setCookieHeader->lpszValue[nPosEnd] != ';' && setCookieHeader->lpszValue[nPosEnd] != ',' &&
+                       setCookieHeader->lpszValue[nPosEnd] != '\0')
+                {
+                    nPosEnd++;
+                }
+                if (setCookieHeader->lpszValue[nPosEnd] == ';')
+                {
+                    /* fixme: not case sensitive, strcasestr is gnu only */
+                    int nDomainPosEnd = 0;
+                    int nDomainPosStart = 0, nDomainLength = 0;
+                    LPSTR lpszDomain = strstr(&setCookieHeader->lpszValue[nPosEnd], "domain=");
+                    if (lpszDomain)
+                    { /* they have specified their own domain, lets use it */
+                        while (lpszDomain[nDomainPosEnd] != ';' && lpszDomain[nDomainPosEnd] != ',' &&
+                               lpszDomain[nDomainPosEnd] != '\0')
+                        {
+                            nDomainPosEnd++;
+                        }
+                        nDomainPosStart = strlen("domain=");
+                        nDomainLength = (nDomainPosEnd - nDomainPosStart) + 1;
+                        domain = HeapAlloc(GetProcessHeap(), 0, nDomainLength + 1);
+                        strncpy(domain, &lpszDomain[nDomainPosStart], nDomainLength);
+                        domain[nDomainLength] = '\0';
+                    }
+                }
+                if (setCookieHeader->lpszValue[nPosEnd] == '\0') break;
+                buf_cookie = HeapAlloc(GetProcessHeap(), 0, (nPosEnd - nPosStart) + 1);
+                strncpy(buf_cookie, &setCookieHeader->lpszValue[nPosStart], (nPosEnd - nPosStart));
+                buf_cookie[(nPosEnd - nPosStart)] = '\0';
+                TRACE("%s\n", buf_cookie);
+                while (buf_cookie[nEqualPos] != '=' && buf_cookie[nEqualPos] != '\0')
+                {
+                    nEqualPos++;
+                }
+                if (buf_cookie[nEqualPos] == '\0' || buf_cookie[nEqualPos + 1] == '\0')
+                {
+                    HeapFree(GetProcessHeap(), 0, buf_cookie);
+                    break;
+                }
+
+                cookie_name = HeapAlloc(GetProcessHeap(), 0, nEqualPos + 1);
+                strncpy(cookie_name, buf_cookie, nEqualPos);
+                cookie_name[nEqualPos] = '\0';
+                cookie_data = &buf_cookie[nEqualPos + 1];
+
+
+                buf_url = HeapAlloc(GetProcessHeap(), 0, strlen((domain ? domain : lpwhr->lpszHostName)) + strlen(lpwhr->lpszPath) + 9);
+                sprintf(buf_url, "http://%s/", (domain ? domain : lpwhr->lpszHostName)); /* FIXME PATH!!! */
+                InternetSetCookieA(buf_url, cookie_name, cookie_data);
+
+                HeapFree(GetProcessHeap(), 0, buf_url);
+                HeapFree(GetProcessHeap(), 0, buf_cookie);
+                HeapFree(GetProcessHeap(), 0, cookie_name);
+                if (domain) HeapFree(GetProcessHeap(), 0, domain);
+                nPosStart = nPosEnd;
+            }
+        }
+
+        /* FIXME: is this right? I'm not sure if this should be here or elsewhere (the loop, too)
+         * FIXME: don't do this if they specify INTERNET_FLAG_NO_AUTO_REDIRECT */
+        if (lpwhr->StdHeaders[HTTP_QUERY_LOCATION].lpszValue)
+        {
+            URL_COMPONENTSA urlComponents;
+            char protocol[32], hostName[MAXHOSTNAME], userName[1024];
+            char password[1024], path[2048], extra[1024];
+
+            TRACE("Got a Location header: Going around to a new location: %s",
+                   debugstr_a(lpwhr->StdHeaders[HTTP_QUERY_LOCATION].lpszValue));
+
+            urlComponents.dwStructSize = sizeof(URL_COMPONENTSA);
+            urlComponents.lpszScheme = protocol;
+            urlComponents.dwSchemeLength = 32;
+            urlComponents.lpszHostName = hostName;
+            urlComponents.dwHostNameLength = MAXHOSTNAME;
+            urlComponents.lpszUserName = userName;
+            urlComponents.dwUserNameLength = 1024;
+            urlComponents.lpszPassword = password;
+            urlComponents.dwPasswordLength = 1024;
+            urlComponents.lpszUrlPath = path;
+            urlComponents.dwUrlPathLength = 2048;
+            urlComponents.lpszExtraInfo = extra;
+            urlComponents.dwExtraInfoLength = 1024;
+            if (!InternetCrackUrlA(lpwhr->StdHeaders[HTTP_QUERY_LOCATION].lpszValue,
+                                   strlen(lpwhr->StdHeaders[HTTP_QUERY_LOCATION].lpszValue),
+                                   0, &urlComponents))
+                goto lend;
+
+            if (urlComponents.nScheme != INTERNET_SCHEME_HTTP)
+            {
+                FIXME("cannot redirect to non HTTP page\n");
+                goto lend;
+            }
+
+            HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath);
+            HeapAlloc(GetProcessHeap(), 0, strlen(path) + 1);
+            strcpy(lpwhr->lpszPath, path);
+
+            if (urlComponents.dwHostNameLength)
+            {
+                HeapFree(GetProcessHeap(), 0, lpwhr->lpszHostName);
+                HeapAlloc(GetProcessHeap(), 0, strlen(hostName) + 1);
+                strcpy(lpwhr->lpszHostName, hostName);
+            }
+
+            SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
+                              INTERNET_STATUS_REDIRECT, NULL, 0);
+
+            HeapFree(GetProcessHeap(), 0, lpwhr->StdHeaders[HTTP_QUERY_LOCATION].lpszValue);
+            lpwhr->StdHeaders[HTTP_QUERY_LOCATION].lpszValue = NULL;
+            loop_next = TRUE;
+        }
+    }
+    while (loop_next);
 
 lend:
 
@@ -1121,8 +1376,8 @@
  *
  */
 HINTERNET HTTP_Connect(HINTERNET hInternet, LPCSTR lpszServerName,
-	INTERNET_PORT nServerPort, LPCSTR lpszUserName,
-	LPCSTR lpszPassword, DWORD dwFlags, DWORD dwContext)
+        INTERNET_PORT nServerPort, LPCSTR lpszUserName,
+        LPCSTR lpszPassword, DWORD dwFlags, DWORD dwContext)
 {
     BOOL bSuccess = FALSE;
     LPWININETAPPINFOA hIC = NULL;
@@ -1140,7 +1395,7 @@
     if (NULL == lpwhs)
     {
         INTERNET_SetLastError(ERROR_OUTOFMEMORY);
-	goto lerror;
+        goto lerror;
     }
 
    /*
@@ -1148,7 +1403,7 @@
     */
 
     if (nServerPort == INTERNET_INVALID_PORT_NUMBER)
-	nServerPort = INTERNET_DEFAULT_HTTP_PORT;
+        nServerPort = INTERNET_DEFAULT_HTTP_PORT;
 
     lpwhs->hdr.htype = WH_HHTTPSESSION;
     lpwhs->hdr.lpwhparent = (LPWININETHANDLEHEADER)hInternet;
@@ -1184,7 +1439,7 @@
     if (!bSuccess && lpwhs)
     {
         HeapFree(GetProcessHeap(), 0, lpwhs);
-	lpwhs = NULL;
+        lpwhs = NULL;
     }
 
 /*
@@ -1192,7 +1447,7 @@
  * windows
  */
 
-TRACE("<--\n");
+    TRACE("%p -->\n", hInternet);
     return (HINTERNET)lpwhs;
 }
 
@@ -1210,7 +1465,6 @@
 BOOL HTTP_OpenConnection(LPWININETHTTPREQA lpwhr)
 {
     BOOL bSuccess = FALSE;
-    INT result;
     LPWININETHTTPSESSIONA lpwhs;
     LPWININETAPPINFOA hIC = NULL;
 
@@ -1231,17 +1485,15 @@
                       &(lpwhs->socketAddress),
                        sizeof(struct sockaddr_in));
 
-    lpwhr->nSocketFD = socket(lpwhs->phostent->h_addrtype,SOCK_STREAM,0);
-    if (lpwhr->nSocketFD == -1)
+    if (!NETCON_create(&lpwhr->netConnection, lpwhs->phostent->h_addrtype,
+                         SOCK_STREAM, 0))
     {
-	WARN("Socket creation failed\n");
+        WARN("Socket creation failed\n");
         goto lend;
     }
 
-    result = connect(lpwhr->nSocketFD, (struct sockaddr *)&lpwhs->socketAddress,
-        sizeof(lpwhs->socketAddress));
-
-    if (result == -1)
+    if (!NETCON_connect(&lpwhr->netConnection, (struct sockaddr *)&lpwhs->socketAddress,
+                      sizeof(lpwhs->socketAddress)))
     {
        WARN("Unable to connect to host (%s)\n", strerror(errno));
        goto lend;
@@ -1281,19 +1533,20 @@
 
     TRACE("-->\n");
 
-    if (lpwhr->nSocketFD == -1)
+    if (!NETCON_connected(&lpwhr->netConnection))
         goto lend;
 
     /*
      * HACK peek at the buffer
      */
-    rc = recv(lpwhr->nSocketFD,buffer,buflen,MSG_PEEK);
+    NETCON_recv(&lpwhr->netConnection, buffer, buflen, MSG_PEEK, &rc);
 
     /*
      * We should first receive 'HTTP/1.x nnn' where nnn is the status code.
      */
     buflen = MAX_REPLY_LEN;
-    if (!INTERNET_GetNextLine(lpwhr->nSocketFD, buffer, &buflen))
+    memset(buffer, 0, MAX_REPLY_LEN);
+    if (!NETCON_getNextLine(&lpwhr->netConnection, buffer, &buflen))
         goto lend;
 
     if (strncmp(buffer, "HTTP", 4) != 0)
@@ -1305,20 +1558,21 @@
     /* Parse each response line */
     do
     {
-	buflen = MAX_REPLY_LEN;
-	if (INTERNET_GetNextLine(lpwhr->nSocketFD, buffer, &buflen))
-	{
+        buflen = MAX_REPLY_LEN;
+        if (NETCON_getNextLine(&lpwhr->netConnection, buffer, &buflen))
+        {
+            TRACE("got line %s, now interpretting\n", debugstr_a(buffer));
             if (!HTTP_InterpretHttpHeader(buffer, field, MAX_FIELD_LEN, value, MAX_FIELD_VALUE_LEN))
                 break;
 
             HTTP_ProcessHeader(lpwhr, field, value, (HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE));
-	}
-	else
-	{
-	    cbreaks++;
-	    if (cbreaks >= 2)
-	       break;
-	}
+        }
+        else
+        {
+            cbreaks++;
+            if (cbreaks >= 2)
+               break;
+        }
     }while(1);
 
     bSuccess = TRUE;
@@ -1351,15 +1605,15 @@
     srclen = 0;
 
     while (*lpszSrc == ' ' && *lpszSrc != '\0')
-	lpszSrc++;
+        lpszSrc++;
 
     lpsztmp = lpszSrc;
     while(*lpsztmp != '\0')
     {
         if (*lpsztmp != ' ')
-	    srclen = lpsztmp - lpszSrc + 1;
+            srclen = lpsztmp - lpszSrc + 1;
 
-	lpsztmp++;
+        lpsztmp++;
     }
 
     *len = min(*len, srclen);
@@ -1383,12 +1637,12 @@
     pd = strchr(buffer, ':');
     if (pd)
     {
-	*pd = '\0';
-	if (stripSpaces(buffer, field, &fieldlen) > 0)
-	{
-	    if (stripSpaces(pd+1, value, &valuelen) > 0)
-		bSuccess = TRUE;
-	}
+        *pd = '\0';
+        if (stripSpaces(buffer, field, &fieldlen) > 0)
+        {
+            if (stripSpaces(pd+1, value, &valuelen) > 0)
+                bSuccess = TRUE;
+        }
     }
 
     TRACE("%d: field(%s) Value(%s)\n", bSuccess, field, value);
@@ -1473,7 +1727,7 @@
 
     /* Adjust modifier flags */
     if (dwModifier & COALESCEFLASG)
-	dwModifier |= HTTP_ADDHDR_FLAG_ADD;
+        dwModifier |= HTTP_ADDHDR_FLAG_ADD;
 
     /* Try to get index into standard header array */
     index = HTTP_GetStdHeaderIndex(field);
@@ -1509,7 +1763,7 @@
     }
 
     if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
-	lphttpHdr->wFlags |= HDR_ISREQUEST;
+        lphttpHdr->wFlags |= HDR_ISREQUEST;
     else
         lphttpHdr->wFlags &= ~HDR_ISREQUEST;
 
@@ -1548,7 +1802,7 @@
 
             if (len <= 0)
             {
-	        /* if custom header delete from array */
+                /* if custom header delete from array */
                 HeapFree(GetProcessHeap(), 0, lphttpHdr->lpszValue);
                 lphttpHdr->lpszValue = NULL;
                 bSuccess = TRUE;
@@ -1593,7 +1847,7 @@
             lpsztmp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,  lphttpHdr->lpszValue, len+1);
             if (lpsztmp)
             {
-		/* FIXME: Increment lphttpHdr->wCount. Perhaps lpszValue should be an array */
+                /* FIXME: Increment lphttpHdr->wCount. Perhaps lpszValue should be an array */
                 if (ch > 0)
                 {
                     lphttpHdr->lpszValue[origlen] = ch;
@@ -1637,11 +1891,10 @@
     SendAsyncCallback(hIC, lpwhr, lpwhr->hdr.dwContext,
                       INTERNET_STATUS_CLOSING_CONNECTION, 0, 0);
 
-	if (lpwhr->nSocketFD != -1)
-	{
-		close(lpwhr->nSocketFD);
-		lpwhr->nSocketFD = -1;
-	}
+    if (NETCON_connected(&lpwhr->netConnection))
+    {
+        NETCON_close(&lpwhr->netConnection);
+    }
 
     SendAsyncCallback(hIC, lpwhr, lpwhr->hdr.dwContext,
                       INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
@@ -1662,7 +1915,7 @@
 
     TRACE("\n");
 
-    if (lpwhr->nSocketFD != -1)
+    if (NETCON_connected(&lpwhr->netConnection))
         HTTP_CloseConnection(lpwhr);
 
     lpwhs = (LPWININETHTTPSESSIONA) lpwhr->hdr.lpwhparent;
@@ -1681,17 +1934,17 @@
 
     for (i = 0; i <= HTTP_QUERY_MAX; i++)
     {
-	   if (lpwhr->StdHeaders[i].lpszField)
+           if (lpwhr->StdHeaders[i].lpszField)
             HeapFree(GetProcessHeap(), 0, lpwhr->StdHeaders[i].lpszField);
-	   if (lpwhr->StdHeaders[i].lpszValue)
+           if (lpwhr->StdHeaders[i].lpszValue)
             HeapFree(GetProcessHeap(), 0, lpwhr->StdHeaders[i].lpszValue);
     }
 
     for (i = 0; i < lpwhr->nCustHeaders; i++)
     {
-	   if (lpwhr->pCustHeaders[i].lpszField)
+           if (lpwhr->pCustHeaders[i].lpszField)
             HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszField);
-	   if (lpwhr->pCustHeaders[i].lpszValue)
+           if (lpwhr->pCustHeaders[i].lpszValue)
             HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszValue);
     }
 
@@ -1709,7 +1962,7 @@
 void HTTP_CloseHTTPSessionHandle(LPWININETHTTPSESSIONA lpwhs)
 {
     LPWININETAPPINFOA hIC = NULL;
-    TRACE("\n");
+    TRACE("%p\n", lpwhs);
 
     hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent;
 
@@ -1739,13 +1992,13 @@
 
     for (index = 0; index < lpwhr->nCustHeaders; index++)
     {
-	if (!strcasecmp(lpwhr->pCustHeaders[index].lpszField, lpszField))
-	    break;
+        if (!strcasecmp(lpwhr->pCustHeaders[index].lpszField, lpszField))
+            break;
 
     }
 
     if (index >= lpwhr->nCustHeaders)
-	index = -1;
+        index = -1;
 
     TRACE("Return: %d\n", index);
     return index;
@@ -1766,23 +2019,23 @@
     TRACE("--> %s: %s\n", lpHdr->lpszField, lpHdr->lpszValue);
     count = lpwhr->nCustHeaders + 1;
     if (count > 1)
-	lph = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpwhr->pCustHeaders, sizeof(HTTPHEADERA) * count);
+        lph = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpwhr->pCustHeaders, sizeof(HTTPHEADERA) * count);
     else
-	lph = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HTTPHEADERA) * count);
+        lph = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HTTPHEADERA) * count);
 
     if (NULL != lph)
     {
-	lpwhr->pCustHeaders = lph;
+        lpwhr->pCustHeaders = lph;
         lpwhr->pCustHeaders[count-1].lpszField = HTTP_strdup(lpHdr->lpszField);
         lpwhr->pCustHeaders[count-1].lpszValue = HTTP_strdup(lpHdr->lpszValue);
         lpwhr->pCustHeaders[count-1].wFlags = lpHdr->wFlags;
         lpwhr->pCustHeaders[count-1].wCount= lpHdr->wCount;
-	lpwhr->nCustHeaders++;
+        lpwhr->nCustHeaders++;
     }
     else
     {
         INTERNET_SetLastError(ERROR_OUTOFMEMORY);
-	count = 0;
+        count = 0;
     }
 
     TRACE("%d <--\n", count-1);
Index: dlls/wininet/internet.c
===================================================================
RCS file: /home/wine/wine/dlls/wininet/internet.c,v
retrieving revision 1.56
diff -u -u -r1.56 internet.c
--- dlls/wininet/internet.c	11 May 2003 02:59:52 -0000	1.56
+++ dlls/wininet/internet.c	2 Jun 2003 09:31:53 -0000
@@ -3,11 +3,12 @@
  *
  * Copyright 1999 Corel Corporation
  * Copyright 2002 CodeWeavers Inc.
+ * Copyright 2002 Jaco Greeff
+ * Copyright 2002 TransGaming Technologies Inc.
  *
  * Ulrich Czekalla
  * Aric Stewart
- *
- * Copyright 2002 Jaco Greeff
+ * David Hammerton
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -222,7 +223,8 @@
 {
     LPWININETAPPINFOA lpwai = NULL;
 
-    TRACE("\n");
+    TRACE("(%s, %li, %s, %s, %li)\n", debugstr_a(lpszAgent), dwAccessType,
+	 debugstr_a(lpszProxy), debugstr_a(lpszProxyBypass), dwFlags);
 
     /* Clear any error information */
     INTERNET_SetLastError(0);
@@ -278,6 +280,7 @@
         lpwai->dwAccessType = dwAccessType;
     }
 
+    TRACE("returning %p\n", (HINTERNET)lpwai);
     return (HINTERNET)lpwai;
 }
 
@@ -299,9 +302,9 @@
     INT lenAgent = lstrlenW(lpszAgent)+1;
     INT lenProxy = lstrlenW(lpszProxy)+1;
     INT lenBypass = lstrlenW(lpszProxyBypass)+1;
-    CHAR *szAgent = (CHAR *)malloc(lenAgent*sizeof(CHAR));
-    CHAR *szProxy = (CHAR *)malloc(lenProxy*sizeof(CHAR));
-    CHAR *szBypass = (CHAR *)malloc(lenBypass*sizeof(CHAR));
+    CHAR *szAgent = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenAgent*sizeof(CHAR));
+    CHAR *szProxy = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenProxy*sizeof(CHAR));
+    CHAR *szBypass = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenBypass*sizeof(CHAR));
 
     if (!szAgent || !szProxy || !szBypass)
     {
@@ -323,9 +326,9 @@
 
     rc = InternetOpenA(szAgent, dwAccessType, szProxy, szBypass, dwFlags);
 
-    free(szAgent);
-    free(szProxy);
-    free(szBypass);
+    HeapFree(GetProcessHeap(), 0, szAgent);
+    HeapFree(GetProcessHeap(), 0, szProxy);
+    HeapFree(GetProcessHeap(), 0, szBypass);
 
     return rc;
 }
@@ -398,7 +401,9 @@
 {
     HINTERNET rc = (HINTERNET) NULL;
 
-    TRACE("ServerPort %i\n",nServerPort);
+    TRACE("(%p, %s, %i, %s, %s, %li, %li, %li)\n", hInternet, debugstr_a(lpszServerName),
+	  nServerPort, debugstr_a(lpszUserName), debugstr_a(lpszPassword),
+	  dwService, dwFlags, dwContext);
 
     /* Clear any error information */
     INTERNET_SetLastError(0);
@@ -420,6 +425,7 @@
             break;
     }
 
+    TRACE("returning %p\n", rc);
     return rc;
 }
 
@@ -440,37 +446,42 @@
     DWORD dwService, DWORD dwFlags, DWORD dwContext)
 {
     HINTERNET rc = (HINTERNET)NULL;
-    INT lenServer = lstrlenW(lpszServerName)+1;
-    INT lenUser = lstrlenW(lpszUserName)+1;
-    INT lenPass = lstrlenW(lpszPassword)+1;
-    CHAR *szServerName = (CHAR *)malloc(lenServer*sizeof(CHAR));
-    CHAR *szUserName = (CHAR *)malloc(lenUser*sizeof(CHAR));
-    CHAR *szPassword = (CHAR *)malloc(lenPass*sizeof(CHAR));
-
-    if (!szServerName || !szUserName || !szPassword)
-    {
-        if (szServerName)
-            free(szServerName);
-        if (szUserName)
-            free(szUserName);
-        if (szPassword)
-            free(szPassword);
-        return (HINTERNET)NULL;
-    }
+    INT lenServer = 0;
+    INT lenUser = 0;
+    INT lenPass = 0;
+    CHAR *szServerName = NULL;
+    CHAR *szUserName = NULL;
+    CHAR *szPassword = NULL;
 
+    if (lpszServerName)
+    {
+	lenServer = lstrlenW(lpszServerName)+1;
+        szServerName = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenServer*sizeof(CHAR));
     WideCharToMultiByte(CP_ACP, -1, lpszServerName, -1, szServerName, lenServer,
         NULL, NULL);
+    }
+    if (lpszUserName)
+    {
+	lenUser = lstrlenW(lpszUserName)+1;
+        szUserName = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenUser*sizeof(CHAR));
     WideCharToMultiByte(CP_ACP, -1, lpszUserName, -1, szUserName, lenUser,
         NULL, NULL);
+    }
+    if (lpszPassword)
+    {
+	lenPass = lstrlenW(lpszPassword)+1;
+        szPassword = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenPass*sizeof(CHAR));
     WideCharToMultiByte(CP_ACP, -1, lpszPassword, -1, szPassword, lenPass,
         NULL, NULL);
+ }
+
 
     rc = InternetConnectA(hInternet, szServerName, nServerPort,
         szUserName, szPassword, dwService, dwFlags, dwContext);
 
-    free(szServerName);
-    free(szUserName);
-    free(szPassword);
+    if (szServerName) HeapFree(GetProcessHeap(), 0, szServerName);
+    if (szUserName) HeapFree(GetProcessHeap(), 0, szUserName);
+    if (szPassword) HeapFree(GetProcessHeap(), 0, szPassword);
     return rc;
 }
 
@@ -690,7 +701,7 @@
                               LPCSTR lpszStart,
                               LPCWSTR lpwszStart)
 {
-    if (*dwComponentLen != 0)
+    if (*dwComponentLen != 0 )
     {
         int nASCIILength=WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,NULL,0,NULL,NULL);
         if (*lppszComponent == NULL)
@@ -846,7 +857,7 @@
 {
     TRACE("%s (%d)\n", debugstr_wn(lpszStart,len), len);
 
-    if (*dwComponentLen != 0)
+    if (*dwComponentLen != 0 || *lppszComponent == NULL)
     {
         if (*lppszComponent == NULL)
         {
@@ -1220,7 +1231,10 @@
     switch (lpwh->htype)
     {
         case WH_HHTTPREQ:
-            nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
+            FIXME("This shouldn't be here! We don't support this kind"
+                  " of connection anymore. Must use NETCON functions,"
+                  " especially if using SSL\n");
+            nSocket = ((LPWININETHTTPREQA)hFile)->netConnection.socketFD;
             break;
 
         case WH_HFILE:
@@ -1264,10 +1278,14 @@
     if (NULL == lpwh)
         return FALSE;
 
+    /* FIXME: this should use NETCON functions! */
     switch (lpwh->htype)
     {
         case WH_HHTTPREQ:
-            nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
+	    FIXME("This shouldn't be here! We don't support this kind"
+		  " of connection anymore. Must use NETCON functions,"
+		  " especially if using SSL\n");
+	    nSocket = ((LPWININETHTTPREQA)hFile)->netConnection.socketFD;
             break;
 
         case WH_HFILE:
@@ -1332,7 +1350,7 @@
     LPWININETHANDLEHEADER lpwhh;
     BOOL bSuccess = FALSE;
 
-    TRACE("0x%08lx\n", dwOption);
+    TRACE("(%p, 0x%08lx, %p, %p)\n", hInternet, dwOption, lpBuffer, lpdwBufferLength);
 
     if (NULL == hInternet)
     {
@@ -1607,86 +1625,6 @@
 
 
 /***********************************************************************
- *           InternetGetCookieA (WININET.@)
- *
- * Retrieve cookie from the specified url
- *
- * RETURNS
- *    TRUE  on success
- *    FALSE on failure
- *
- */
-BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
-    LPSTR lpCookieData, LPDWORD lpdwSize)
-{
-    FIXME("STUB\n");
-    TRACE("(%s,%s,%p)\n", debugstr_a(lpszUrl),debugstr_a(lpszCookieName),
-        lpCookieData);
-    return FALSE;
-}
-
-
-/***********************************************************************
- *           InternetGetCookieW (WININET.@)
- *
- * Retrieve cookie from the specified url
- *
- * RETURNS
- *    TRUE  on success
- *    FALSE on failure
- *
- */
-BOOL WINAPI InternetGetCookieW(LPCSTR lpszUrl, LPCWSTR lpszCookieName,
-    LPWSTR lpCookieData, LPDWORD lpdwSize)
-{
-    FIXME("STUB\n");
-    TRACE("(%s,%s,%p)\n", debugstr_a(lpszUrl), debugstr_w(lpszCookieName),
-        lpCookieData);
-    return FALSE;
-}
-
-
-/***********************************************************************
- *           InternetSetCookieA (WININET.@)
- *
- * Sets cookie for the specified url
- *
- * RETURNS
- *    TRUE  on success
- *    FALSE on failure
- *
- */
-BOOL WINAPI InternetSetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
-    LPCSTR lpCookieData)
-{
-    FIXME("STUB\n");
-    TRACE("(%s,%s,%s)\n", debugstr_a(lpszUrl),
-        debugstr_a(lpszCookieName), debugstr_a(lpCookieData));
-    return FALSE;
-}
-
-
-/***********************************************************************
- *           InternetSetCookieW (WININET.@)
- *
- * Sets cookie for the specified url
- *
- * RETURNS
- *    TRUE  on success
- *    FALSE on failure
- *
- */
-BOOL WINAPI InternetSetCookieW(LPCSTR lpszUrl, LPCWSTR lpszCookieName,
-    LPCWSTR lpCookieData)
-{
-    FIXME("STUB\n");
-    TRACE("(%s,%s,%s)\n", debugstr_a(lpszUrl),
-        debugstr_w(lpszCookieName), debugstr_w(lpCookieData));
-    return FALSE;
-}
-
-
-/***********************************************************************
  *	InternetCheckConnectionA (WININET.@)
  *
  * Pings a requested host to check internet connection
@@ -1783,11 +1721,11 @@
     BOOL rc;
 
     len = lstrlenW(lpszUrl)+1;
-    if (!(szUrl = (CHAR *)malloc(len*sizeof(CHAR))))
+    if (!(szUrl = (CHAR *)HeapAlloc(GetProcessHeap(), 0, len*sizeof(CHAR))))
         return FALSE;
     WideCharToMultiByte(CP_ACP, -1, lpszUrl, -1, szUrl, len, NULL, NULL);
     rc = InternetCheckConnectionA((LPCSTR)szUrl, dwFlags, dwReserved);
-    free(szUrl);
+    HeapFree(GetProcessHeap(), 0, szUrl);
     
     return rc;
 }
@@ -1808,6 +1746,10 @@
   char protocol[32], hostName[MAXHOSTNAME], userName[1024];
   char password[1024], path[2048], extra[1024];
   HINTERNET client = NULL, client1 = NULL;
+
+  TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hInternet, debugstr_a(lpszUrl), debugstr_a(lpszHeaders),
+       dwHeadersLength, dwFlags, dwContext);
+
   urlComponents.dwStructSize = sizeof(URL_COMPONENTSA);
   urlComponents.lpszScheme = protocol;
   urlComponents.dwSchemeLength = 32;
@@ -1883,15 +1825,15 @@
 
     INT lenUrl = lstrlenW(lpszUrl)+1;
     INT lenHeaders = lstrlenW(lpszHeaders)+1;
-    CHAR *szUrl = (CHAR *)malloc(lenUrl*sizeof(CHAR));
-    CHAR *szHeaders = (CHAR *)malloc(lenHeaders*sizeof(CHAR));
+    CHAR *szUrl = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenUrl*sizeof(CHAR));
+    CHAR *szHeaders = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenHeaders*sizeof(CHAR));
 
     if (!szUrl || !szHeaders)
     {
         if (szUrl)
-            free(szUrl);
+            HeapFree(GetProcessHeap(), 0, szUrl);
         if (szHeaders)
-            free(szHeaders);
+            HeapFree(GetProcessHeap(), 0, szHeaders);
         return (HINTERNET)NULL;
     }
 
@@ -1903,8 +1845,8 @@
     rc = InternetOpenUrlA(hInternet, szUrl, szHeaders,
         dwHeadersLength, dwFlags, dwContext);
 
-    free(szUrl);
-    free(szHeaders);
+    HeapFree(GetProcessHeap(), 0, szUrl);
+    HeapFree(GetProcessHeap(), 0, szHeaders);
 
     return rc;
 }
@@ -2242,7 +2184,6 @@
     return lpwite->response;
 }
 
-
 /***********************************************************************
  *           INTERNET_GetNextLine  (internal)
  *
@@ -2316,7 +2257,7 @@
 {
     LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hFile;
     INT retval = -1;
-    int nSocket = -1;
+    char buffer[4048];
 
 
     if (NULL == lpwhr)
@@ -2325,32 +2266,24 @@
         return FALSE;
     }
 
-    TRACE("-->  %p %i %i\n",lpwhr,lpwhr->hdr.htype,lpwhr->nSocketFD);
+    TRACE("-->  %p %i\n",lpwhr,lpwhr->hdr.htype);
 
     switch (lpwhr->hdr.htype)
     {
         case WH_HHTTPREQ:
-            nSocket = lpwhr->nSocketFD;
+	    if (!NETCON_recv(&((LPWININETHTTPREQA)hFile)->netConnection, buffer,
+			     4048, MSG_PEEK, (int *)lpdwNumberOfBytesAvailble))
+            {
+                SetLastError(ERROR_NO_MORE_FILES);
+                retval = FALSE;
+            }
+	    else
+		retval = TRUE;
             break;
 
         default:
-            break;
-    }
-
-    if (nSocket != -1)
-    {
-        char buffer[4048];
-
-        retval = recv(nSocket,buffer,4048,MSG_PEEK);
-    }
-    else
-    {
-        SetLastError(ERROR_NO_MORE_FILES);
-    }
-
-    if (lpdwNumberOfBytesAvailble)
-    {
-        (*lpdwNumberOfBytesAvailble) = retval;
+            FIXME("unsuported file type\n");
+	    break;
     }
 
     TRACE("<-- %i\n",retval);
Index: dlls/wininet/internet.h
===================================================================
RCS file: /home/wine/wine/dlls/wininet/internet.h,v
retrieving revision 1.10
diff -u -u -r1.10 internet.h
--- dlls/wininet/internet.h	28 Aug 2002 23:43:43 -0000	1.10
+++ dlls/wininet/internet.h	2 Jun 2003 09:31:53 -0000
@@ -32,6 +32,22 @@
 # include <netinet/in.h>
 #endif
 
+#include "config.h"
+#ifdef HAVE_OPENSSL
+# include <openssl/ssl.h>
+#endif
+
+/* used for netconnection.c stuff */
+typedef struct
+{
+    BOOL useSSL;
+    int socketFD;
+#ifdef HAVE_OPENSSL
+    SSL *ssl_s;
+    int ssl_sock;
+#endif
+} WININET_NETCONNECTION;
+
 typedef enum
 {
     WH_HINIT = INTERNET_HANDLE_TYPE_INTERNET,
@@ -93,7 +109,7 @@
     LPSTR lpszPath;
     LPSTR lpszVerb;
     LPSTR lpszHostName;
-    INT	nSocketFD;
+    WININET_NETCONNECTION netConnection;
     HTTPHEADERA StdHeaders[HTTP_QUERY_MAX+1];
     HTTPHEADERA *pCustHeaders;
     INT nCustHeaders;
@@ -264,6 +280,19 @@
                              DWORD dwContext, DWORD dwInternetStatus, LPVOID
                              lpvStatusInfo , DWORD dwStatusInfoLength);
 
+
+BOOL NETCON_connected(WININET_NETCONNECTION *connection);
+void NETCON_init(WININET_NETCONNECTION *connnection, BOOL useSSL);
+BOOL NETCON_create(WININET_NETCONNECTION *connection, int domain,
+	      int type, int protocol);
+BOOL NETCON_close(WININET_NETCONNECTION *connection);
+BOOL NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *serv_addr,
+		    socklen_t addrlen);
+BOOL NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int flags,
+		int *sent /* out */);
+BOOL NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags,
+		int *recvd /* out */);
+BOOL NETCON_getNextLine(WININET_NETCONNECTION *connection, LPSTR lpszBuffer, LPDWORD dwBuffer);
 
 #define MAX_REPLY_LEN	 	0x5B4
 
Index: include/config.h.in
===================================================================
RCS file: /home/wine/wine/include/config.h.in,v
retrieving revision 1.155
diff -u -u -r1.155 config.h.in
--- include/config.h.in	20 May 2003 17:48:40 -0000	1.155
+++ include/config.h.in	2 Jun 2003 09:31:54 -0000
@@ -218,6 +218,9 @@
 /* Define if you have libjpeg including devel headers */
 #undef HAVE_LIBJPEG
 
+/* Define if you have openssl headers */
+#undef HAVE_OPENSSL
+
 /* Define to 1 if you have the `m' library (-lm). */
 #undef HAVE_LIBM
 
@@ -763,6 +766,12 @@
 
 /* Define to the soname of the libGL library. */
 #undef SONAME_LIBGL
+
+/* Define to the soname of the open ssl library. */
+#undef SONAME_LIBSSL
+
+/* Define to the soname of the open ssl crypto library. */
+#undef SONAME_LIBCRYPTO
 
 /* Define to the soname of the libjack library. */
 #undef SONAME_LIBJACK
--- /dev/null	1994-07-18 08:46:18.000000000 +0900
+++ dlls/wininet/netconnection.c	2003-06-02 17:55:54.000000000 +0900
@@ -0,0 +1,491 @@
+/*
+ * Wininet - networking layer. Uses unix sockets or OpenSSL.
+ *
+ * Copyright 2002 TransGaming Technologies Inc.
+ *
+ * David Hammerton
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wine/port.h"
+#include "wine/library.h"
+#include "windef.h"
+#include "winbase.h"
+#include "wininet.h"
+#include "winerror.h"
+
+#include "wine/debug.h"
+#include "internet.h"
+
+#define RESPONSE_TIMEOUT        30            /* FROM internet.c */
+
+
+WINE_DEFAULT_DEBUG_CHANNEL(wininet);
+
+/* FIXME!!!!!!
+ *    This should use winsock - To use winsock the funtions will have to change a bit
+ *        as they are designed for unix sockets.
+ *    SSL stuff should use crypt32.dll
+ */
+
+#ifdef HAVE_OPENSSL
+#ifndef SONAME_LIBSSL
+#define SONAME_LIBSSL "libssl.so"
+#endif
+#ifndef SONAME_LIBCRYPTO
+#define SONAME_LIBCRYPTO "libcrypto.so"
+#endif
+
+void *OpenSSL_ssl_handle = NULL;
+void *OpenSSL_crypto_handle = NULL;
+
+BOOL ssl_initilized = FALSE; /* FIXME: should we be able to uninitilze ssl? */
+SSL_METHOD *meth;
+SSL_CTX *ctx;
+
+#define MAKE_FUNCPTR(f) typeof(f) * p##f = NULL
+
+/* OpenSSL funtions that we use */
+MAKE_FUNCPTR(SSL_library_init);
+MAKE_FUNCPTR(SSL_load_error_strings);
+MAKE_FUNCPTR(SSLv23_method);
+MAKE_FUNCPTR(SSL_CTX_new);
+MAKE_FUNCPTR(SSL_new);
+MAKE_FUNCPTR(SSL_set_bio);
+MAKE_FUNCPTR(SSL_connect);
+MAKE_FUNCPTR(SSL_write);
+MAKE_FUNCPTR(SSL_read);
+MAKE_FUNCPTR(SSL_CTX_get_timeout);
+MAKE_FUNCPTR(SSL_CTX_set_timeout);
+
+/* OpenSSL's libcrypto functions that we use */
+MAKE_FUNCPTR(BIO_new_socket);
+MAKE_FUNCPTR(BIO_new_fp);
+#undef MAKE_FUNCPTR
+
+#endif
+
+void NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
+{
+    connection->useSSL = useSSL;
+    connection->socketFD = -1;
+    if (connection->useSSL)
+    {
+#ifdef HAVE_OPENSSL
+        TRACE("using SSL connection\n");
+	connection->ssl_sock = -1;
+	if (OpenSSL_ssl_handle) /* already initilzed everything */
+            return;
+	OpenSSL_ssl_handle = wine_dlopen(SONAME_LIBSSL, RTLD_NOW, NULL, 0);
+	if (!OpenSSL_ssl_handle)
+	{
+	    ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n",
+		SONAME_LIBSSL);
+            connection->useSSL = FALSE;
+            return;
+	}
+	OpenSSL_crypto_handle = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0);
+	if (!OpenSSL_crypto_handle)
+	{
+	    ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n",
+		SONAME_LIBCRYPTO);
+            connection->useSSL = FALSE;
+            return;
+	}
+
+        /* mmm nice ugly macroness */
+#define DYNSSL(x) \
+    p##x = wine_dlsym(OpenSSL_ssl_handle, #x, NULL, 0); \
+    if (!p##x) \
+    { \
+        ERR("failed to load symbol %s\n", #x); \
+        connection->useSSL = FALSE; \
+        return; \
+    }
+
+	DYNSSL(SSL_library_init);
+	DYNSSL(SSL_load_error_strings);
+	DYNSSL(SSLv23_method);
+	DYNSSL(SSL_CTX_new);
+	DYNSSL(SSL_new);
+	DYNSSL(SSL_set_bio);
+	DYNSSL(SSL_connect);
+	DYNSSL(SSL_write);
+	DYNSSL(SSL_read);
+	DYNSSL(SSL_CTX_get_timeout);
+        DYNSSL(SSL_CTX_set_timeout);
+#undef DYNSSL
+
+#define DYNCRYPTO(x) \
+    p##x = wine_dlsym(OpenSSL_crypto_handle, #x, NULL, 0); \
+    if (!p##x) \
+    { \
+        ERR("failed to load symbol %s\n", #x); \
+        connection->useSSL = FALSE; \
+        return; \
+    }
+	DYNCRYPTO(BIO_new_fp);
+	DYNCRYPTO(BIO_new_socket);
+#undef DYNCRYPTO
+
+	pSSL_library_init();
+	pSSL_load_error_strings();
+	pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */
+
+	meth = pSSLv23_method();
+	/* FIXME: SECURITY PROBLEM! WE ARN'T VERIFYING THE HOSTS CERTIFICATES OR ANYTHING */
+#else
+	FIXME("can't use SSL, not compiled in.\n");
+        connection->useSSL = FALSE;
+#endif
+    }
+}
+
+BOOL NETCON_connected(WININET_NETCONNECTION *connection)
+{
+    if (!connection->useSSL)
+    {
+	if (connection->socketFD == -1)
+	    return FALSE;
+	return TRUE;
+    }
+    else
+    {
+#ifdef HAVE_OPENSSL
+	if (connection->ssl_sock == -1)
+	    return FALSE;
+        return TRUE;
+#else
+	return FALSE;
+#endif
+    }
+}
+
+/******************************************************************************
+ * NETCON_create
+ * Basically calls 'socket()' unless useSSL is supplised,
+ *  in which case we do other things.
+ */
+BOOL NETCON_create(WININET_NETCONNECTION *connection, int domain,
+	      int type, int protocol)
+{
+    if (!connection->useSSL)
+    {
+	connection->socketFD = socket(domain, type, protocol);
+	if (connection->socketFD == -1)
+	    return FALSE;
+	return TRUE;
+    }
+    else
+    {
+#ifdef HAVE_OPENSSL
+        connection->ssl_sock = socket(domain, type, protocol);
+        return TRUE;
+#else
+	return FALSE;
+#endif
+    }
+}
+
+/******************************************************************************
+ * NETCON_close
+ * Basically calls 'close()' unless we should use SSL
+ */
+BOOL NETCON_close(WININET_NETCONNECTION *connection)
+{
+    if (!NETCON_connected) return FALSE;
+    if (!connection->useSSL)
+    {
+        int result;
+	result = close(connection->socketFD);
+        connection->socketFD = -1;
+	if (result == -1)
+	    return FALSE;
+        return TRUE;
+    }
+    else
+    {
+#ifdef HAVE_OPENSSL
+	close(connection->ssl_sock);
+	connection->ssl_sock = -1;
+	/* FIXME should we call SSL_shutdown here?? Probably on whatever is the
+	 * opposite of NETCON_init.... */
+        return TRUE;
+#else
+	return FALSE;
+#endif
+    }
+}
+
+/******************************************************************************
+ * NETCON_connect
+ * Basically calls 'connect()' unless we should use SSL
+ */
+BOOL NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *serv_addr,
+		    socklen_t addrlen)
+{
+    if (!NETCON_connected) return FALSE;
+    if (!connection->useSSL)
+    {
+	int result;
+	result = connect(connection->socketFD, serv_addr, addrlen);
+	if (result == -1)
+	    return FALSE;
+        return TRUE;
+    }
+    else
+    {
+#ifdef HAVE_OPENSSL
+        BIO *sbio;
+
+        ctx = pSSL_CTX_new(meth);
+	connection->ssl_s = pSSL_new(ctx);
+
+	if (connect(connection->ssl_sock, serv_addr, addrlen) == -1)
+	    return FALSE;
+
+	sbio = pBIO_new_socket(connection->ssl_sock, BIO_NOCLOSE);
+        pSSL_set_bio(connection->ssl_s, sbio, sbio);
+	if (pSSL_connect(connection->ssl_s) <= 0)
+	{
+            ERR("ssl couldn't connect\n");
+	    return FALSE;
+	}
+	return TRUE;
+#else
+	return FALSE;
+#endif
+    }
+}
+
+/******************************************************************************
+ * NETCON_send
+ * Basically calls 'send()' unless we should use SSL
+ * number of chars send is put in *sent
+ */
+BOOL NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int flags,
+		int *sent /* out */)
+{
+    if (!NETCON_connected) return FALSE;
+    if (!connection->useSSL)
+    {
+	*sent = send(connection->socketFD, msg, len, flags);
+	if (*sent == -1)
+	    return FALSE;
+        return TRUE;
+    }
+    else
+    {
+#ifdef HAVE_OPENSSL
+	if (flags)
+            FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
+	*sent = pSSL_write(connection->ssl_s, msg, len);
+	if (*sent < 1 && len)
+	    return FALSE;
+        return TRUE;
+#else
+	return FALSE;
+#endif
+    }
+}
+
+/******************************************************************************
+ * NETCON_recv
+ * Basically calls 'recv()' unless we should use SSL
+ * number of chars receieved is put in *recvd
+ */
+BOOL NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags,
+		int *recvd /* out */)
+{
+    if (!NETCON_connected) return FALSE;
+    if (!connection->useSSL)
+    {
+	*recvd = recv(connection->socketFD, buf, len, flags);
+	if (*recvd == -1)
+	    return FALSE;
+        return TRUE;
+    }
+    else
+    {
+#ifdef HAVE_OPENSSL
+	static char *peek_msg = NULL;
+	static char *peek_msg_mem = NULL;
+
+	if (flags & (~MSG_PEEK))
+	    FIXME("SSL_read does not support the following flag: %08x\n", flags);
+
+        /* this ugly hack is all for MSG_PEEK. eww gross */
+	if (flags & MSG_PEEK && !peek_msg)
+	{
+	    peek_msg = peek_msg_mem = HeapAlloc(GetProcessHeap(), 0, (sizeof(char) * len) + 1);
+	}
+	else if (flags & MSG_PEEK && peek_msg)
+	{
+	    if (len < strlen(peek_msg))
+		FIXME("buffer isn't big enough. Do the expect us to wrap?\n");
+	    strncpy(buf, peek_msg, len);
+	    *recvd = (strlen(peek_msg) <= len ? strlen(peek_msg) : len);
+            return TRUE;
+	}
+	else if (peek_msg)
+	{
+	    strncpy(buf, peek_msg, len);
+	    peek_msg += *recvd = min(len, strlen(peek_msg));
+	    if (*peek_msg == '\0' || *(peek_msg - 1) == '\0')
+	    {
+		HeapFree(GetProcessHeap(), 0, peek_msg_mem);
+		peek_msg_mem = NULL;
+                peek_msg = NULL;
+	    }
+            return TRUE;
+	}
+	*recvd = pSSL_read(connection->ssl_s, buf, len);
+	if (flags & MSG_PEEK) /* must copy stuff into buffer */
+	{
+	    if (!*recvd)
+	    {
+		HeapFree(GetProcessHeap(), 0, peek_msg_mem);
+		peek_msg_mem = NULL;
+                peek_msg = NULL;
+	    }
+	    else
+	    {
+		strncpy(peek_msg, buf, *recvd);
+		peek_msg[*recvd] = '\0';
+	    }
+	}
+	if (*recvd < 1 && len)
+            return FALSE;
+        return TRUE;
+#else
+	return FALSE;
+#endif
+    }
+}
+
+/******************************************************************************
+ * NETCON_getNextLine
+ */
+BOOL NETCON_getNextLine(WININET_NETCONNECTION *connection, LPSTR lpszBuffer, LPDWORD dwBuffer)
+{
+
+    TRACE("\n");
+
+    if (!NETCON_connected(connection)) return FALSE;
+
+    if (!connection->useSSL)
+    {
+	struct timeval tv;
+	fd_set infd;
+	BOOL bSuccess = FALSE;
+	INT nRecv = 0;
+
+	FD_ZERO(&infd);
+	FD_SET(connection->socketFD, &infd);
+	tv.tv_sec=RESPONSE_TIMEOUT;
+	tv.tv_usec=0;
+
+	while (nRecv < *dwBuffer)
+	{
+	    if (select(connection->socketFD+1,&infd,NULL,NULL,&tv) > 0)
+	    {
+		if (recv(connection->socketFD, &lpszBuffer[nRecv], 1, 0) <= 0)
+		{
+		    INTERNET_SetLastError(ERROR_CONNECTION_ABORTED); /* fixme: right error? */
+		    goto lend;
+		}
+
+		if (lpszBuffer[nRecv] == '\n')
+		{
+		    bSuccess = TRUE;
+		    break;
+		}
+		if (lpszBuffer[nRecv] != '\r')
+		    nRecv++;
+	    }
+	    else
+	    {
+		INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
+		goto lend;
+	    }
+	}
+
+    lend:             /* FIXME: don't use labels */
+	if (bSuccess)
+	{
+	    lpszBuffer[nRecv] = '\0';
+	    *dwBuffer = nRecv - 1;
+	    TRACE(":%d %s\n", nRecv, lpszBuffer);
+            return TRUE;
+	}
+	else
+	{
+	    return FALSE;
+	}
+    }
+    else
+    {
+#ifdef HAVE_OPENSSL
+	long prev_timeout;
+	INT nRecv = 0;
+        BOOL success = TRUE;
+
+        prev_timeout = pSSL_CTX_get_timeout(ctx);
+	pSSL_CTX_set_timeout(ctx, RESPONSE_TIMEOUT);
+
+	while (nRecv < *dwBuffer)
+	{
+	    int recv = 1;
+	    if (!NETCON_recv(connection, &lpszBuffer[nRecv], 1, 0, &recv))
+	    {
+                INTERNET_SetLastError(ERROR_CONNECTION_ABORTED);
+		success = FALSE;
+	    }
+
+	    if (lpszBuffer[nRecv] == '\n')
+	    {
+		success = TRUE;
+                break;
+	    }
+	    if (lpszBuffer[nRecv] != '\r')
+		nRecv++;
+	}
+
+        pSSL_CTX_set_timeout(ctx, prev_timeout);
+	if (success)
+	{
+	    lpszBuffer[nRecv] = '\0';
+	    *dwBuffer = nRecv - 1;
+	    TRACE("_SSL:%d %s\n", nRecv, lpszBuffer);
+            return TRUE;
+	}
+        return FALSE;
+#else
+	return FALSE;
+#endif
+    }
+}
+
--- /dev/null	1994-07-18 08:46:18.000000000 +0900
+++ dlls/wininet/cookie.c	2003-06-02 17:55:54.000000000 +0900
@@ -0,0 +1,493 @@
+/*
+ * Wininet - cookie handling stuff
+ *
+ * Copyright 2002 TransGaming Technologies Inc.
+ *
+ * David Hammerton
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wininet.h"
+#include "winerror.h"
+
+#include "wine/debug.h"
+#include "internet.h"
+
+#define RESPONSE_TIMEOUT        30            /* FROM internet.c */
+
+
+WINE_DEFAULT_DEBUG_CHANNEL(wininet);
+
+/* FIXME
+ *     Cookies are currently memory only.
+ *     Cookies are NOT THREAD SAFE
+ *     Cookies could use ALOT OF MEMORY. We need some kind of memory management here!
+ *     Cookies should care about the expiry time
+ */
+
+typedef struct _cookie_domain cookie_domain;
+typedef struct _cookie cookie;
+
+struct _cookie
+{
+    struct _cookie *next;
+    struct _cookie *prev;
+
+    struct _cookie_domain *parent;
+
+    LPSTR lpCookieName;
+    LPSTR lpCookieData;
+    time_t expiry; /* FIXME: not used */
+};
+
+struct _cookie_domain
+{
+    struct _cookie_domain *next;
+    struct _cookie_domain *prev;
+
+    LPSTR lpCookieDomain;
+    LPSTR lpCookiePath;
+    cookie *cookie_tail;
+};
+
+cookie_domain *cookieDomainTail = NULL;
+
+cookie *COOKIE_addCookie(cookie_domain *domain, LPCSTR name, LPCSTR data);
+cookie *COOKIE_findCookie(cookie_domain *domain, LPCSTR lpszCookieName);
+void COOKIE_deleteCookie(cookie *deadCookie, BOOL deleteDomain);
+cookie_domain *COOKIE_addDomain(LPCSTR domain, LPCSTR path);
+cookie_domain *COOKIE_addDomainFromUrl(LPCSTR lpszUrl);
+cookie_domain *COOKIE_findNextDomain(LPCSTR lpszCookieDomain, LPCSTR lpszCookiePath,
+				    cookie_domain *prev_domain, BOOL allow_partial);
+cookie_domain *COOKIE_findNextDomainFromUrl(LPCSTR lpszUrl, cookie_domain *prev_domain,
+					   BOOL allow_partial);
+void COOKIE_deleteDomain(cookie_domain *deadDomain);
+
+
+/* adds a cookie to the domain */
+cookie *COOKIE_addCookie(cookie_domain *domain, LPCSTR name, LPCSTR data)
+{
+    cookie *newCookie = HeapAlloc(GetProcessHeap(), 0, sizeof(cookie));
+
+    newCookie->next = NULL;
+    newCookie->prev = NULL;
+    newCookie->lpCookieName = NULL;
+    newCookie->lpCookieData = NULL;
+
+    if (name)
+    {
+	newCookie->lpCookieName = HeapAlloc(GetProcessHeap(), 0, strlen(name) + 1);
+        strcpy(newCookie->lpCookieName, name);
+    }
+    if (data)
+    {
+	newCookie->lpCookieData = HeapAlloc(GetProcessHeap(), 0, strlen(data) + 1);
+        strcpy(newCookie->lpCookieData, data);
+    }
+
+    TRACE("added cookie %p (data is %s)\n", newCookie, data);
+
+    newCookie->prev = domain->cookie_tail;
+    newCookie->parent = domain;
+    domain->cookie_tail = newCookie;
+    return newCookie;
+}
+
+
+/* finds a cookie in the domain matching the cookie name */
+cookie *COOKIE_findCookie(cookie_domain *domain, LPCSTR lpszCookieName)
+{
+    cookie *searchCookie = domain->cookie_tail;
+    TRACE("(%p, %s)\n", domain, debugstr_a(lpszCookieName));
+
+    while (searchCookie)
+    {
+	BOOL candidate = TRUE;
+	if (candidate && lpszCookieName)
+	{
+	    if (candidate && !searchCookie->lpCookieName)
+		candidate = FALSE;
+	    if (candidate && strcmp(lpszCookieName, searchCookie->lpCookieName) != 0)
+                candidate = FALSE;
+	}
+	if (candidate)
+	    return searchCookie;
+        searchCookie = searchCookie->prev;
+    }
+    return NULL;
+}
+
+/* removes a cookie from the list, if its the last cookie we also remove the domain */
+void COOKIE_deleteCookie(cookie *deadCookie, BOOL deleteDomain)
+{
+    if (deadCookie->lpCookieName)
+	HeapFree(GetProcessHeap(), 0, deadCookie->lpCookieName);
+    if (deadCookie->lpCookieData)
+	HeapFree(GetProcessHeap(), 0, deadCookie->lpCookieData);
+    if (deadCookie->prev)
+        deadCookie->prev->next = deadCookie->next;
+    if (deadCookie->next)
+	deadCookie->next->prev = deadCookie->prev;
+
+    if (deadCookie == deadCookie->parent->cookie_tail)
+    {
+	/* special case: last cookie, lets remove the domain to save memory */
+	deadCookie->parent->cookie_tail = deadCookie->prev;
+        if (!deadCookie->parent->cookie_tail && deleteDomain)
+	    COOKIE_deleteDomain(deadCookie->parent);
+    }
+}
+
+/* allocates a domain and adds it to the end */
+cookie_domain *COOKIE_addDomain(LPCSTR domain, LPCSTR path)
+{
+    cookie_domain *newDomain = HeapAlloc(GetProcessHeap(), 0, sizeof(cookie_domain));
+
+    newDomain->next = NULL;
+    newDomain->prev = NULL;
+    newDomain->cookie_tail = NULL;
+    newDomain->lpCookieDomain = NULL;
+    newDomain->lpCookiePath = NULL;
+
+    if (domain)
+    {
+	newDomain->lpCookieDomain = HeapAlloc(GetProcessHeap(), 0, strlen(domain) + 1);
+        strcpy(newDomain->lpCookieDomain, domain);
+    }
+    if (path)
+    {
+	newDomain->lpCookiePath = HeapAlloc(GetProcessHeap(), 0, strlen(path) + 1);
+        strcpy(newDomain->lpCookiePath, path);
+    }
+
+    newDomain->prev = cookieDomainTail;
+    cookieDomainTail = newDomain;
+    TRACE("Adding domain: %p\n", newDomain);
+    return newDomain;
+}
+
+cookie_domain *COOKIE_addDomainFromUrl(LPCSTR lpszUrl)
+{
+    char hostName[2048], path[2048];
+    URL_COMPONENTSA UrlComponents;
+
+    UrlComponents.lpszExtraInfo = NULL;
+    UrlComponents.lpszPassword = NULL;
+    UrlComponents.lpszScheme = NULL;
+    UrlComponents.lpszUrlPath = path;
+    UrlComponents.lpszUserName = NULL;
+    UrlComponents.lpszHostName = hostName;
+    UrlComponents.dwHostNameLength = 2048;
+    UrlComponents.dwUrlPathLength = 2048;
+
+    InternetCrackUrlA(lpszUrl, 0, 0, &UrlComponents);
+
+    TRACE("Url cracked. Domain: %s, Path: %s.\n", debugstr_a(UrlComponents.lpszHostName),
+	  debugstr_a(UrlComponents.lpszUrlPath));
+
+    /* hack for now - FIXME - There seems to be a bug in InternetCrackUrl?? */
+    UrlComponents.lpszUrlPath = NULL;
+
+    return COOKIE_addDomain(UrlComponents.lpszHostName, UrlComponents.lpszUrlPath);
+}
+
+/* find a domain. domain must match if its not NULL. path must match if its not NULL */
+cookie_domain *COOKIE_findNextDomain(LPCSTR lpszCookieDomain, LPCSTR lpszCookiePath,
+				    cookie_domain *prev_domain, BOOL allow_partial)
+{
+    cookie_domain *searchDomain;
+
+    if (prev_domain)
+    {
+	if(!prev_domain->prev)
+	{
+	    TRACE("no more domains available, it would seem.\n");
+            return NULL;
+	}
+	searchDomain = prev_domain->prev;
+    }
+    else searchDomain = cookieDomainTail;
+
+    while (searchDomain)
+    {
+	BOOL candidate = TRUE;
+        TRACE("searching on domain %p\n", searchDomain);
+	if (candidate && lpszCookieDomain)
+	{
+	    if (candidate && !searchDomain->lpCookieDomain)
+		candidate = FALSE;
+            TRACE("candidate! (%p)\n", searchDomain->lpCookieDomain);
+	    TRACE("comparing domain %s with %s\n", lpszCookieDomain, searchDomain->lpCookieDomain);
+	    if (candidate && allow_partial && !strstr(lpszCookieDomain, searchDomain->lpCookieDomain))
+                candidate = FALSE;
+	    else if (candidate && !allow_partial &&
+		     strcmp(lpszCookieDomain, searchDomain->lpCookieDomain) != 0)
+                candidate = FALSE;
+ 	}
+	if (candidate && lpszCookiePath)
+	{                           TRACE("comparing paths\n");
+	    if (candidate && !searchDomain->lpCookiePath)
+                candidate = FALSE;
+	    if (candidate && strcmp(lpszCookiePath, searchDomain->lpCookiePath) != 0)
+                candidate = FALSE;
+	}
+	if (candidate)
+	{
+            TRACE("returning the domain %p\n", searchDomain);
+	    return searchDomain;
+	}
+	searchDomain = searchDomain->prev;
+    }
+    TRACE("found no domain, returning NULL\n");
+    return NULL;
+}
+
+cookie_domain *COOKIE_findNextDomainFromUrl(LPCSTR lpszUrl, cookie_domain *previous_domain,
+					   BOOL allow_partial)
+{
+    char hostName[2048], path[2048];
+    URL_COMPONENTSA UrlComponents;
+
+    UrlComponents.lpszExtraInfo = NULL;
+    UrlComponents.lpszPassword = NULL;
+    UrlComponents.lpszScheme = NULL;
+    UrlComponents.lpszUrlPath = path;
+    UrlComponents.lpszUserName = NULL;
+    UrlComponents.lpszHostName = hostName;
+    UrlComponents.dwHostNameLength = 2048;
+    UrlComponents.dwUrlPathLength = 2048;
+
+    InternetCrackUrlA(lpszUrl, 0, 0, &UrlComponents);
+
+    TRACE("Url cracked. Domain: %s, Path: %s.\n", debugstr_a(UrlComponents.lpszHostName),
+	  debugstr_a(UrlComponents.lpszUrlPath));
+
+    /* hack for now - FIXME - There seems to be a bug in InternetCrackUrl?? */
+    UrlComponents.lpszUrlPath = NULL;
+
+    return COOKIE_findNextDomain(UrlComponents.lpszHostName, UrlComponents.lpszUrlPath,
+				 previous_domain, allow_partial);
+}
+
+/* remove a domain from the list and delete it */
+void COOKIE_deleteDomain(cookie_domain *deadDomain)
+{
+    while (deadDomain->cookie_tail)
+	COOKIE_deleteCookie(deadDomain->cookie_tail, FALSE);
+    if (deadDomain->lpCookieDomain)
+	HeapFree(GetProcessHeap(), 0, deadDomain->lpCookieDomain);
+    if (deadDomain->lpCookiePath)
+	HeapFree(GetProcessHeap(), 0, deadDomain->lpCookiePath);
+    if (deadDomain->prev)
+	deadDomain->prev->next = deadDomain->next;
+    if (deadDomain->next)
+	deadDomain->next->prev = deadDomain->prev;
+
+    if (cookieDomainTail == deadDomain)
+	cookieDomainTail = deadDomain->prev;
+    HeapFree(GetProcessHeap(), 0, deadDomain);
+}
+
+/***********************************************************************
+ *           InternetGetCookieA (WININET.@)
+ *
+ * Retrieve cookie from the specified url
+ *
+ *  It should be noted that on windows the lpszCookieName parameter is "not implemented".
+ *    So it won't be implemented here.
+ *
+ * RETURNS
+ *    TRUE  on success
+ *    FALSE on failure
+ *
+ */
+BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
+    LPSTR lpCookieData, LPDWORD lpdwSize)
+{
+    cookie_domain *cookiesDomain = NULL;
+    cookie *thisCookie;
+    int cnt = 0, domain_count = 0;
+    /* Ok, this is just ODD!. During my tests, it appears M$ like to send out
+     * a cookie called 'MtrxTracking' to some urls. Also returns it from InternetGetCookie.
+     * I'm not exactly sure what to make of this, so its here for now.
+     * It'd be nice to know what exactly is going on, M$ tracking users? Does this need
+     * to be unique? Should I generate a random number here? etc.
+     */
+    char *TrackingString = "MtrxTrackingID=01234567890123456789012345678901";
+
+    TRACE("(%s, %s, %p, %p)\n", debugstr_a(lpszUrl),debugstr_a(lpszCookieName),
+	  lpCookieData, lpdwSize);
+
+    if (lpCookieData)
+	cnt += snprintf(lpCookieData + cnt, *lpdwSize - cnt, "%s", TrackingString);
+    else
+	cnt += strlen(TrackingString);
+
+    while ((cookiesDomain = COOKIE_findNextDomainFromUrl(lpszUrl, cookiesDomain, TRUE)))
+    {
+        domain_count++;
+	TRACE("found domain %p\n", cookiesDomain);
+
+	thisCookie = cookiesDomain->cookie_tail;
+	if (lpCookieData == NULL) /* return the size of the buffer required to lpdwSize */
+	{
+	    while (thisCookie)
+	    {
+		cnt += 2; /* '; ' */
+		cnt += strlen(thisCookie->lpCookieName);
+		cnt += 1; /* = */
+		cnt += strlen(thisCookie->lpCookieData);
+
+		thisCookie = thisCookie->prev;
+	    }
+	}
+	while (thisCookie)
+	{
+            cnt += snprintf(lpCookieData + cnt, *lpdwSize - cnt, "; ");
+	    cnt += snprintf(lpCookieData + cnt, *lpdwSize - cnt, "%s=%s", thisCookie->lpCookieName,
+			    thisCookie->lpCookieData);
+
+	    thisCookie = thisCookie->prev;
+	}
+    }
+    if (lpCookieData == NULL)
+    {
+	cnt += 1; /* NULL */
+	*lpdwSize = cnt;
+	TRACE("returning\n");
+	return TRUE;
+    }
+
+    if (!domain_count)
+        return FALSE;
+
+    *lpdwSize = cnt + 1;
+
+    TRACE("Returning %i (from %i domains): %s\n", cnt, domain_count, lpCookieData);
+
+    return (cnt ? TRUE : FALSE);
+}
+
+
+/***********************************************************************
+ *           InternetGetCookieW (WININET.@)
+ *
+ * Retrieve cookie from the specified url
+ *
+ * RETURNS
+ *    TRUE  on success
+ *    FALSE on failure
+ *
+ */
+BOOL WINAPI InternetGetCookieW(LPCSTR lpszUrl, LPCWSTR lpszCookieName,
+    LPWSTR lpCookieData, LPDWORD lpdwSize)
+{
+    FIXME("STUB\n");
+    TRACE("(%s,%s,%p)\n", debugstr_a(lpszUrl), debugstr_w(lpszCookieName),
+        lpCookieData);
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           InternetSetCookieA (WININET.@)
+ *
+ * Sets cookie for the specified url
+ *
+ * RETURNS
+ *    TRUE  on success
+ *    FALSE on failure
+ *
+ */
+BOOL WINAPI InternetSetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
+    LPCSTR lpCookieData)
+{
+    cookie *thisCookie;
+    cookie_domain *thisCookieDomain;
+
+    TRACE("(%s,%s,%s)\n", debugstr_a(lpszUrl),
+        debugstr_a(lpszCookieName), lpCookieData);
+
+    if (!lpCookieData || !strlen(lpCookieData))
+    {
+        TRACE("no cookie data, not adding\n");
+	return FALSE;
+    }
+    if (!lpszCookieName)
+    {
+	/* some apps (or is it us??) try to add a cookie with no cookie name, but
+         * the cookie data in the form of name=data. */
+	/* FIXME, probably a bug here, for now I don't care */
+	char *ourCookieName, *ourCookieData;
+	int ourCookieNameSize;
+        BOOL ret;
+	if (!(ourCookieData = strchr(lpCookieData, '=')))
+	{
+            TRACE("something terribly wrong with cookie data %s\n", ourCookieData);
+	    return FALSE;
+	}
+	ourCookieNameSize = ourCookieData - lpCookieData;
+	ourCookieData += 1;
+	ourCookieName = HeapAlloc(GetProcessHeap(), 0, ourCookieNameSize + 1);
+	strncpy(ourCookieName, ourCookieData, ourCookieNameSize);
+	ourCookieName[ourCookieNameSize] = '\0';
+	TRACE("setting (hacked) cookie of %s, %s\n", ourCookieName, ourCookieData);
+        ret = InternetSetCookieA(lpszUrl, ourCookieName, ourCookieData);
+	HeapFree(GetProcessHeap(), 0, ourCookieName);
+        return ret;
+    }
+
+    if (!(thisCookieDomain = COOKIE_findNextDomainFromUrl(lpszUrl, NULL, FALSE)))
+        thisCookieDomain = COOKIE_addDomainFromUrl(lpszUrl);
+
+    if ((thisCookie = COOKIE_findCookie(thisCookieDomain, lpszCookieName)))
+	COOKIE_deleteCookie(thisCookie, FALSE);
+
+    thisCookie = COOKIE_addCookie(thisCookieDomain, lpszCookieName, lpCookieData);
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           InternetSetCookieW (WININET.@)
+ *
+ * Sets cookie for the specified url
+ *
+ * RETURNS
+ *    TRUE  on success
+ *    FALSE on failure
+ *
+ */
+BOOL WINAPI InternetSetCookieW(LPCSTR lpszUrl, LPCWSTR lpszCookieName,
+    LPCWSTR lpCookieData)
+{
+    FIXME("STUB\n");
+    TRACE("(%s,%s,%s)\n", debugstr_a(lpszUrl),
+        debugstr_w(lpszCookieName), debugstr_w(lpCookieData));
+    return FALSE;
+}
+
+
+
+


More information about the wine-patches mailing list