📄 htcache.c
字号:
HTChunk_clear(me->buffer); continue; } } else if (*b == CR) { me->EOLstate = EOL_FCR; } else if (*b == LF) { me->EOLstate = EOL_FLF; /* Line found */ } else HTChunk_putc(me->buffer, *b); l--; b++; } return HT_OK;}PRIVATE int HTCacheIndex_put_character (HTStream * me, char c){ return HTCacheIndex_put_block(me, &c, 1);}PRIVATE int HTCacheIndex_put_string (HTStream * me, const char * s){ return HTCacheIndex_put_block(me, s, (int) strlen(s));}PRIVATE int HTCacheIndex_flush (HTStream * me){ if (me) { char * flush = HTChunk_data(me->buffer); if (flush) HTCacheIndex_parseLine(flush); HTChunk_clear(me->buffer); } return HT_OK;}PRIVATE int HTCacheIndex_free (HTStream * me){ if (me) { int status = HTCacheIndex_flush(me); HTTRACE(APP_TRACE, "Cache Index. FREEING....\n"); HTChunk_delete(me->buffer); HT_FREE(me); return status; } return HT_ERROR;}PRIVATE int HTCacheIndex_abort (HTStream * me, HTList * e){ if (me) { int status = HT_ERROR; HTTRACE(APP_TRACE, "Cache Index. ABORTING...\n"); HTChunk_delete(me->buffer); HT_FREE(me); return status; } return HT_ERROR;}/* Structured Object Class** -----------------------*/PRIVATE const HTStreamClass HTCacheIndexClass ={ "CacheIndexParser", HTCacheIndex_flush, HTCacheIndex_free, HTCacheIndex_abort, HTCacheIndex_put_character, HTCacheIndex_put_string, HTCacheIndex_put_block};PRIVATE HTStream * HTCacheIndexReader (HTRequest * request){ HTStream * me; if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL) HT_OUTOFMEM("HTCacheIndexs"); me->isa = &HTCacheIndexClass; me->request = request; me->buffer = HTChunk_new(512); me->EOLstate = EOL_BEGIN; return me;}/*** Read the saved set of cached entries from disk. we only allow the index** ro be read when there is no entries in memory. That way we can ensure** consistancy.*/PUBLIC BOOL HTCacheIndex_read (const char * cache_root){ BOOL status = NO; if (cache_root && CacheTable == NULL) { BOOL wasInteractive; char * file = cache_index_name(cache_root); char * index = HTLocalToWWW(file, "cache:"); HTAnchor * anchor = HTAnchor_findAddress(index); HTRequest * request = HTRequest_new(); HTRequest_setPreemptive(request, YES); HTRequest_setOutputFormat(request, WWW_SOURCE); /* Make sure we don't use any filters */ HTRequest_addBefore(request, NULL, NULL, NULL, 0, YES); HTRequest_addAfter(request, NULL, NULL, NULL, HT_ALL, 0, YES); /* Set the output */ HTRequest_setOutputStream(request, HTCacheIndexReader(request)); HTRequest_setAnchor(request, anchor); HTAnchor_setFormat((HTParentAnchor *) anchor, HTAtom_for("www/cache-index")); wasInteractive = HTAlert_interactive(); HTAlert_setInteractive(NO); status = HTLoad(request, NO); HTAlert_setInteractive(wasInteractive); HTRequest_delete(request); HT_FREE(file); HT_FREE(index); } return status;}/* ------------------------------------------------------------------------- *//* CACHE PARAMETERS *//* ------------------------------------------------------------------------- */PRIVATE BOOL create_cache_root (const char * cache_root){ struct stat stat_info; char * loc = NULL; char * cur = NULL; BOOL create = NO; if (!cache_root) return NO; StrAllocCopy(loc, cache_root); /* Get our own copy */#ifdef WWW_MSWINDOWS cur = *(loc+1) == ':' ? loc+3 : loc+1;#else cur = loc+1;#endif while ((cur = strchr(cur, DIR_SEPARATOR_CHAR))) { *cur = '\0'; if (create || HT_STAT(loc, &stat_info) == -1) { create = YES; /* To avoid doing stat()s in vain */ HTTRACE(CACHE_TRACE, "Cache....... Creating dir `%s\'\n" _ loc); if (MKDIR(loc, 0777) < 0) { HTTRACE(CACHE_TRACE, "Cache....... can't create\n"); HT_FREE(loc); return NO; } } else { HTTRACE(CACHE_TRACE, "Cache....... dir `%s\' already exists\n" _ loc); } *cur++ = DIR_SEPARATOR_CHAR; } HT_FREE(loc); return YES;}/*** If `cache_root' is NULL then the current value (might be a define)** Should we check if the cache_root is actually OK? I think not!*/PRIVATE BOOL HTCacheMode_setRoot (const char * cache_root){ if (cache_root) { if ((HTCacheRoot = HTWWWToLocal(cache_root, "file:", NULL)) == NULL) return NO; if (*(HTCacheRoot+strlen(HTCacheRoot)-1) != DIR_SEPARATOR_CHAR) StrAllocCat(HTCacheRoot, DIR_SEPARATOR_STR); } else { /* ** If no cache root has been indicated then look for a suitable ** location. */ char * addr = NULL; char * cr = (char *) getenv("WWW_CACHE"); if (!cr) cr = (char *) getenv("TMP"); if (!cr) cr = (char *) getenv("TEMP"); if (!cr) cr = HT_CACHE_LOC; addr = HTLocalToWWW(cr, NULL); if (*(addr+strlen(addr)-1) != DIR_SEPARATOR_CHAR) StrAllocCat(addr, DIR_SEPARATOR_STR); StrAllocCat(addr, HT_CACHE_ROOT); if (*(addr+strlen(addr)-1) != DIR_SEPARATOR_CHAR) StrAllocCat(addr, DIR_SEPARATOR_STR); if ((HTCacheRoot = HTWWWToLocal(addr, "file:", NULL)) == NULL) { HT_FREE(addr); return NO; } HT_FREE(addr); } if (create_cache_root(HTCacheRoot) == NO) return NO; HTTRACE(CACHE_TRACE, "Cache Root.. Local root set to `%s\'\n" _ HTCacheRoot); return YES;}/*** Return the value of the cache root. The cache root can only be** set through the HTCacheInit() function*/PUBLIC char * HTCacheMode_getRoot (void){ return HTLocalToWWW(HTCacheRoot, NULL);}/*** As this is a single user cache, we have to lock it when in use.*/PRIVATE FILE *locked_open_file = {NULL};PRIVATE BOOL HTCache_getSingleUserLock (const char * root){ if (root && !locked_open_file) { FILE * fp; char * location = NULL; if ((location = (char *) HT_MALLOC(strlen(root) + strlen(HT_CACHE_LOCK) + 1)) == NULL) HT_OUTOFMEM("HTCache_getLock"); strcpy(location, root); strcat(location, HT_CACHE_LOCK); if ((fp = fopen(location, "r")) != NULL) { HTAlertCallback *cbf = HTAlert_find(HT_A_CONFIRM); HTTRACE(CACHE_TRACE, "Cache....... In `%s\' is already in use\n" _ root); fclose(fp); if (cbf) { BOOL result = (*cbf)(NULL, HT_A_CONFIRM, HT_MSG_CACHE_LOCK,NULL,location,NULL); if (result == YES) { REMOVE(location); } else { HT_FREE(location); return NO; } } else { HT_FREE(location); return NO; } } if ((fp = fopen(location, "w")) == NULL) { HTTRACE(CACHE_TRACE, "Cache....... Can't open `%s\' for writing\n" _ location); HT_FREE(location); return NO; } locked_open_file = fp; HT_FREE(location); return YES; } return NO;}/*** Release the single user lock*/PRIVATE BOOL HTCache_deleteSingleUserLock (const char * root){ if (root) { char * location = NULL; if ((location = (char *) HT_MALLOC(strlen(root) + strlen(HT_CACHE_LOCK) + 1)) == NULL) HT_OUTOFMEM("HTCache_deleteLock"); strcpy(location, root); strcat(location, HT_CACHE_LOCK); /* under UNIX you can remove an open file, not so under NT */ if (locked_open_file) { fclose(locked_open_file); locked_open_file = NULL; } REMOVE(location); HT_FREE(location); return YES; } return NO;}/*** If `cache_root' is NULL then reuse old value or use HT_CACHE_ROOT.** An empty string will make '/' as cache root** We can only enable the cache if the HTSecure flag is not set. This** is for example the case if using an application as a telnet shell.*/PUBLIC BOOL HTCacheInit (const char * cache_root, int size){ if (!HTLib_secure() && !HTCacheRoot) { /* ** Find an appropriate root for the cache */ if (HTCacheMode_setRoot(cache_root) != YES) return NO; /* ** Set the max size of the cache */ HTCacheMode_setMaxSize(size); /* ** Set a lock on the cache so that multiple users ** don't step on each other. */ if (HTCache_getSingleUserLock(HTCacheRoot) == NO) return NO; /* ** Look for the cache index and read the contents */ HTCacheIndex_read(HTCacheRoot); /* ** Register the cache before and after filters */ HTNet_addBefore(HTCacheFilter, "http://*", NULL, HT_FILTER_MIDDLE); HTNet_addAfter(HTCacheUpdateFilter, "http://*", NULL, HT_NOT_MODIFIED, HT_FILTER_MIDDLE); /* ** Register the cache AFTER filter for checking whether ** we should invalidate the cached entry */ HTNet_addAfter(HTCacheCheckFilter, "http://*", NULL, HT_ALL, HT_FILTER_MIDDLE); /* ** Do caching from now on */ HTCacheEnable = YES; HTCacheInitialized = YES; return YES; } return NO;}/*** Turns off the cache and updates entries on disk.*/PUBLIC BOOL HTCacheTerminate (void){ if (HTCacheInitialized) { /* ** Write the index to file */ HTCacheIndex_write(HTCacheRoot); /* ** Unregister the cache before and after filters */ HTNet_deleteBefore(HTCacheFilter); HTNet_deleteAfter(HTCacheUpdateFilter); HTNet_deleteAfter(HTCacheCheckFilter); /* ** Remove the global cache lock. */ HTCache_deleteSingleUserLock(HTCacheRoot); /* ** Cleanup memory by deleting all HTCache objects */ HTCache_deleteAll(); /* ** Don't do anymore caching from now on */ HT_FREE(HTCacheRoot); HTCacheEnable = NO; return YES; } return NO;}/*** The cache can be temporarily suspended by using the enable/disable** flag. This does not prevent the cache from being enabled/disable at** a later point in time.*/PUBLIC void HTCacheMode_setEnabled (BOOL mode){ HTCacheEnable = mode;}PUBLIC BOOL HTCacheMode_enabled (void){ return HTCacheEnable;}PUBLIC void HTCacheMode_setProtected (BOOL mode){ HTCacheProtected = mode;}PUBLIC BOOL HTCacheMode_protected (void){ return HTCacheProtected;}/*** We can set the cache to operate in disconnected mode in which we only** return (valid) responses from the cache. Disconnected mode does not** automatically deliver stale documents as this must be declared ** explicitly. */PUBLIC void HTCacheMode_setDisconnected (HTDisconnectedMode mode){ DisconnectedMode = mode;}PUBLIC HTDisconnectedMode HTCacheMode_disconnected (void){ return DisconnectedMode;}PUBLIC BOOL HTCacheMode_isDisconnected (HTReload mode){ return (DisconnectedMode != HT_DISCONNECT_NONE);}/*** Set the mode for how we handle Expires header from the local history** list. The following modes are available:**** HT_EXPIRES_IGNORE : No update in the history list** HT_EXPIRES_NOTIFY : The user is notified but no reload** HT_EXPIRES_AUTO : Automatic reload*/PUBLIC void HTCacheMode_setExpires (HTExpiresMode mode){ HTExpMode = mode;}PUBLIC HTExpiresMode HTCacheMode_expires (void){ return HTExpMode;}/*** Cache size management. We set the default cache size to 20M.** We set the minimum size to 5M in order not to get into weird** problems while writing the cache. The size is indicated in Mega** bytes*/PUBLIC BOOL HTCacheMode_setMaxSize (int size){ long new_size = size < HT_MIN_CACHE_TOTAL_SIZE ? HT_MIN_CACHE_TOTAL_SIZE*MEGA : size*MEGA; long old_size = HTCacheTotalSize; HTCacheTotalSize = new_size; HTCacheFolderSize = HTCacheTotalSize/HT_CACHE_FOLDER_PCT; HTCacheGCBuffer = HTCacheTotalSize/HT_CACHE_GC_PCT; if (new_size < old_size) HTCacheGarbage(); HTTRACE(CACHE_TRACE, "Cache....... Total cache size: %ld with %ld bytes for metainformation and folders and at least %ld bytes free after every gc\n" _ HTCacheTotalSize _ HTCacheFolderSize _ HTCacheGCBuffer); return YES;}PUBLIC int HTCacheMode_maxSize (void){ return HTCacheTotalSize / MEGA;}/*** How big can a single cached entry be in Mbytes. The default is 3M** */PUBLIC BOOL HTCacheMode_setMaxCacheEntrySize (int size){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -