Changelog: - when sending a request using HttpOpenRequest/HttpSendRequest, send the User-Agent header; fixed the Accept and the Referer header handling to really work - fixed bug in the HTTP_ProcessHeader: when a second value was supposed to be added to an existing one, the buffer was reduced to be 1 char long instead of being expanded, due to the precedence rules of the operator '?' - added support for opening URLs that redirect to a different place Alberto Index: http.c =================================================================== RCS file: /home/wine/wine/dlls/wininet/http.c,v retrieving revision 1.31 diff -u -r1.31 http.c --- http.c 13 Nov 2002 04:08:26 -0000 1.31 +++ http.c 5 Dec 2002 19:32:37 -0000 @@ -58,8 +58,9 @@ #define MAX_FIELD_LEN 256 -#define HTTP_REFERER "Referer" -#define HTTP_ACCEPT "Accept" +#define HTTP_REFERER "Referer" +#define HTTP_ACCEPT "Accept" +#define HTTP_USERAGENT "User-Agent" #define HTTP_ADDHDR_FLAG_ADD 0x20000000 #define HTTP_ADDHDR_FLAG_ADD_IF_NEW 0x10000000 @@ -200,7 +201,13 @@ LPWININETHTTPSESSIONA lpwhs = (LPWININETHTTPSESSIONA) hHttpSession; LPWININETAPPINFOA hIC = NULL; - TRACE("\n"); + TRACE("(%s, %s, %s, %s, %ld, %ld)\n", lpszVerb, lpszObjectName, lpszVersion, lpszReferrer, dwFlags, dwContext); + if(lpszAcceptTypes!=NULL) + { + int i; + for(i=0;lpszAcceptTypes[i]!=NULL;i++) + TRACE("\taccept type: %s\n",lpszAcceptTypes[i]); + } if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION) { @@ -266,6 +273,8 @@ { char szVerb[20], szObjectName[INTERNET_MAX_PATH_LENGTH]; + TRACE("(%s, %s, %s, %s, %ld, %ld)\n", debugstr_w(lpszVerb), debugstr_w(lpszObjectName), debugstr_w(lpszVersion), debugstr_w(lpszReferrer), dwFlags, dwContext); + if(lpszVerb!=NULL) WideCharToMultiByte(CP_ACP,0,lpszVerb,-1,szVerb,20,NULL,NULL); else @@ -276,7 +285,7 @@ szObjectName[0]=0; TRACE("object name=%s\n",szObjectName); FIXME("lpszVersion, lpszReferrer and lpszAcceptTypes ignored\n"); - return HttpOpenRequestA(hHttpSession, szVerb, szObjectName, NULL, NULL, NULL, dwFlags, dwContext); + return HttpOpenRequestA(hHttpSession, szVerb[0]?szVerb:NULL, szObjectName, NULL, NULL, NULL, dwFlags, dwContext); } /*********************************************************************** @@ -337,12 +346,18 @@ } } + if (NULL != hIC->lpszAgent && strlen(hIC->lpszAgent)) + HTTP_ProcessHeader(lpwhr, HTTP_USERAGENT, hIC->lpszAgent, HTTP_ADDHDR_FLAG_REQ|HTTP_ADDREQ_FLAG_REPLACE|HTTP_ADDHDR_FLAG_ADD_IF_NEW); + if (NULL != lpszReferrer && strlen(lpszReferrer)) - HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpszReferrer, HTTP_ADDHDR_FLAG_COALESCE); + HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpszReferrer, HTTP_ADDHDR_FLAG_REQ|HTTP_ADDREQ_FLAG_REPLACE|HTTP_ADDHDR_FLAG_ADD_IF_NEW); - /* FIXME */ - if (NULL != lpszAcceptTypes && strlen(*lpszAcceptTypes)) - HTTP_ProcessHeader(lpwhr, HTTP_ACCEPT, *lpszAcceptTypes, HTTP_ADDHDR_FLAG_COALESCE); + if(lpszAcceptTypes!=NULL) + { + int i; + for(i=0;lpszAcceptTypes[i]!=NULL;i++) + HTTP_ProcessHeader(lpwhr, HTTP_ACCEPT, lpszAcceptTypes[i], HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA|HTTP_ADDHDR_FLAG_REQ|HTTP_ADDHDR_FLAG_ADD_IF_NEW); + } if (NULL == lpszVerb) lpwhr->lpszVerb = HTTP_strdup("GET"); @@ -695,9 +710,9 @@ INTERNET_AsyncCall(&workRequest); /* - * This is from windows. I do not know what the name is + * This is from windows. */ - SetLastError(0x3e5); + SetLastError(ERROR_IO_PENDING); return 0; } else @@ -737,6 +752,103 @@ } /*********************************************************************** + * HandleRedirect (internal) + */ + +BOOL HandleRedirect(LPWININETHTTPREQA lpwhr, LPCSTR lpszUrl, LPCSTR lpszHeaders, + DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength) +{ + LPWININETHTTPSESSIONA lpwhs = (LPWININETHTTPSESSIONA) lpwhr->hdr.lpwhparent; + LPWININETAPPINFOA hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent; + char path[2048]; + if(lpszUrl[0]=='/') + { + /* if it's an absolute path, keep the same session info */ + strcpy(path,lpszUrl); + } + else + { + URL_COMPONENTSA urlComponents; + char protocol[32], hostName[MAXHOSTNAME], userName[1024]; + char password[1024], extra[1024]; + urlComponents.dwStructSize = sizeof(URL_COMPONENTSA); + urlComponents.lpszScheme = protocol; + urlComponents.dwSchemeLength = 32; + urlComponents.lpszHostName = hostName; + urlComponents.dwHostNameLength = MAXHOSTNAME; + urlComponents.lpszUserName = userName; + urlComponents.dwUserNameLength = 1024; + urlComponents.lpszPassword = password; + urlComponents.dwPasswordLength = 1024; + urlComponents.lpszUrlPath = path; + urlComponents.dwUrlPathLength = 2048; + urlComponents.lpszExtraInfo = extra; + urlComponents.dwExtraInfoLength = 1024; + if(!InternetCrackUrlA(lpszUrl, strlen(lpszUrl), 0, &urlComponents)) + return FALSE; + + if (urlComponents.nPort == INTERNET_INVALID_PORT_NUMBER) + urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT; + + /* consider the current host as the referef */ + if (NULL != lpwhs->lpszServerName && strlen(lpwhs->lpszServerName)) + HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpwhs->lpszServerName, HTTP_ADDHDR_FLAG_REQ|HTTP_ADDREQ_FLAG_REPLACE|HTTP_ADDHDR_FLAG_ADD_IF_NEW); + + if (NULL != lpwhs->lpszServerName) + HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName); + lpwhs->lpszServerName = HTTP_strdup(hostName); + if (NULL != lpwhs->lpszUserName) + HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName); + lpwhs->lpszUserName = HTTP_strdup(userName); + lpwhs->nServerPort = urlComponents.nPort; + + if (NULL != lpwhr->lpszHostName) + HeapFree(GetProcessHeap(), 0, lpwhr->lpszHostName); + lpwhr->lpszHostName=HTTP_strdup(hostName); + + SendAsyncCallback(hIC, lpwhs, lpwhr->hdr.dwContext, + INTERNET_STATUS_RESOLVING_NAME, + lpwhs->lpszServerName, + strlen(lpwhs->lpszServerName)+1); + + if (!GetAddress(lpwhs->lpszServerName, lpwhs->nServerPort, + &lpwhs->phostent, &lpwhs->socketAddress)) + { + INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED); + return FALSE; + } + + SendAsyncCallback(hIC, lpwhs, lpwhr->hdr.dwContext, + INTERNET_STATUS_NAME_RESOLVED, + &(lpwhs->socketAddress), + sizeof(struct sockaddr_in)); + + } + + if(lpwhr->lpszPath) + HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath); + lpwhr->lpszPath=NULL; + if (strlen(path)) + { + DWORD needed = 0; + HRESULT rc; + rc = UrlEscapeA(path, NULL, &needed, URL_ESCAPE_SPACES_ONLY); + if (rc != E_POINTER) + needed = strlen(path)+1; + lpwhr->lpszPath = HeapAlloc(GetProcessHeap(), 0, needed); + rc = UrlEscapeA(path, lpwhr->lpszPath, &needed, + URL_ESCAPE_SPACES_ONLY); + if (rc) + { + ERR("Unable to escape string!(%s) (%ld)\n",path,rc); + strcpy(lpwhr->lpszPath,path); + } + } + + return HttpSendRequestA((HINTERNET)lpwhr, lpszHeaders, dwHeaderLength, lpOptional, dwOptionalLength); +} + +/*********************************************************************** * HTTP_HttpSendRequestA (internal) * * Sends the specified request to the HTTP server @@ -863,6 +975,7 @@ { cnt += sprintf(requestString + cnt, "\r\n%s: %s", lpwhr->StdHeaders[i].lpszField, lpwhr->StdHeaders[i].lpszValue); + TRACE("Adding header %s (%s)\n",lpwhr->StdHeaders[i].lpszField,lpwhr->StdHeaders[i].lpszValue); } } @@ -873,6 +986,7 @@ { cnt += sprintf(requestString + cnt, "\r\n%s: %s", lpwhr->pCustHeaders[i].lpszField, lpwhr->pCustHeaders[i].lpszValue); + TRACE("Adding custom header %s (%s)\n",lpwhr->pCustHeaders[i].lpszField,lpwhr->pCustHeaders[i].lpszValue); } } @@ -921,6 +1035,27 @@ if (requestString) HeapFree(GetProcessHeap(), 0, requestString); + /* TODO: send notification for P3P header */ + + if(!(hIC->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && bSuccess) + { + DWORD dwCode,dwCodeLength=sizeof(DWORD),dwIndex=0; + if(HttpQueryInfoA(hHttpRequest,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,&dwCode,&dwCodeLength,&dwIndex) && + (dwCode==302 || dwCode==301)) + { + char szNewLocation[2048]; + DWORD dwBufferSize=2048; + dwIndex=0; + if(HttpQueryInfoA(hHttpRequest,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,&dwIndex)) + { + SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext, + INTERNET_STATUS_REDIRECT, szNewLocation, + dwBufferSize); + return HandleRedirect(lpwhr, szNewLocation, lpszHeaders, + dwHeaderLength, lpOptional, dwOptionalLength); + } + } + } if (hIC->lpfnStatusCB) { @@ -1292,7 +1427,7 @@ BOOL bSuccess = FALSE; INT index; - TRACE("--> %s:%s - 0x%08x\n", field, value, (unsigned int)dwModifier); + TRACE("--> %s: %s - 0x%08x\n", field, value, (unsigned int)dwModifier); /* Adjust modifier flags */ if (dwModifier & COALESCEFLASG) @@ -1387,6 +1522,7 @@ } else { + WARN("HeapReAlloc (%d bytes) failed\n",len+1); INTERNET_SetLastError(ERROR_OUTOFMEMORY); } } @@ -1410,7 +1546,7 @@ lphttpHdr->wFlags |= HDR_COMMADELIMITED; } - len = origlen + valuelen + (ch > 0) ? 1 : 0; + len = origlen + valuelen + ((ch > 0) ? 1 : 0); lpsztmp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lphttpHdr->lpszValue, len+1); if (lpsztmp) @@ -1428,11 +1564,12 @@ } else { + WARN("HeapReAlloc (%d bytes) failed\n",len+1); INTERNET_SetLastError(ERROR_OUTOFMEMORY); } } } - TRACE("<--\n"); + TRACE("<-- %d\n",bSuccess); return bSuccess; }