📄 cache.c
字号:
* the request comes from the history.
* "isWTA": if this is > 0, only content belonging to WTA is considered,
* otherwise only content NOT belonging to WTA is considered
* "uiLastMod" points to a location where the last modified time
* will be stored, in case the function returns 2, and similarly
* "etag" points to a location where a BYTE-pointer to an entity tag
* will be stored.
*
* Return values:
* 0 => the URL is not in the cache, or has expired and cannot be
* revalidated.
* 1 => the URL is in the cache and has not expired.
* 2 => the URL is in the cache, has expired, but can be revalidated;
* in this case, the last modified time is returned in
* the 'uiLastMod' parameter and the entity tag in "etag".
*/
INT16
Cache_URLisPresent (void *pvUrl, /* URL, as null-terminated byte string */
UINT8 iWmlBackNav, /* the request comes from the history */
UINT8 isWTA, /* */
UINT32 *uiLastMod, /* return last modified time */
BYTE **etag /* return entity tag */
)
{
CacheRecord rec;
UINT32 currentTime;
UINT8 cacheMode;
ListNode *p;
if (!theCache.isInitialized) {
return 0;
}
if (uiLastMod != NULL)
*uiLastMod = 0;
if ((pvUrl == NULL) || (uiLastMod == NULL)) {
return 0;
}
/* Search for the record with matching URL */
p = Cache_Find ((BYTE*) pvUrl, &rec, (INT16)(isWTA ? 1 : 0));
if (p == NULL) {
/* URL is not in the cache */
return 0;
}
cacheMode = (UINT8)(theCache.waeMainObj->iCacheMode);
currentTime = CLNTa_currentTime( );
if ((rec.expire > currentTime) || (rec.expire == 0)) {
/* URL is in the cache and has not expired, or will never expire. */
return 1;
}
else if ( iWmlBackNav && !(rec.flags & MUSTREVALIDATE) ){
/* URL is in the cache and has expired, but the request comes
from the history and the MustRevalidate flag is not set. */
return 1;
}
else if ((rec.last_mod != 0) || (rec.etag_len > 0)) {
/* URL is in the cache, has expired, but has a last modified date
or an entity tag.
In this case, we might get away by revalidating the page with
the server. Exception: the cache mode says we don't have
to check; in this case we treat it as if it had not expired. */
if (!(rec.flags & MUSTREVALIDATE) &&
((cacheMode == CACHE_MODE_NEVER_CHECK) ||
((cacheMode == CACHE_MODE_FIRSTTIME_CHECK) &&
(rec.flags & HASREAD)))) {
return 1;
}
else {
if (rec.etag_len > 0) {
*etag = NEWARRAY (BYTE, rec.etag_len + 1);
if (*etag == NULL) {
return 0;
}
#ifdef FILE_CACHE
FILEa_read ('C', p->id, *etag,
sizeof (CacheRecord) + rec.url_len + rec.header_len +
rec.body_len, rec.etag_len);
#else
Storage_Get (&(theCache.store), p->id,
sizeof (CacheRecord) + rec.url_len + rec.header_len +
rec.body_len, rec.etag_len, *etag);
#endif
(*etag)[rec.etag_len] = '\0';
}
else {
*etag = NULL;
}
*uiLastMod = rec.last_mod;
return 2;
}
}
else {
/* URL is in cache, has expired, and cannot be revalidated: remove it. */
#ifdef FILE_CACHE
theCache.size -= FILEa_getSize ('C', p->id);
FILEa_delete ('C', p->id);
#else
Storage_DeleteBlock (&(theCache.store), p->id);
#endif
list_out (p);
DEALLOC (&p);
return 0;
}
}
/*
* Cache_Read
*
* Given a URL, read the corresponding Header and Body from the cache.
* "pvUrl" is the URL, as a null-terminated byte string,
* "pvHeader" points to a location where a pointer to the header
* contents will be stored, and "liHeaderLen" points to a location
* where the length of the header will be stored.
* Similarly, "pvBody" points to a location where a pointer to the body
* contents will be stored, and "liBodLen" points to a location
* where the length of the body will be stored.
*
* Returns 1 if successful, otherwise 0.
*/
INT16
Cache_Read (void* pvUrl,
void **pvHeader, UINT32 *liHeaderLen,
void **pvBody, UINT32 *liBodLen
)
{
CacheRecord rec;
ListNode *p;
if (!theCache.isInitialized) {
return 0;
}
if ((pvUrl == NULL)
|| (pvHeader == NULL)
|| (liHeaderLen == NULL)
|| (pvBody == NULL)
|| (liBodLen == NULL))
return 0;
p = Cache_Find ((BYTE*) pvUrl, &rec, -1);
if (p == NULL)
return 0;
if (!(rec.flags & HASREAD)) {
rec.flags |= HASREAD;
#ifdef FILE_CACHE
if (FILEa_write ('C', p->id, &rec, 0, sizeof (CacheRecord))
!= sizeof (CacheRecord)) {
#else
if (!Storage_Put (&(theCache.store), p->id, 0,
sizeof (CacheRecord), &rec)) {
#endif
return 0;
}
}
*pvHeader = NULL;
*liHeaderLen = 0;
*pvBody = NULL;
*liBodLen = 0;
if (rec.header_len > 0) {
if ((*pvHeader = NEWARRAY (BYTE, rec.header_len)) == NULL) {
return 0;
}
#ifdef FILE_CACHE
if (FILEa_read ('C', p->id, *pvHeader,
sizeof (CacheRecord) + rec.url_len,
rec.header_len) != rec.header_len) {
#else
if (!Storage_Get (&(theCache.store), p->id,
sizeof (CacheRecord) + rec.url_len,
rec.header_len, *pvHeader)) {
#endif
return 0;
}
}
if (rec.body_len > 0) {
if ((*pvBody = NEWARRAY (BYTE, rec.body_len)) == NULL) {
DEALLOC (pvHeader);
return 0;
}
#ifdef FILE_CACHE
if (FILEa_read ('C', p->id, *pvBody,
sizeof (CacheRecord) + rec.url_len + rec.header_len,
rec.body_len) != (INT32)rec.body_len) {
#else
if (!Storage_Get (&(theCache.store), p->id,
sizeof (CacheRecord) + rec.url_len + rec.header_len,
rec.body_len, *pvBody)) {
#endif
DEALLOC (pvHeader);
DEALLOC (pvBody);
return 0;
}
}
*liHeaderLen = rec.header_len;
*liBodLen = rec.body_len;
return 1;
}
/*
* Cache_GetParameters
*
* Compute Expire and LastModified from a Header.
*/
void
Cache_GetParameters (BYTE* pbHeader, UINT32 uiHeadLen,
UINT32 *uiExp,
UINT32 *uiLastMod,
UINT8 *uiMustRevalidate,
UINT32 *uiDate,
BYTE **pbEtag)
{
pHEADERDEF pHeaderList = NULL;
pHEADERELEMENT pHeaderElement = NULL;
UINT32 uiAge = 0;
UINT32 uiExpire = 0;
UINT32 uiNow = 0;
unsigned char ucCacheControl = 0;
UINT32 uiDeltaSec = 0;
BOOL bError = FALSE;
UINT8 uiEncVer = 0;
*uiDate = 0;
*uiExp = 0;
*pbEtag = NULL;
if (pbHeader == NULL)
return;
pHeaderList = WSP_PreParseHeaders (pbHeader, uiHeadLen, &bError);
if (bError || (pHeaderList == NULL))
return;
if (pHeaderList->pHeadList == NULL) {
DeleteHEADERDEF (pHeaderList);
return;
}
/* Cache-Control Header */
pHeaderElement = WSP_GetHeaderWK (1, Field_Cache_Control,
pHeaderList->pHeadList);
if( pHeaderElement == NULL ){
pHeaderElement = WSP_GetHeaderWK ( 1, Field_Cache_Control_1_3,
pHeaderList->pHeadList );
uiEncVer++;
if( pHeaderElement == NULL ){
pHeaderElement = WSP_GetHeaderWK ( 1, Field_Cache_Control_1_4,
pHeaderList->pHeadList );
uiEncVer++;
}
}
do {
if (pHeaderElement == NULL)
break;
ucCacheControl = WSP_GetCacheControlByte (pHeaderElement,
&uiDeltaSec, &bError);
/* Must-Revalidate, Proxy-Revalidate */
if ((ucCacheControl == 137 || ucCacheControl == 138) && !bError ) {
*uiMustRevalidate = 1;
} /* Max-Age */
else if ((ucCacheControl == 130) && !bError) {
uiNow = CLNTa_currentTime ();
*uiExp = uiNow + uiDeltaSec;
}
/* Second CacheDirective */
if (pHeaderElement->pNext == NULL)
break;
if( uiEncVer == 0 )
pHeaderElement = WSP_GetHeaderWK (1, Field_Cache_Control,
pHeaderElement->pNext);
else if( uiEncVer == 1 )
pHeaderElement = WSP_GetHeaderWK (1, Field_Cache_Control_1_3,
pHeaderElement->pNext);
else if( uiEncVer == 2 )
pHeaderElement = WSP_GetHeaderWK (1, Field_Cache_Control_1_4,
pHeaderElement->pNext);
if (pHeaderElement == NULL)
break;
ucCacheControl = WSP_GetCacheControlByte (pHeaderElement,
&uiDeltaSec, &bError);
/* Must-Revalidate, Proxy-Revalidate */
if (((ucCacheControl == 137) || (ucCacheControl == 138)) && !bError) {
*uiMustRevalidate = 1;
} /* Max-Age */
else if ((ucCacheControl == 130) && !bError) {
uiNow = CLNTa_currentTime ();
*uiExp = uiNow + uiDeltaSec;
}
} while (0);
bError = FALSE;
/* Date Header */
pHeaderElement = WSP_GetHeaderWK (1, Field_Date,
pHeaderList->pHeadList);
if (pHeaderElement != NULL)
*uiDate = WSP_GetDate (pHeaderElement, &bError);
if ((*uiExp == 0) && (*uiDate > 0)) {
bError = FALSE;
/* Expire Header */
pHeaderElement = WSP_GetHeaderWK (1, Field_Expires,
pHeaderList->pHeadList);
if (pHeaderElement != NULL) {
uiExpire = WSP_GetExpires (pHeaderElement, &bError);
if ((uiExpire == 0) || bError)
*uiExp = 1;
else if (uiExpire > 0) {
/* Age Header */
pHeaderElement = WSP_GetHeaderWK (1, Field_Age,
pHeaderList->pHeadList);
if (pHeaderElement != NULL) {
uiAge = WSP_GetAge (pHeaderElement, &bError);
}
uiNow = CLNTa_currentTime ();
if (uiExpire > (*uiDate + uiAge))
*uiExp = uiNow + (uiExpire - (*uiDate + uiAge));
else
*uiExp = uiNow;
}
}
}
bError = FALSE;
/* Last-Modified Header */
pHeaderElement = WSP_GetHeaderWK (1, Field_Last_Modified,
pHeaderList->pHeadList);
if (pHeaderElement != NULL) {
*uiLastMod = WSP_GetLastModified (pHeaderElement, &bError);
}
bError = FALSE;
/* E-Tag Header */
pHeaderElement = WSP_GetHeaderWK (1, Field_Etag,
pHeaderList->pHeadList);
if (pHeaderElement != NULL) {
BYTE *tmp = WSP_GetEtag (pHeaderElement);
UINT16 etag_len = B_STRINGLENGTH (tmp);
*pbEtag = NEWARRAY (BYTE, etag_len + 1);
if (*pbEtag != NULL) {
B_COPYSTRING (*pbEtag, tmp);
}
}
DeleteHEADERDEF (pHeaderList);
}
/*
* Cache_Write
*
* Write a URL, Header and Body to the cache.
* "pvUrl" is the URL, as a null-terminated byte string,
* "isWTA", if > 0, this content is flagged as belonging to WTA
* "pvHeader" points to the header content and "iHeaderLen" is the length
* of the header. Similarly, "pvBody" points to the body content and
* "iBodLen" is the length of the body.
*
* Returns 1 if successful, otherwise 0.
*/
INT16
Cache_Write (void *pvUrl,
UINT8 isWTA,
void *pvHeader, UINT32 iHeaderLen,
void *pvBody, UINT32 iBodLen
)
{
CacheRecord rec;
UINT32 pos, tot_len, newid;
UINT16 etag_len = 0, url_len = 0;
UINT32 currentTime, expire = 0, lastModified = 0, date = 0;
UINT8 mustRevalidate = 0;
BYTE* etag = NULL;
ListNode *p;
if (!theCache.isInitialized) {
return 0;
}
if ((pvUrl == NULL)
|| (pvHeader == NULL)
|| (iHeaderLen == 0)
|| (pvBody == NULL)
|| (iBodLen == 0)) {
return 0;
}
Cache_GetParameters ((BYTE*) pvHeader, iHeaderLen, &expire, &lastModified,
&mustRevalidate, &date, &etag );
if (expire == 0 && mustRevalidate == 0) {
if (theCache.waeMainObj != NULL) {
currentTime = CLNTa_currentTime ();
expire = currentTime + theCache.waeMainObj->iDefaultExpireTime;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -