mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-06 17:16:12 +00:00
1569 lines
37 KiB
C
1569 lines
37 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
/* Created: Lou Montulli */
|
|
/* Modifications/Additions: Gagan Saksena */
|
|
/* Please leave outside of ifdef for windows precompiled headers. */
|
|
|
|
#ifdef MOZILLA_CLIENT
|
|
|
|
#include "xp.h"
|
|
#include "mktrace.h"
|
|
#include "mkcache.h"
|
|
#include "glhist.h"
|
|
#include "xp_hash.h"
|
|
#include "xp_mcom.h"
|
|
#include "client.h"
|
|
#include "mkgeturl.h"
|
|
#include "mkstream.h"
|
|
#include "secnav.h"
|
|
#include "extcache.h"
|
|
#include "mkextcac.h"
|
|
#include "prmem.h"
|
|
#include "plstr.h"
|
|
#include "timing.h"
|
|
#include "net_xp_file.h"
|
|
|
|
/* For 197 java hookup */
|
|
#include "jri.h"
|
|
|
|
#ifdef PROFILE
|
|
#pragma profile on
|
|
#endif
|
|
|
|
/* for XP_GetString() */
|
|
#include "xpgetstr.h"
|
|
extern int XP_DATABASE_CANT_BE_VALIDATED_MISSING_NAME_ENTRY;
|
|
extern int XP_DB_SELECTED_DB_NAMED;
|
|
extern int XP_REQUEST_EXTERNAL_CACHE;
|
|
|
|
PRIVATE XP_List * ext_cache_database_list = 0;
|
|
PRIVATE XP_Bool AtLeastOneOpenCache = FALSE;
|
|
|
|
|
|
/* ************************************ Defines ************************************** */
|
|
#define SAR_CACHE_INFO_STRING "CACHE_ExternalSARCacheNameString"
|
|
|
|
#define EXTCACHE 1
|
|
#define SARCACHE 2
|
|
#define SUCCESS 0
|
|
#define FAILURE -1
|
|
#define MIN_MAX_SIZE 1000
|
|
|
|
/* ************************************ Proto's ************************************** */
|
|
|
|
/* Modified existing functions to call these (read Cut n Paste with passed in args) */
|
|
PRIVATE void cache_ReadCacheInfo(XP_File fp, XP_List **list_ptr, int type);
|
|
PRIVATE void cache_SaveCacheInfo(XP_File fp, XP_List *list_ptr, int type);
|
|
PRIVATE void cache_SaveSARCacheInfo(void);
|
|
|
|
/* Newly written functions */
|
|
PRIVATE int cache_PutSARCacheInfoIntoDB(ExtCacheDBInfo *db_info);
|
|
PRIVATE ExtCacheDBInfo * cache_GetSARCacheInfoFromDB(ExtCacheDBInfo *db_info);
|
|
MODULE_PRIVATE DBT * cache_ExtCacheDBInfoStructToDBData(ExtCacheDBInfo * old_obj);
|
|
MODULE_PRIVATE ExtCacheDBInfo * cache_DBDataToExtCacheDBInfoStruct(DBT * db_obj);
|
|
MODULE_PRIVATE void cache_freeExtCacheDBInfoObj (ExtCacheDBInfo * cache_obj);
|
|
|
|
/* ************************************ Variables ************************************** */
|
|
PRIVATE XP_List * SAR_cache_database_list = 0;
|
|
PRIVATE XP_Bool SARCacheIndexOpen = FALSE;
|
|
|
|
|
|
/* close an external cache
|
|
*/
|
|
PRIVATE void
|
|
net_CloseExtCacheFat(ExtCacheDBInfo *db_info)
|
|
{
|
|
if(db_info->database)
|
|
{
|
|
(*db_info->database->close)(db_info->database);
|
|
db_info->database = 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
PRIVATE char *
|
|
net_GetExtCacheNameFromDB(ExtCacheDBInfo *db_info)
|
|
{
|
|
DBT key;
|
|
DBT data;
|
|
|
|
if(!db_info->database)
|
|
return NULL;
|
|
|
|
key.data = EXT_CACHE_NAME_STRING;
|
|
key.size = PL_strlen(EXT_CACHE_NAME_STRING);
|
|
|
|
if(0 == (*db_info->database->get)(db_info->database, &key, &data, 0))
|
|
{
|
|
/* make sure it's a valid cstring */
|
|
char *name = (char *)data.data;
|
|
if(name[data.size-1] == '\0')
|
|
return(PL_strdup(name));
|
|
else
|
|
return(NULL);
|
|
}
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
/* read/open an External Cache File allocation table.
|
|
*
|
|
* Returns a True if successfully opened
|
|
* Returns False if not.
|
|
*/
|
|
PRIVATE XP_Bool
|
|
net_OpenExtCacheFat(MWContext *ctxt, ExtCacheDBInfo *db_info)
|
|
{
|
|
char *slash;
|
|
char *db_name;
|
|
XP_Bool close_db=FALSE;
|
|
|
|
if(!db_info->database)
|
|
{
|
|
/* @@@ add .db to the end of the files
|
|
*/
|
|
char* filename = WH_FilePlatformName(db_info->filename);
|
|
db_info->database = dbopen(filename,
|
|
O_RDONLY,
|
|
0600,
|
|
DB_HASH,
|
|
0);
|
|
#ifdef XP_PC
|
|
/* This is probably the last checkin into Akbar */
|
|
/* What really needs to be fixed is that Warren's implementation */
|
|
/* of WH_FilePlatformName needs to return a malloc'd string */
|
|
/* Right now, on Mac & X, it does not. See xp_file.c */
|
|
PR_FREEIF(filename);
|
|
#endif
|
|
if(!db_info->database)
|
|
return(FALSE);
|
|
else
|
|
AtLeastOneOpenCache = TRUE;
|
|
|
|
StrAllocCopy(db_info->path, db_info->filename);
|
|
|
|
/* figure out the path to the database */
|
|
#ifdef XP_PC
|
|
slash = PL_strrchr(db_info->path, '\\');
|
|
#elif defined(XP_MAC)
|
|
slash = PL_strrchr(db_info->path, '/');
|
|
#else
|
|
slash = PL_strrchr(db_info->path, '/');
|
|
#endif
|
|
|
|
if(slash)
|
|
{
|
|
*(slash+1) = '\0';
|
|
}
|
|
else
|
|
{
|
|
*db_info->path = '\0';
|
|
}
|
|
|
|
db_name = net_GetExtCacheNameFromDB(db_info);
|
|
|
|
if(!db_name)
|
|
{
|
|
close_db = !FE_Confirm(ctxt,
|
|
XP_GetString( XP_DATABASE_CANT_BE_VALIDATED_MISSING_NAME_ENTRY ) );
|
|
}
|
|
else if(PL_strcmp(db_name, db_info->name))
|
|
{
|
|
char buffer[2048];
|
|
|
|
PR_snprintf(buffer, sizeof(buffer),
|
|
XP_GetString( XP_DB_SELECTED_DB_NAMED ),
|
|
db_name, db_info->name);
|
|
|
|
close_db = !FE_Confirm(ctxt, buffer);
|
|
}
|
|
|
|
if(close_db)
|
|
{
|
|
(*db_info->database->close)(db_info->database);
|
|
db_info->database = 0;
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
PRIVATE void
|
|
net_SaveExtCacheInfo(void)
|
|
{
|
|
XP_File fp;
|
|
XP_List *list_ptr;
|
|
|
|
fp = NET_XP_FileOpen("", xpExtCacheIndex, XP_FILE_WRITE);
|
|
list_ptr = ext_cache_database_list;
|
|
|
|
cache_SaveCacheInfo(fp, list_ptr, EXTCACHE);
|
|
}
|
|
|
|
#define BUF_SIZE 2048
|
|
PRIVATE void
|
|
net_ReadExtCacheInfo(void)
|
|
{
|
|
XP_File fp;
|
|
|
|
fp = NET_XP_FileOpen("", xpExtCacheIndex, XP_FILE_READ);
|
|
|
|
cache_ReadCacheInfo(fp, &ext_cache_database_list, EXTCACHE);
|
|
}
|
|
|
|
PRIVATE void
|
|
net_OpenExtCacheFATCallback(MWContext *ctxt, char * filename, void *closure)
|
|
{
|
|
ExtCacheDBInfo *db_info = (ExtCacheDBInfo*)closure;
|
|
|
|
if(!db_info || !filename)
|
|
return;
|
|
|
|
StrAllocCopy(db_info->filename, filename);
|
|
|
|
/* once we have the name try and open the
|
|
* cache fat
|
|
*/
|
|
if(net_OpenExtCacheFat(ctxt, db_info))
|
|
{
|
|
AtLeastOneOpenCache = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if(FE_Confirm(ctxt, "Unable to open External Cache. Try again?"))
|
|
{
|
|
/* try and open again */
|
|
|
|
FE_PromptForFileName (ctxt, /* context */
|
|
db_info->name, /* prompt string */
|
|
db_info->filename, /* default file/path */
|
|
TRUE, /* file must exist */
|
|
FALSE, /* directories allowed */
|
|
net_OpenExtCacheFATCallback, /* callback */
|
|
(void *)db_info); /* closure */
|
|
|
|
|
|
return; /* don't save ExtCache info */
|
|
}
|
|
}
|
|
|
|
net_SaveExtCacheInfo();
|
|
}
|
|
|
|
PUBLIC void
|
|
NET_OpenExtCacheFAT(MWContext *ctxt, char * cache_name, char * instructions)
|
|
{
|
|
ExtCacheDBInfo *db_info=0, *db_ptr;
|
|
XP_Bool done = FALSE;
|
|
XP_List *list_ptr;
|
|
|
|
if(!ext_cache_database_list)
|
|
{
|
|
net_ReadExtCacheInfo();
|
|
if(!ext_cache_database_list)
|
|
return;
|
|
}
|
|
|
|
/* look up the name in a list and open the file
|
|
* if it's not open already
|
|
*/
|
|
list_ptr = ext_cache_database_list;
|
|
while((db_ptr = (ExtCacheDBInfo *)XP_ListNextObject(list_ptr)) != NULL)
|
|
{
|
|
if(db_ptr->name && !PL_strcmp(db_ptr->name, cache_name))
|
|
{
|
|
db_info = db_ptr;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!db_info)
|
|
{
|
|
db_info = PR_NEW(ExtCacheDBInfo);
|
|
if(!db_info)
|
|
return;
|
|
memset(db_info, 0, sizeof(ExtCacheDBInfo));
|
|
StrAllocCopy(db_info->name, cache_name);
|
|
|
|
XP_ListAddObject(ext_cache_database_list, db_info);
|
|
}
|
|
else if(db_info->queried_this_session)
|
|
{
|
|
/* don't query or try and open again.
|
|
*/
|
|
return;
|
|
}
|
|
|
|
if(db_info->filename)
|
|
{
|
|
done = net_OpenExtCacheFat(ctxt, db_info);
|
|
|
|
if(done)
|
|
{
|
|
char buffer[1024];
|
|
|
|
PR_snprintf(buffer, sizeof(buffer),
|
|
"Now using external cache: %.900s",
|
|
db_info->name);
|
|
if(!FE_Confirm(ctxt, buffer))
|
|
net_CloseExtCacheFat(db_info);
|
|
}
|
|
}
|
|
|
|
/* If we don't have the correct filename, query the
|
|
* user for the name
|
|
*/
|
|
if(!done)
|
|
{
|
|
|
|
if(instructions)
|
|
done = !FE_Confirm(ctxt, instructions);
|
|
else
|
|
done = !FE_Confirm(ctxt, XP_GetString( XP_REQUEST_EXTERNAL_CACHE ) );
|
|
|
|
if(!done)
|
|
FE_PromptForFileName (ctxt, /* context */
|
|
db_info->name, /* prompt string */
|
|
db_info->filename, /* default file/path */
|
|
TRUE, /* file must exist */
|
|
FALSE, /* directories allowed */
|
|
net_OpenExtCacheFATCallback, /* callback */
|
|
(void *)db_info); /* closure */
|
|
}
|
|
|
|
db_info->queried_this_session = TRUE;
|
|
|
|
return;
|
|
}
|
|
|
|
/* lookup routine
|
|
*
|
|
* builds a key and looks for it in
|
|
* the database. Returns an access
|
|
* method and sets a filename in the
|
|
* URL struct if found
|
|
*/
|
|
MODULE_PRIVATE int
|
|
NET_FindURLInExtCache(URL_Struct * URL_s, MWContext *ctxt)
|
|
{
|
|
return CACHE_FindURLInCache(URL_s, ctxt);
|
|
}
|
|
|
|
/* ****************************************************************************************************************************
|
|
* Exposed Navigator Cache Calls
|
|
* ****************************************************************************************************************************/
|
|
|
|
/*
|
|
* allows java to enumerate through all of the managed cache
|
|
*/
|
|
PUBLIC XP_List *
|
|
CACHE_GetManagedCacheList()
|
|
{
|
|
XP_File fp;
|
|
|
|
/* If the Cache Index is not open, we can not see if the cache is open now can we */
|
|
if (!SARCacheIndexOpen)
|
|
{
|
|
fp = NET_XP_FileOpen("", xpSARCacheIndex, XP_FILE_READ);
|
|
|
|
/* check to see if the open succeeds */
|
|
if (fp)
|
|
{
|
|
cache_ReadCacheInfo(fp, &SAR_cache_database_list, SARCACHE);
|
|
SARCacheIndexOpen = TRUE;
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
return SAR_cache_database_list;
|
|
}
|
|
|
|
|
|
MODULE_PRIVATE void
|
|
CACHE_CloseAllOpenSARCache()
|
|
{
|
|
ExtCacheDBInfo * db_info;
|
|
XP_StatStruct stat_entry;
|
|
|
|
if (!SARCacheIndexOpen) return;
|
|
|
|
if (!SAR_cache_database_list) return;
|
|
|
|
while(NULL != (db_info = (ExtCacheDBInfo *)XP_ListNextObject(SAR_cache_database_list)))
|
|
{
|
|
CACHE_CloseCache(db_info);
|
|
|
|
if ( db_info->logFile )
|
|
NET_XP_FileClose(db_info->logFile);
|
|
|
|
/* stat the db file to see if it exists, if it doesn't remove it from */
|
|
/* the archive.fat file to keep things consistent */
|
|
if(db_info->filename && (NET_XP_Stat(db_info->filename, &stat_entry, xpSARCache) == -1) )
|
|
{
|
|
/* file does not exist!!
|
|
* remove the entry
|
|
*/
|
|
TRACEMSG(("Error! Cache db file missing: %s", db_info->filename));
|
|
|
|
if ( NULL != SAR_cache_database_list->prev )
|
|
SAR_cache_database_list = SAR_cache_database_list->prev;
|
|
|
|
XP_ListRemoveObject(SAR_cache_database_list, db_info);
|
|
}
|
|
cache_freeExtCacheDBInfoObj(db_info);
|
|
}
|
|
|
|
cache_SaveSARCacheInfo();
|
|
|
|
SAR_cache_database_list = 0;
|
|
SARCacheIndexOpen = FALSE;
|
|
}
|
|
|
|
MODULE_PRIVATE void
|
|
CACHE_OpenAllSARCache()
|
|
{
|
|
XP_File fp;
|
|
XP_List *tmpList;
|
|
ExtCacheDBInfo *db_info,
|
|
*tmpDB_info;
|
|
char * filename, /* The platform specific filename returned by WH_PlatformFileName */
|
|
* tmpName; /* The filename returned by WH_FileName */
|
|
|
|
if (!SARCacheIndexOpen)
|
|
{
|
|
fp = NET_XP_FileOpen("", xpSARCacheIndex, XP_FILE_READ);
|
|
|
|
/* check to see if the open succeeds */
|
|
if (fp)
|
|
cache_ReadCacheInfo(fp, &SAR_cache_database_list, SARCACHE);
|
|
else
|
|
return;
|
|
}
|
|
|
|
SARCacheIndexOpen = TRUE;
|
|
|
|
if (!SAR_cache_database_list) return;
|
|
|
|
tmpList = SAR_cache_database_list;
|
|
while(NULL != (db_info = (ExtCacheDBInfo *)XP_ListNextObject(tmpList)))
|
|
{
|
|
if ( !db_info->database )
|
|
{
|
|
tmpName = WH_FileName(db_info->filename, xpSARCache);
|
|
filename = WH_FilePlatformName(tmpName);
|
|
|
|
/* Open or create the db file they specified */
|
|
db_info->database = dbopen(filename,
|
|
O_RDWR | O_CREAT,
|
|
0600,
|
|
DB_HASH,
|
|
0);
|
|
|
|
/* check to see if the dbopen failed */
|
|
if ( NULL == db_info->database )
|
|
{
|
|
CACHE_CloseCache(db_info);
|
|
PR_FREEIF(db_info);
|
|
db_info = NULL;
|
|
}
|
|
|
|
/* Do stuff to get the type, and name */
|
|
tmpDB_info = cache_GetSARCacheInfoFromDB(db_info);
|
|
|
|
if ( !tmpDB_info ) return;
|
|
|
|
/* Since they can access this one, fill in the cache name value */
|
|
db_info->DiskCacheSize = tmpDB_info->DiskCacheSize;
|
|
db_info->NumberInDiskCache = tmpDB_info->NumberInDiskCache;
|
|
db_info->MaxSize = tmpDB_info->MaxSize;
|
|
db_info->name = PL_strdup(tmpDB_info->name);
|
|
db_info->logFile = NULL;
|
|
|
|
cache_freeExtCacheDBInfoObj(tmpDB_info);
|
|
#ifdef XP_PC
|
|
PR_FREEIF(filename);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* Closes the cache db
|
|
*/
|
|
PUBLIC int
|
|
CACHE_CloseCache(ExtCacheDBInfo *db)
|
|
{
|
|
/* If there is no Cache Struct return */
|
|
if (!db) return 0;
|
|
|
|
/* If there is no db return */
|
|
if (!db->database) return 0;
|
|
|
|
if(-1 == (*db->database->close)(db->database))
|
|
{
|
|
TRACEMSG(("Error closing cache database"));
|
|
|
|
return 0;
|
|
}
|
|
|
|
db->database = 0;
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Closes the cache db
|
|
*/
|
|
PUBLIC void
|
|
CACHE_UpdateCache(ExtCacheDBInfo *db)
|
|
{
|
|
if ( db )
|
|
cache_PutSARCacheInfoIntoDB(db);
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns a handle to the desired persitent cache,
|
|
* It also adds this newly opened cache to the list
|
|
* of opened caches
|
|
*/
|
|
PUBLIC ExtCacheDBInfo *
|
|
CACHE_GetCache(ExtCacheDBInfo *db)
|
|
{
|
|
XP_File fp;
|
|
char * filename, /* The platform specific filename returned by WH_PlatformFileName */
|
|
* tmpName; /* The filename returned by WH_FileName */
|
|
|
|
ExtCacheDBInfo *db_info,
|
|
*tmpDB_info;
|
|
XP_Bool inIndex = FALSE,
|
|
add2Index = FALSE;
|
|
XP_List *tmpList;
|
|
uint32 maxSize;
|
|
|
|
/* If there is no Cache Struct return */
|
|
if (!db) return NULL;
|
|
|
|
/* **************************************************************************************************
|
|
This is a hack. It is a temp fix for bug 69098. The plan is to go with this for 4.0 and
|
|
do the right thing in 4.1
|
|
************************************************************************************************** */
|
|
if ( -1 == db->type ) {
|
|
tmpName = WH_FileName(db->filename, xpSARCache);
|
|
#ifndef XP_MAC
|
|
filename = WH_FilePlatformName(tmpName);
|
|
#else
|
|
filename = tmpName;
|
|
#endif
|
|
|
|
/* Open or create the db file they specified */
|
|
db->database = dbopen(filename,
|
|
O_RDWR | O_CREAT,
|
|
0600,
|
|
DB_HASH,
|
|
0);
|
|
return db;
|
|
}
|
|
/* **************************************************************************************************
|
|
The above was a hack.
|
|
************************************************************************************************** */
|
|
|
|
|
|
/* Set up the max size for the cache */
|
|
if (db->MaxSize < 0) {
|
|
maxSize = NET_GetDiskCacheSize();
|
|
|
|
if (maxSize < MIN_MAX_SIZE)
|
|
maxSize = MIN_MAX_SIZE;
|
|
}
|
|
else {
|
|
maxSize = db->MaxSize;
|
|
}
|
|
|
|
/* Kludge to prevent NULL writes to the Cache Index */
|
|
if ( db->path == NULL || *(db->path) == '\0' || *(db->path) == ' ')
|
|
{
|
|
db->path = PL_strdup("\\");
|
|
}
|
|
|
|
/* If the Cache Index is not open, we can not see if the cache is open now can we */
|
|
if (!SARCacheIndexOpen)
|
|
{
|
|
fp = NET_XP_FileOpen("", xpSARCacheIndex, XP_FILE_READ);
|
|
|
|
/* check to see if the open succeeds */
|
|
if (fp)
|
|
cache_ReadCacheInfo(fp, &SAR_cache_database_list, SARCACHE);
|
|
else
|
|
{
|
|
/* I guess the index isn't there, let's make a new one */
|
|
SAR_cache_database_list = XP_ListNew();
|
|
if(!SAR_cache_database_list)
|
|
return NULL;
|
|
|
|
/* set the db_info values here since they will not be retrieved later */
|
|
db_info = (ExtCacheDBInfo *)PR_Malloc(sizeof(ExtCacheDBInfo));
|
|
db_info->name = PL_strdup(db->name);
|
|
db_info->filename = PL_strdup(db->filename);
|
|
db_info->path = PL_strdup(db->path);
|
|
db_info->queried_this_session = FALSE;
|
|
db_info->type = db->type;
|
|
db_info->database = NULL;
|
|
db_info->DiskCacheSize = 0;
|
|
db_info->NumberInDiskCache = 0;
|
|
db_info->MaxSize = maxSize;
|
|
db_info->logFile = NULL;
|
|
|
|
add2Index = TRUE;
|
|
}
|
|
SARCacheIndexOpen = TRUE;
|
|
}
|
|
|
|
if (!SAR_cache_database_list) return NULL;
|
|
|
|
/* If I have to add it, I already know it's not there */
|
|
if ( !add2Index )
|
|
{
|
|
tmpList = SAR_cache_database_list;
|
|
while( NULL != (db_info = (ExtCacheDBInfo *)XP_ListNextObject(tmpList)))
|
|
{
|
|
if(!PL_strcmp(db->filename, db_info->filename) ) /* && !PL_strcmp(db->path, db_info->path) ) */
|
|
{
|
|
inIndex = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!inIndex && !add2Index)
|
|
{
|
|
/* We know nothing about this cache so add it */
|
|
db_info = (ExtCacheDBInfo *)PR_Malloc(sizeof(ExtCacheDBInfo));
|
|
db_info->name = PL_strdup(db->name);
|
|
db_info->filename = PL_strdup(db->filename);
|
|
db_info->path = PL_strdup(db->path);
|
|
db_info->queried_this_session = FALSE;
|
|
db_info->type = db->type;
|
|
db_info->database = NULL;
|
|
db_info->DiskCacheSize = 0;
|
|
db_info->NumberInDiskCache = 0;
|
|
db_info->MaxSize = maxSize;
|
|
db_info->logFile = NULL;
|
|
|
|
add2Index = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* if it is already open I am going to return the handle to it,
|
|
if it is not open I will return NULL since we have a name conflict */
|
|
if ((db_info!= NULL) && (db_info->database))
|
|
{
|
|
/* Do the meager name check to see if they can access this cache */
|
|
if ( PL_strcmp(db->name, db_info->name) )
|
|
{
|
|
db_info = NULL;
|
|
}
|
|
|
|
return db_info;
|
|
}
|
|
}
|
|
|
|
tmpName = WH_FileName(db->filename, xpSARCache);
|
|
#ifndef XP_MAC
|
|
filename = WH_FilePlatformName(tmpName);
|
|
#else
|
|
filename = tmpName;
|
|
#endif
|
|
|
|
if (!db_info)
|
|
return NULL ;
|
|
|
|
/* Open or create the db file they specified */
|
|
db_info->database = dbopen(filename,
|
|
O_RDWR | O_CREAT,
|
|
0600,
|
|
DB_HASH,
|
|
0);
|
|
|
|
/* check to see if the dbopen failed */
|
|
if ( NULL == db_info->database )
|
|
{
|
|
CACHE_CloseCache(db_info);
|
|
PR_FREEIF(db_info);
|
|
|
|
db_info = NULL;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* Do stuff to get the type, and name */
|
|
tmpDB_info = cache_GetSARCacheInfoFromDB(db_info);
|
|
|
|
/* If tmpDB_info doesn't exist then this is a new cache */
|
|
if ( !tmpDB_info )
|
|
{
|
|
/* Since they can access this one, fill in the cache name value before it is saved */
|
|
db_info->name = PL_strdup(db->name);
|
|
cache_PutSARCacheInfoIntoDB(db_info);
|
|
}
|
|
else
|
|
{
|
|
/* Do the meager name check to see if they can access this cache */
|
|
if ( PL_strcmp(db->name, tmpDB_info->name) )
|
|
{
|
|
CACHE_CloseCache(db_info);
|
|
PR_FREEIF(db_info);
|
|
|
|
db_info = NULL;
|
|
}
|
|
else
|
|
{
|
|
/* Since they can access this one, fill in the cache name value */
|
|
db_info->name = PL_strdup(db->name);
|
|
db_info->DiskCacheSize = tmpDB_info->DiskCacheSize;
|
|
db_info->NumberInDiskCache = tmpDB_info->NumberInDiskCache;
|
|
db_info->MaxSize = maxSize;
|
|
db_info->logFile = NULL;
|
|
}
|
|
|
|
cache_freeExtCacheDBInfoObj(tmpDB_info);
|
|
}
|
|
|
|
if ( add2Index )
|
|
{
|
|
/* Since this is not in the index, add it */
|
|
XP_ListAddObject(SAR_cache_database_list, db_info);
|
|
cache_SaveSARCacheInfo();
|
|
}
|
|
|
|
/* This might cause problems for FileName routins
|
|
PR_FREEIF(tmpName);
|
|
*/
|
|
#ifdef XP_PC
|
|
PR_FREEIF(filename);
|
|
#endif
|
|
|
|
if (db_info != NULL)
|
|
db_info->type = db->type;
|
|
|
|
/* free the struct they passed in, and have it point to the new
|
|
* struct we will be using.
|
|
*/
|
|
PR_FREEIF(db);
|
|
db = db_info;
|
|
|
|
return db_info;
|
|
}
|
|
|
|
PUBLIC XP_Bool
|
|
CACHE_Put(char *filename, URL_Struct *url_s)
|
|
#ifdef NU_CACHE
|
|
{
|
|
PR_ASSERT(0); /* Should not be getting called */
|
|
return FALSE;
|
|
}
|
|
#else
|
|
{
|
|
net_CacheObject *cacheObject = PR_NEW(net_CacheObject);
|
|
memset(cacheObject, 0, sizeof(net_CacheObject));
|
|
|
|
cacheObject->last_modified = url_s->last_modified;
|
|
cacheObject->content_length = url_s->content_length;
|
|
StrAllocCopy(cacheObject->filename, filename);
|
|
cacheObject->is_relative_path = TRUE;
|
|
StrAllocCopy(cacheObject->address, url_s->address);
|
|
StrAllocCopy(cacheObject->content_type, url_s->content_type);
|
|
|
|
return NET_CacheStore(cacheObject, url_s, FALSE);
|
|
}
|
|
#endif /* NU_CACHE */
|
|
|
|
PUBLIC char *
|
|
CACHE_GetCachePath(char * name)
|
|
{
|
|
char * tmpName, * filename;
|
|
|
|
tmpName = WH_FileName(name, xpSARCache);
|
|
filename = WH_FilePlatformName(tmpName);
|
|
|
|
return filename;
|
|
}
|
|
|
|
|
|
PUBLIC ExtCacheDBInfo *
|
|
CACHE_GetCacheStruct(char * path, char * filename, char * name)
|
|
{
|
|
ExtCacheDBInfo * db_info;
|
|
XP_List *tmpList;
|
|
|
|
tmpList = SAR_cache_database_list;
|
|
while( NULL != (db_info = (ExtCacheDBInfo *)XP_ListNextObject(tmpList)))
|
|
{
|
|
if(!PL_strcmp(path, db_info->path) && !PL_strcmp(filename, db_info->filename) && !PL_strcmp(name, db_info->name) )
|
|
{
|
|
return db_info;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* New Cache version to allow for different files, and cache lists
|
|
*/
|
|
PRIVATE void
|
|
cache_SaveCacheInfo(XP_File fp, XP_List *list_ptr, int type)
|
|
{
|
|
ExtCacheDBInfo *db_info;
|
|
int32 len = 0;
|
|
|
|
if(!list_ptr)
|
|
return;
|
|
|
|
if(!fp)
|
|
return;
|
|
|
|
len = NET_XP_FileWrite("# Netscape External Cache Index" LINEBREAK
|
|
"# This is a generated file! Do not edit." LINEBREAK
|
|
LINEBREAK,
|
|
-1, fp);
|
|
if (len < 0)
|
|
{
|
|
NET_XP_FileClose(fp);
|
|
return;
|
|
}
|
|
|
|
/* file format is:
|
|
* Filename <TAB> database_name
|
|
*/
|
|
while((db_info = (ExtCacheDBInfo *)XP_ListNextObject(list_ptr)) != NULL)
|
|
{
|
|
|
|
if( !db_info->filename && ( (type == EXTCACHE && !db_info->name) || (type == SARCACHE && !db_info->path) ) )
|
|
continue;
|
|
|
|
len = NET_XP_FileWrite(db_info->filename, -1, fp);
|
|
if (len < 0)
|
|
{
|
|
NET_XP_FileClose(fp);
|
|
return;
|
|
}
|
|
NET_XP_FileWrite("\t", -1, fp);
|
|
|
|
if ( type == EXTCACHE )
|
|
NET_XP_FileWrite(db_info->name, -1, fp);
|
|
else
|
|
{
|
|
if ( db_info->path == NULL || *(db_info->path) == '\0' || *(db_info->path) == ' ')
|
|
{
|
|
NET_XP_FileWrite("\\", -1, fp);
|
|
}
|
|
else
|
|
{
|
|
NET_XP_FileWrite(db_info->path, -1, fp);
|
|
}
|
|
}
|
|
|
|
len = NET_XP_FileWrite(LINEBREAK, -1, fp);
|
|
if (len < 0)
|
|
{
|
|
NET_XP_FileClose(fp);
|
|
return;
|
|
}
|
|
}
|
|
|
|
NET_XP_FileClose(fp);
|
|
}
|
|
|
|
PRIVATE void
|
|
cache_SaveSARCacheInfo(void)
|
|
{
|
|
XP_File fp;
|
|
XP_List *list_ptr;
|
|
|
|
fp = NET_XP_FileOpen("", xpSARCacheIndex, XP_FILE_WRITE);
|
|
list_ptr = SAR_cache_database_list;
|
|
|
|
cache_SaveCacheInfo(fp, list_ptr, SARCACHE);
|
|
}
|
|
|
|
/*
|
|
* New Cache version to allow for different files, and cache lists
|
|
*/
|
|
PRIVATE void
|
|
cache_ReadCacheInfo(XP_File fp, XP_List **list_ptr, int type)
|
|
{
|
|
ExtCacheDBInfo *new_db_info;
|
|
char buf[BUF_SIZE];
|
|
char *name;
|
|
|
|
if(!*list_ptr)
|
|
{
|
|
*list_ptr = XP_ListNew();
|
|
if(!*list_ptr)
|
|
return;
|
|
}
|
|
|
|
if(!fp)
|
|
return;
|
|
|
|
/* file format is:
|
|
* Filename <TAB> database_name
|
|
*/
|
|
while(NET_XP_FileReadLine(buf, BUF_SIZE-1, fp))
|
|
{
|
|
if (*buf == 0 || *buf == '#' || *buf == CR || *buf == LF)
|
|
continue;
|
|
|
|
/* remove /r and /n from the end of the line */
|
|
XP_StripLine(buf);
|
|
|
|
name = PL_strchr(buf, '\t');
|
|
|
|
if(!name)
|
|
continue;
|
|
|
|
*name++ = '\0';
|
|
|
|
new_db_info = PR_NEW(ExtCacheDBInfo);
|
|
if(!new_db_info)
|
|
return;
|
|
|
|
memset(new_db_info, 0, sizeof(ExtCacheDBInfo));
|
|
|
|
StrAllocCopy(new_db_info->filename, buf);
|
|
|
|
if ( type == EXTCACHE )
|
|
StrAllocCopy(new_db_info->name, name);
|
|
else
|
|
StrAllocCopy(new_db_info->path, name);
|
|
|
|
XP_ListAddObject(*list_ptr, new_db_info);
|
|
}
|
|
|
|
NET_XP_FileClose(fp);
|
|
}
|
|
|
|
/*
|
|
* Delete the specified cache and all the files in it.
|
|
*/
|
|
PUBLIC int CACHE_EmptyCache(ExtCacheDBInfo *db)
|
|
{
|
|
DBT data;
|
|
DBT key;
|
|
int ret;
|
|
char *filename;
|
|
|
|
#ifdef DEBUG_francis
|
|
printf("CACHE_EmptyCache()\n");
|
|
#endif
|
|
|
|
ret = (*db->database->seq)(db->database, &key, &data, R_FIRST);
|
|
|
|
if( 0 != ret )
|
|
{
|
|
#ifdef DEBUG_francis
|
|
printf("CACHE_EmptyCache(): 0 != ret\n");
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
do
|
|
{
|
|
filename = net_GetFilenameInCacheDBT(&data);
|
|
if(filename)
|
|
{
|
|
#ifdef DEBUG_francis
|
|
printf("CACHE_EmptyCache(): removing %s\n",filename);
|
|
#endif
|
|
|
|
TRACEMSG(("Removing file: %s due to disk"
|
|
" cache remove",filename));
|
|
NET_XP_FileRemove(filename, xpSARCache); /* *X* What will happen if I pass this */
|
|
PR_Free(filename); /* a relative path */
|
|
}
|
|
}
|
|
while(0 == (*db->database->seq)(db->database, &key, &data, R_NEXT));
|
|
|
|
db->DiskCacheSize = 0;
|
|
db->NumberInDiskCache = 0;
|
|
|
|
#ifdef DEBUG_francis
|
|
printf("CACHE_EmptyCache(): success\n");
|
|
#endif
|
|
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Delete the specified cache and all the files in it.
|
|
*/
|
|
PUBLIC int CACHE_RemoveCache(ExtCacheDBInfo *db)
|
|
{
|
|
int ret = 0;
|
|
ExtCacheDBInfo *db_info;
|
|
XP_List *tmpList;
|
|
|
|
/* See if the database is open */
|
|
if (!db->database) return 0;
|
|
|
|
CACHE_EmptyCache(db);
|
|
CACHE_CloseCache(db);
|
|
|
|
/* Find the database object in my internal list */
|
|
tmpList = SAR_cache_database_list;
|
|
while(NULL != (db_info = (ExtCacheDBInfo *)XP_ListNextObject(tmpList)))
|
|
{
|
|
if(!PL_strcmp(db->path, db_info->path) && !PL_strcmp(db->filename, db_info->filename)) break;
|
|
}
|
|
|
|
/* Remove the cache from SAR_cache_database_list */
|
|
if ( XP_ListRemoveObject(SAR_cache_database_list, db_info) )
|
|
ret = NET_XP_FileRemove(db->filename, xpSARCache);
|
|
|
|
/* This was released in the call to CACHE_CloseCache above */
|
|
db_info->database = 0;
|
|
|
|
cache_freeExtCacheDBInfoObj(db_info);
|
|
|
|
cache_SaveSARCacheInfo();
|
|
|
|
return ret;
|
|
}
|
|
|
|
MODULE_PRIVATE int
|
|
CACHE_FindURLInCache(URL_Struct *URL_s, MWContext *ctxt)
|
|
{
|
|
DBT *key;
|
|
DBT data;
|
|
net_CacheObject *found_cache_obj;
|
|
ExtCacheDBInfo *db_ptr;
|
|
int status;
|
|
XP_StatStruct stat_entry;
|
|
char *filename=0;
|
|
XP_List *list_ptr;
|
|
|
|
/* larubbio */
|
|
XP_FileType fileType = (XP_FileType)0;
|
|
|
|
TRACEMSG(("Checking for URL in external cache"));
|
|
|
|
/* zero the last modified date so that we don't
|
|
* screw up the If-modified-since header by
|
|
* having it in even when the document isn't
|
|
* cached.
|
|
*/
|
|
URL_s->last_modified = 0;
|
|
|
|
if(!AtLeastOneOpenCache && !SARCacheIndexOpen)
|
|
{
|
|
TRACEMSG(("No External Cache databases open"));
|
|
return(0);
|
|
}
|
|
|
|
key = net_GenCacheDBKey(URL_s->address,
|
|
URL_s->post_data,
|
|
URL_s->post_data_size);
|
|
|
|
status = 1;
|
|
|
|
/* Search the external caches first */
|
|
if (AtLeastOneOpenCache)
|
|
{
|
|
list_ptr = ext_cache_database_list;
|
|
while((db_ptr = (ExtCacheDBInfo *)XP_ListNextObject(list_ptr)) != NULL)
|
|
{
|
|
if(db_ptr->database)
|
|
{
|
|
TRACEMSG(("Searching databse: %s", db_ptr->name));
|
|
status = (*db_ptr->database->get)(db_ptr->database, key, &data, 0);
|
|
if(status == 0)
|
|
{
|
|
fileType = xpExtCache;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Search the SAR caches next */
|
|
if (SARCacheIndexOpen && status != 0)
|
|
{
|
|
list_ptr = SAR_cache_database_list;
|
|
while((db_ptr = (ExtCacheDBInfo *)XP_ListNextObject(list_ptr)) != NULL)
|
|
{
|
|
if(db_ptr->database)
|
|
{
|
|
TRACEMSG(("Searching databse: %s", db_ptr->name));
|
|
status = (*db_ptr->database->get)(db_ptr->database, key, &data, 0);
|
|
if(status == 0)
|
|
{
|
|
time_t cur_time = time(NULL);
|
|
|
|
/*
|
|
* larubbio: If were here, then the file must have
|
|
* been found in an external (CD or archive) cache.
|
|
* In order to prevent unnecessary network refresh,
|
|
* override the network check if the file has
|
|
* not already expired out of the cache and the call
|
|
* isnt being made from Java (so its not the Netcaster
|
|
* crawler).
|
|
*/
|
|
if( (NULL == URL_s->SARCache) &&
|
|
( (0 == URL_s->expires) || (cur_time < URL_s->expires) ))
|
|
URL_s->use_local_copy = 1;
|
|
|
|
fileType = xpSARCache;
|
|
URL_s->SARCache = db_ptr;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(status != 0)
|
|
{
|
|
TRACEMSG(("Key not found in any database"));
|
|
net_FreeCacheDBTdata(key);
|
|
return(0);
|
|
}
|
|
|
|
found_cache_obj = net_Fast_DBDataToCacheStruct(&data);
|
|
|
|
TRACEMSG(("mkextcache: found URL in cache!"));
|
|
|
|
if(!found_cache_obj)
|
|
return(0);
|
|
|
|
/* copy in the cache file name
|
|
*/
|
|
if(db_ptr->path
|
|
#if REAL_TIME /* use this for real */
|
|
&& found_cache_obj->is_relative_path
|
|
#endif
|
|
)
|
|
{
|
|
if ( PL_strcmp(db_ptr->path, "\\" ) )
|
|
StrAllocCopy(filename, db_ptr->path);
|
|
|
|
StrAllocCat(filename, found_cache_obj->filename);
|
|
}
|
|
else
|
|
{
|
|
StrAllocCopy(filename, found_cache_obj->filename);
|
|
}
|
|
|
|
/* make sure the file still exists
|
|
* Looks like the new cache is ok since xpExtCache tells NET_XP_Stat to use it's default
|
|
* settings, which is what we want so I won't touch it.
|
|
*/
|
|
if(NET_XP_Stat(filename, &stat_entry, fileType) == -1)
|
|
{
|
|
/* file does not exist!!
|
|
* remove the entry
|
|
*/
|
|
TRACEMSG(("Error! Cache file missing: %s", filename));
|
|
|
|
net_FreeCacheDBTdata(key);
|
|
|
|
PR_Free(filename);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
/*
|
|
* if the last accessed date is before the startup date set the
|
|
* expiration date really low so that the URL is forced to be rechecked
|
|
* again. We don't just not return the URL as being in the
|
|
* cache because we want to use "If-modified-since"
|
|
*
|
|
* This works correctly because mkhttp will zero the
|
|
* expires field.
|
|
*
|
|
* if it's not an http url then just delete the entry
|
|
* since we can't do an If-modified-since
|
|
*/
|
|
|
|
/* since we can't set a last accessed time
|
|
* we can't do the once per session thing.
|
|
* Always assume EVERY TIME
|
|
*
|
|
* if(found_cache_obj->last_accessed < NET_StartupTime
|
|
* && NET_CacheUseMethod != CU_NEVER_CHECK)
|
|
*/
|
|
if(URL_s->use_local_copy || URL_s->history_num)
|
|
{
|
|
/* we already did an IMS get or it's coming out
|
|
* of the history.
|
|
* Set the expires to 0 so that we can now use the
|
|
* object
|
|
*/
|
|
URL_s->expires = 0;
|
|
}
|
|
|
|
else if(NET_CacheUseMethod != CU_NEVER_CHECK)
|
|
{
|
|
if(!PL_strncasecmp(URL_s->address, "http", 4))
|
|
{
|
|
#ifdef MOZ_OFFLINE
|
|
if ( NET_IsOffline() )
|
|
{
|
|
time_t cur_time = time(NULL);
|
|
|
|
if ( (0 == URL_s->expires) || (cur_time < URL_s->expires) )
|
|
URL_s->use_local_copy = 1;
|
|
}
|
|
#endif /* MOZ_OFFLINE */
|
|
}
|
|
else
|
|
{
|
|
/* object has expired and cant use IMS. Don't return it */
|
|
|
|
net_FreeCacheDBTdata(key);
|
|
PR_Free(filename);
|
|
|
|
return(0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* otherwise use the normal expires date for CU_NEVER_CHECK */
|
|
URL_s->expires = found_cache_obj->expires;
|
|
}
|
|
|
|
/* won't need the key anymore */
|
|
net_FreeCacheDBTdata(key);
|
|
|
|
URL_s->cache_file = filename;
|
|
|
|
/* copy the contents of the URL struct so that the content type
|
|
* and other stuff gets recorded
|
|
*/
|
|
StrAllocCopy(URL_s->content_type, found_cache_obj->content_type);
|
|
StrAllocCopy(URL_s->charset, found_cache_obj->charset);
|
|
StrAllocCopy(URL_s->content_encoding, found_cache_obj->content_encoding);
|
|
URL_s->content_length = found_cache_obj->content_length;
|
|
URL_s->real_content_length = found_cache_obj->real_content_length;
|
|
URL_s->last_modified = found_cache_obj->last_modified;
|
|
URL_s->is_netsite = found_cache_obj->is_netsite;
|
|
|
|
/* copy security info */
|
|
URL_s->security_on = found_cache_obj->security_on;
|
|
URL_s->sec_info = SECNAV_CopySSLSocketStatus(found_cache_obj->sec_info);
|
|
|
|
TIMING_MESSAGE(("cache,%s,on disk", URL_s->address));
|
|
TRACEMSG(("Cached copy is valid. returning method"));
|
|
|
|
TRACEMSG(("Using Disk Copy"));
|
|
|
|
URL_s->ext_cache_file = TRUE;
|
|
|
|
return(FILE_CACHE_TYPE_URL);
|
|
}
|
|
|
|
|
|
/* free the cache object
|
|
*/
|
|
MODULE_PRIVATE void cache_freeExtCacheDBInfoObj (ExtCacheDBInfo * cache_obj)
|
|
{
|
|
|
|
PR_FREEIF(cache_obj->database);
|
|
PR_FREEIF(cache_obj->filename);
|
|
PR_FREEIF(cache_obj->path);
|
|
PR_FREEIF(cache_obj->name);
|
|
|
|
PR_Free(cache_obj);
|
|
}
|
|
|
|
|
|
PRIVATE ExtCacheDBInfo *
|
|
cache_GetSARCacheInfoFromDB(ExtCacheDBInfo *db_info)
|
|
{
|
|
DBT key;
|
|
DBT data;
|
|
|
|
if(!db_info->database)
|
|
return NULL;
|
|
|
|
key.data = SAR_CACHE_INFO_STRING;
|
|
key.size = PL_strlen(SAR_CACHE_INFO_STRING);
|
|
|
|
if(0 == (*db_info->database->get)(db_info->database, &key, &data, 0))
|
|
{
|
|
/* convert it to a struct */
|
|
return cache_DBDataToExtCacheDBInfoStruct(&data);
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
/* Flushes the DB's contents to disk */
|
|
PUBLIC void
|
|
CACHE_FlushCache(ExtCacheDBInfo *db_info)
|
|
{
|
|
(*db_info->database->sync)(db_info->database, 0);
|
|
}
|
|
|
|
PUBLIC void
|
|
CACHE_SaveCacheInfoToDB(ExtCacheDBInfo *db_info)
|
|
{
|
|
cache_PutSARCacheInfoIntoDB(db_info);
|
|
}
|
|
|
|
PRIVATE int
|
|
cache_PutSARCacheInfoIntoDB(ExtCacheDBInfo *db_info)
|
|
{
|
|
DBT key;
|
|
DBT * data;
|
|
|
|
if(!db_info->database)
|
|
return 0;
|
|
|
|
key.data = SAR_CACHE_INFO_STRING;
|
|
key.size = PL_strlen(SAR_CACHE_INFO_STRING);
|
|
|
|
data = cache_ExtCacheDBInfoStructToDBData(db_info);
|
|
|
|
if(0 == (*db_info->database->put)(db_info->database, &key, data, 0))
|
|
{
|
|
/* Flush the db to disk */
|
|
(*db_info->database->sync)(db_info->database, 0);
|
|
return(SUCCESS);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* takes a cache object and returns a malloc'd
|
|
* (void *) suitible for passing in as a database
|
|
* data storage object
|
|
*/
|
|
MODULE_PRIVATE DBT *
|
|
cache_ExtCacheDBInfoStructToDBData(ExtCacheDBInfo * old_obj)
|
|
{
|
|
int32 len;
|
|
char *cur_ptr;
|
|
void *new_obj;
|
|
int32 total_size;
|
|
DBT *rv;
|
|
|
|
rv = PR_NEW(DBT);
|
|
|
|
if(!rv)
|
|
return(NULL);
|
|
|
|
total_size = sizeof(ExtCacheDBInfo);
|
|
|
|
#define ADD_STRING_SIZE(string) \
|
|
total_size += old_obj->string ? PL_strlen(old_obj->string)+1 : 0
|
|
|
|
total_size += sizeof(NULL);
|
|
ADD_STRING_SIZE(filename);
|
|
ADD_STRING_SIZE(path);
|
|
ADD_STRING_SIZE(name);
|
|
total_size += sizeof(XP_Bool);
|
|
total_size += sizeof(uint32);
|
|
total_size += sizeof(uint32);
|
|
total_size += sizeof(uint32);
|
|
total_size += sizeof(uint32);
|
|
|
|
#undef ADD_STRING_SIZE
|
|
|
|
new_obj = PR_Malloc(total_size * sizeof(char));
|
|
|
|
if(!new_obj)
|
|
{
|
|
PR_Free(rv);
|
|
return NULL;
|
|
}
|
|
|
|
memset(new_obj, 0, total_size * sizeof(char));
|
|
/* VERY VERY IMPORTANT. Whenever the
|
|
* format of the record structure changes
|
|
* you must verify that the byte positions
|
|
* in extcache.h are updated
|
|
*/
|
|
|
|
#define STUFF_STRING(string) \
|
|
{ \
|
|
len = (old_obj->string ? PL_strlen(old_obj->string)+1 : 0); \
|
|
COPY_INT32((void *)cur_ptr, &len); \
|
|
cur_ptr = cur_ptr + sizeof(int32); \
|
|
if(len) \
|
|
memcpy((void *)cur_ptr, old_obj->string, len); \
|
|
cur_ptr += len; \
|
|
}
|
|
|
|
#define STUFF_NUMBER(number) \
|
|
{ \
|
|
COPY_INT32((void *)cur_ptr, &old_obj->number); \
|
|
cur_ptr = cur_ptr + sizeof(int32); \
|
|
}
|
|
|
|
#define STUFF_BOOL(bool_val) \
|
|
{ \
|
|
if(old_obj->bool_val) \
|
|
((char *)(cur_ptr))[0] = 1; \
|
|
else \
|
|
((char *)(cur_ptr))[0] = 0; \
|
|
cur_ptr = cur_ptr + sizeof(char); \
|
|
}
|
|
|
|
cur_ptr = (char *)new_obj;
|
|
|
|
/* put the total size of the struct into
|
|
* the first field so that we have
|
|
* a cross check against corruption
|
|
*/
|
|
COPY_INT32((void *)cur_ptr, &total_size);
|
|
cur_ptr = cur_ptr + sizeof(int32);
|
|
|
|
STUFF_STRING(filename);
|
|
STUFF_STRING(path);
|
|
STUFF_STRING(name);
|
|
STUFF_BOOL(queried_this_session);
|
|
STUFF_NUMBER(type);
|
|
STUFF_NUMBER(DiskCacheSize);
|
|
STUFF_NUMBER(NumberInDiskCache);
|
|
STUFF_NUMBER(MaxSize);
|
|
|
|
#undef STUFF_STRING
|
|
#undef STUFF_NUMBER
|
|
#undef STUFF_BOOL
|
|
|
|
rv->data = new_obj;
|
|
rv->size = total_size;
|
|
|
|
return(rv);
|
|
}
|
|
|
|
/* takes a database storage object and returns a malloc'd
|
|
* cache data object. The cache object needs all of
|
|
* it's parts free'd.
|
|
*
|
|
* returns NULL on parse error
|
|
*/
|
|
MODULE_PRIVATE ExtCacheDBInfo *
|
|
cache_DBDataToExtCacheDBInfoStruct(DBT * db_obj)
|
|
{
|
|
ExtCacheDBInfo * rv = PR_NEW(ExtCacheDBInfo);
|
|
char * cur_ptr;
|
|
char * max_ptr;
|
|
uint32 len;
|
|
|
|
if(!rv)
|
|
return NULL;
|
|
|
|
memset(rv, 0, sizeof(ExtCacheDBInfo));
|
|
|
|
/* if any strings are larger than this then
|
|
* there was a serious database error
|
|
*/
|
|
#define MAX_HUGE_STRING_SIZE 10000
|
|
|
|
#define RETRIEVE_STRING(string) \
|
|
{ \
|
|
if(cur_ptr > max_ptr) \
|
|
{ \
|
|
cache_freeExtCacheDBInfoObj(rv); \
|
|
return(NULL); \
|
|
} \
|
|
COPY_INT32(&len, cur_ptr); \
|
|
cur_ptr += sizeof(int32); \
|
|
if(len) \
|
|
{ \
|
|
if(len > MAX_HUGE_STRING_SIZE) \
|
|
{ \
|
|
cache_freeExtCacheDBInfoObj(rv); \
|
|
return(NULL); \
|
|
} \
|
|
rv->string = (char*)PR_Malloc(len); \
|
|
if(!rv->string) \
|
|
{ \
|
|
cache_freeExtCacheDBInfoObj(rv); \
|
|
return(NULL); \
|
|
} \
|
|
memcpy(rv->string, cur_ptr, len); \
|
|
cur_ptr += len; \
|
|
} \
|
|
}
|
|
|
|
#define RETRIEVE_NUMBER(number) \
|
|
{ \
|
|
if(cur_ptr > max_ptr) \
|
|
return(rv); \
|
|
COPY_INT32(&rv->number, cur_ptr); \
|
|
cur_ptr += sizeof(int32); \
|
|
}
|
|
|
|
#define RETRIEVE_BOOL(bool) \
|
|
{ \
|
|
if(cur_ptr > max_ptr) \
|
|
return(rv); \
|
|
if(((char *)(cur_ptr))[0]) \
|
|
rv->bool = TRUE; \
|
|
else \
|
|
rv->bool = FALSE; \
|
|
cur_ptr += sizeof(char); \
|
|
}
|
|
|
|
cur_ptr = (char *)db_obj->data;
|
|
|
|
max_ptr = cur_ptr+db_obj->size;
|
|
|
|
/* get the total size of the struct out of
|
|
* the first field to check it
|
|
*/
|
|
COPY_INT32(&len, cur_ptr);
|
|
cur_ptr += sizeof(int32);
|
|
|
|
if(len != db_obj->size)
|
|
{
|
|
TRACEMSG(("Size going in is not the same as size coming out"));
|
|
PR_Free(rv);
|
|
return(NULL);
|
|
}
|
|
|
|
RETRIEVE_STRING(filename);
|
|
RETRIEVE_STRING(path);
|
|
RETRIEVE_STRING(name);
|
|
RETRIEVE_BOOL(queried_this_session);
|
|
RETRIEVE_NUMBER(type);
|
|
RETRIEVE_NUMBER(DiskCacheSize);
|
|
RETRIEVE_NUMBER(NumberInDiskCache);
|
|
RETRIEVE_NUMBER(MaxSize);
|
|
|
|
return(rv);
|
|
}
|
|
|
|
#endif /* MOZILLA_CLIENT */
|