Take 2.
Fixed an error in the merge of InternetReadFile. Use diff -uw to make the formatting ugly.
Take 1.
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@transgaming.com for Transgaming * implement support for https protocol * fixes to the http protocol
Mike Hearn wrote:
Well, I'm spending my fun afternoon trying to get IE to install in Wine (it breaks in a new and interesting way every time I try this).
Before the patch, it didn't work, couldn't contact download sites. After the patch, it still doesn't work, and I get this fixme:
fixme:wininet:InternetReadFile This shouldn't be here! We don't support this kind of connection anymore. Must use NETCON functions, especially if using SSL
Which seems a bit of a bummer, if IE6 setup needs that type of connection I think we should still support it really......
I think the problem might be lack of proxy workingness. Am investigating now. Would be nice to lift proxy details from the http_proxy variable in future....
One last thing, the patch seemed to have a lot of whitespace no-ops, running diff with -bB should eliminate some.
thanks -mike
Index: configure.ac =================================================================== RCS file: /home/wine/wine/configure.ac,v retrieving revision 1.160 diff -u -w -r1.160 configure.ac --- configure.ac 21 May 2003 18:50:53 -0000 1.160 +++ configure.ac 3 Jun 2003 11:09:01 -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 -w -r1.20 Makefile.in --- dlls/wininet/Makefile.in 14 Apr 2003 21:32:36 -0000 1.20 +++ dlls/wininet/Makefile.in 3 Jun 2003 11:09:01 -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 -w -r1.35 http.c --- dlls/wininet/http.c 16 May 2003 20:12:03 -0000 1.35 +++ dlls/wininet/http.c 3 Jun 2003 11:09:02 -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 @@ -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) { @@ -121,6 +125,8 @@ if (!lpszHeader) return TRUE; + + TRACE("copying header: %s\n", lpszHeader); buffer = HTTP_strdup(lpszHeader); lpszStart = buffer; @@ -140,6 +146,7 @@ *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); @@ -203,7 +210,10 @@ 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; @@ -249,15 +259,20 @@ 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); - - 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); + 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) + { + 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; } /*********************************************************************** @@ -308,6 +391,9 @@ LPWININETHTTPSESSIONA lpwhs = (LPWININETHTTPSESSIONA) hHttpSession; LPWININETAPPINFOA hIC = NULL; LPWININETHTTPREQA lpwhr; + LPSTR lpszCookies; + LPSTR lpszUrl = NULL; + DWORD nCookieSize; TRACE("--> \n"); @@ -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)) { @@ -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); @@ -940,6 +1054,11 @@ goto lend; } + do + { + TRACE("Going to url %s %s\n", debugstr_a(lpwhr->lpszHostName), debugstr_a(lpwhr->lpszPath)); + loop_next = FALSE; + /* If we don't have a path we set it to root */ if (NULL == lpwhr->lpszPath) lpwhr->lpszPath = HTTP_strdup("/"); @@ -958,7 +1077,6 @@ requestStringLen = strlen(lpwhr->lpszVerb) + strlen(lpwhr->lpszPath) + - (lpwhr->lpszHostName ? (strlen(HTTPHOSTHEADER) + strlen(lpwhr->lpszHostName)) : 0) + strlen(HTTPHEADER) + 5; /* " \r\n\r\n" */ @@ -989,6 +1107,10 @@ } } + if (lpwhr->lpszHostName) + requestStringLen += (strlen(HTTPHOSTHEADER) + strlen(lpwhr->lpszHostName)); + + /* Allocate string to hold entire request */ requestString = HeapAlloc(GetProcessHeap(), 0, requestStringLen + 1); if (NULL == requestString) @@ -998,11 +1120,10 @@ } /* Build request string */ - cnt = sprintf(requestString, "%s %s%s%s", + cnt = sprintf(requestString, "%s %s%s", lpwhr->lpszVerb, lpwhr->lpszPath, - lpwhr->lpszHostName ? (HTTPHEADER HTTPHOSTHEADER) : HTTPHEADER, - lpwhr->lpszHostName ? lpwhr->lpszHostName : ""); + HTTPHEADER); /* Append standard request headers */ for (i = 0; i <= HTTP_QUERY_MAX; i++) @@ -1026,6 +1147,9 @@ } } + if (lpwhr->lpszHostName) + cnt += sprintf(requestString + cnt, "%s%s", HTTPHOSTHEADER, lpwhr->lpszHostName); + /* Append passed request headers */ if (lpszHeaders) { @@ -1046,7 +1170,9 @@ SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0); - cnt = send(lpwhr->nSocketFD, requestString, requestStringLen, 0); + NETCON_send(&lpwhr->netConnection, requestString, requestStringLen, + 0, &cnt); + SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext, INTERNET_STATUS_REQUEST_SENT, @@ -1066,6 +1192,135 @@ 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; + + 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: if (requestString) @@ -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"); 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) @@ -1306,8 +1559,9 @@ do { buflen = MAX_REPLY_LEN; - if (INTERNET_GetNextLine(lpwhr->nSocketFD, buffer, &buflen)) + 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; @@ -1637,10 +1891,9 @@ SendAsyncCallback(hIC, lpwhr, lpwhr->hdr.dwContext, INTERNET_STATUS_CLOSING_CONNECTION, 0, 0); - if (lpwhr->nSocketFD != -1) + if (NETCON_connected(&lpwhr->netConnection)) { - close(lpwhr->nSocketFD); - lpwhr->nSocketFD = -1; + NETCON_close(&lpwhr->netConnection); } SendAsyncCallback(hIC, lpwhr, lpwhr->hdr.dwContext, @@ -1662,7 +1915,7 @@ TRACE("\n"); - if (lpwhr->nSocketFD != -1) + if (NETCON_connected(&lpwhr->netConnection)) HTTP_CloseConnection(lpwhr); lpwhs = (LPWININETHTTPSESSIONA) lpwhr->hdr.lpwhparent; @@ -1709,7 +1962,7 @@ void HTTP_CloseHTTPSessionHandle(LPWININETHTTPSESSIONA lpwhs) { LPWININETAPPINFOA hIC = NULL; - TRACE("\n"); + TRACE("%p\n", lpwhs); hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent; Index: dlls/wininet/internet.c =================================================================== RCS file: /home/wine/wine/dlls/wininet/internet.c,v retrieving revision 1.56 diff -u -w -r1.56 internet.c --- dlls/wininet/internet.c 11 May 2003 02:59:52 -0000 1.56 +++ dlls/wininet/internet.c 3 Jun 2003 11:09:03 -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; } @@ -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,14 +1278,29 @@ if (NULL == lpwh) return FALSE; + /* FIXME: this should use NETCON functions! */ switch (lpwh->htype) { case WH_HHTTPREQ: - nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD; + if (!NETCON_recv(&((LPWININETHTTPREQA)hFile)->netConnection, lpBuffer, + dwNumOfBytesToRead, 0, (int *)dwNumOfBytesRead)) + { + *dwNumOfBytesRead = 0; + retval = TRUE; /* Under windows, it seems to return 0 even if nothing was read... */ + } + else + retval = TRUE; break; case WH_HFILE: + /* FIXME: FTP should use NETCON_ stuff */ nSocket = ((LPWININETFILE)hFile)->nDataSocket; + if (nSocket != -1) + { + int res = recv(nSocket, lpBuffer, dwNumOfBytesToRead, 0); + retval = (res >= 0); + *dwNumOfBytesRead = retval ? res : 0; + } break; default: @@ -1332,7 +1361,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 +1636,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 +1732,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 +1757,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 +1836,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 +1856,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 +2195,6 @@ return lpwite->response; } - /*********************************************************************** * INTERNET_GetNextLine (internal) * @@ -2316,7 +2268,7 @@ { LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hFile; INT retval = -1; - int nSocket = -1; + char buffer[4048]; if (NULL == lpwhr) @@ -2325,32 +2277,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; - break; - - default: - break; - } - - if (nSocket != -1) - { - char buffer[4048]; - - retval = recv(nSocket,buffer,4048,MSG_PEEK); - } - else + if (!NETCON_recv(&((LPWININETHTTPREQA)hFile)->netConnection, buffer, + 4048, MSG_PEEK, (int *)lpdwNumberOfBytesAvailble)) { SetLastError(ERROR_NO_MORE_FILES); + retval = FALSE; } + else + retval = TRUE; + break; - if (lpdwNumberOfBytesAvailble) - { - (*lpdwNumberOfBytesAvailble) = retval; + default: + 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 -w -r1.10 internet.h --- dlls/wininet/internet.h 28 Aug 2002 23:43:43 -0000 1.10 +++ dlls/wininet/internet.h 3 Jun 2003 11:09:03 -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 -w -r1.155 config.h.in --- include/config.h.in 20 May 2003 17:48:40 -0000 1.155 +++ include/config.h.in 3 Jun 2003 11:09:04 -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