wininet: Store entries in url cache with valid last-modified date.
This commit is contained in:
parent
f9f431186f
commit
28e9229336
|
@ -1572,14 +1572,12 @@ static void HTTPREQ_Destroy(object_header_t *hdr)
|
||||||
|
|
||||||
if(request->hCacheFile) {
|
if(request->hCacheFile) {
|
||||||
WCHAR url[INTERNET_MAX_URL_LENGTH];
|
WCHAR url[INTERNET_MAX_URL_LENGTH];
|
||||||
FILETIME ft;
|
|
||||||
|
|
||||||
CloseHandle(request->hCacheFile);
|
CloseHandle(request->hCacheFile);
|
||||||
|
|
||||||
memset(&ft, 0, sizeof(FILETIME));
|
|
||||||
if(HTTP_GetRequestURL(request, url)) {
|
if(HTTP_GetRequestURL(request, url)) {
|
||||||
CommitUrlCacheEntryW(url, request->cacheFile, request->expires, ft,
|
CommitUrlCacheEntryW(url, request->cacheFile, request->expires,
|
||||||
NORMAL_CACHE_ENTRY, NULL, 0, NULL, 0);
|
request->last_modified, NORMAL_CACHE_ENTRY, NULL, 0, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3630,24 +3628,152 @@ static WORD HTTP_ParseMonth(LPCWSTR month)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: only accepts dates in RFC 1123 format, which is the only correct
|
/* Parses the string pointed to by *str, assumed to be a 24-hour time HH:MM:SS,
|
||||||
* format for HTTP, but which may not be the only format actually seen in the
|
* optionally preceded by whitespace.
|
||||||
* wild. http://www.hackcraft.net/web/datetime/ suggests at least RFC 850
|
* Upon success, returns TRUE, sets the wHour, wMinute, and wSecond fields of
|
||||||
* dates and dates as formatted by asctime() should be accepted as well.
|
* st, and sets *str to the first character after the time format.
|
||||||
*/
|
*/
|
||||||
static BOOL HTTP_ParseDate(LPCWSTR value, FILETIME *ft)
|
static BOOL HTTP_ParseTime(SYSTEMTIME *st, LPCWSTR *str)
|
||||||
|
{
|
||||||
|
LPCWSTR ptr = *str;
|
||||||
|
WCHAR *nextPtr;
|
||||||
|
unsigned long num;
|
||||||
|
|
||||||
|
while (isspaceW(*ptr))
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
num = strtoulW(ptr, &nextPtr, 10);
|
||||||
|
if (!nextPtr || nextPtr <= ptr || *nextPtr != ':')
|
||||||
|
{
|
||||||
|
ERR("unexpected time format %s\n", debugstr_w(ptr));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (num > 23)
|
||||||
|
{
|
||||||
|
ERR("unexpected hour in time format %s\n", debugstr_w(ptr));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
ptr = nextPtr + 1;
|
||||||
|
st->wHour = (WORD)num;
|
||||||
|
num = strtoulW(ptr, &nextPtr, 10);
|
||||||
|
if (!nextPtr || nextPtr <= ptr || *nextPtr != ':')
|
||||||
|
{
|
||||||
|
ERR("unexpected time format %s\n", debugstr_w(ptr));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (num > 59)
|
||||||
|
{
|
||||||
|
ERR("unexpected minute in time format %s\n", debugstr_w(ptr));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
ptr = nextPtr + 1;
|
||||||
|
st->wMinute = (WORD)num;
|
||||||
|
num = strtoulW(ptr, &nextPtr, 10);
|
||||||
|
if (!nextPtr || nextPtr <= ptr)
|
||||||
|
{
|
||||||
|
ERR("unexpected time format %s\n", debugstr_w(ptr));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (num > 59)
|
||||||
|
{
|
||||||
|
ERR("unexpected second in time format %s\n", debugstr_w(ptr));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
ptr = nextPtr + 1;
|
||||||
|
*str = ptr;
|
||||||
|
st->wSecond = (WORD)num;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL HTTP_ParseDateAsAsctime(LPCWSTR value, FILETIME *ft)
|
||||||
{
|
{
|
||||||
static const WCHAR gmt[]= { 'G','M','T',0 };
|
static const WCHAR gmt[]= { 'G','M','T',0 };
|
||||||
WCHAR *ptr, *nextPtr, day[4], month[4], *monthPtr;
|
WCHAR day[4], *dayPtr, month[4], *monthPtr, *nextPtr;
|
||||||
|
LPCWSTR ptr;
|
||||||
|
SYSTEMTIME st = { 0 };
|
||||||
|
unsigned long num;
|
||||||
|
|
||||||
|
for (ptr = value, dayPtr = day; *ptr && !isspaceW(*ptr) &&
|
||||||
|
dayPtr - day < sizeof(day) / sizeof(day[0]) - 1; ptr++, dayPtr++)
|
||||||
|
*dayPtr = *ptr;
|
||||||
|
*dayPtr = 0;
|
||||||
|
st.wDayOfWeek = HTTP_ParseDay(day);
|
||||||
|
if (st.wDayOfWeek >= 7)
|
||||||
|
{
|
||||||
|
ERR("unexpected weekday %s\n", debugstr_w(day));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (isspaceW(*ptr))
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
for (monthPtr = month; !isspace(*ptr) &&
|
||||||
|
monthPtr - month < sizeof(month) / sizeof(month[0]) - 1;
|
||||||
|
monthPtr++, ptr++)
|
||||||
|
*monthPtr = *ptr;
|
||||||
|
*monthPtr = 0;
|
||||||
|
st.wMonth = HTTP_ParseMonth(month);
|
||||||
|
if (!st.wMonth || st.wMonth > 12)
|
||||||
|
{
|
||||||
|
ERR("unexpected month %s\n", debugstr_w(month));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (isspaceW(*ptr))
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
num = strtoulW(ptr, &nextPtr, 10);
|
||||||
|
if (!nextPtr || nextPtr <= ptr || !num || num > 31)
|
||||||
|
{
|
||||||
|
ERR("unexpected day %s\n", debugstr_w(ptr));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
ptr = nextPtr;
|
||||||
|
st.wDay = (WORD)num;
|
||||||
|
|
||||||
|
while (isspaceW(*ptr))
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
if (!HTTP_ParseTime(&st, &ptr))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (isspaceW(*ptr))
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
num = strtoulW(ptr, &nextPtr, 10);
|
||||||
|
if (!nextPtr || nextPtr <= ptr || num < 1601 || num > 30827)
|
||||||
|
{
|
||||||
|
ERR("unexpected year %s\n", debugstr_w(ptr));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
ptr = nextPtr;
|
||||||
|
st.wYear = (WORD)num;
|
||||||
|
|
||||||
|
while (isspaceW(*ptr))
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
/* asctime() doesn't report a timezone, but some web servers do, so accept
|
||||||
|
* with or without GMT.
|
||||||
|
*/
|
||||||
|
if (*ptr && strcmpW(ptr, gmt))
|
||||||
|
{
|
||||||
|
ERR("unexpected timezone %s\n", debugstr_w(ptr));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return SystemTimeToFileTime(&st, ft);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL HTTP_ParseRfc1123Date(LPCWSTR value, FILETIME *ft)
|
||||||
|
{
|
||||||
|
static const WCHAR gmt[]= { 'G','M','T',0 };
|
||||||
|
WCHAR *nextPtr, day[4], month[4], *monthPtr;
|
||||||
|
LPCWSTR ptr;
|
||||||
unsigned long num;
|
unsigned long num;
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
|
|
||||||
ptr = strchrW(value, ',');
|
ptr = strchrW(value, ',');
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
{
|
|
||||||
ERR("unexpected date format %s\n", debugstr_w(value));
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
if (ptr - value != 3)
|
if (ptr - value != 3)
|
||||||
{
|
{
|
||||||
ERR("unexpected weekday %s\n", debugstr_wn(value, ptr - value));
|
ERR("unexpected weekday %s\n", debugstr_wn(value, ptr - value));
|
||||||
|
@ -3702,48 +3828,8 @@ static BOOL HTTP_ParseDate(LPCWSTR value, FILETIME *ft)
|
||||||
ptr = nextPtr;
|
ptr = nextPtr;
|
||||||
st.wYear = (WORD)num;
|
st.wYear = (WORD)num;
|
||||||
|
|
||||||
while (isspaceW(*ptr))
|
if (!HTTP_ParseTime(&st, &ptr))
|
||||||
ptr++;
|
|
||||||
|
|
||||||
num = strtoulW(ptr, &nextPtr, 10);
|
|
||||||
if (!nextPtr || nextPtr <= ptr || *nextPtr != ':')
|
|
||||||
{
|
|
||||||
ERR("unexpected time format %s\n", debugstr_w(ptr));
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
if (num > 23)
|
|
||||||
{
|
|
||||||
ERR("unexpected hour in time format %s\n", debugstr_w(ptr));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
ptr = nextPtr + 1;
|
|
||||||
st.wHour = (WORD)num;
|
|
||||||
num = strtoulW(ptr, &nextPtr, 10);
|
|
||||||
if (!nextPtr || nextPtr <= ptr || *nextPtr != ':')
|
|
||||||
{
|
|
||||||
ERR("unexpected time format %s\n", debugstr_w(ptr));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (num > 59)
|
|
||||||
{
|
|
||||||
ERR("unexpected minute in time format %s\n", debugstr_w(ptr));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
ptr = nextPtr + 1;
|
|
||||||
st.wMinute = (WORD)num;
|
|
||||||
num = strtoulW(ptr, &nextPtr, 10);
|
|
||||||
if (!nextPtr || nextPtr <= ptr)
|
|
||||||
{
|
|
||||||
ERR("unexpected time format %s\n", debugstr_w(ptr));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (num > 59)
|
|
||||||
{
|
|
||||||
ERR("unexpected second in time format %s\n", debugstr_w(ptr));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
ptr = nextPtr + 1;
|
|
||||||
st.wSecond = (WORD)num;
|
|
||||||
|
|
||||||
while (isspaceW(*ptr))
|
while (isspaceW(*ptr))
|
||||||
ptr++;
|
ptr++;
|
||||||
|
@ -3756,6 +3842,26 @@ static BOOL HTTP_ParseDate(LPCWSTR value, FILETIME *ft)
|
||||||
return SystemTimeToFileTime(&st, ft);
|
return SystemTimeToFileTime(&st, ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: only accepts dates in RFC 1123 format and asctime() format,
|
||||||
|
* which may not be the only formats actually seen in the wild.
|
||||||
|
* http://www.hackcraft.net/web/datetime/ suggests at least RFC 850 dates
|
||||||
|
* should be accepted as well.
|
||||||
|
*/
|
||||||
|
static BOOL HTTP_ParseDate(LPCWSTR value, FILETIME *ft)
|
||||||
|
{
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
if (strchrW(value, ','))
|
||||||
|
ret = HTTP_ParseRfc1123Date(value, ft);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = HTTP_ParseDateAsAsctime(value, ft);
|
||||||
|
if (!ret)
|
||||||
|
ERR("unexpected date format %s\n", debugstr_w(value));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void HTTP_ProcessExpires(http_request_t *request)
|
static void HTTP_ProcessExpires(http_request_t *request)
|
||||||
{
|
{
|
||||||
BOOL expirationFound = FALSE;
|
BOOL expirationFound = FALSE;
|
||||||
|
@ -3843,6 +3949,21 @@ static void HTTP_ProcessExpires(http_request_t *request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void HTTP_ProcessLastModified(http_request_t *request)
|
||||||
|
{
|
||||||
|
int headerIndex;
|
||||||
|
|
||||||
|
headerIndex = HTTP_GetCustomHeaderIndex(request, szLast_Modified, 0, FALSE);
|
||||||
|
if (headerIndex != -1)
|
||||||
|
{
|
||||||
|
LPHTTPHEADERW expiresHeader = &request->custHeaders[headerIndex];
|
||||||
|
FILETIME ft;
|
||||||
|
|
||||||
|
if (HTTP_ParseDate(expiresHeader->lpszValue, &ft))
|
||||||
|
request->last_modified = ft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void HTTP_CacheRequest(http_request_t *request)
|
static void HTTP_CacheRequest(http_request_t *request)
|
||||||
{
|
{
|
||||||
WCHAR url[INTERNET_MAX_URL_LENGTH];
|
WCHAR url[INTERNET_MAX_URL_LENGTH];
|
||||||
|
@ -4051,6 +4172,7 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
|
||||||
|
|
||||||
HTTP_ProcessCookies(request);
|
HTTP_ProcessCookies(request);
|
||||||
HTTP_ProcessExpires(request);
|
HTTP_ProcessExpires(request);
|
||||||
|
HTTP_ProcessLastModified(request);
|
||||||
|
|
||||||
if (!set_content_length( request )) HTTP_FinishedReading(request);
|
if (!set_content_length( request )) HTTP_FinishedReading(request);
|
||||||
|
|
||||||
|
@ -4214,6 +4336,7 @@ static DWORD HTTP_HttpEndRequestW(http_request_t *request, DWORD dwFlags, DWORD_
|
||||||
/* process cookies here. Is this right? */
|
/* process cookies here. Is this right? */
|
||||||
HTTP_ProcessCookies(request);
|
HTTP_ProcessCookies(request);
|
||||||
HTTP_ProcessExpires(request);
|
HTTP_ProcessExpires(request);
|
||||||
|
HTTP_ProcessLastModified(request);
|
||||||
|
|
||||||
if (!set_content_length( request )) HTTP_FinishedReading(request);
|
if (!set_content_length( request )) HTTP_FinishedReading(request);
|
||||||
|
|
||||||
|
|
|
@ -274,6 +274,7 @@ typedef struct
|
||||||
DWORD bytesWritten;
|
DWORD bytesWritten;
|
||||||
HTTPHEADERW *custHeaders;
|
HTTPHEADERW *custHeaders;
|
||||||
DWORD nCustHeaders;
|
DWORD nCustHeaders;
|
||||||
|
FILETIME last_modified;
|
||||||
HANDLE hCacheFile;
|
HANDLE hCacheFile;
|
||||||
LPWSTR cacheFile;
|
LPWSTR cacheFile;
|
||||||
FILETIME expires;
|
FILETIME expires;
|
||||||
|
|
Loading…
Reference in New Issue