From 773786eb4c9f2c63e7c01b6ffa5bfd634a876ee1 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 22 Jun 2009 06:45:21 +0000 Subject: [PATCH] - Revert wininet back to pre-41059 - Fixes random corruption of downloads svn path=/trunk/; revision=41526 --- reactos/dll/win32/wininet/cookie.c | 182 +-- reactos/dll/win32/wininet/dialogs.c | 4 - reactos/dll/win32/wininet/ftp.c | 441 +++---- reactos/dll/win32/wininet/http.c | 1293 +++++++++------------ reactos/dll/win32/wininet/internet.c | 211 +--- reactos/dll/win32/wininet/internet.h | 40 +- reactos/dll/win32/wininet/netconnection.c | 185 ++- reactos/dll/win32/wininet/urlcache.c | 32 +- reactos/dll/win32/wininet/utility.c | 37 +- reactos/dll/win32/wininet/wininet.rbuild | 1 - reactos/dll/win32/wininet/wininet.spec | 12 +- 11 files changed, 979 insertions(+), 1459 deletions(-) diff --git a/reactos/dll/win32/wininet/cookie.c b/reactos/dll/win32/wininet/cookie.c index dc77b17265b..12d841bc7b9 100644 --- a/reactos/dll/win32/wininet/cookie.c +++ b/reactos/dll/win32/wininet/cookie.c @@ -23,10 +23,6 @@ #include "config.h" #include "wine/port.h" -#if defined(__MINGW32__) || defined (_MSC_VER) -#include -#endif - #include #include #include @@ -52,6 +48,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet); * Cookies are currently memory only. * Cookies are NOT THREAD SAFE * Cookies could use A LOT OF MEMORY. We need some kind of memory management here! + * Cookies should care about the expiry time */ typedef struct _cookie_domain cookie_domain; @@ -65,7 +62,7 @@ struct _cookie LPWSTR lpCookieName; LPWSTR lpCookieData; - FILETIME expiry; + time_t expiry; /* FIXME: not used */ }; struct _cookie_domain @@ -79,7 +76,7 @@ struct _cookie_domain static struct list domain_list = LIST_INIT(domain_list); -static cookie *COOKIE_addCookie(cookie_domain *domain, LPCWSTR name, LPCWSTR data, FILETIME expiry); +static cookie *COOKIE_addCookie(cookie_domain *domain, LPCWSTR name, LPCWSTR data); static cookie *COOKIE_findCookie(cookie_domain *domain, LPCWSTR lpszCookieName); static void COOKIE_deleteCookie(cookie *deadCookie, BOOL deleteDomain); static cookie_domain *COOKIE_addDomain(LPCWSTR domain, LPCWSTR path); @@ -87,14 +84,13 @@ static void COOKIE_deleteDomain(cookie_domain *deadDomain); /* adds a cookie to the domain */ -static cookie *COOKIE_addCookie(cookie_domain *domain, LPCWSTR name, LPCWSTR data, FILETIME expiry) +static cookie *COOKIE_addCookie(cookie_domain *domain, LPCWSTR name, LPCWSTR data) { cookie *newCookie = HeapAlloc(GetProcessHeap(), 0, sizeof(cookie)); list_init(&newCookie->entry); newCookie->lpCookieName = NULL; newCookie->lpCookieData = NULL; - newCookie->expiry = expiry; if (name) { @@ -181,7 +177,6 @@ static cookie_domain *COOKIE_addDomain(LPCWSTR domain, LPCWSTR path) static BOOL COOKIE_crackUrlSimple(LPCWSTR lpszUrl, LPWSTR hostName, int hostNameLen, LPWSTR path, int pathLen) { URL_COMPONENTSW UrlComponents; - BOOL rc; UrlComponents.lpszExtraInfo = NULL; UrlComponents.lpszPassword = NULL; @@ -196,22 +191,7 @@ static BOOL COOKIE_crackUrlSimple(LPCWSTR lpszUrl, LPWSTR hostName, int hostName UrlComponents.dwHostNameLength = hostNameLen; UrlComponents.dwUrlPathLength = pathLen; - rc = InternetCrackUrlW(lpszUrl, 0, 0, &UrlComponents); - - /* discard the webpage off the end of the path */ - if (pathLen > 0 && path[pathLen-1] != '/') - { - LPWSTR ptr; - ptr = strrchrW(path,'/'); - if (ptr) - *(++ptr) = 0; - else - { - path[0] = '/'; - path[1] = 0; - } - } - return rc; + return InternetCrackUrlW(lpszUrl, 0, 0, &UrlComponents); } /* match a domain. domain must match if the domain is not NULL. path must match if the path is not NULL */ @@ -235,22 +215,11 @@ static BOOL COOKIE_matchDomain(LPCWSTR lpszCookieDomain, LPCWSTR lpszCookiePath, } if (lpszCookiePath) { - INT len; TRACE("comparing paths: %s with %s\n", debugstr_w(lpszCookiePath), debugstr_w(searchDomain->lpCookiePath)); - /* paths match at the beginning. so a path of /foo would match - * /foobar and /foo/bar - */ if (!searchDomain->lpCookiePath) return FALSE; - if (allow_partial) - { - len = lstrlenW(searchDomain->lpCookiePath); - if (strncmpiW(searchDomain->lpCookiePath, lpszCookiePath, len)!=0) - return FALSE; - } - else if (strcmpW(lpszCookiePath, searchDomain->lpCookiePath)) + if (strcmpW(lpszCookiePath, searchDomain->lpCookiePath)) return FALSE; - } return TRUE; } @@ -293,7 +262,6 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, struct list * cursor; unsigned int cnt = 0, domain_count = 0, cookie_count = 0; WCHAR hostName[2048], path[2048]; - FILETIME tm; TRACE("(%s, %s, %p, %p)\n", debugstr_w(lpszUrl),debugstr_w(lpszCookieName), lpCookieData, lpdwSize); @@ -308,12 +276,10 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, ret = COOKIE_crackUrlSimple(lpszUrl, hostName, sizeof(hostName)/sizeof(hostName[0]), path, sizeof(path)/sizeof(path[0])); if (!ret || !hostName[0]) return FALSE; - GetSystemTimeAsFileTime(&tm); - LIST_FOR_EACH(cursor, &domain_list) { cookie_domain *cookiesDomain = LIST_ENTRY(cursor, cookie_domain, entry); - if (COOKIE_matchDomain(hostName, path, cookiesDomain, TRUE)) + if (COOKIE_matchDomain(hostName, NULL /* FIXME: path */, cookiesDomain, TRUE)) { struct list * cursor; domain_count++; @@ -322,14 +288,6 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, LIST_FOR_EACH(cursor, &cookiesDomain->cookie_list) { cookie *thisCookie = LIST_ENTRY(cursor, cookie, entry); - /* check for expiry */ - if ((thisCookie->expiry.dwLowDateTime != 0 || thisCookie->expiry.dwHighDateTime != 0) && CompareFileTime(&tm,&thisCookie->expiry) > 0) - { - TRACE("Found expired cookie. deleting\n"); - COOKIE_deleteCookie(thisCookie, FALSE); - continue; - } - if (lpCookieData == NULL) /* return the size of the buffer required to lpdwSize */ { unsigned int len; @@ -447,116 +405,27 @@ static BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWST cookie_domain *thisCookieDomain = NULL; cookie *thisCookie; struct list *cursor; - LPWSTR data, value; - WCHAR *ptr; - FILETIME expiry; - BOOL expired = FALSE; - - value = data = HeapAlloc(GetProcessHeap(), 0, (strlenW(cookie_data) + 1) * sizeof(WCHAR)); - strcpyW(data,cookie_data); - memset(&expiry,0,sizeof(expiry)); - - /* lots of information can be parsed out of the cookie value */ - - ptr = data; - for (;;) - { - static const WCHAR szDomain[] = {'d','o','m','a','i','n','=',0}; - static const WCHAR szPath[] = {'p','a','t','h','=',0}; - static const WCHAR szExpires[] = {'e','x','p','i','r','e','s','=',0}; - static const WCHAR szSecure[] = {'s','e','c','u','r','e',0}; - static const WCHAR szHttpOnly[] = {'h','t','t','p','o','n','l','y',0}; - - if (!(ptr = strchrW(ptr,';'))) break; - *ptr++ = 0; - - value = HeapAlloc(GetProcessHeap(), 0, (ptr - data) * sizeof(WCHAR)); - strcpyW(value, data); - - while (*ptr == ' ') ptr++; /* whitespace */ - - if (strncmpiW(ptr, szDomain, 7) == 0) - { - ptr+=strlenW(szDomain); - domain = ptr; - TRACE("Parsing new domain %s\n",debugstr_w(domain)); - } - else if (strncmpiW(ptr, szPath, 5) == 0) - { - ptr+=strlenW(szPath); - path = ptr; - TRACE("Parsing new path %s\n",debugstr_w(path)); - } - else if (strncmpiW(ptr, szExpires, 8) == 0) - { - FILETIME ft; - SYSTEMTIME st; - FIXME("persistent cookies not handled (%s)\n",debugstr_w(ptr)); - ptr+=strlenW(szExpires); - if (InternetTimeToSystemTimeW(ptr, &st, 0)) - { - SystemTimeToFileTime(&st, &expiry); - GetSystemTimeAsFileTime(&ft); - - if (CompareFileTime(&ft,&expiry) > 0) - { - TRACE("Cookie already expired.\n"); - expired = TRUE; - } - } - } - else if (strncmpiW(ptr, szSecure, 6) == 0) - { - FIXME("secure not handled (%s)\n",debugstr_w(ptr)); - ptr += strlenW(szSecure); - } - else if (strncmpiW(ptr, szHttpOnly, 8) == 0) - { - FIXME("httponly not handled (%s)\n",debugstr_w(ptr)); - ptr += strlenW(szHttpOnly); - } - else if (*ptr) - { - FIXME("Unknown additional option %s\n",debugstr_w(ptr)); - break; - } - } LIST_FOR_EACH(cursor, &domain_list) { thisCookieDomain = LIST_ENTRY(cursor, cookie_domain, entry); - if (COOKIE_matchDomain(domain, path, thisCookieDomain, FALSE)) + if (COOKIE_matchDomain(domain, NULL /* FIXME: path */, thisCookieDomain, FALSE)) break; thisCookieDomain = NULL; } if (!thisCookieDomain) - { - if (!expired) - thisCookieDomain = COOKIE_addDomain(domain, path); - else - { - HeapFree(GetProcessHeap(),0,data); - if (value != data) HeapFree(GetProcessHeap(), 0, value); - return TRUE; - } - } + thisCookieDomain = COOKIE_addDomain(domain, path); if ((thisCookie = COOKIE_findCookie(thisCookieDomain, cookie_name))) COOKIE_deleteCookie(thisCookie, FALSE); - TRACE("setting cookie %s=%s for domain %s path %s\n", debugstr_w(cookie_name), - debugstr_w(value), debugstr_w(thisCookieDomain->lpCookieDomain),debugstr_w(thisCookieDomain->lpCookiePath)); + TRACE("setting cookie %s=%s for domain %s\n", debugstr_w(cookie_name), + debugstr_w(cookie_data), debugstr_w(thisCookieDomain->lpCookieDomain)); - if (!expired && !COOKIE_addCookie(thisCookieDomain, cookie_name, value, expiry)) - { - HeapFree(GetProcessHeap(),0,data); - if (value != data) HeapFree(GetProcessHeap(), 0, value); + if (!COOKIE_addCookie(thisCookieDomain, cookie_name, cookie_data)) return FALSE; - } - HeapFree(GetProcessHeap(),0,data); - if (value != data) HeapFree(GetProcessHeap(), 0, value); return TRUE; } @@ -606,7 +475,7 @@ BOOL WINAPI InternetSetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, * the cookie data in the form of name[=data]. */ if (!(data = strchrW(cookie, '='))) data = cookie + len; - else *data++ = 0; + else data++; ret = set_cookie(hostName, path, cookie, data); @@ -823,28 +692,3 @@ BOOL WINAPI InternetSetPerSiteCookieDecisionW( LPCWSTR pchHostName, DWORD dwDeci FIXME("(%s, 0x%08x) stub\n", debugstr_w(pchHostName), dwDecision); return FALSE; } - -/*********************************************************************** - * IsDomainLegalCookieDomainW (WININET.@) - */ -BOOL WINAPI IsDomainLegalCookieDomainW( LPCWSTR s1, LPCWSTR s2 ) -{ - const WCHAR *p; - - FIXME("(%s, %s)\n", debugstr_w(s1), debugstr_w(s2)); - - if (!s1 || !s2) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - if (s1[0] == '.' || !s1[0] || s2[0] == '.' || !s2[0]) - { - SetLastError(ERROR_INVALID_NAME); - return FALSE; - } - if (!(p = strchrW(s2, '.'))) return FALSE; - if (strchrW(p + 1, '.') && !strcmpW(p + 1, s1)) return TRUE; - else if (!strcmpW(s1, s2)) return TRUE; - return FALSE; -} diff --git a/reactos/dll/win32/wininet/dialogs.c b/reactos/dll/win32/wininet/dialogs.c index 41494a67509..dd5aa315a63 100644 --- a/reactos/dll/win32/wininet/dialogs.c +++ b/reactos/dll/win32/wininet/dialogs.c @@ -21,10 +21,6 @@ #include "config.h" #include "wine/port.h" -#if defined(__MINGW32__) || defined (_MSC_VER) -#include -#endif - #include #include "windef.h" diff --git a/reactos/dll/win32/wininet/ftp.c b/reactos/dll/win32/wininet/ftp.c index db0bf569ebc..cb24782fa4b 100644 --- a/reactos/dll/win32/wininet/ftp.c +++ b/reactos/dll/win32/wininet/ftp.c @@ -30,10 +30,6 @@ #include "config.h" #include "wine/port.h" -#if defined(__MINGW32__) || defined (_MSC_VER) -#include -#endif - #include #include #include @@ -46,9 +42,6 @@ #ifdef HAVE_UNISTD_H # include #endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif #include #include @@ -97,7 +90,7 @@ typedef struct BOOL bIsDirectory; LPWSTR lpszName; DWORD nSize; - SYSTEMTIME tmLastModified; + struct tm tmLastModified; unsigned short permissions; } FILEPROPERTIESW, *LPFILEPROPERTIESW; @@ -206,6 +199,8 @@ static BOOL FTP_FtpGetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPWSTR lpszC static BOOL FTP_FtpRenameFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszSrc, LPCWSTR lpszDest); static BOOL FTP_FtpRemoveDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory); static BOOL FTP_FtpDeleteFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName); +static HINTERNET FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName, + DWORD fdwAccess, DWORD dwFlags, DWORD_PTR dwContext); static BOOL FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile, BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags, DWORD_PTR dwContext); @@ -859,13 +854,13 @@ lend: if (hFindNext) { - iar.dwResult = (DWORD_PTR)hFindNext; + iar.dwResult = (DWORD)hFindNext; iar.dwError = ERROR_SUCCESS; SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED, &iar, sizeof(INTERNET_ASYNC_RESULT)); } - iar.dwResult = (DWORD_PTR)hFindNext; + iar.dwResult = (DWORD)hFindNext; iar.dwError = hFindNext ? ERROR_SUCCESS : INTERNET_GetLastError(); SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar, sizeof(INTERNET_ASYNC_RESULT)); @@ -1076,6 +1071,118 @@ lend: return bSuccess; } +/*********************************************************************** + * FtpOpenFileA (WININET.@) + * + * Open a remote file for writing or reading + * + * RETURNS + * HINTERNET handle on success + * NULL on failure + * + */ +HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession, + LPCSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags, + DWORD_PTR dwContext) +{ + LPWSTR lpwzFileName; + HINTERNET ret; + + lpwzFileName = lpszFileName?WININET_strdup_AtoW(lpszFileName):NULL; + ret = FtpOpenFileW(hFtpSession, lpwzFileName, fdwAccess, dwFlags, dwContext); + HeapFree(GetProcessHeap(), 0, lpwzFileName); + return ret; +} + + +static void AsyncFtpOpenFileProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_FTPOPENFILEW const *req = &workRequest->u.FtpOpenFileW; + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr; + + TRACE("%p\n", lpwfs); + + FTP_FtpOpenFileW(lpwfs, req->lpszFilename, + req->dwAccess, req->dwFlags, req->dwContext); + HeapFree(GetProcessHeap(), 0, req->lpszFilename); +} + +/*********************************************************************** + * FtpOpenFileW (WININET.@) + * + * Open a remote file for writing or reading + * + * RETURNS + * HINTERNET handle on success + * NULL on failure + * + */ +HINTERNET WINAPI FtpOpenFileW(HINTERNET hFtpSession, + LPCWSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags, + DWORD_PTR dwContext) +{ + LPWININETFTPSESSIONW lpwfs; + LPWININETAPPINFOW hIC = NULL; + HINTERNET r = NULL; + + TRACE("(%p,%s,0x%08x,0x%08x,0x%08lx)\n", hFtpSession, + debugstr_w(lpszFileName), fdwAccess, dwFlags, dwContext); + + lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession ); + if (!lpwfs) + { + INTERNET_SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (WH_HFTPSESSION != lpwfs->hdr.htype) + { + INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); + goto lend; + } + + if ((!lpszFileName) || + ((fdwAccess != GENERIC_READ) && (fdwAccess != GENERIC_WRITE)) || + ((dwFlags & FTP_CONDITION_MASK) > FTP_TRANSFER_TYPE_BINARY)) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + goto lend; + } + + if (lpwfs->download_in_progress != NULL) + { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + goto lend; + } + + hIC = lpwfs->lpAppInfo; + if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) + { + WORKREQUEST workRequest; + struct WORKREQ_FTPOPENFILEW *req; + + workRequest.asyncproc = AsyncFtpOpenFileProc; + workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); + req = &workRequest.u.FtpOpenFileW; + req->lpszFilename = WININET_strdupW(lpszFileName); + req->dwAccess = fdwAccess; + req->dwFlags = dwFlags; + req->dwContext = dwContext; + + INTERNET_AsyncCall(&workRequest); + r = NULL; + } + else + { + r = FTP_FtpOpenFileW(lpwfs, lpszFileName, fdwAccess, dwFlags, dwContext); + } + +lend: + WININET_Release( &lpwfs->hdr ); + + return r; +} + /*********************************************************************** * FTPFILE_Destroy(internal) @@ -1092,6 +1199,8 @@ static void FTPFILE_Destroy(WININETHANDLEHEADER *hdr) TRACE("\n"); + WININET_Release(&lpwh->lpFtpSession->hdr); + if (!lpwh->session_deleted) lpwfs->download_in_progress = NULL; @@ -1101,8 +1210,6 @@ static void FTPFILE_Destroy(WININETHANDLEHEADER *hdr) nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext); if (nResCode > 0 && nResCode != 226) WARN("server reports failed transfer\n"); - WININET_Release(&lpwh->lpFtpSession->hdr); - HeapFree(GetProcessHeap(), 0, lpwh); } @@ -1138,18 +1245,6 @@ static DWORD FTPFILE_ReadFile(WININETHANDLEHEADER *hdr, void *buffer, DWORD size return res>=0 ? ERROR_SUCCESS : INTERNET_ERROR_BASE; /* FIXME*/ } -static DWORD FTPFILE_ReadFileExA(WININETHANDLEHEADER *hdr, INTERNET_BUFFERSA *buffers, - DWORD flags, DWORD_PTR context) -{ - return FTPFILE_ReadFile(hdr, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength); -} - -static DWORD FTPFILE_ReadFileExW(WININETHANDLEHEADER *hdr, INTERNET_BUFFERSW *buffers, - DWORD flags, DWORD_PTR context) -{ - return FTPFILE_ReadFile(hdr, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength); -} - static BOOL FTPFILE_WriteFile(WININETHANDLEHEADER *hdr, const void *buffer, DWORD size, DWORD *written) { LPWININETFTPFILE lpwh = (LPWININETFTPFILE) hdr; @@ -1161,85 +1256,15 @@ static BOOL FTPFILE_WriteFile(WININETHANDLEHEADER *hdr, const void *buffer, DWOR return res >= 0; } -static void FTP_ReceiveRequestData(WININETFTPFILE *file, BOOL first_notif) -{ - INTERNET_ASYNC_RESULT iar; - BYTE buffer[4096]; - int available; - - TRACE("%p\n", file); - - available = recv(file->nDataSocket, buffer, sizeof(buffer), MSG_PEEK); - - if(available != -1) { - iar.dwResult = (DWORD_PTR)file->hdr.hInternet; - iar.dwError = first_notif ? 0 : available; - }else { - iar.dwResult = 0; - iar.dwError = INTERNET_GetLastError(); - } - - INTERNET_SendCallback(&file->hdr, file->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar, - sizeof(INTERNET_ASYNC_RESULT)); -} - -static void FTPFILE_AsyncQueryDataAvailableProc(WORKREQUEST *workRequest) -{ - WININETFTPFILE *file = (WININETFTPFILE*)workRequest->hdr; - - FTP_ReceiveRequestData(file, FALSE); -} - -static DWORD FTPFILE_QueryDataAvailable(WININETHANDLEHEADER *hdr, DWORD *available, DWORD flags, DWORD_PTR ctx) -{ - LPWININETFTPFILE file = (LPWININETFTPFILE) hdr; - int retval, unread = 0; - - TRACE("(%p %p %x %lx)\n", file, available, flags, ctx); - -#ifdef FIONREAD - retval = ioctlsocket(file->nDataSocket, FIONREAD, &unread); - if (!retval) - TRACE("%d bytes of queued, but unread data\n", unread); -#else - FIXME("FIONREAD not available\n"); -#endif - - *available = unread; - - if(!unread) { - BYTE byte; - - *available = 0; - - retval = recv(file->nDataSocket, &byte, 1, MSG_PEEK); - if(retval > 0) { - WORKREQUEST workRequest; - - *available = 0; - workRequest.asyncproc = FTPFILE_AsyncQueryDataAvailableProc; - workRequest.hdr = WININET_AddRef( &file->hdr ); - - INTERNET_AsyncCall(&workRequest); - - return ERROR_IO_PENDING; - } - } - - return ERROR_SUCCESS; -} - - static const HANDLEHEADERVtbl FTPFILEVtbl = { FTPFILE_Destroy, NULL, FTPFILE_QueryOption, NULL, FTPFILE_ReadFile, - FTPFILE_ReadFileExA, - FTPFILE_ReadFileExW, + NULL, FTPFILE_WriteFile, - FTPFILE_QueryDataAvailable, + NULL, NULL }; @@ -1314,20 +1339,16 @@ HINTERNET FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs, if (lpwh) { - iar.dwResult = (DWORD_PTR)handle; + iar.dwResult = (DWORD)handle; iar.dwError = ERROR_SUCCESS; SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED, &iar, sizeof(INTERNET_ASYNC_RESULT)); } - if(bSuccess) { - FTP_ReceiveRequestData(lpwh, TRUE); - }else { - iar.dwResult = 0; - iar.dwError = INTERNET_GetLastError(); - SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, - &iar, sizeof(INTERNET_ASYNC_RESULT)); - } + iar.dwResult = (DWORD)bSuccess; + iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError(); + SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, + &iar, sizeof(INTERNET_ASYNC_RESULT)); } lend: @@ -1338,119 +1359,6 @@ lend: } -/*********************************************************************** - * FtpOpenFileA (WININET.@) - * - * Open a remote file for writing or reading - * - * RETURNS - * HINTERNET handle on success - * NULL on failure - * - */ -HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession, - LPCSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags, - DWORD_PTR dwContext) -{ - LPWSTR lpwzFileName; - HINTERNET ret; - - lpwzFileName = lpszFileName?WININET_strdup_AtoW(lpszFileName):NULL; - ret = FtpOpenFileW(hFtpSession, lpwzFileName, fdwAccess, dwFlags, dwContext); - HeapFree(GetProcessHeap(), 0, lpwzFileName); - return ret; -} - - -static void AsyncFtpOpenFileProc(WORKREQUEST *workRequest) -{ - struct WORKREQ_FTPOPENFILEW const *req = &workRequest->u.FtpOpenFileW; - LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr; - - TRACE("%p\n", lpwfs); - - FTP_FtpOpenFileW(lpwfs, req->lpszFilename, - req->dwAccess, req->dwFlags, req->dwContext); - HeapFree(GetProcessHeap(), 0, req->lpszFilename); -} - -/*********************************************************************** - * FtpOpenFileW (WININET.@) - * - * Open a remote file for writing or reading - * - * RETURNS - * HINTERNET handle on success - * NULL on failure - * - */ -HINTERNET WINAPI FtpOpenFileW(HINTERNET hFtpSession, - LPCWSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags, - DWORD_PTR dwContext) -{ - LPWININETFTPSESSIONW lpwfs; - LPWININETAPPINFOW hIC = NULL; - HINTERNET r = NULL; - - TRACE("(%p,%s,0x%08x,0x%08x,0x%08lx)\n", hFtpSession, - debugstr_w(lpszFileName), fdwAccess, dwFlags, dwContext); - - lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession ); - if (!lpwfs) - { - INTERNET_SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - - if (WH_HFTPSESSION != lpwfs->hdr.htype) - { - INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); - goto lend; - } - - if ((!lpszFileName) || - ((fdwAccess != GENERIC_READ) && (fdwAccess != GENERIC_WRITE)) || - ((dwFlags & FTP_CONDITION_MASK) > FTP_TRANSFER_TYPE_BINARY)) - { - INTERNET_SetLastError(ERROR_INVALID_PARAMETER); - goto lend; - } - - if (lpwfs->download_in_progress != NULL) - { - INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); - goto lend; - } - - hIC = lpwfs->lpAppInfo; - if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) - { - WORKREQUEST workRequest; - struct WORKREQ_FTPOPENFILEW *req; - - workRequest.asyncproc = AsyncFtpOpenFileProc; - workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); - req = &workRequest.u.FtpOpenFileW; - req->lpszFilename = WININET_strdupW(lpszFileName); - req->dwAccess = fdwAccess; - req->dwFlags = dwFlags; - req->dwContext = dwContext; - - INTERNET_AsyncCall(&workRequest); - r = NULL; - } - else - { - r = FTP_FtpOpenFileW(lpwfs, lpszFileName, fdwAccess, dwFlags, dwContext); - } - -lend: - WININET_Release( &lpwfs->hdr ); - - return r; -} - - /*********************************************************************** * FtpGetFileA (WININET.@) * @@ -2348,7 +2256,7 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, assert( hIC->hdr.htype == WH_HINIT ); - if ((!lpszUserName || !*lpszUserName) && lpszPassword && *lpszPassword) + if (NULL == lpszUserName && NULL != lpszPassword) { INTERNET_SetLastError(ERROR_INVALID_PARAMETER); goto lerror; @@ -2394,7 +2302,7 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, if(hIC->lpszProxyBypass) FIXME("Proxy bypass is ignored.\n"); } - if (!lpszUserName || !strlenW(lpszUserName)) { + if ( !lpszUserName) { HKEY key; WCHAR szPassword[MAX_PATH]; DWORD len = sizeof(szPassword); @@ -2428,7 +2336,7 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, { INTERNET_ASYNC_RESULT iar; - iar.dwResult = (DWORD_PTR)handle; + iar.dwResult = (DWORD)handle; iar.dwError = ERROR_SUCCESS; SendAsyncCallback(&hIC->hdr, dwContext, @@ -2489,6 +2397,16 @@ lerror: handle = NULL; } + if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) + { + INTERNET_ASYNC_RESULT iar; + + iar.dwResult = bSuccess ? (DWORD_PTR)lpwfs : 0; + iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError(); + SendAsyncCallback(&hIC->hdr, dwContext, INTERNET_STATUS_REQUEST_COMPLETE, + &iar, sizeof(INTERNET_ASYNC_RESULT)); + } + return handle; } @@ -2819,7 +2737,7 @@ static BOOL FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs) lpwfs->lstnSocketAddress = lpwfs->socketAddress; /* and get the system to assign us a port */ - lpwfs->lstnSocketAddress.sin_port = htons(0); + lpwfs->lstnSocketAddress.sin_port = htons((u_short) 0); if (bind(lpwfs->lstnSocket,(struct sockaddr *) &lpwfs->lstnSocketAddress, sizeof(struct sockaddr_in)) == -1) { @@ -3302,7 +3220,7 @@ static void FTPFINDNEXT_Destroy(WININETHANDLEHEADER *hdr) HeapFree(GetProcessHeap(), 0, lpwfn); } -static DWORD FTPFINDNEXT_FindNextFileProc(WININETFTPFINDNEXTW *find, LPVOID data) +static DWORD WINAPI FTPFINDNEXT_FindNextFileProc(WININETFTPFINDNEXTW *find, LPVOID data) { WIN32_FIND_DATAW *find_data = data; DWORD res = ERROR_SUCCESS; @@ -3390,7 +3308,6 @@ static const HANDLEHEADERVtbl FTPFINDNEXTVtbl = { NULL, NULL, NULL, - NULL, FTPFINDNEXT_FindNextFileW }; @@ -3465,7 +3382,9 @@ static BOOL FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp, LPWIN32_FIND_DATAW lpFi if (lpafp) { - SystemTimeToFileTime( &lpafp->tmLastModified, &lpFindFileData->ftLastAccessTime ); + /* Convert 'Unix' time to Windows time */ + RtlSecondsSince1970ToTime(mktime(&lpafp->tmLastModified), + (LARGE_INTEGER *) &(lpFindFileData->ftLastAccessTime)); lpFindFileData->ftLastWriteTime = lpFindFileData->ftLastAccessTime; lpFindFileData->ftCreationTime = lpFindFileData->ftLastAccessTime; @@ -3533,12 +3452,12 @@ static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERT lpfp->nSize = atol(pszToken); } - lpfp->tmLastModified.wSecond = 0; - lpfp->tmLastModified.wMinute = 0; - lpfp->tmLastModified.wHour = 0; - lpfp->tmLastModified.wDay = 0; - lpfp->tmLastModified.wMonth = 0; - lpfp->tmLastModified.wYear = 0; + lpfp->tmLastModified.tm_sec = 0; + lpfp->tmLastModified.tm_min = 0; + lpfp->tmLastModified.tm_hour = 0; + lpfp->tmLastModified.tm_mday = 0; + lpfp->tmLastModified.tm_mon = 0; + lpfp->tmLastModified.tm_year = 0; /* Determine month */ pszToken = strtok(NULL, szSpace); @@ -3546,31 +3465,34 @@ static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERT if(strlen(pszToken) >= 3) { pszToken[3] = 0; if((pszTmp = StrStrIA(szMonths, pszToken))) - lpfp->tmLastModified.wMonth = ((pszTmp - szMonths) / 3)+1; + lpfp->tmLastModified.tm_mon = ((pszTmp - szMonths) / 3)+1; } /* Determine day */ pszToken = strtok(NULL, szSpace); if(!pszToken) continue; - lpfp->tmLastModified.wDay = atoi(pszToken); + lpfp->tmLastModified.tm_mday = atoi(pszToken); /* Determine time or year */ pszToken = strtok(NULL, szSpace); if(!pszToken) continue; if((pszTmp = strchr(pszToken, ':'))) { - SYSTEMTIME curr_time; + struct tm* apTM; + time_t aTime; *pszTmp = 0; pszTmp++; - lpfp->tmLastModified.wMinute = atoi(pszTmp); - lpfp->tmLastModified.wHour = atoi(pszToken); - GetLocalTime( &curr_time ); - lpfp->tmLastModified.wYear = curr_time.wYear; + lpfp->tmLastModified.tm_min = atoi(pszTmp); + lpfp->tmLastModified.tm_hour = atoi(pszToken); + time(&aTime); + apTM = localtime(&aTime); + lpfp->tmLastModified.tm_year = apTM->tm_year; } else { - lpfp->tmLastModified.wYear = atoi(pszToken); - lpfp->tmLastModified.wHour = 12; + lpfp->tmLastModified.tm_year = atoi(pszToken) - 1900; + lpfp->tmLastModified.tm_hour = 12; } - TRACE("Mod time: %02d:%02d:%02d %04d/%02d/%02d\n", - lpfp->tmLastModified.wHour, lpfp->tmLastModified.wMinute, lpfp->tmLastModified.wSecond, - lpfp->tmLastModified.wYear, lpfp->tmLastModified.wMonth, lpfp->tmLastModified.wDay); + TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n", + lpfp->tmLastModified.tm_hour, lpfp->tmLastModified.tm_min, lpfp->tmLastModified.tm_sec, + (lpfp->tmLastModified.tm_year >= 100) ? lpfp->tmLastModified.tm_year - 100 : lpfp->tmLastModified.tm_year, + lpfp->tmLastModified.tm_mon, lpfp->tmLastModified.tm_mday); pszToken = strtok(NULL, szSpace); if(!pszToken) continue; @@ -3583,31 +3505,32 @@ static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERT 05-09-03 06:02PM 12656686 2003-04-21bgm_cmd_e.rgz */ else if(isdigit(pszToken[0]) && 8 == strlen(pszToken)) { - int mon, mday, year, hour, min; lpfp->permissions = 0xFFFF; /* No idea, put full permission :-) */ - sscanf(pszToken, "%d-%d-%d", &mon, &mday, &year); - lpfp->tmLastModified.wDay = mday; - lpfp->tmLastModified.wMonth = mon; - lpfp->tmLastModified.wYear = year; + sscanf(pszToken, "%d-%d-%d", + &lpfp->tmLastModified.tm_mon, + &lpfp->tmLastModified.tm_mday, + &lpfp->tmLastModified.tm_year); /* Hacky and bad Y2K protection :-) */ - if (lpfp->tmLastModified.wYear < 70) lpfp->tmLastModified.wYear += 2000; - + if (lpfp->tmLastModified.tm_year < 70) + lpfp->tmLastModified.tm_year += 100; + pszToken = strtok(NULL, szSpace); if(!pszToken) continue; - sscanf(pszToken, "%d:%d", &hour, &min); - lpfp->tmLastModified.wHour = hour; - lpfp->tmLastModified.wMinute = min; + sscanf(pszToken, "%d:%d", + &lpfp->tmLastModified.tm_hour, + &lpfp->tmLastModified.tm_min); if((pszToken[5] == 'P') && (pszToken[6] == 'M')) { - lpfp->tmLastModified.wHour += 12; + lpfp->tmLastModified.tm_hour += 12; } - lpfp->tmLastModified.wSecond = 0; - - TRACE("Mod time: %02d:%02d:%02d %04d/%02d/%02d\n", - lpfp->tmLastModified.wHour, lpfp->tmLastModified.wMinute, lpfp->tmLastModified.wSecond, - lpfp->tmLastModified.wYear, lpfp->tmLastModified.wMonth, lpfp->tmLastModified.wDay); + lpfp->tmLastModified.tm_sec = 0; + TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n", + lpfp->tmLastModified.tm_hour, lpfp->tmLastModified.tm_min, lpfp->tmLastModified.tm_sec, + (lpfp->tmLastModified.tm_year >= 100) ? lpfp->tmLastModified.tm_year - 100 : lpfp->tmLastModified.tm_year, + lpfp->tmLastModified.tm_mon, lpfp->tmLastModified.tm_mday); + pszToken = strtok(NULL, szSpace); if(!pszToken) continue; if(!strcasecmp(pszToken, "")) { diff --git a/reactos/dll/win32/wininet/http.c b/reactos/dll/win32/wininet/http.c index 6e699ff3437..f0ad6beddc1 100644 --- a/reactos/dll/win32/wininet/http.c +++ b/reactos/dll/win32/wininet/http.c @@ -29,10 +29,6 @@ #include "config.h" #include "wine/port.h" -#if defined(__MINGW32__) || defined (_MSC_VER) -#include -#endif - #include #ifdef HAVE_SYS_SOCKET_H # include @@ -63,7 +59,6 @@ #include "internet.h" #include "wine/debug.h" -#include "wine/exception.h" #include "wine/unicode.h" #include "inet_ntop.c" @@ -81,7 +76,6 @@ static const WCHAR szProxy_Authorization[] = { 'P','r','o','x','y','-','A','u',' static const WCHAR szStatus[] = { 'S','t','a','t','u','s',0 }; static const WCHAR szKeepAlive[] = {'K','e','e','p','-','A','l','i','v','e',0}; static const WCHAR szGET[] = { 'G','E','T', 0 }; -static const WCHAR szCrLf[] = {'\r','\n', 0}; #define MAXHOSTNAME 100 #define MAX_FIELD_VALUE_LEN 256 @@ -122,15 +116,15 @@ static BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQW lpwhr, LPHTTPHEADERW lpHdr static INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQW lpwhr, LPCWSTR lpszField, INT index, BOOL Request); static BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQW lpwhr, DWORD index); static LPWSTR HTTP_build_req( LPCWSTR *list, int len ); -static BOOL HTTP_HttpQueryInfoW(LPWININETHTTPREQW, DWORD, LPVOID, LPDWORD, LPDWORD); -static LPWSTR HTTP_GetRedirectURL(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl); +static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD + dwInfoLevel, LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD + lpdwIndex); static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl); static UINT HTTP_DecodeBase64(LPCWSTR base64, LPSTR bin); static BOOL HTTP_VerifyValidHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field); static void HTTP_DrainContent(WININETHTTPREQW *req); -static BOOL HTTP_FinishedReading(LPWININETHTTPREQW lpwhr); -static LPHTTPHEADERW HTTP_GetHeader(LPWININETHTTPREQW req, LPCWSTR head) +LPHTTPHEADERW HTTP_GetHeader(LPWININETHTTPREQW req, LPCWSTR head) { int HeaderIndex = 0; HeaderIndex = HTTP_GetCustomHeaderIndex(req, head, 0, TRUE); @@ -140,29 +134,6 @@ static LPHTTPHEADERW HTTP_GetHeader(LPWININETHTTPREQW req, LPCWSTR head) return &req->pCustHeaders[HeaderIndex]; } -/* set the request content length based on the headers */ -static DWORD set_content_length( LPWININETHTTPREQW lpwhr ) -{ - static const WCHAR szChunked[] = {'c','h','u','n','k','e','d',0}; - WCHAR encoding[20]; - DWORD size; - - size = sizeof(lpwhr->dwContentLength); - if (!HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH, - &lpwhr->dwContentLength, &size, NULL)) - lpwhr->dwContentLength = ~0u; - - size = sizeof(encoding); - if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_TRANSFER_ENCODING, encoding, &size, NULL) && - !strcmpiW(encoding, szChunked)) - { - lpwhr->dwContentLength = ~0u; - lpwhr->read_chunked = TRUE; - } - - return lpwhr->dwContentLength; -} - /*********************************************************************** * HTTP_Tokenize (internal) * @@ -175,26 +146,21 @@ static LPWSTR * HTTP_Tokenize(LPCWSTR string, LPCWSTR token_string) int i; LPCWSTR next_token; - if (string) - { - /* empty string has no tokens */ - if (*string) - tokens++; - /* count tokens */ - for (i = 0; string[i]; i++) + /* empty string has no tokens */ + if (*string) + tokens++; + /* count tokens */ + for (i = 0; string[i]; i++) + if (!strncmpW(string+i, token_string, strlenW(token_string))) { - if (!strncmpW(string+i, token_string, strlenW(token_string))) - { - DWORD j; - tokens++; - /* we want to skip over separators, but not the null terminator */ - for (j = 0; j < strlenW(token_string) - 1; j++) - if (!string[i+j]) - break; - i += j; - } + DWORD j; + tokens++; + /* we want to skip over separators, but not the null terminator */ + for (j = 0; j < strlenW(token_string) - 1; j++) + if (!string[i+j]) + break; + i += j; } - } /* add 1 for terminating NULL */ token_array = HeapAlloc(GetProcessHeap(), 0, (tokens+1) * sizeof(*token_array)); @@ -292,6 +258,7 @@ static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR ve LPWSTR p; static const WCHAR szSpace[] = { ' ',0 }; + static const WCHAR szcrlf[] = {'\r','\n', 0}; static const WCHAR szColon[] = { ':',' ',0 }; static const WCHAR sztwocrlf[] = {'\r','\n','\r','\n', 0}; @@ -312,7 +279,7 @@ static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR ve { if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST) { - req[n++] = szCrLf; + req[n++] = szcrlf; req[n++] = lpwhr->pCustHeaders[i].lpszField; req[n++] = szColon; req[n++] = lpwhr->pCustHeaders[i].lpszValue; @@ -346,29 +313,82 @@ static void HTTP_ProcessCookies( LPWININETHTTPREQW lpwhr ) { static const WCHAR szSet_Cookie[] = { 'S','e','t','-','C','o','o','k','i','e',0 }; int HeaderIndex; - int numCookies = 0; LPHTTPHEADERW setCookieHeader; - while((HeaderIndex = HTTP_GetCustomHeaderIndex(lpwhr, szSet_Cookie, numCookies, FALSE)) != -1) - { - setCookieHeader = &lpwhr->pCustHeaders[HeaderIndex]; + HeaderIndex = HTTP_GetCustomHeaderIndex(lpwhr, szSet_Cookie, 0, FALSE); + if (HeaderIndex == -1) + return; + setCookieHeader = &lpwhr->pCustHeaders[HeaderIndex]; - if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES) && setCookieHeader->lpszValue) + if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES) && setCookieHeader->lpszValue) + { + int nPosStart = 0, nPosEnd = 0, len; + static const WCHAR szFmt[] = { 'h','t','t','p',':','/','/','%','s','/',0}; + + while (setCookieHeader->lpszValue[nPosEnd] != '\0') { - int len; - static const WCHAR szFmt[] = { 'h','t','t','p',':','/','/','%','s','%','s',0}; + LPWSTR buf_cookie, cookie_name, cookie_data; LPWSTR buf_url; + LPWSTR domain = NULL; LPHTTPHEADERW Host; + 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; + static const WCHAR szDomain[] = {'d','o','m','a','i','n','=',0}; + LPWSTR lpszDomain = strstrW(&setCookieHeader->lpszValue[nPosEnd], szDomain); + if (lpszDomain) + { /* they have specified their own domain, lets use it */ + while (lpszDomain[nDomainPosEnd] != ';' && lpszDomain[nDomainPosEnd] != ',' && + lpszDomain[nDomainPosEnd] != '\0') + { + nDomainPosEnd++; + } + nDomainPosStart = strlenW(szDomain); + nDomainLength = (nDomainPosEnd - nDomainPosStart) + 1; + domain = HeapAlloc(GetProcessHeap(), 0, (nDomainLength + 1)*sizeof(WCHAR)); + lstrcpynW(domain, &lpszDomain[nDomainPosStart], nDomainLength + 1); + } + } + if (setCookieHeader->lpszValue[nPosEnd] == '\0') break; + buf_cookie = HeapAlloc(GetProcessHeap(), 0, ((nPosEnd - nPosStart) + 1)*sizeof(WCHAR)); + lstrcpynW(buf_cookie, &setCookieHeader->lpszValue[nPosStart], (nPosEnd - nPosStart) + 1); + TRACE("%s\n", debugstr_w(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)*sizeof(WCHAR)); + lstrcpynW(cookie_name, buf_cookie, nEqualPos + 1); + cookie_data = &buf_cookie[nEqualPos + 1]; + Host = HTTP_GetHeader(lpwhr,szHost); - len = lstrlenW(Host->lpszValue) + 9 + lstrlenW(lpwhr->lpszPath); + len = lstrlenW((domain ? domain : (Host?Host->lpszValue:NULL))) + + strlenW(lpwhr->lpszPath) + 9; buf_url = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); - sprintfW(buf_url, szFmt, Host->lpszValue, lpwhr->lpszPath); - InternetSetCookieW(buf_url, NULL, setCookieHeader->lpszValue); + sprintfW(buf_url, szFmt, (domain ? domain : (Host?Host->lpszValue:NULL))); /* FIXME PATH!!! */ + InternetSetCookieW(buf_url, cookie_name, cookie_data); HeapFree(GetProcessHeap(), 0, buf_url); + HeapFree(GetProcessHeap(), 0, buf_cookie); + HeapFree(GetProcessHeap(), 0, cookie_name); + HeapFree(GetProcessHeap(), 0, domain); + nPosStart = nPosEnd; } - numCookies++; } } @@ -594,7 +614,7 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue, /*********************************************************************** * HTTP_HttpAddRequestHeadersW (internal) */ -static BOOL HTTP_HttpAddRequestHeadersW(LPWININETHTTPREQW lpwhr, +static BOOL WINAPI HTTP_HttpAddRequestHeadersW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier) { LPWSTR lpszStart; @@ -636,13 +656,6 @@ static BOOL HTTP_HttpAddRequestHeadersW(LPWININETHTTPREQW lpwhr, lpszEnd += 2; /* Jump over \r\n */ } TRACE("interpreting header %s\n", debugstr_w(lpszStart)); - if (*lpszStart == '\0') - { - /* Skip 0-length headers */ - lpszStart = lpszEnd; - bSuccess = TRUE; - continue; - } pFieldAndValue = HTTP_InterpretHttpHeader(lpszStart); if (pFieldAndValue) { @@ -747,85 +760,57 @@ BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest, BOOL WINAPI HttpEndRequestA(HINTERNET hRequest, LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext) { - TRACE("(%p, %p, %08x, %08lx)\n", hRequest, lpBuffersOut, dwFlags, dwContext); + LPINTERNET_BUFFERSA ptr; + LPINTERNET_BUFFERSW lpBuffersOutW,ptrW; + BOOL rc = FALSE; - if (lpBuffersOut) + TRACE("(%p, %p, %08x, %08lx): stub\n", hRequest, lpBuffersOut, dwFlags, + dwContext); + + ptr = lpBuffersOut; + if (ptr) + lpBuffersOutW = (LPINTERNET_BUFFERSW)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, sizeof(INTERNET_BUFFERSW)); + else + lpBuffersOutW = NULL; + + ptrW = lpBuffersOutW; + while (ptr) { - INTERNET_SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + if (ptr->lpvBuffer && ptr->dwBufferLength) + ptrW->lpvBuffer = HeapAlloc(GetProcessHeap(),0,ptr->dwBufferLength); + ptrW->dwBufferLength = ptr->dwBufferLength; + ptrW->dwBufferTotal= ptr->dwBufferTotal; + + if (ptr->Next) + ptrW->Next = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, + sizeof(INTERNET_BUFFERSW)); + + ptr = ptr->Next; + ptrW = ptrW->Next; } - return HttpEndRequestW(hRequest, NULL, dwFlags, dwContext); -} + rc = HttpEndRequestW(hRequest, lpBuffersOutW, dwFlags, dwContext); -static BOOL HTTP_HttpEndRequestW(LPWININETHTTPREQW lpwhr, DWORD dwFlags, DWORD_PTR dwContext) -{ - BOOL rc = FALSE; - INT responseLen; - DWORD dwBufferSize; - INTERNET_ASYNC_RESULT iar; - - INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, - INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); - - responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE); - if (responseLen) - rc = TRUE; - - INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, - INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD)); - - /* process cookies here. Is this right? */ - HTTP_ProcessCookies(lpwhr); - - if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr); - - if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT)) + if (lpBuffersOutW) { - DWORD dwCode,dwCodeLength = sizeof(DWORD); - if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &dwCode, &dwCodeLength, NULL) && - (dwCode == 302 || dwCode == 301 || dwCode == 303)) + ptrW = lpBuffersOutW; + while (ptrW) { - WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH]; - dwBufferSize=sizeof(szNewLocation); - if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_LOCATION, szNewLocation, &dwBufferSize, NULL)) - { - /* redirects are always GETs */ - HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb); - lpwhr->lpszVerb = WININET_strdupW(szGET); - HTTP_DrainContent(lpwhr); - if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation ))) - { - INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT, - new_url, (strlenW(new_url) + 1) * sizeof(WCHAR)); - rc = HTTP_HandleRedirect(lpwhr, new_url); - if (rc) - rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE); - HeapFree( GetProcessHeap(), 0, new_url ); - } - } + LPINTERNET_BUFFERSW ptrW2; + + FIXME("Do we need to translate info out of these buffer?\n"); + + HeapFree(GetProcessHeap(),0,ptrW->lpvBuffer); + ptrW2 = ptrW->Next; + HeapFree(GetProcessHeap(),0,ptrW); + ptrW = ptrW2; } } - iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet; - iar.dwError = rc ? 0 : INTERNET_GetLastError(); - - INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, - INTERNET_STATUS_REQUEST_COMPLETE, &iar, - sizeof(INTERNET_ASYNC_RESULT)); return rc; } -static void AsyncHttpEndRequestProc(WORKREQUEST *work) -{ - struct WORKREQ_HTTPENDREQUESTW const *req = &work->u.HttpEndRequestW; - LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW)work->hdr; - - TRACE("%p\n", lpwhr); - - HTTP_HttpEndRequestW(lpwhr, req->dwFlags, req->dwContext); -} - /*********************************************************************** * HttpEndRequestW (WININET.@) * @@ -841,15 +826,10 @@ BOOL WINAPI HttpEndRequestW(HINTERNET hRequest, { BOOL rc = FALSE; LPWININETHTTPREQW lpwhr; + INT responseLen; + DWORD dwBufferSize; TRACE("-->\n"); - - if (lpBuffersOut) - { - INTERNET_SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest ); if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ) @@ -857,27 +837,58 @@ BOOL WINAPI HttpEndRequestW(HINTERNET hRequest, INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); if (lpwhr) WININET_Release( &lpwhr->hdr ); - return FALSE; + return FALSE; } + lpwhr->hdr.dwFlags |= dwFlags; + lpwhr->hdr.dwContext = dwContext; - if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) + /* We appear to do nothing with lpBuffersOut.. is that correct? */ + + SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, + INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); + + responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE); + if (responseLen) + rc = TRUE; + + SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, + INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD)); + + /* process cookies here. Is this right? */ + HTTP_ProcessCookies(lpwhr); + + dwBufferSize = sizeof(lpwhr->dwContentLength); + if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH, + &lpwhr->dwContentLength,&dwBufferSize,NULL)) + lpwhr->dwContentLength = -1; + + if (lpwhr->dwContentLength == 0) + HTTP_FinishedReading(lpwhr); + + if(!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT)) { - WORKREQUEST work; - struct WORKREQ_HTTPENDREQUESTW *request; - - work.asyncproc = AsyncHttpEndRequestProc; - work.hdr = WININET_AddRef( &lpwhr->hdr ); - - request = &work.u.HttpEndRequestW; - request->dwFlags = dwFlags; - request->dwContext = dwContext; - - INTERNET_AsyncCall(&work); - INTERNET_SetLastError(ERROR_IO_PENDING); + DWORD dwCode,dwCodeLength=sizeof(DWORD); + if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,&dwCode,&dwCodeLength,NULL) && + (dwCode==302 || dwCode==301)) + { + WCHAR szNewLocation[INTERNET_MAX_URL_LENGTH]; + dwBufferSize=sizeof(szNewLocation); + if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL)) + { + /* redirects are always GETs */ + HeapFree(GetProcessHeap(),0,lpwhr->lpszVerb); + lpwhr->lpszVerb = WININET_strdupW(szGET); + HTTP_DrainContent(lpwhr); + INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, + INTERNET_STATUS_REDIRECT, szNewLocation, + dwBufferSize); + rc = HTTP_HandleRedirect(lpwhr, szNewLocation); + if (rc) + rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE); + } + } } - else - rc = HTTP_HttpEndRequestW(lpwhr, dwFlags, dwContext); WININET_Release( &lpwhr->hdr ); TRACE("%i <--\n",rc); @@ -1006,20 +1017,12 @@ HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession, types = lpszAcceptTypes; while (*types) { - __TRY + /* find out how many there are */ + if (((ULONG_PTR)*types >> 16) && **types) { - /* find out how many there are */ - if (*types && **types) - { - TRACE("accept type: %s\n", debugstr_a(*types)); - acceptTypesCount++; - } + TRACE("accept type: %s\n", debugstr_a(*types)); + acceptTypesCount++; } - __EXCEPT_PAGE_FAULT - { - WARN("invalid accept type pointer\n"); - } - __ENDTRY; types++; } szAcceptTypes = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *) * (acceptTypesCount+1)); @@ -1029,26 +1032,20 @@ HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession, types = lpszAcceptTypes; while (*types) { - __TRY + if (((ULONG_PTR)*types >> 16) && **types) { - if (*types && **types) - { - len = MultiByteToWideChar(CP_ACP, 0, *types, -1, NULL, 0 ); - szAcceptTypes[acceptTypesCount] = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + len = MultiByteToWideChar(CP_ACP, 0, *types, -1, NULL, 0 ); + szAcceptTypes[acceptTypesCount] = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!szAcceptTypes[acceptTypesCount]) goto end; - MultiByteToWideChar(CP_ACP, 0, *types, -1, szAcceptTypes[acceptTypesCount], len); - acceptTypesCount++; - } + MultiByteToWideChar(CP_ACP, 0, *types, -1, szAcceptTypes[acceptTypesCount], len); + acceptTypesCount++; } - __EXCEPT_PAGE_FAULT - { - /* ignore invalid pointer */ - } - __ENDTRY; types++; } szAcceptTypes[acceptTypesCount] = NULL; } + else szAcceptTypes = 0; rc = HttpOpenRequestW(hHttpSession, szVerb, szObjectName, szVersion, szReferrer, @@ -1380,32 +1377,6 @@ static void HTTPREQ_Destroy(WININETHANDLEHEADER *hdr) WININET_Release(&lpwhr->lpHttpSession->hdr); - if (lpwhr->pAuthInfo) - { - if (SecIsValidHandle(&lpwhr->pAuthInfo->ctx)) - DeleteSecurityContext(&lpwhr->pAuthInfo->ctx); - if (SecIsValidHandle(&lpwhr->pAuthInfo->cred)) - FreeCredentialsHandle(&lpwhr->pAuthInfo->cred); - - HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->auth_data); - HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->scheme); - HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo); - lpwhr->pAuthInfo = NULL; - } - - if (lpwhr->pProxyAuthInfo) - { - if (SecIsValidHandle(&lpwhr->pProxyAuthInfo->ctx)) - DeleteSecurityContext(&lpwhr->pProxyAuthInfo->ctx); - if (SecIsValidHandle(&lpwhr->pProxyAuthInfo->cred)) - FreeCredentialsHandle(&lpwhr->pProxyAuthInfo->cred); - - HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->auth_data); - HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->scheme); - HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo); - lpwhr->pProxyAuthInfo = NULL; - } - HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath); HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb); HeapFree(GetProcessHeap(), 0, lpwhr->lpszRawHeaders); @@ -1431,6 +1402,31 @@ static void HTTPREQ_CloseConnection(WININETHANDLEHEADER *hdr) if (!NETCON_connected(&lpwhr->netConnection)) return; + if (lpwhr->pAuthInfo) + { + if (SecIsValidHandle(&lpwhr->pAuthInfo->ctx)) + DeleteSecurityContext(&lpwhr->pAuthInfo->ctx); + if (SecIsValidHandle(&lpwhr->pAuthInfo->cred)) + FreeCredentialsHandle(&lpwhr->pAuthInfo->cred); + + HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->auth_data); + HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->scheme); + HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo); + lpwhr->pAuthInfo = NULL; + } + if (lpwhr->pProxyAuthInfo) + { + if (SecIsValidHandle(&lpwhr->pProxyAuthInfo->ctx)) + DeleteSecurityContext(&lpwhr->pProxyAuthInfo->ctx); + if (SecIsValidHandle(&lpwhr->pProxyAuthInfo->cred)) + FreeCredentialsHandle(&lpwhr->pProxyAuthInfo->cred); + + HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->auth_data); + HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->scheme); + HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo); + lpwhr->pProxyAuthInfo = NULL; + } + INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_CLOSING_CONNECTION, 0, 0); @@ -1602,224 +1598,29 @@ static DWORD HTTPREQ_SetOption(WININETHANDLEHEADER *hdr, DWORD option, void *buf return NETCON_set_timeout(&req->netConnection, option == INTERNET_OPTION_SEND_TIMEOUT, *(DWORD*)buffer); - - case INTERNET_OPTION_USERNAME: - HeapFree(GetProcessHeap(), 0, req->lpHttpSession->lpszUserName); - if (!(req->lpHttpSession->lpszUserName = WININET_strdupW(buffer))) return ERROR_OUTOFMEMORY; - return ERROR_SUCCESS; - - case INTERNET_OPTION_PASSWORD: - HeapFree(GetProcessHeap(), 0, req->lpHttpSession->lpszPassword); - if (!(req->lpHttpSession->lpszPassword = WININET_strdupW(buffer))) return ERROR_OUTOFMEMORY; - return ERROR_SUCCESS; } return ERROR_INTERNET_INVALID_OPTION; } -/* read some more data into the read buffer */ -static BOOL read_more_data( WININETHTTPREQW *req, int maxlen ) +static DWORD HTTP_Read(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync) { - int len; + int bytes_read; - if (req->read_size && req->read_pos) - { - /* move existing data to the start of the buffer */ - memmove( req->read_buf, req->read_buf + req->read_pos, req->read_size ); - req->read_pos = 0; - } + if(!NETCON_recv(&req->netConnection, buffer, min(size, req->dwContentLength - req->dwContentRead), + sync ? MSG_WAITALL : 0, &bytes_read)) { + if(req->dwContentLength != -1 && req->dwContentRead != req->dwContentLength) + ERR("not all data received %d/%d\n", req->dwContentRead, req->dwContentLength); - if (maxlen == -1) maxlen = sizeof(req->read_buf); - if (!NETCON_recv( &req->netConnection, req->read_buf + req->read_size, - maxlen - req->read_size, 0, &len )) return FALSE; - req->read_size += len; - return TRUE; -} - -/* remove some amount of data from the read buffer */ -static void remove_data( WININETHTTPREQW *req, int count ) -{ - if (!(req->read_size -= count)) req->read_pos = 0; - else req->read_pos += count; -} - -static BOOL read_line( WININETHTTPREQW *req, LPSTR buffer, DWORD *len ) -{ - int count, bytes_read, pos = 0; - - for (;;) - { - char *eol = memchr( req->read_buf + req->read_pos, '\n', req->read_size ); - - if (eol) - { - count = eol - (req->read_buf + req->read_pos); - bytes_read = count + 1; - } - else count = bytes_read = req->read_size; - - count = min( count, *len - pos ); - memcpy( buffer + pos, req->read_buf + req->read_pos, count ); - pos += count; - remove_data( req, bytes_read ); - if (eol) break; - - if (!read_more_data( req, -1 )) return FALSE; - if (!req->read_size) - { - *len = 0; - TRACE( "returning empty string\n" ); - return FALSE; - } - } - - if (pos < *len) - { - if (pos && buffer[pos - 1] == '\r') pos--; - *len = pos + 1; - } - buffer[*len - 1] = 0; - TRACE( "returning %s\n", debugstr_a(buffer)); - return TRUE; -} - -/* discard data contents until we reach end of line */ -static BOOL discard_eol( WININETHTTPREQW *req ) -{ - do - { - char *eol = memchr( req->read_buf + req->read_pos, '\n', req->read_size ); - if (eol) - { - remove_data( req, (eol + 1) - (req->read_buf + req->read_pos) ); - break; - } - req->read_pos = req->read_size = 0; /* discard everything */ - if (!read_more_data( req, -1 )) return FALSE; - } while (req->read_size); - return TRUE; -} - -/* read the size of the next chunk */ -static BOOL start_next_chunk( WININETHTTPREQW *req ) -{ - DWORD chunk_size = 0; - - if (!req->dwContentLength) return TRUE; - if (req->dwContentLength == req->dwContentRead) - { - /* read terminator for the previous chunk */ - if (!discard_eol( req )) return FALSE; - req->dwContentLength = ~0u; - req->dwContentRead = 0; - } - for (;;) - { - while (req->read_size) - { - char ch = req->read_buf[req->read_pos]; - if (ch >= '0' && ch <= '9') chunk_size = chunk_size * 16 + ch - '0'; - else if (ch >= 'a' && ch <= 'f') chunk_size = chunk_size * 16 + ch - 'a' + 10; - else if (ch >= 'A' && ch <= 'F') chunk_size = chunk_size * 16 + ch - 'A' + 10; - else if (ch == ';' || ch == '\r' || ch == '\n') - { - TRACE( "reading %u byte chunk\n", chunk_size ); - req->dwContentLength = chunk_size; - req->dwContentRead = 0; - if (!discard_eol( req )) return FALSE; - return TRUE; - } - remove_data( req, 1 ); - } - if (!read_more_data( req, -1 )) return FALSE; - if (!req->read_size) - { - req->dwContentLength = req->dwContentRead = 0; - return TRUE; - } - } -} - -/* return the size of data available to be read immediately */ -static DWORD get_avail_data( WININETHTTPREQW *req ) -{ - if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead)) - return 0; - return min( req->read_size, req->dwContentLength - req->dwContentRead ); -} - -/* check if we have reached the end of the data to read */ -static BOOL end_of_read_data( WININETHTTPREQW *req ) -{ - if (req->read_chunked) return (req->dwContentLength == 0); - if (req->dwContentLength == ~0u) return FALSE; - return (req->dwContentLength == req->dwContentRead); -} - -static BOOL refill_buffer( WININETHTTPREQW *req ) -{ - int len = sizeof(req->read_buf); - - if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead)) - { - if (!start_next_chunk( req )) return FALSE; - } - - if (req->dwContentLength != ~0u) len = min( len, req->dwContentLength - req->dwContentRead ); - if (len <= req->read_size) return TRUE; - - if (!read_more_data( req, len )) return FALSE; - if (!req->read_size) req->dwContentLength = req->dwContentRead = 0; - return TRUE; -} - -static void HTTP_ReceiveRequestData(WININETHTTPREQW *req, BOOL first_notif) -{ - INTERNET_ASYNC_RESULT iar; - - TRACE("%p\n", req); - - if (refill_buffer( req )) { - iar.dwResult = (DWORD_PTR)req->hdr.hInternet; - iar.dwError = first_notif ? 0 : get_avail_data(req); - }else { - iar.dwResult = 0; - iar.dwError = INTERNET_GetLastError(); - } - - INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar, - sizeof(INTERNET_ASYNC_RESULT)); -} - -static DWORD HTTPREQ_Read(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync) -{ - int len, bytes_read = 0; - - if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead)) - { - if (!start_next_chunk( req )) goto done; - } - if (req->dwContentLength != ~0u) size = min( size, req->dwContentLength - req->dwContentRead ); - - if (req->read_size) - { - bytes_read = min( req->read_size, size ); - memcpy( buffer, req->read_buf + req->read_pos, bytes_read ); - remove_data( req, bytes_read ); - } - - if (size > bytes_read && (!bytes_read || sync)) - { - if (NETCON_recv( &req->netConnection, (char *)buffer + bytes_read, size - bytes_read, - sync ? MSG_WAITALL : 0, &len)) - bytes_read += len; /* always return success, even if the network layer returns an error */ + *read = 0; + HTTP_FinishedReading(req); + return ERROR_SUCCESS; } -done: + req->dwContentRead += bytes_read; *read = bytes_read; - TRACE( "retrieved %u bytes (%u/%u)\n", bytes_read, req->dwContentRead, req->dwContentLength ); if(req->lpszCacheFile) { BOOL res; DWORD dwBytesWritten; @@ -1835,6 +1636,102 @@ done: return ERROR_SUCCESS; } +static DWORD get_chunk_size(const char *buffer) +{ + const char *p; + DWORD size = 0; + + for (p = buffer; *p; p++) + { + if (*p >= '0' && *p <= '9') size = size * 16 + *p - '0'; + else if (*p >= 'a' && *p <= 'f') size = size * 16 + *p - 'a' + 10; + else if (*p >= 'A' && *p <= 'F') size = size * 16 + *p - 'A' + 10; + else if (*p == ';') break; + } + return size; +} + +static DWORD HTTP_ReadChunked(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync) +{ + char reply[MAX_REPLY_LEN], *p = buffer; + DWORD buflen, to_read, to_write = size; + int bytes_read; + + *read = 0; + for (;;) + { + if (*read == size) break; + + if (req->dwContentLength == ~0UL) /* new chunk */ + { + buflen = sizeof(reply); + if (!NETCON_getNextLine(&req->netConnection, reply, &buflen)) break; + + if (!(req->dwContentLength = get_chunk_size(reply))) + { + /* zero sized chunk marks end of transfer; read any trailing headers and return */ + HTTP_GetResponseHeaders(req, FALSE); + break; + } + } + to_read = min(to_write, req->dwContentLength - req->dwContentRead); + + if (!NETCON_recv(&req->netConnection, p, to_read, sync ? MSG_WAITALL : 0, &bytes_read)) + { + if (bytes_read != to_read) + ERR("Not all data received %d/%d\n", bytes_read, to_read); + + /* always return success, even if the network layer returns an error */ + *read = 0; + break; + } + if (!bytes_read) break; + + req->dwContentRead += bytes_read; + to_write -= bytes_read; + *read += bytes_read; + + if (req->lpszCacheFile) + { + DWORD dwBytesWritten; + + if (!WriteFile(req->hCacheFile, p, bytes_read, &dwBytesWritten, NULL)) + WARN("WriteFile failed: %u\n", GetLastError()); + } + p += bytes_read; + + if (req->dwContentRead == req->dwContentLength) /* chunk complete */ + { + req->dwContentRead = 0; + req->dwContentLength = ~0UL; + + buflen = sizeof(reply); + if (!NETCON_getNextLine(&req->netConnection, reply, &buflen)) + { + ERR("Malformed chunk\n"); + *read = 0; + break; + } + } + } + if (!*read) HTTP_FinishedReading(req); + return ERROR_SUCCESS; +} + +static DWORD HTTPREQ_Read(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync) +{ + WCHAR encoding[20]; + DWORD buflen = sizeof(encoding); + static const WCHAR szChunked[] = {'c','h','u','n','k','e','d',0}; + + if (HTTP_HttpQueryInfoW(req, HTTP_QUERY_TRANSFER_ENCODING, encoding, &buflen, NULL) && + !strcmpiW(encoding, szChunked)) + { + return HTTP_ReadChunked(req, buffer, size, read, sync); + } + else + return HTTP_Read(req, buffer, size, read, sync); +} static DWORD HTTPREQ_ReadFile(WININETHANDLEHEADER *hdr, void *buffer, DWORD size, DWORD *read) { @@ -1842,7 +1739,7 @@ static DWORD HTTPREQ_ReadFile(WININETHANDLEHEADER *hdr, void *buffer, DWORD size return HTTPREQ_Read(req, buffer, size, read, TRUE); } -static void HTTPREQ_AsyncReadFileExAProc(WORKREQUEST *workRequest) +static void HTTPREQ_AsyncReadFileExProc(WORKREQUEST *workRequest) { struct WORKREQ_INTERNETREADFILEEXA const *data = &workRequest->u.InternetReadFileExA; WININETHTTPREQW *req = (WININETHTTPREQW*)workRequest->hdr; @@ -1877,77 +1774,22 @@ static DWORD HTTPREQ_ReadFileExA(WININETHANDLEHEADER *hdr, INTERNET_BUFFERSA *bu INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); - if ((hdr->dwFlags & INTERNET_FLAG_ASYNC) && !get_avail_data(req)) - { - WORKREQUEST workRequest; + if (hdr->dwFlags & INTERNET_FLAG_ASYNC) { + DWORD available = 0; - workRequest.asyncproc = HTTPREQ_AsyncReadFileExAProc; - workRequest.hdr = WININET_AddRef(&req->hdr); - workRequest.u.InternetReadFileExA.lpBuffersOut = buffers; + NETCON_query_data_available(&req->netConnection, &available); + if (!available) + { + WORKREQUEST workRequest; - INTERNET_AsyncCall(&workRequest); + workRequest.asyncproc = HTTPREQ_AsyncReadFileExProc; + workRequest.hdr = WININET_AddRef(&req->hdr); + workRequest.u.InternetReadFileExA.lpBuffersOut = buffers; - return ERROR_IO_PENDING; - } + INTERNET_AsyncCall(&workRequest); - res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength, - !(flags & IRF_NO_WAIT)); - - if (res == ERROR_SUCCESS) { - DWORD size = buffers->dwBufferLength; - INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED, - &size, sizeof(size)); - } - - return res; -} - -static void HTTPREQ_AsyncReadFileExWProc(WORKREQUEST *workRequest) -{ - struct WORKREQ_INTERNETREADFILEEXW const *data = &workRequest->u.InternetReadFileExW; - WININETHTTPREQW *req = (WININETHTTPREQW*)workRequest->hdr; - INTERNET_ASYNC_RESULT iar; - DWORD res; - - TRACE("INTERNETREADFILEEXW %p\n", workRequest->hdr); - - res = HTTPREQ_Read(req, data->lpBuffersOut->lpvBuffer, - data->lpBuffersOut->dwBufferLength, &data->lpBuffersOut->dwBufferLength, TRUE); - - iar.dwResult = res == ERROR_SUCCESS; - iar.dwError = res; - - INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, - INTERNET_STATUS_REQUEST_COMPLETE, &iar, - sizeof(INTERNET_ASYNC_RESULT)); -} - -static DWORD HTTPREQ_ReadFileExW(WININETHANDLEHEADER *hdr, INTERNET_BUFFERSW *buffers, - DWORD flags, DWORD_PTR context) -{ - - WININETHTTPREQW *req = (WININETHTTPREQW*)hdr; - DWORD res; - - if (flags & ~(IRF_ASYNC|IRF_NO_WAIT)) - FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT)); - - if (buffers->dwStructSize != sizeof(*buffers)) - return ERROR_INVALID_PARAMETER; - - INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); - - if ((hdr->dwFlags & INTERNET_FLAG_ASYNC) && !get_avail_data(req)) - { - WORKREQUEST workRequest; - - workRequest.asyncproc = HTTPREQ_AsyncReadFileExWProc; - workRequest.hdr = WININET_AddRef(&req->hdr); - workRequest.u.InternetReadFileExW.lpBuffersOut = buffers; - - INTERNET_AsyncCall(&workRequest); - - return ERROR_IO_PENDING; + return ERROR_IO_PENDING; + } } res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength, @@ -1964,62 +1806,58 @@ static DWORD HTTPREQ_ReadFileExW(WININETHANDLEHEADER *hdr, INTERNET_BUFFERSW *bu static BOOL HTTPREQ_WriteFile(WININETHANDLEHEADER *hdr, const void *buffer, DWORD size, DWORD *written) { - BOOL ret; LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW)hdr; - INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0); - - *written = 0; - if ((ret = NETCON_send(&lpwhr->netConnection, buffer, size, 0, (LPINT)written))) - lpwhr->dwBytesWritten += *written; - - INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REQUEST_SENT, written, sizeof(DWORD)); - return ret; + return NETCON_send(&lpwhr->netConnection, buffer, size, 0, (LPINT)written); } static void HTTPREQ_AsyncQueryDataAvailableProc(WORKREQUEST *workRequest) { WININETHTTPREQW *req = (WININETHTTPREQW*)workRequest->hdr; + INTERNET_ASYNC_RESULT iar; + char buffer[4048]; - HTTP_ReceiveRequestData(req, FALSE); + TRACE("%p\n", workRequest->hdr); + + iar.dwResult = NETCON_recv(&req->netConnection, buffer, + min(sizeof(buffer), req->dwContentLength - req->dwContentRead), + MSG_PEEK, (int *)&iar.dwError); + + INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar, + sizeof(INTERNET_ASYNC_RESULT)); } static DWORD HTTPREQ_QueryDataAvailable(WININETHANDLEHEADER *hdr, DWORD *available, DWORD flags, DWORD_PTR ctx) { WININETHTTPREQW *req = (WININETHTTPREQW*)hdr; + BYTE buffer[4048]; + BOOL async; TRACE("(%p %p %x %lx)\n", req, available, flags, ctx); - if (!(*available = get_avail_data( req ))) + if(!NETCON_query_data_available(&req->netConnection, available) || *available) + return ERROR_SUCCESS; + + /* Even if we are in async mode, we need to determine whether + * there is actually more data available. We do this by trying + * to peek only a single byte in async mode. */ + async = (req->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) != 0; + + if (NETCON_recv(&req->netConnection, buffer, + min(async ? 1 : sizeof(buffer), req->dwContentLength - req->dwContentRead), + MSG_PEEK, (int *)available) && async && *available) { - if (end_of_read_data( req )) return ERROR_SUCCESS; + WORKREQUEST workRequest; - if (req->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) - { - WORKREQUEST workRequest; + *available = 0; + workRequest.asyncproc = HTTPREQ_AsyncQueryDataAvailableProc; + workRequest.hdr = WININET_AddRef( &req->hdr ); - workRequest.asyncproc = HTTPREQ_AsyncQueryDataAvailableProc; - workRequest.hdr = WININET_AddRef( &req->hdr ); + INTERNET_AsyncCall(&workRequest); - INTERNET_AsyncCall(&workRequest); - - return ERROR_IO_PENDING; - } - else - { - refill_buffer( req ); - *available = get_avail_data( req ); - } + return ERROR_IO_PENDING; } - if (*available == sizeof(req->read_buf)) /* check if we have even more pending in the socket */ - { - DWORD extra; - if (NETCON_query_data_available(&req->netConnection, &extra)) - *available = min( *available + extra, req->dwContentLength - req->dwContentRead ); - } - - TRACE( "returning %u\n", *available ); return ERROR_SUCCESS; } @@ -2030,7 +1868,6 @@ static const HANDLEHEADERVtbl HTTPREQVtbl = { HTTPREQ_SetOption, HTTPREQ_ReadFile, HTTPREQ_ReadFileExA, - HTTPREQ_ReadFileExW, HTTPREQ_WriteFile, HTTPREQ_QueryDataAvailable, NULL @@ -2076,7 +1913,6 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs, lpwhr->hdr.refs = 1; lpwhr->hdr.lpfnStatusCB = lpwhs->hdr.lpfnStatusCB; lpwhr->hdr.dwInternalFlags = lpwhs->hdr.dwInternalFlags & INET_CALLBACKW; - lpwhr->dwContentLength = ~0u; WININET_AddRef( &lpwhs->hdr ); lpwhr->lpHttpSession = lpwhs; @@ -2114,7 +1950,7 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs, lpwhr->lpszPath = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); rc = UrlEscapeW(lpszObjectName, lpwhr->lpszPath, &len, URL_ESCAPE_SPACES_ONLY); - if (rc != S_OK) + if (rc) { ERR("Unable to escape string!(%s) (%d)\n",debugstr_w(lpszObjectName),rc); strcpyW(lpwhr->lpszPath,lpszObjectName); @@ -2191,15 +2027,12 @@ static void HTTP_DrainContent(WININETHTTPREQW *req) if (!NETCON_connected(&req->netConnection)) return; if (req->dwContentLength == -1) - { NETCON_close(&req->netConnection); - return; - } do { char buffer[2048]; - if (HTTPREQ_Read(req, buffer, sizeof(buffer), &bytes_read, TRUE) != ERROR_SUCCESS) + if (HTTP_Read(req, buffer, sizeof(buffer), &bytes_read, TRUE) != ERROR_SUCCESS) return; } while (bytes_read); } @@ -2336,28 +2169,27 @@ static const LPCWSTR header_lookup[] = { /*********************************************************************** * HTTP_HttpQueryInfoW (internal) */ -static BOOL HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLevel, +static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLevel, LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex) { LPHTTPHEADERW lphttpHdr = NULL; BOOL bSuccess = FALSE; BOOL request_only = dwInfoLevel & HTTP_QUERY_FLAG_REQUEST_HEADERS; INT requested_index = lpdwIndex ? *lpdwIndex : 0; - DWORD level = (dwInfoLevel & ~HTTP_QUERY_MODIFIER_FLAGS_MASK); + INT level = (dwInfoLevel & ~HTTP_QUERY_MODIFIER_FLAGS_MASK); INT index = -1; /* Find requested header structure */ switch (level) { case HTTP_QUERY_CUSTOM: - if (!lpBuffer) return FALSE; index = HTTP_GetCustomHeaderIndex(lpwhr, lpBuffer, requested_index, request_only); break; case HTTP_QUERY_RAW_HEADERS_CRLF: { LPWSTR headers; - DWORD len = 0; + DWORD len; BOOL ret = FALSE; if (request_only) @@ -2365,24 +2197,15 @@ static BOOL HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLevel, else headers = lpwhr->lpszRawHeaders; - if (headers) - len = strlenW(headers) * sizeof(WCHAR); - - if (len + sizeof(WCHAR) > *lpdwBufferLength) + len = (strlenW(headers) + 1) * sizeof(WCHAR); + if (len > *lpdwBufferLength) { - len += sizeof(WCHAR); INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); ret = FALSE; } else if (lpBuffer) { - if (headers) - memcpy(lpBuffer, headers, len + sizeof(WCHAR)); - else - { - len = strlenW(szCrLf) * sizeof(WCHAR); - memcpy(lpBuffer, szCrLf, sizeof(szCrLf)); - } + memcpy(lpBuffer, headers, len); TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len / sizeof(WCHAR))); ret = TRUE; } @@ -2394,9 +2217,10 @@ static BOOL HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLevel, } case HTTP_QUERY_RAW_HEADERS: { + static const WCHAR szCrLf[] = {'\r','\n',0}; LPWSTR * ppszRawHeaderLines = HTTP_Tokenize(lpwhr->lpszRawHeaders, szCrLf); DWORD i, size = 0; - LPWSTR pszString = lpBuffer; + LPWSTR pszString = (WCHAR*)lpBuffer; for (i = 0; ppszRawHeaderLines[i]; i++) size += strlenW(ppszRawHeaderLines[i]) + 1; @@ -2408,17 +2232,17 @@ static BOOL HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLevel, INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } - if (pszString) + + for (i = 0; ppszRawHeaderLines[i]; i++) { - for (i = 0; ppszRawHeaderLines[i]; i++) - { - DWORD len = strlenW(ppszRawHeaderLines[i]); - memcpy(pszString, ppszRawHeaderLines[i], (len+1)*sizeof(WCHAR)); - pszString += len+1; - } - *pszString = '\0'; - TRACE("returning data: %s\n", debugstr_wn(lpBuffer, size)); + DWORD len = strlenW(ppszRawHeaderLines[i]); + memcpy(pszString, ppszRawHeaderLines[i], (len+1)*sizeof(WCHAR)); + pszString += len+1; } + *pszString = '\0'; + + TRACE("returning data: %s\n", debugstr_wn((WCHAR*)lpBuffer, size)); + *lpdwBufferLength = size * sizeof(WCHAR); HTTP_FreeTokens(ppszRawHeaderLines); @@ -2434,12 +2258,11 @@ static BOOL HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLevel, INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } - if (lpBuffer) - { - memcpy(lpBuffer, lpwhr->lpszStatusText, (len + 1) * sizeof(WCHAR)); - TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len)); - } + memcpy(lpBuffer, lpwhr->lpszStatusText, (len+1)*sizeof(WCHAR)); *lpdwBufferLength = len * sizeof(WCHAR); + + TRACE("returning data: %s\n", debugstr_wn((WCHAR*)lpBuffer, len)); + return TRUE; } break; @@ -2453,19 +2276,18 @@ static BOOL HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLevel, INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } - if (lpBuffer) - { - memcpy(lpBuffer, lpwhr->lpszVersion, (len + 1) * sizeof(WCHAR)); - TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len)); - } + memcpy(lpBuffer, lpwhr->lpszVersion, (len+1)*sizeof(WCHAR)); *lpdwBufferLength = len * sizeof(WCHAR); + + TRACE("returning data: %s\n", debugstr_wn((WCHAR*)lpBuffer, len)); + return TRUE; } break; default: assert (LAST_TABLE_HEADER == (HTTP_QUERY_UNLESS_MODIFIED_SINCE + 1)); - if (level < LAST_TABLE_HEADER && header_lookup[level]) + if (level >= 0 && level < LAST_TABLE_HEADER && header_lookup[level]) index = HTTP_GetCustomHeaderIndex(lpwhr, header_lookup[level], requested_index,request_only); } @@ -2482,16 +2304,18 @@ static BOOL HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLevel, return bSuccess; } - if (lpdwIndex && level != HTTP_QUERY_STATUS_CODE) (*lpdwIndex)++; + if (lpdwIndex) + (*lpdwIndex)++; /* coalesce value to requested type */ - if (dwInfoLevel & HTTP_QUERY_FLAG_NUMBER && lpBuffer) + if (dwInfoLevel & HTTP_QUERY_FLAG_NUMBER) { - *(int *)lpBuffer = atoiW(lphttpHdr->lpszValue); - TRACE(" returning number: %d\n", *(int *)lpBuffer); - bSuccess = TRUE; + *(int *)lpBuffer = atoiW(lphttpHdr->lpszValue); + bSuccess = TRUE; + + TRACE(" returning number : %d\n", *(int *)lpBuffer); } - else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME && lpBuffer) + else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME) { time_t tmpTime; struct tm tmpTM; @@ -2500,20 +2324,24 @@ static BOOL HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLevel, tmpTime = ConvertTimeString(lphttpHdr->lpszValue); tmpTM = *gmtime(&tmpTime); - STHook = (SYSTEMTIME *)lpBuffer; - 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; + STHook = (SYSTEMTIME *) lpBuffer; + if(STHook==NULL) + return bSuccess; + + 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; - TRACE(" returning time: %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n", - STHook->wYear, STHook->wMonth, STHook->wDay, STHook->wDayOfWeek, - STHook->wHour, STHook->wMinute, STHook->wSecond, STHook->wMilliseconds); + bSuccess = TRUE; + + TRACE(" returning time : %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n", + STHook->wYear, STHook->wMonth, STHook->wDay, STHook->wDayOfWeek, + STHook->wHour, STHook->wMinute, STHook->wSecond, STHook->wMilliseconds); } else if (lphttpHdr->lpszValue) { @@ -2525,13 +2353,12 @@ static BOOL HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLevel, INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); return bSuccess; } - if (lpBuffer) - { - memcpy(lpBuffer, lphttpHdr->lpszValue, len); - TRACE(" returning string: %s\n", debugstr_w(lpBuffer)); - } + + memcpy(lpBuffer, lphttpHdr->lpszValue, len); *lpdwBufferLength = len - sizeof(WCHAR); bSuccess = TRUE; + + TRACE(" returning string : %s\n", debugstr_w(lpBuffer)); } return bSuccess; } @@ -2951,13 +2778,8 @@ BOOL WINAPI HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders, req = &workRequest.u.HttpSendRequestW; if (lpszHeaders) { - DWORD size; - - if (dwHeaderLength == ~0u) size = (strlenW(lpszHeaders) + 1) * sizeof(WCHAR); - else size = dwHeaderLength * sizeof(WCHAR); - - req->lpszHeader = HeapAlloc(GetProcessHeap(), 0, size); - memcpy(req->lpszHeader, lpszHeaders, size); + req->lpszHeader = HeapAlloc(GetProcessHeap(), 0, dwHeaderLength * sizeof(WCHAR)); + memcpy(req->lpszHeader, lpszHeaders, dwHeaderLength * sizeof(WCHAR)); } else req->lpszHeader = 0; @@ -3027,75 +2849,13 @@ static BOOL HTTP_GetRequestURL(WININETHTTPREQW *req, LPWSTR buf) return TRUE; } -/*********************************************************************** - * HTTP_GetRedirectURL (internal) - */ -static LPWSTR HTTP_GetRedirectURL(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl) -{ - static WCHAR szHttp[] = {'h','t','t','p',0}; - static WCHAR szHttps[] = {'h','t','t','p','s',0}; - LPWININETHTTPSESSIONW lpwhs = lpwhr->lpHttpSession; - URL_COMPONENTSW urlComponents; - DWORD url_length = 0; - LPWSTR orig_url; - LPWSTR combined_url; - - if (lpszUrl[0]=='/') return WININET_strdupW( lpszUrl ); - - urlComponents.dwStructSize = sizeof(URL_COMPONENTSW); - urlComponents.lpszScheme = (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp; - urlComponents.dwSchemeLength = 0; - urlComponents.lpszHostName = lpwhs->lpszHostName; - urlComponents.dwHostNameLength = 0; - urlComponents.nPort = lpwhs->nHostPort; - urlComponents.lpszUserName = lpwhs->lpszUserName; - urlComponents.dwUserNameLength = 0; - urlComponents.lpszPassword = NULL; - urlComponents.dwPasswordLength = 0; - urlComponents.lpszUrlPath = lpwhr->lpszPath; - urlComponents.dwUrlPathLength = 0; - urlComponents.lpszExtraInfo = NULL; - urlComponents.dwExtraInfoLength = 0; - - if (!InternetCreateUrlW(&urlComponents, 0, NULL, &url_length) && - (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) - return NULL; - - orig_url = HeapAlloc(GetProcessHeap(), 0, url_length); - - /* convert from bytes to characters */ - url_length = url_length / sizeof(WCHAR) - 1; - if (!InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length)) - { - HeapFree(GetProcessHeap(), 0, orig_url); - return NULL; - } - - url_length = 0; - if (!InternetCombineUrlW(orig_url, lpszUrl, NULL, &url_length, ICU_ENCODE_SPACES_ONLY) && - (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) - { - HeapFree(GetProcessHeap(), 0, orig_url); - return NULL; - } - combined_url = HeapAlloc(GetProcessHeap(), 0, url_length * sizeof(WCHAR)); - - if (!InternetCombineUrlW(orig_url, lpszUrl, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY)) - { - HeapFree(GetProcessHeap(), 0, orig_url); - HeapFree(GetProcessHeap(), 0, combined_url); - return NULL; - } - HeapFree(GetProcessHeap(), 0, orig_url); - return combined_url; -} - - /*********************************************************************** * HTTP_HandleRedirect (internal) */ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl) { + static const WCHAR szContentType[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0}; + static const WCHAR szContentLength[] = {'C','o','n','t','e','n','t','-','L','e','n','g','t','h',0}; LPWININETHTTPSESSIONW lpwhs = lpwhr->lpHttpSession; LPWININETAPPINFOW hIC = lpwhs->lpAppInfo; BOOL using_proxy = hIC->lpszProxy && hIC->lpszProxy[0]; @@ -3113,6 +2873,55 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl) WCHAR protocol[32], hostName[MAXHOSTNAME], userName[1024]; static WCHAR szHttp[] = {'h','t','t','p',0}; static WCHAR szHttps[] = {'h','t','t','p','s',0}; + DWORD url_length = 0; + LPWSTR orig_url; + LPWSTR combined_url; + + urlComponents.dwStructSize = sizeof(URL_COMPONENTSW); + urlComponents.lpszScheme = (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp; + urlComponents.dwSchemeLength = 0; + urlComponents.lpszHostName = lpwhs->lpszHostName; + urlComponents.dwHostNameLength = 0; + urlComponents.nPort = lpwhs->nHostPort; + urlComponents.lpszUserName = lpwhs->lpszUserName; + urlComponents.dwUserNameLength = 0; + urlComponents.lpszPassword = NULL; + urlComponents.dwPasswordLength = 0; + urlComponents.lpszUrlPath = lpwhr->lpszPath; + urlComponents.dwUrlPathLength = 0; + urlComponents.lpszExtraInfo = NULL; + urlComponents.dwExtraInfoLength = 0; + + if (!InternetCreateUrlW(&urlComponents, 0, NULL, &url_length) && + (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) + return FALSE; + + orig_url = HeapAlloc(GetProcessHeap(), 0, url_length); + + /* convert from bytes to characters */ + url_length = url_length / sizeof(WCHAR) - 1; + if (!InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length)) + { + HeapFree(GetProcessHeap(), 0, orig_url); + return FALSE; + } + + url_length = 0; + if (!InternetCombineUrlW(orig_url, lpszUrl, NULL, &url_length, ICU_ENCODE_SPACES_ONLY) && + (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) + { + HeapFree(GetProcessHeap(), 0, orig_url); + return FALSE; + } + combined_url = HeapAlloc(GetProcessHeap(), 0, url_length * sizeof(WCHAR)); + + if (!InternetCombineUrlW(orig_url, lpszUrl, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY)) + { + HeapFree(GetProcessHeap(), 0, orig_url); + HeapFree(GetProcessHeap(), 0, combined_url); + return FALSE; + } + HeapFree(GetProcessHeap(), 0, orig_url); userName[0] = 0; hostName[0] = 0; @@ -3131,8 +2940,13 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl) urlComponents.dwUrlPathLength = 2048; urlComponents.lpszExtraInfo = NULL; urlComponents.dwExtraInfoLength = 0; - if(!InternetCrackUrlW(lpszUrl, strlenW(lpszUrl), 0, &urlComponents)) + if(!InternetCrackUrlW(combined_url, strlenW(combined_url), 0, &urlComponents)) + { + HeapFree(GetProcessHeap(), 0, combined_url); return FALSE; + } + + HeapFree(GetProcessHeap(), 0, combined_url); if (!strncmpW(szHttp, urlComponents.lpszScheme, strlenW(szHttp)) && (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE)) @@ -3206,8 +3020,6 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl) NETCON_close(&lpwhr->netConnection); if (!HTTP_ResolveName(lpwhr)) return FALSE; if (!NETCON_init(&lpwhr->netConnection, lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE)) return FALSE; - lpwhr->read_pos = lpwhr->read_size = 0; - lpwhr->read_chunked = FALSE; } } else @@ -3227,7 +3039,7 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl) lpwhr->lpszPath = HeapAlloc(GetProcessHeap(), 0, needed*sizeof(WCHAR)); rc = UrlEscapeW(path, lpwhr->lpszPath, &needed, URL_ESCAPE_SPACES_ONLY); - if (rc != S_OK) + if (rc) { ERR("Unable to escape string!(%s) (%d)\n",debugstr_w(path),rc); strcpyW(lpwhr->lpszPath,path); @@ -3235,10 +3047,10 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl) } /* Remove custom content-type/length headers on redirects. */ - index = HTTP_GetCustomHeaderIndex(lpwhr, szContent_Type, 0, TRUE); + index = HTTP_GetCustomHeaderIndex(lpwhr, szContentType, 0, TRUE); if (0 <= index) HTTP_DeleteCustomHeader(lpwhr, index); - index = HTTP_GetCustomHeaderIndex(lpwhr, szContent_Length, 0, TRUE); + index = HTTP_GetCustomHeaderIndex(lpwhr, szContentLength, 0, TRUE); if (0 <= index) HTTP_DeleteCustomHeader(lpwhr, index); @@ -3312,28 +3124,29 @@ static BOOL HTTP_SecureProxyConnect(LPWININETHTTPREQW lpwhr) static void HTTP_InsertCookies(LPWININETHTTPREQW lpwhr) { - static const WCHAR szUrlForm[] = {'h','t','t','p',':','/','/','%','s','%','s',0}; + static const WCHAR szUrlForm[] = {'h','t','t','p',':','/','/','%','s',0}; LPWSTR lpszCookies, lpszUrl = NULL; DWORD nCookieSize, size; LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr,szHost); - size = (strlenW(Host->lpszValue) + strlenW(szUrlForm) + strlenW(lpwhr->lpszPath)) * sizeof(WCHAR); + size = (strlenW(Host->lpszValue) + strlenW(szUrlForm)) * sizeof(WCHAR); if (!(lpszUrl = HeapAlloc(GetProcessHeap(), 0, size))) return; - sprintfW( lpszUrl, szUrlForm, Host->lpszValue, lpwhr->lpszPath); + sprintfW( lpszUrl, szUrlForm, Host->lpszValue ); if (InternetGetCookieW(lpszUrl, NULL, NULL, &nCookieSize)) { int cnt = 0; static const WCHAR szCookie[] = {'C','o','o','k','i','e',':',' ',0}; + static const WCHAR szcrlf[] = {'\r','\n',0}; - size = sizeof(szCookie) + nCookieSize * sizeof(WCHAR) + sizeof(szCrLf); + size = sizeof(szCookie) + nCookieSize * sizeof(WCHAR) + sizeof(szcrlf); if ((lpszCookies = HeapAlloc(GetProcessHeap(), 0, size))) { cnt += sprintfW(lpszCookies, szCookie); InternetGetCookieW(lpszUrl, NULL, lpszCookies + cnt, &nCookieSize); - strcatW(lpszCookies, szCrLf); + strcatW(lpszCookies, szcrlf); - HTTP_HttpAddRequestHeadersW(lpwhr, lpszCookies, strlenW(lpszCookies), HTTP_ADDREQ_FLAG_REPLACE); + HTTP_HttpAddRequestHeadersW(lpwhr, lpszCookies, strlenW(lpszCookies), HTTP_ADDREQ_FLAG_ADD); HeapFree(GetProcessHeap(), 0, lpszCookies); } } @@ -3355,7 +3168,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, DWORD dwContentLength, BOOL bEndRequest) { INT cnt; - BOOL bSuccess = FALSE, redirected = FALSE; + BOOL bSuccess = FALSE; LPWSTR requestString = NULL; INT responseLen; BOOL loop_next; @@ -3373,11 +3186,10 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, if (!lpwhr->lpszVerb) lpwhr->lpszVerb = WININET_strdupW(szGET); - if (dwContentLength || strcmpW(lpwhr->lpszVerb, szGET)) + if (dwContentLength || !strcmpW(lpwhr->lpszVerb, szPost)) { sprintfW(contentLengthStr, szContentLength, dwContentLength); - HTTP_HttpAddRequestHeadersW(lpwhr, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_REPLACE); - lpwhr->dwBytesToWrite = dwContentLength; + HTTP_HttpAddRequestHeadersW(lpwhr, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_ADD_IF_NEW); } if (lpwhr->lpHttpSession->lpAppInfo->lpszAgent) { @@ -3457,7 +3269,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, goto lend; /* send the request as ASCII, tack on the optional data */ - if (!lpOptional || redirected) + if( !lpOptional ) dwOptionalLength = 0; len = WideCharToMultiByte( CP_ACP, 0, requestString, -1, NULL, 0, NULL, NULL ); @@ -3476,8 +3288,6 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, NETCON_send(&lpwhr->netConnection, ascii_req, len, 0, &cnt); HeapFree( GetProcessHeap(), 0, ascii_req ); - lpwhr->dwBytesWritten = dwOptionalLength; - INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REQUEST_SENT, &len, sizeof(DWORD)); @@ -3486,6 +3296,8 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, { DWORD dwBufferSize; DWORD dwStatusCode; + WCHAR encoding[20]; + static const WCHAR szChunked[] = {'c','h','u','n','k','e','d',0}; INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); @@ -3503,7 +3315,22 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, HTTP_ProcessCookies(lpwhr); - if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr); + dwBufferSize = sizeof(lpwhr->dwContentLength); + if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH, + &lpwhr->dwContentLength,&dwBufferSize,NULL)) + lpwhr->dwContentLength = -1; + + if (lpwhr->dwContentLength == 0) + HTTP_FinishedReading(lpwhr); + + /* Correct the case where both a Content-Length and Transfer-encoding = chunked are set */ + + dwBufferSize = sizeof(encoding); + if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_TRANSFER_ENCODING, encoding, &dwBufferSize, NULL) && + !strcmpiW(encoding, szChunked)) + { + lpwhr->dwContentLength = -1; + } dwBufferSize = sizeof(dwStatusCode); if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, @@ -3512,29 +3339,21 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && bSuccess) { - WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH]; + WCHAR szNewLocation[INTERNET_MAX_URL_LENGTH]; dwBufferSize=sizeof(szNewLocation); if ((dwStatusCode==HTTP_STATUS_REDIRECT || dwStatusCode==HTTP_STATUS_MOVED) && HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL)) { - /* redirects are always GETs */ - HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb); - lpwhr->lpszVerb = WININET_strdupW(szGET); - HTTP_DrainContent(lpwhr); - if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation ))) + INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, + INTERNET_STATUS_REDIRECT, szNewLocation, + dwBufferSize); + bSuccess = HTTP_HandleRedirect(lpwhr, szNewLocation); + if (bSuccess) { - INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT, - new_url, (strlenW(new_url) + 1) * sizeof(WCHAR)); - bSuccess = HTTP_HandleRedirect(lpwhr, new_url); - if (bSuccess) - { - HeapFree(GetProcessHeap(), 0, requestString); - loop_next = TRUE; - } - HeapFree( GetProcessHeap(), 0, new_url ); + HeapFree(GetProcessHeap(), 0, requestString); + loop_next = TRUE; } - redirected = TRUE; } } if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTH) && bSuccess) @@ -3610,31 +3429,12 @@ lend: /* TODO: send notification for P3P header */ - if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) - { - if (bSuccess) - { - if (lpwhr->dwBytesWritten == lpwhr->dwBytesToWrite) HTTP_ReceiveRequestData(lpwhr, TRUE); - else - { - iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet; - iar.dwError = 0; + iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet; + iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError(); - INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, - INTERNET_STATUS_REQUEST_COMPLETE, &iar, - sizeof(INTERNET_ASYNC_RESULT)); - } - } - else - { - iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet; - iar.dwError = INTERNET_GetLastError(); - - INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, - INTERNET_STATUS_REQUEST_COMPLETE, &iar, - sizeof(INTERNET_ASYNC_RESULT)); - } - } + INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, + INTERNET_STATUS_REQUEST_COMPLETE, &iar, + sizeof(INTERNET_ASYNC_RESULT)); TRACE("<--\n"); if (bSuccess) INTERNET_SetLastError(ERROR_SUCCESS); @@ -3679,34 +3479,11 @@ static DWORD HTTPSESSION_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, voi return INET_QueryOption(option, buffer, size, unicode); } -static DWORD HTTPSESSION_SetOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD size) -{ - WININETHTTPSESSIONW *ses = (WININETHTTPSESSIONW*)hdr; - - switch(option) { - case INTERNET_OPTION_USERNAME: - { - HeapFree(GetProcessHeap(), 0, ses->lpszUserName); - if (!(ses->lpszUserName = WININET_strdupW(buffer))) return ERROR_OUTOFMEMORY; - return ERROR_SUCCESS; - } - case INTERNET_OPTION_PASSWORD: - { - HeapFree(GetProcessHeap(), 0, ses->lpszPassword); - if (!(ses->lpszPassword = WININET_strdupW(buffer))) return ERROR_OUTOFMEMORY; - return ERROR_SUCCESS; - } - default: break; - } - - return ERROR_INTERNET_INVALID_OPTION; -} - static const HANDLEHEADERVtbl HTTPSESSIONVtbl = { HTTPSESSION_Destroy, NULL, HTTPSESSION_QueryOption, - HTTPSESSION_SetOption, + NULL, NULL, NULL, NULL, @@ -3834,7 +3611,7 @@ static BOOL HTTP_OpenConnection(LPWININETHTTPREQW lpwhr) TRACE("-->\n"); - if (lpwhr->hdr.htype != WH_HHTTPREQ) + if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ) { INTERNET_SetLastError(ERROR_INVALID_PARAMETER); goto lend; @@ -3893,9 +3670,6 @@ static BOOL HTTP_OpenConnection(LPWININETHTTPREQW lpwhr) bSuccess = TRUE; lend: - lpwhr->read_pos = lpwhr->read_size = 0; - lpwhr->read_chunked = FALSE; - TRACE("%d <--\n", bSuccess); return bSuccess; } @@ -3940,6 +3714,7 @@ static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr, BOOL clear) DWORD buflen = MAX_REPLY_LEN; BOOL bSuccess = FALSE; INT rc = 0; + static const WCHAR szCrLf[] = {'\r','\n',0}; static const WCHAR szHundred[] = {'1','0','0',0}; char bufferA[MAX_REPLY_LEN]; LPWSTR status_code, status_text; @@ -3957,12 +3732,17 @@ static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr, BOOL clear) do { /* - * We should first receive 'HTTP/1.x nnn OK' where nnn is the status code. + * HACK peek at the buffer */ buflen = MAX_REPLY_LEN; - if (!read_line(lpwhr, bufferA, &buflen)) + NETCON_recv(&lpwhr->netConnection, buffer, buflen, MSG_PEEK, &rc); + + /* + * We should first receive 'HTTP/1.x nnn OK' where nnn is the status code. + */ + memset(buffer, 0, MAX_REPLY_LEN); + if (!NETCON_getNextLine(&lpwhr->netConnection, bufferA, &buflen)) goto lend; - rc += buflen; MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN ); /* split the version from the status code */ @@ -4012,18 +3792,11 @@ static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr, BOOL clear) do { buflen = MAX_REPLY_LEN; - if (read_line(lpwhr, bufferA, &buflen)) + if (NETCON_getNextLine(&lpwhr->netConnection, bufferA, &buflen)) { LPWSTR * pFieldAndValue; TRACE("got line %s, now interpreting\n", debugstr_a(bufferA)); - - if (!bufferA[0]) break; - if (!strchr(bufferA, ':')) - { - WARN("invalid header\n"); - continue; - } MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN ); while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders) @@ -4278,7 +4051,7 @@ static BOOL HTTP_ProcessHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field, LPCWSTR v * Called when all content from server has been read by client. * */ -static BOOL HTTP_FinishedReading(LPWININETHTTPREQW lpwhr) +BOOL HTTP_FinishedReading(LPWININETHTTPREQW lpwhr) { WCHAR szVersion[10]; WCHAR szConnectionResponse[20]; @@ -4289,9 +4062,9 @@ static BOOL HTTP_FinishedReading(LPWININETHTTPREQW lpwhr) /* as per RFC 2068, S8.1.2.1, if the client is HTTP/1.1 then assume that * the connection is keep-alive by default */ - if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_VERSION, szVersion, - &dwBufferSize, NULL) && - !strcmpiW(szVersion, g_szHttp1_1)) + if (!HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_VERSION, szVersion, + &dwBufferSize, NULL) || + strcmpiW(szVersion, g_szHttp1_1)) { keepalive = TRUE; } diff --git a/reactos/dll/win32/wininet/internet.c b/reactos/dll/win32/wininet/internet.c index aa2a6b720f0..bad795ddbd4 100644 --- a/reactos/dll/win32/wininet/internet.c +++ b/reactos/dll/win32/wininet/internet.c @@ -31,10 +31,6 @@ #define MAXHOSTNAME 100 /* from http.c */ -#if defined(__MINGW32__) || defined (_MSC_VER) -#include -#endif - #include #include #include @@ -117,7 +113,7 @@ HINTERNET WININET_AllocHandle( LPWININETHANDLEHEADER info ) { num = HANDLE_CHUNK_SIZE; p = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof (*WININET_Handles)* num); + sizeof (UINT)* num); if( !p ) goto end; WININET_Handles = p; @@ -127,7 +123,7 @@ HINTERNET WININET_AllocHandle( LPWININETHANDLEHEADER info ) { num = WININET_dwMaxHandles + HANDLE_CHUNK_SIZE; p = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - WININET_Handles, sizeof (*WININET_Handles)* num); + WININET_Handles, sizeof (UINT)* num); if( !p ) goto end; WININET_Handles = p; @@ -186,8 +182,7 @@ BOOL WININET_Release( LPWININETHANDLEHEADER info ) info->vtbl->CloseConnection( info ); } /* Don't send a callback if this is a session handle created with InternetOpenUrl */ - if ((info->htype != WH_HHTTPSESSION && info->htype != WH_HFTPSESSION) - || !(info->dwInternalFlags & INET_OPENURL)) + if (info->htype != WH_HHTTPSESSION || !(info->dwInternalFlags & INET_OPENURL)) { INTERNET_SendCallback(info, info->dwContext, INTERNET_STATUS_HANDLE_CLOSING, &info->hInternet, @@ -415,11 +410,8 @@ static BOOL INTERNET_ConfigureProxy( LPWININETAPPINFOW lpwai ) TRACE("http proxy (from environment) = %s\n", debugstr_w(lpwai->lpszProxy)); enabled = 1; } - if (!enabled) - { - TRACE("Proxy is not enabled.\n"); - lpwai->dwAccessType = INTERNET_OPEN_TYPE_DIRECT; - } + if (!enabled) TRACE("Proxy is not enabled.\n"); + RegCloseKey( key ); return (enabled > 0); } @@ -467,8 +459,8 @@ static void dump_INTERNET_FLAGS(DWORD dwFlags) FE(INTERNET_FLAG_TRANSFER_BINARY) }; #undef FE - unsigned int i; - + int i; + for (i = 0; i < (sizeof(flag) / sizeof(flag[0])); i++) { if (flag[i].val & dwFlags) { TRACE(" %s", flag[i].name); @@ -551,10 +543,8 @@ static DWORD APPINFO_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *b if (ai->lpszProxyBypass) proxyBypassBytesRequired = (lstrlenW(ai->lpszProxyBypass) + 1) * sizeof(WCHAR); if (*size < sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired + proxyBypassBytesRequired) - { - *size = sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired + proxyBypassBytesRequired; - return ERROR_INSUFFICIENT_BUFFER; - } + return ERROR_INSUFFICIENT_BUFFER; + proxy = (LPWSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOW)); proxy_bypass = (LPWSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired); @@ -584,10 +574,8 @@ static DWORD APPINFO_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *b proxyBypassBytesRequired = WideCharToMultiByte(CP_ACP, 0, ai->lpszProxyBypass, -1, NULL, 0, NULL, NULL); if (*size < sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired + proxyBypassBytesRequired) - { - *size = sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired + proxyBypassBytesRequired; return ERROR_INSUFFICIENT_BUFFER; - } + proxy = (LPSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOA)); proxy_bypass = (LPSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired); @@ -791,7 +779,7 @@ HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType, BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError, LPSTR lpszBuffer, LPDWORD lpdwBufferLength) { - LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex); + LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex); TRACE("\n"); @@ -828,7 +816,7 @@ BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError, BOOL WINAPI InternetGetLastResponseInfoW(LPDWORD lpdwError, LPWSTR lpszBuffer, LPDWORD lpdwBufferLength) { - LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex); + LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex); TRACE("\n"); @@ -868,7 +856,7 @@ BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved) TRACE("(%p, 0x%08x)\n", lpdwStatus, dwReserved); if (lpdwStatus) { - WARN("always returning LAN connection.\n"); + FIXME("always returning LAN connection.\n"); *lpdwStatus = INTERNET_CONNECTION_LAN; } return TRUE; @@ -912,7 +900,7 @@ BOOL WINAPI InternetGetConnectedStateExW(LPDWORD lpdwStatus, LPWSTR lpszConnecti return FALSE; if (lpdwStatus) { - WARN("always returning LAN connection.\n"); + FIXME("always returning LAN connection.\n"); *lpdwStatus = INTERNET_CONNECTION_LAN; } return LoadStringW(WININET_hModule, IDS_LANCONNECTION, lpszConnectionName, dwNameLen); @@ -1825,8 +1813,8 @@ INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackA( INTERNET_STATUS_CALLBACK retVal; LPWININETHANDLEHEADER lpwh; - TRACE("%p\n", hInternet); - + TRACE("0x%08x\n", (ULONG)hInternet); + if (!(lpwh = WININET_GetObject(hInternet))) return INTERNET_INVALID_STATUS_CALLBACK; @@ -1853,7 +1841,7 @@ INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackW( INTERNET_STATUS_CALLBACK retVal; LPWININETHANDLEHEADER lpwh; - TRACE("%p\n", hInternet); + TRACE("0x%08x\n", (ULONG)hInternet); if (!(lpwh = WININET_GetObject(hInternet))) return INTERNET_INVALID_STATUS_CALLBACK; @@ -2006,40 +1994,33 @@ BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffersOu /*********************************************************************** * InternetReadFileExW (WININET.@) - * SEE - * InternetReadFileExA() + * + * Read data from an open internet file. + * + * PARAMS + * hFile [I] Handle returned by InternetOpenUrl() or HttpOpenRequest(). + * lpBuffersOut [I/O] Buffer. + * dwFlags [I] Flags. + * dwContext [I] Context for callbacks. + * + * RETURNS + * FALSE, last error is set to ERROR_CALL_NOT_IMPLEMENTED + * + * NOTES + * Not implemented in Wine or native either (as of IE6 SP2). + * */ BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer, DWORD dwFlags, DWORD_PTR dwContext) { - LPWININETHANDLEHEADER hdr; - DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE; + ERR("(%p, %p, 0x%x, 0x%lx): not implemented in native\n", hFile, lpBuffer, dwFlags, dwContext); - TRACE("(%p %p 0x%x 0x%lx)\n", hFile, lpBuffer, dwFlags, dwContext); - - hdr = WININET_GetObject(hFile); - if (!hdr) { - INTERNET_SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - - if(hdr->vtbl->ReadFileExW) - res = hdr->vtbl->ReadFileExW(hdr, lpBuffer, dwFlags, dwContext); - - WININET_Release(hdr); - - TRACE("-- %s (%u, bytes read: %d)\n", res == ERROR_SUCCESS ? "TRUE": "FALSE", - res, lpBuffer->dwBufferLength); - - if(res != ERROR_SUCCESS) - SetLastError(res); - return res == ERROR_SUCCESS; + INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; } DWORD INET_QueryOption(DWORD option, void *buffer, DWORD *size, BOOL unicode) { - static BOOL warn = TRUE; - switch(option) { case INTERNET_OPTION_REQUEST_FLAGS: TRACE("INTERNET_OPTION_REQUEST_FLAGS\n"); @@ -2066,11 +2047,8 @@ DWORD INET_QueryOption(DWORD option, void *buffer, DWORD *size, BOOL unicode) return ERROR_SUCCESS; case INTERNET_OPTION_CONNECTED_STATE: + FIXME("INTERNET_OPTION_CONNECTED_STATE: semi-stub\n"); - if (warn) { - FIXME("INTERNET_OPTION_CONNECTED_STATE: semi-stub\n"); - warn = FALSE; - } if (*size < sizeof(ULONG)) return ERROR_INSUFFICIENT_BUFFER; @@ -2155,7 +2133,8 @@ DWORD INET_QueryOption(DWORD option, void *buffer, DWORD *size, BOOL unicode) case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME: case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL: FIXME("Unhandled dwOption %d\n", option->dwOption); - memset(&option->Value, 0, sizeof(option->Value)); + option->Value.dwValue = 0; + res = ERROR_INVALID_PARAMETER; break; default: @@ -2277,14 +2256,9 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption, { case INTERNET_OPTION_CALLBACK: { - if (!lpwhh) - { - INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); - return FALSE; - } - WININET_Release(lpwhh); - INTERNET_SetLastError(ERROR_INTERNET_OPTION_NOT_SETTABLE); - return FALSE; + INTERNET_STATUS_CALLBACK callback = *(INTERNET_STATUS_CALLBACK *)lpBuffer; + ret = (set_status_callback(lpwhh, callback, TRUE) != INTERNET_INVALID_STATUS_CALLBACK); + break; } case INTERNET_OPTION_HTTP_VERSION: { @@ -2368,35 +2342,8 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption, case INTERNET_OPTION_DISABLE_AUTODIAL: FIXME("Option INTERNET_OPTION_DISABLE_AUTODIAL; STUB\n"); break; - case INTERNET_OPTION_HTTP_DECODING: - FIXME("INTERNET_OPTION_HTTP_DECODING; STUB\n"); - INTERNET_SetLastError(ERROR_INTERNET_INVALID_OPTION); - ret = FALSE; - break; - case INTERNET_OPTION_COOKIES_3RD_PARTY: - FIXME("INTERNET_OPTION_COOKIES_3RD_PARTY; STUB\n"); - INTERNET_SetLastError(ERROR_INTERNET_INVALID_OPTION); - ret = FALSE; - break; - case INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY: - FIXME("INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY; STUB\n"); - INTERNET_SetLastError(ERROR_INTERNET_INVALID_OPTION); - ret = FALSE; - break; - case INTERNET_OPTION_CODEPAGE_PATH: - FIXME("INTERNET_OPTION_CODEPAGE_PATH; STUB\n"); - INTERNET_SetLastError(ERROR_INTERNET_INVALID_OPTION); - ret = FALSE; - break; - case INTERNET_OPTION_CODEPAGE_EXTRA: - FIXME("INTERNET_OPTION_CODEPAGE_EXTRA; STUB\n"); - INTERNET_SetLastError(ERROR_INTERNET_INVALID_OPTION); - ret = FALSE; - break; - case INTERNET_OPTION_IDN: - FIXME("INTERNET_OPTION_IDN; STUB\n"); - INTERNET_SetLastError(ERROR_INTERNET_INVALID_OPTION); - ret = FALSE; + case 86: + FIXME("86\n"); break; default: FIXME("Option %d STUB\n",dwOption); @@ -2434,15 +2381,12 @@ BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption, case INTERNET_OPTION_CALLBACK: { LPWININETHANDLEHEADER lpwh; + INTERNET_STATUS_CALLBACK callback = *(INTERNET_STATUS_CALLBACK *)lpBuffer; - if (!(lpwh = WININET_GetObject(hInternet))) - { - INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); - return FALSE; - } + if (!(lpwh = WININET_GetObject(hInternet))) return FALSE; + r = (set_status_callback(lpwh, callback, FALSE) != INTERNET_INVALID_STATUS_CALLBACK); WININET_Release(lpwh); - INTERNET_SetLastError(ERROR_INTERNET_OPTION_NOT_SETTABLE); - return FALSE; + return r; } case INTERNET_OPTION_PROXY: { @@ -2531,18 +2475,6 @@ BOOL WINAPI InternetTimeFromSystemTimeA( const SYSTEMTIME* time, DWORD format, L TRACE( "%p 0x%08x %p 0x%08x\n", time, format, string, size ); - if (!time || !string || format != INTERNET_RFC1123_FORMAT) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (size < INTERNET_RFC1123_BUFSIZE * sizeof(*string)) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - ret = InternetTimeFromSystemTimeW( time, format, stringW, sizeof(stringW) ); if (ret) WideCharToMultiByte( CP_ACP, 0, stringW, -1, string, size, NULL, NULL ); @@ -2560,17 +2492,10 @@ BOOL WINAPI InternetTimeFromSystemTimeW( const SYSTEMTIME* time, DWORD format, L TRACE( "%p 0x%08x %p 0x%08x\n", time, format, string, size ); - if (!time || !string || format != INTERNET_RFC1123_FORMAT) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } + if (!time || !string) return FALSE; - if (size < INTERNET_RFC1123_BUFSIZE * sizeof(*string)) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); + if (format != INTERNET_RFC1123_FORMAT || size < INTERNET_RFC1123_BUFSIZE * sizeof(WCHAR)) return FALSE; - } sprintfW( string, date, WININET_wkday[time->wDayOfWeek], @@ -2880,8 +2805,6 @@ static HINTERNET INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUr else urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT; } - if (urlComponents.nScheme == INTERNET_SCHEME_HTTPS) dwFlags |= INTERNET_FLAG_SECURE; - /* FIXME: should use pointers, not handles, as handles are not thread-safe */ client = HTTP_Connect(hIC, hostName, urlComponents.nPort, userName, password, dwFlags, dwContext, INET_OPENURL); @@ -3087,7 +3010,7 @@ static LPWITHREADERROR INTERNET_AllocThreadError(void) */ void INTERNET_SetLastError(DWORD dwError) { - LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex); + LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex); if (!lpwite) lpwite = INTERNET_AllocThreadError(); @@ -3108,7 +3031,7 @@ void INTERNET_SetLastError(DWORD dwError) */ DWORD INTERNET_GetLastError(void) { - LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex); + LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex); if (!lpwite) return 0; /* TlsGetValue clears last error, so set it again here */ SetLastError(lpwite->dwError); @@ -3181,7 +3104,7 @@ BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest) */ LPSTR INTERNET_GetResponseBuffer(void) { - LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex); + LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex); if (!lpwite) lpwite = INTERNET_AllocThreadError(); TRACE("\n"); @@ -3528,9 +3451,6 @@ static BOOL calc_url_length(LPURL_COMPONENTSW lpUrlComponents, if (lpUrlComponents->lpszUrlPath) *lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, UrlPath); - if (lpUrlComponents->lpszExtraInfo) - *lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, ExtraInfo); - return TRUE; } @@ -3779,6 +3699,7 @@ BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags, } } + if (lpUrlComponents->lpszUrlPath) { dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, UrlPath); @@ -3786,13 +3707,6 @@ BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags, lpszUrl += dwLen; } - if (lpUrlComponents->lpszExtraInfo) - { - dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, ExtraInfo); - memcpy(lpszUrl, lpUrlComponents->lpszExtraInfo, dwLen * sizeof(WCHAR)); - lpszUrl += dwLen; - } - *lpszUrl = '\0'; return TRUE; @@ -3818,25 +3732,6 @@ DWORD WINAPI InternetConfirmZoneCrossingW( HWND hWnd, LPWSTR szUrlPrev, LPWSTR s return ERROR_SUCCESS; } -/*********************************************************************** - * PrivacySetZonePreferenceW (WININET.@) - */ -DWORD WINAPI PrivacySetZonePreferenceW( DWORD zone, DWORD type, DWORD template, LPCWSTR preference ) -{ - FIXME( "%x %x %x %s: stub\n", zone, type, template, debugstr_w(preference) ); - return 0; -} - -/*********************************************************************** - * PrivacyGetZonePreferenceW (WININET.@) - */ -DWORD WINAPI PrivacyGetZonePreferenceW( DWORD zone, DWORD type, LPDWORD template, - LPWSTR preference, LPDWORD length ) -{ - FIXME( "%x %x: stub\n", zone, type ); - return 0; -} - DWORD WINAPI InternetDialA( HWND hwndParent, LPSTR lpszConnectoid, DWORD dwFlags, DWORD_PTR* lpdwConnection, DWORD dwReserved ) { diff --git a/reactos/dll/win32/wininet/internet.h b/reactos/dll/win32/wininet/internet.h index 48271d650ec..0dcf5a22ce6 100644 --- a/reactos/dll/win32/wininet/internet.h +++ b/reactos/dll/win32/wininet/internet.h @@ -42,17 +42,29 @@ # include #endif -#if !defined(__MINGW32__) && !defined(_MSC_VER) +#if defined(__MINGW32__) || defined (_MSC_VER) +#include "ws2tcpip.h" +#ifndef MSG_WAITALL +#define MSG_WAITALL 0 +#endif +#else #define closesocket close #define ioctlsocket ioctl #endif /* __MINGW32__ */ +/* ReactOS-specific definitions */ +#undef CP_UNIXCP +#define CP_UNIXCP CP_THREAD_ACP + /* used for netconnection.c stuff */ typedef struct { BOOL useSSL; int socketFD; void *ssl_s; + char *peek_msg; + char *peek_msg_mem; + size_t peek_len; } WININET_NETCONNECTION; static inline LPWSTR WININET_strdupW( LPCWSTR str ) @@ -121,7 +133,6 @@ typedef struct { DWORD (*SetOption)(WININETHANDLEHEADER*,DWORD,void*,DWORD); DWORD (*ReadFile)(WININETHANDLEHEADER*,void*,DWORD,DWORD*); DWORD (*ReadFileExA)(WININETHANDLEHEADER*,INTERNET_BUFFERSA*,DWORD,DWORD_PTR); - DWORD (*ReadFileExW)(WININETHANDLEHEADER*,INTERNET_BUFFERSW*,DWORD,DWORD_PTR); BOOL (*WriteFile)(WININETHANDLEHEADER*,const void*,DWORD,DWORD*); DWORD (*QueryDataAvailable)(WININETHANDLEHEADER*,DWORD*,DWORD,DWORD_PTR); DWORD (*FindNextFileW)(WININETHANDLEHEADER*,void*); @@ -195,18 +206,12 @@ typedef struct LPWSTR lpszStatusText; DWORD dwContentLength; /* total number of bytes to be read */ DWORD dwContentRead; /* bytes of the content read so far */ - DWORD dwBytesToWrite; - DWORD dwBytesWritten; HTTPHEADERW *pCustHeaders; DWORD nCustHeaders; HANDLE hCacheFile; LPWSTR lpszCacheFile; struct HttpAuthInfo *pAuthInfo; struct HttpAuthInfo *pProxyAuthInfo; - BOOL read_chunked; /* are we reading in chunked mode? */ - DWORD read_pos; /* current read position in read_buf */ - DWORD read_size; /* valid data size in read_buf */ - char read_buf[4096]; /* buffer for already read but not returned data */ } WININETHTTPREQW, *LPWININETHTTPREQW; @@ -292,12 +297,6 @@ struct WORKREQ_HTTPSENDREQUESTW BOOL bEndRequest; }; -struct WORKREQ_HTTPENDREQUESTW -{ - DWORD dwFlags; - DWORD_PTR dwContext; -}; - struct WORKREQ_SENDCALLBACK { DWORD_PTR dwContext; @@ -321,11 +320,6 @@ struct WORKREQ_INTERNETREADFILEEXA LPINTERNET_BUFFERSA lpBuffersOut; }; -struct WORKREQ_INTERNETREADFILEEXW -{ - LPINTERNET_BUFFERSW lpBuffersOut; -}; - typedef struct WORKREQ { void (*asyncproc)(struct WORKREQ*); @@ -344,11 +338,9 @@ typedef struct WORKREQ struct WORKREQ_FTPRENAMEFILEW FtpRenameFileW; struct WORKREQ_FTPFINDNEXTW FtpFindNextW; struct WORKREQ_HTTPSENDREQUESTW HttpSendRequestW; - struct WORKREQ_HTTPENDREQUESTW HttpEndRequestW; struct WORKREQ_SENDCALLBACK SendCallback; - struct WORKREQ_INTERNETOPENURLW InternetOpenUrlW; + struct WORKREQ_INTERNETOPENURLW InternetOpenUrlW; struct WORKREQ_INTERNETREADFILEEXA InternetReadFileExA; - struct WORKREQ_INTERNETREADFILEEXW InternetReadFileExW; } u; } WORKREQUEST, *LPWORKREQUEST; @@ -389,6 +381,7 @@ INTERNETAPI HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs, LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion, LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes, DWORD dwFlags, DWORD_PTR dwContext); +BOOL HTTP_FinishedReading(LPWININETHTTPREQW lpwhr); VOID SendAsyncCallback(LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInfo, @@ -398,6 +391,8 @@ VOID INTERNET_SendCallback(LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInfo, DWORD dwStatusInfoLength); +LPHTTPHEADERW HTTP_GetHeader(LPWININETHTTPREQW lpwhr, LPCWSTR header); + BOOL NETCON_connected(WININET_NETCONNECTION *connection); BOOL NETCON_init(WININET_NETCONNECTION *connnection, BOOL useSSL); BOOL NETCON_create(WININET_NETCONNECTION *connection, int domain, @@ -411,6 +406,7 @@ BOOL NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, BOOL NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags, int *recvd /* out */); BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *available); +BOOL NETCON_getNextLine(WININET_NETCONNECTION *connection, LPSTR lpszBuffer, LPDWORD dwBuffer); LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection); DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value); diff --git a/reactos/dll/win32/wininet/netconnection.c b/reactos/dll/win32/wininet/netconnection.c index d0d6f8e1dd2..5d8b4d75534 100644 --- a/reactos/dll/win32/wininet/netconnection.c +++ b/reactos/dll/win32/wininet/netconnection.c @@ -23,10 +23,6 @@ #include "config.h" #include "wine/port.h" -#if defined(__MINGW32__) || defined (_MSC_VER) -#include -#endif - #include #ifdef HAVE_POLL_H #include @@ -37,12 +33,10 @@ #ifdef HAVE_SYS_TIME_H # include #endif +#include #ifdef HAVE_SYS_SOCKET_H # include #endif -#ifdef HAVE_SYS_FILIO_H -# include -#endif #ifdef HAVE_UNISTD_H # include #endif @@ -61,6 +55,9 @@ #undef FAR #undef DSA #endif +#ifdef HAVE_SYS_SOCKET_H +# include +#endif #include #include @@ -118,18 +115,17 @@ MAKE_FUNCPTR(SSL_connect); MAKE_FUNCPTR(SSL_shutdown); MAKE_FUNCPTR(SSL_write); MAKE_FUNCPTR(SSL_read); -MAKE_FUNCPTR(SSL_pending); MAKE_FUNCPTR(SSL_get_verify_result); MAKE_FUNCPTR(SSL_get_peer_certificate); MAKE_FUNCPTR(SSL_CTX_get_timeout); MAKE_FUNCPTR(SSL_CTX_set_timeout); MAKE_FUNCPTR(SSL_CTX_set_default_verify_paths); +MAKE_FUNCPTR(i2d_X509); /* OpenSSL's libcrypto functions that we use */ MAKE_FUNCPTR(BIO_new_fp); MAKE_FUNCPTR(ERR_get_error); MAKE_FUNCPTR(ERR_error_string); -MAKE_FUNCPTR(i2d_X509); #undef MAKE_FUNCPTR #endif @@ -182,12 +178,12 @@ BOOL NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL) DYNSSL(SSL_shutdown); DYNSSL(SSL_write); DYNSSL(SSL_read); - DYNSSL(SSL_pending); DYNSSL(SSL_get_verify_result); DYNSSL(SSL_get_peer_certificate); DYNSSL(SSL_CTX_get_timeout); DYNSSL(SSL_CTX_set_timeout); DYNSSL(SSL_CTX_set_default_verify_paths); + DYNSSL(i2d_X509); #undef DYNSSL #define DYNCRYPTO(x) \ @@ -201,7 +197,6 @@ BOOL NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL) DYNCRYPTO(BIO_new_fp); DYNCRYPTO(ERR_get_error); DYNCRYPTO(ERR_error_string); - DYNCRYPTO(i2d_X509); #undef DYNCRYPTO pSSL_library_init(); @@ -209,6 +204,8 @@ BOOL NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL) pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */ meth = pSSLv23_method(); + connection->peek_msg = NULL; + connection->peek_msg_mem = NULL; #else FIXME("can't use SSL, not compiled in.\n"); INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR); @@ -329,6 +326,11 @@ BOOL NETCON_close(WININET_NETCONNECTION *connection) #ifdef SONAME_LIBSSL if (connection->useSSL) { + HeapFree(GetProcessHeap(),0,connection->peek_msg_mem); + connection->peek_msg = NULL; + connection->peek_msg_mem = NULL; + connection->peek_len = 0; + pSSL_shutdown(connection->ssl_s); pSSL_free(connection->ssl_s); connection->ssl_s = NULL; @@ -536,8 +538,55 @@ BOOL NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int f else { #ifdef SONAME_LIBSSL - *recvd = pSSL_read(connection->ssl_s, buf, len); - return *recvd > 0 || !len; + if (flags & ~(MSG_PEEK|MSG_WAITALL)) + 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 && !connection->peek_msg) + { + connection->peek_msg = connection->peek_msg_mem = HeapAlloc(GetProcessHeap(), 0, (sizeof(char) * len) + 1); + } + else if (flags & MSG_PEEK && connection->peek_msg) + { + if (len < connection->peek_len) + FIXME("buffer isn't big enough. Do the expect us to wrap?\n"); + *recvd = min(len, connection->peek_len); + memcpy(buf, connection->peek_msg, *recvd); + return TRUE; + } + else if (connection->peek_msg) + { + *recvd = min(len, connection->peek_len); + memcpy(buf, connection->peek_msg, *recvd); + connection->peek_len -= *recvd; + connection->peek_msg += *recvd; + if (connection->peek_len == 0) + { + HeapFree(GetProcessHeap(), 0, connection->peek_msg_mem); + connection->peek_msg_mem = NULL; + connection->peek_msg = NULL; + } + /* check if we got enough data from the peek buffer */ + if (!(flags & MSG_WAITALL) || (*recvd == len)) + return TRUE; + /* otherwise, fall through */ + } + *recvd += pSSL_read(connection->ssl_s, (char*)buf + *recvd, len - *recvd); + if (flags & MSG_PEEK) /* must copy stuff into buffer */ + { + connection->peek_len = *recvd; + if (!*recvd) + { + HeapFree(GetProcessHeap(), 0, connection->peek_msg_mem); + connection->peek_msg_mem = NULL; + connection->peek_msg = NULL; + } + else + memcpy(connection->peek_msg, buf, *recvd); + } + if (*recvd < 1 && len) + return FALSE; + return TRUE; #else return FALSE; #endif @@ -555,9 +604,13 @@ BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *avail if (!NETCON_connected(connection)) return FALSE; +#ifdef SONAME_LIBSSL + if (connection->peek_msg) *available = connection->peek_len; +#endif + +#ifdef FIONREAD if (!connection->useSSL) { -#ifdef FIONREAD int unread; int retval = ioctlsocket(connection->socketFD, FIONREAD, &unread); if (!retval) @@ -565,17 +618,115 @@ BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *avail TRACE("%d bytes of queued, but unread data\n", unread); *available += unread; } + } #endif + return TRUE; +} + +/****************************************************************************** + * 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; + DWORD 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(sock_get_error(errno)); + 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; + TRACE(":%u %s\n", nRecv, lpszBuffer); + return TRUE; + } + else + { + return FALSE; + } } else { #ifdef SONAME_LIBSSL - *available = pSSL_pending(connection->ssl_s); + long prev_timeout; + DWORD 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; + TRACE("_SSL:%u %s\n", nRecv, lpszBuffer); + return TRUE; + } + return FALSE; +#else + return FALSE; #endif } - return TRUE; } + LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection) { #ifdef SONAME_LIBSSL @@ -637,7 +788,7 @@ DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value tv.tv_usec = (value % 1000) * 1000; result = setsockopt(connection->socketFD, SOL_SOCKET, - send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv, + send ? SO_SNDTIMEO : SO_RCVTIMEO, &tv, sizeof(tv)); if (result == -1) diff --git a/reactos/dll/win32/wininet/urlcache.c b/reactos/dll/win32/wininet/urlcache.c index f385c7e81cb..b4feba3260c 100644 --- a/reactos/dll/win32/wininet/urlcache.c +++ b/reactos/dll/win32/wininet/urlcache.c @@ -692,7 +692,6 @@ static LPURLCACHE_HEADER URLCacheContainer_LockIndex(URLCACHECONTAINER * pContai * of the memory mapped file */ if (pHeader->dwFileSize != pContainer->file_size) { - UnmapViewOfFile( pHeader ); URLCacheContainer_CloseIndex(pContainer); error = URLCacheContainer_OpenIndex(pContainer); if (error != ERROR_SUCCESS) @@ -3624,26 +3623,10 @@ BOOL WINAPI IsUrlCacheEntryExpiredW( LPCWSTR url, DWORD dwFlags, FILETIME* pftLa /*********************************************************************** * GetDiskInfoA (WININET.@) */ -BOOL WINAPI GetDiskInfoA(PCSTR path, PDWORD cluster_size, PDWORDLONG free, PDWORDLONG total) +DWORD WINAPI GetDiskInfoA(void *p0, void *p1, void *p2, void *p3) { - BOOL ret; - ULARGE_INTEGER bytes_free, bytes_total; - - TRACE("(%s, %p, %p, %p)\n", debugstr_a(path), cluster_size, free, total); - - if (!path) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if ((ret = GetDiskFreeSpaceExA(path, NULL, &bytes_total, &bytes_free))) - { - if (cluster_size) *cluster_size = 1; - if (free) *free = bytes_free.QuadPart; - if (total) *total = bytes_total.QuadPart; - } - return ret; + FIXME("(%p, %p, %p, %p)\n", p0, p1, p2, p3); + return 0; } /*********************************************************************** @@ -3654,12 +3637,3 @@ DWORD WINAPI RegisterUrlCacheNotification(LPVOID a, DWORD b, DWORD c, DWORD d, D FIXME("(%p %x %x %x %x %x)\n", a, b, c, d, e, f); return 0; } - -/*********************************************************************** - * IncrementUrlCacheHeaderData (WININET.@) - */ -BOOL WINAPI IncrementUrlCacheHeaderData(DWORD index, LPDWORD data) -{ - FIXME("(%u, %p)\n", index, data); - return FALSE; -} diff --git a/reactos/dll/win32/wininet/utility.c b/reactos/dll/win32/wininet/utility.c index b68cf8d4a57..b0d9c9c91c6 100644 --- a/reactos/dll/win32/wininet/utility.c +++ b/reactos/dll/win32/wininet/utility.c @@ -25,10 +25,6 @@ #include "config.h" #include "wine/port.h" -#if defined(__MINGW32__) || defined (_MSC_VER) -#include -#endif - #include #include #include @@ -44,8 +40,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet); -#ifndef HAVE_GETADDRINFO - /* critical section to protect non-reentrant gethostbyname() */ static CRITICAL_SECTION cs_gethostbyname; static CRITICAL_SECTION_DEBUG critsect_debug = @@ -56,8 +50,6 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION cs_gethostbyname = { &critsect_debug, -1, 0, 0, 0, 0 }; -#endif - #define TIME_STRING_LEN 30 time_t ConvertTimeString(LPCWSTR asctime) @@ -150,12 +142,7 @@ BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort, WCHAR *found; char *name; int len, sz; -#ifdef HAVE_GETADDRINFO - struct addrinfo *res, hints; - int ret; -#else struct hostent *phe; -#endif TRACE("%s\n", debugstr_w(lpszServerName)); @@ -171,45 +158,27 @@ BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort, len = strlenW(lpszServerName); sz = WideCharToMultiByte( CP_UNIXCP, 0, lpszServerName, len, NULL, 0, NULL, NULL ); - if (!(name = HeapAlloc( GetProcessHeap(), 0, sz + 1 ))) return FALSE; + name = HeapAlloc(GetProcessHeap(), 0, sz+1); WideCharToMultiByte( CP_UNIXCP, 0, lpszServerName, len, name, sz, NULL, NULL ); name[sz] = 0; -#ifdef HAVE_GETADDRINFO - memset( &hints, 0, sizeof(struct addrinfo) ); - hints.ai_family = AF_INET; - - ret = getaddrinfo( name, NULL, &hints, &res ); - HeapFree( GetProcessHeap(), 0, name ); - if (ret != 0) - { - TRACE("failed to get address of %s (%s)\n", debugstr_w(lpszServerName), gai_strerror(ret)); - return FALSE; - } - memset( psa, 0, sizeof(struct sockaddr_in) ); - memcpy( &psa->sin_addr, &((struct sockaddr_in *)res->ai_addr)->sin_addr, sizeof(struct in_addr) ); - psa->sin_family = res->ai_family; - psa->sin_port = htons(nServerPort); - - freeaddrinfo( res ); -#else EnterCriticalSection( &cs_gethostbyname ); phe = gethostbyname(name); HeapFree( GetProcessHeap(), 0, name ); if (NULL == phe) { - TRACE("failed to get address of %s (%d)\n", debugstr_w(lpszServerName), h_errno); + TRACE("Failed to get hostname: (%s)\n", debugstr_w(lpszServerName) ); LeaveCriticalSection( &cs_gethostbyname ); return FALSE; } + memset(psa,0,sizeof(struct sockaddr_in)); memcpy((char *)&psa->sin_addr, phe->h_addr, phe->h_length); psa->sin_family = phe->h_addrtype; psa->sin_port = htons(nServerPort); LeaveCriticalSection( &cs_gethostbyname ); -#endif return TRUE; } diff --git a/reactos/dll/win32/wininet/wininet.rbuild b/reactos/dll/win32/wininet/wininet.rbuild index e2a96c941f1..cf0064396ea 100644 --- a/reactos/dll/win32/wininet/wininet.rbuild +++ b/reactos/dll/win32/wininet/wininet.rbuild @@ -18,7 +18,6 @@ secur32 crypt32 ws2_32 - pseh cookie.c dialogs.c ftp.c diff --git a/reactos/dll/win32/wininet/wininet.spec b/reactos/dll/win32/wininet/wininet.spec index d5995eb3cc3..dfbc38c02fc 100644 --- a/reactos/dll/win32/wininet/wininet.spec +++ b/reactos/dll/win32/wininet/wininet.spec @@ -1,5 +1,5 @@ 101 stub -noname DoConnectoidsExist -102 stdcall -noname GetDiskInfoA(str ptr ptr ptr) +102 stub -noname GetDiskInfoA 103 stub -noname PerformOperationOverUrlCacheA 104 stub -noname HttpCheckDavComplianceA 105 stub -noname HttpCheckDavComplianceW @@ -9,7 +9,7 @@ 111 stub -noname ExportCookieFileW 112 stub -noname IsProfilesEnabled 116 stub -noname IsDomainlegalCookieDomainA -117 stdcall -noname IsDomainLegalCookieDomainW(wstr wstr) +117 stub -noname IsDomainLegalCookieDomainW 118 stub -noname FindP3PPolicySymbol 120 stub -noname MapResourceToPolicy 121 stub -noname GetP3PPolicy @@ -109,7 +109,7 @@ @ stdcall HttpSendRequestExA(long ptr ptr long long) @ stdcall HttpSendRequestExW(long ptr ptr long long) @ stdcall HttpSendRequestW(ptr wstr long ptr long) -@ stdcall IncrementUrlCacheHeaderData(long ptr) +@ stub IncrementUrlCacheHeaderData @ stub InternetAlgIdToStringA @ stub InternetAlgIdToStringW @ stdcall InternetAttemptConnect(long) @@ -213,10 +213,10 @@ @ stdcall IsUrlCacheEntryExpiredW(wstr long ptr) @ stub LoadUrlCacheContent @ stub ParseX509EncodedCertificateForListBoxEntry -@ stdcall PrivacyGetZonePreferenceW(long long ptr ptr ptr) -@ stdcall PrivacySetZonePreferenceW(long long long wstr) +@ stub PrivacyGetZonePreferenceW # (long long ptr ptr ptr) +@ stub PrivacySetZonePreferenceW # (long long long wstr) @ stdcall ReadUrlCacheEntryStream(ptr long ptr ptr long) -@ stdcall RegisterUrlCacheNotification(ptr long long long long long) +@ stub RegisterUrlCacheNotification @ stdcall ResumeSuspendedDownload(long long) @ stdcall RetrieveUrlCacheEntryFileA(str ptr ptr long) @ stdcall RetrieveUrlCacheEntryFileW(wstr ptr ptr long)