home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libnet / mkextcac.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  38.6 KB  |  1,562 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* Created: Lou Montulli */
  19. /* Modifications/Additions: Gagan Saksena */
  20. /* Please leave outside of ifdef for windows precompiled headers. */
  21. #include "mkutils.h"
  22.  
  23. #ifdef MOZILLA_CLIENT
  24.  
  25. #include "mkcache.h"
  26. #include "glhist.h"
  27. #include "xp_hash.h"
  28. #include "xp_mcom.h"
  29. #include "client.h"
  30. #include "mkgeturl.h"
  31. #include "mkstream.h"
  32. #include "cert.h" /* for CERT_DupCertificate() */
  33. #include "extcache.h"
  34. #include "mkextcac.h"
  35.  
  36. /* For 197 java hookup */
  37. #include "jri.h"
  38.  
  39. #ifdef PROFILE
  40. #pragma profile on
  41. #endif
  42.  
  43. /* for XP_GetString() */
  44. #include "xpgetstr.h"
  45. extern int XP_DATABASE_CANT_BE_VALIDATED_MISSING_NAME_ENTRY;
  46. extern int XP_DB_SELECTED_DB_NAMED;
  47. extern int XP_REQUEST_EXTERNAL_CACHE;
  48.  
  49. PRIVATE XP_List * ext_cache_database_list = 0;
  50. PRIVATE Bool AtLeastOneOpenCache = FALSE;
  51.  
  52.  
  53. /* ************************************ Defines ************************************** */
  54. #define SAR_CACHE_INFO_STRING "CACHE_ExternalSARCacheNameString"
  55.  
  56. #define EXTCACHE      1
  57. #define SARCACHE      2
  58. #define SUCCESS          0
  59. #define FAILURE         -1
  60. #define MIN_MAX_SIZE  1000
  61.  
  62. /* ************************************ Proto's ************************************** */
  63.  
  64. /* Modified existing functions to call these (read Cut n Paste with passed in args) */
  65. PRIVATE void                    cache_ReadCacheInfo(XP_File fp, XP_List **list_ptr, int type);
  66. PRIVATE void                    cache_SaveCacheInfo(XP_File fp, XP_List *list_ptr, int type);
  67. PRIVATE void                    cache_SaveSARCacheInfo(void);
  68.  
  69. /* Newly written functions */
  70. PRIVATE int                        cache_PutSARCacheInfoIntoDB(ExtCacheDBInfo *db_info);
  71. PRIVATE ExtCacheDBInfo *        cache_GetSARCacheInfoFromDB(ExtCacheDBInfo *db_info);
  72. MODULE_PRIVATE DBT *            cache_ExtCacheDBInfoStructToDBData(ExtCacheDBInfo * old_obj);
  73. MODULE_PRIVATE ExtCacheDBInfo * cache_DBDataToExtCacheDBInfoStruct(DBT * db_obj);
  74. MODULE_PRIVATE void                cache_freeExtCacheDBInfoObj (ExtCacheDBInfo * cache_obj);
  75.  
  76. /* ************************************ Variables ************************************** */
  77. PRIVATE XP_List * SAR_cache_database_list = 0;
  78. PRIVATE Bool SARCacheIndexOpen = FALSE;
  79.  
  80.  
  81. /* close an external cache 
  82.  */
  83. PRIVATE void
  84. net_CloseExtCacheFat(ExtCacheDBInfo *db_info)
  85. {
  86.     if(db_info->database)
  87.       {
  88.         (*db_info->database->close)(db_info->database);
  89.         db_info->database = 0;
  90.       }
  91.  
  92. }
  93.  
  94.  
  95. PRIVATE char *
  96. net_GetExtCacheNameFromDB(ExtCacheDBInfo *db_info)
  97. {
  98.     DBT key;
  99.     DBT data;
  100.  
  101.     if(!db_info->database)
  102.         return NULL;
  103.  
  104.     key.data = EXT_CACHE_NAME_STRING;
  105.     key.size = XP_STRLEN(EXT_CACHE_NAME_STRING);
  106.  
  107.     if(0 == (*db_info->database->get)(db_info->database, &key, &data, 0))
  108.       {
  109.         /* make sure it's a valid cstring */
  110.         char *name = (char *)data.data;
  111.         if(name[data.size-1] == '\0')
  112.             return(XP_STRDUP(name));
  113.         else
  114.             return(NULL);
  115.       }
  116.  
  117.     return(NULL);
  118.  
  119. }
  120.  
  121. /* read/open an External Cache File allocation table.
  122.  *
  123.  * Returns a True if successfully opened
  124.  * Returns False if not.
  125.  */
  126. PRIVATE Bool
  127. net_OpenExtCacheFat(MWContext *ctxt, ExtCacheDBInfo *db_info)
  128. {
  129.     char *slash;
  130.     char *db_name;
  131.     XP_Bool close_db=FALSE;
  132.  
  133.     if(!db_info->database)
  134.       {
  135.         /* @@@ add .db to the end of the files
  136.          */
  137.         char* filename = WH_FilePlatformName(db_info->filename);
  138.         db_info->database = dbopen(filename,
  139.                                      O_RDONLY,
  140.                                      0600,
  141.                                      DB_HASH,
  142.                                      0);
  143. #ifdef XP_WIN
  144. /* This is probably the last checkin into Akbar */
  145. /* What really needs to be fixed is that Warren's implementation */
  146. /* of WH_FilePlatformName needs to return a malloc'd string */
  147. /* Right now, on Mac & X, it does not. See xp_file.c */
  148.         FREEIF(filename);
  149. #endif
  150.         if(!db_info->database)
  151.             return(FALSE);
  152.         else
  153.             AtLeastOneOpenCache = TRUE;
  154.  
  155.         StrAllocCopy(db_info->path, db_info->filename);
  156.  
  157.         /* figure out the path to the database */
  158. #if defined(XP_WIN) || defined(XP_OS2)                 /* IBM-SAH */
  159.           slash = XP_STRRCHR(db_info->path, '\\');                        
  160. #elif defined(XP_MAC)
  161.           slash = XP_STRRCHR(db_info->path, '/');                        
  162. #else
  163.           slash = XP_STRRCHR(db_info->path, '/');                        
  164. #endif
  165.  
  166.         if(slash)
  167.           {
  168.             *(slash+1) = '\0';
  169.           }
  170.         else
  171.           {
  172.             *db_info->path = '\0';
  173.           }
  174.  
  175.         db_name = net_GetExtCacheNameFromDB(db_info);
  176.  
  177.         if(!db_name)
  178.           {
  179.             close_db = !FE_Confirm(ctxt,
  180.             XP_GetString( XP_DATABASE_CANT_BE_VALIDATED_MISSING_NAME_ENTRY ) );
  181.           }
  182.         else if(XP_STRCMP(db_name, db_info->name))
  183.           {
  184.             char buffer[2048];
  185.             
  186.             PR_snprintf(buffer, sizeof(buffer),
  187.                               XP_GetString( XP_DB_SELECTED_DB_NAMED ),
  188.                               db_name, db_info->name);
  189.             
  190.             close_db = !FE_Confirm(ctxt, buffer);
  191.           }
  192.  
  193.         if(close_db)
  194.           {
  195.             (*db_info->database->close)(db_info->database);
  196.             db_info->database = 0;
  197.             return(FALSE);
  198.           }
  199.       }
  200.  
  201.      return(TRUE);
  202. }
  203.  
  204.  
  205. PRIVATE void
  206. net_SaveExtCacheInfo(void)
  207. {
  208.     XP_File fp;
  209.     XP_List *list_ptr;
  210.  
  211.     fp = XP_FileOpen("", xpExtCacheIndex, XP_FILE_WRITE);
  212.     list_ptr = ext_cache_database_list;
  213.  
  214.     cache_SaveCacheInfo(fp, list_ptr, EXTCACHE);
  215. }
  216.  
  217. #define BUF_SIZE 2048
  218. PRIVATE void
  219. net_ReadExtCacheInfo(void)
  220. {
  221.     XP_File fp;
  222.  
  223.     fp = XP_FileOpen("", xpExtCacheIndex, XP_FILE_READ);
  224.  
  225.     cache_ReadCacheInfo(fp, &ext_cache_database_list, EXTCACHE);
  226. }
  227.  
  228. PRIVATE void
  229. net_OpenExtCacheFATCallback(MWContext *ctxt, char * filename, void *closure)
  230. {
  231.     ExtCacheDBInfo *db_info = (ExtCacheDBInfo*)closure;
  232.  
  233.     if(!db_info || !filename)
  234.         return;
  235.  
  236.     StrAllocCopy(db_info->filename, filename);
  237.  
  238.     /* once we have the name try and open the
  239.      * cache fat
  240.      */
  241.     if(net_OpenExtCacheFat(ctxt, db_info))
  242.       {
  243.         AtLeastOneOpenCache = TRUE;
  244.       }
  245.     else
  246.       {
  247.         if(FE_Confirm(ctxt, "Unable to open External Cache.  Try again?"))
  248.           {
  249.             /* try and open again */
  250.  
  251.             FE_PromptForFileName (ctxt,                    /* context */
  252.                               db_info->name,            /* prompt string */
  253.                               db_info->filename,    /* default file/path */
  254.                               TRUE,                    /* file must exist */
  255.                               FALSE,                /* directories allowed */
  256.                               net_OpenExtCacheFATCallback, /* callback */
  257.                               (void *)db_info);     /* closure */
  258.  
  259.         
  260.             return; /* don't save ExtCache info */
  261.           }
  262.       }
  263.  
  264.     net_SaveExtCacheInfo();
  265. }
  266.  
  267. PUBLIC void
  268. NET_OpenExtCacheFAT(MWContext *ctxt, char * cache_name, char * instructions)
  269. {
  270.     ExtCacheDBInfo *db_info=0, *db_ptr;
  271.     Bool done = FALSE;
  272.     XP_List *list_ptr;
  273.  
  274.     if(!ext_cache_database_list)
  275.       {
  276.         net_ReadExtCacheInfo();
  277.         if(!ext_cache_database_list)
  278.             return;
  279.       }
  280.  
  281.     /* look up the name in a list and open the file
  282.      * if it's not open already
  283.      */
  284.     list_ptr = ext_cache_database_list;
  285.     while((db_ptr = (ExtCacheDBInfo *)XP_ListNextObject(list_ptr)) != NULL)
  286.       {
  287.         if(db_ptr->name && !XP_STRCMP(db_ptr->name, cache_name))
  288.           {
  289.             db_info = db_ptr;
  290.             break;
  291.           }
  292.       }
  293.  
  294.     if(!db_info)
  295.       {
  296.         db_info = XP_NEW(ExtCacheDBInfo);
  297.         if(!db_info)
  298.             return;
  299.         XP_MEMSET(db_info, 0, sizeof(ExtCacheDBInfo));
  300.         StrAllocCopy(db_info->name, cache_name);
  301.  
  302.         XP_ListAddObject(ext_cache_database_list, db_info);
  303.       }
  304.     else if(db_info->queried_this_session)
  305.       {
  306.         /* don't query or try and open again.
  307.          */
  308.         return;
  309.       }
  310.  
  311.     if(db_info->filename)
  312.       {
  313.         done = net_OpenExtCacheFat(ctxt, db_info);
  314.  
  315.         if(done)
  316.           {
  317.             char buffer[1024];
  318.  
  319.             PR_snprintf(buffer, sizeof(buffer), 
  320.                         "Now using external cache: %.900s", 
  321.                            db_info->name);
  322.             if(!FE_Confirm(ctxt, buffer))
  323.                 net_CloseExtCacheFat(db_info);
  324.           }
  325.       }
  326.  
  327.     /* If we don't have the correct filename, query the
  328.      * user for the name
  329.      */
  330.     if(!done)
  331.       {
  332.  
  333.         if(instructions)
  334.             done = !FE_Confirm(ctxt, instructions);
  335.         else
  336.             done = !FE_Confirm(ctxt, XP_GetString( XP_REQUEST_EXTERNAL_CACHE ) );
  337.  
  338.         if(!done)
  339.             FE_PromptForFileName (ctxt,                    /* context */
  340.                               db_info->name,            /* prompt string */
  341.                               db_info->filename,    /* default file/path */
  342.                               TRUE,                    /* file must exist */
  343.                               FALSE,                /* directories allowed */
  344.                               net_OpenExtCacheFATCallback, /* callback */
  345.                               (void *)db_info);     /* closure */
  346.       }
  347.  
  348.     db_info->queried_this_session = TRUE;
  349.  
  350.     return;
  351. }
  352.  
  353. /* lookup routine
  354.  *
  355.  * builds a key and looks for it in 
  356.  * the database.  Returns an access
  357.  * method and sets a filename in the
  358.  * URL struct if found
  359.  */
  360. MODULE_PRIVATE int
  361. NET_FindURLInExtCache(URL_Struct * URL_s, MWContext *ctxt)
  362. {
  363.     return CACHE_FindURLInCache(URL_s, ctxt);
  364. }
  365.  
  366. /* ****************************************************************************************************************************
  367.  * Exposed Navigator Cache Calls
  368.  * ****************************************************************************************************************************/
  369.  
  370. /*
  371.  * allows java to enumerate through all of the managed cache
  372.  */
  373. PUBLIC XP_List *
  374. CACHE_GetManagedCacheList()
  375. {
  376.     XP_File            fp;
  377.  
  378.     /* If the Cache Index is not open, we can not see if the cache is open now can we */
  379.     if (!SARCacheIndexOpen)
  380.     {
  381.         fp = XP_FileOpen("", xpSARCacheIndex, XP_FILE_READ);
  382.  
  383.         /* check to see if the open succeeds */
  384.         if (fp) 
  385.         {
  386.             cache_ReadCacheInfo(fp, &SAR_cache_database_list, SARCACHE);
  387.             SARCacheIndexOpen = TRUE;
  388.         }
  389.         else
  390.             return NULL;
  391.     }
  392.  
  393.     return SAR_cache_database_list;
  394. }
  395.  
  396.  
  397. MODULE_PRIVATE void
  398. CACHE_CloseAllOpenSARCache()
  399. {
  400.     ExtCacheDBInfo * db_info;
  401.     XP_StatStruct    stat_entry;
  402.  
  403.     if (!SARCacheIndexOpen) return;
  404.  
  405.     if (!SAR_cache_database_list) return;
  406.  
  407.     while(NULL != (db_info = (ExtCacheDBInfo *)XP_ListNextObject(SAR_cache_database_list)))
  408.     {
  409.         CACHE_CloseCache(db_info);
  410.  
  411.         if ( db_info->logFile )
  412.             XP_FileClose(db_info->logFile);
  413.  
  414.         /* stat the db file to see if it exists, if it doesn't remove it from */
  415.         /* the archive.fat file to keep things consistent */
  416.         if(db_info->filename && (XP_Stat(db_info->filename, &stat_entry, xpSARCache) == -1) )
  417.         {
  418.             /* file does not exist!!
  419.              * remove the entry 
  420.              */
  421.              TRACEMSG(("Error! Cache db file missing: %s", db_info->filename));
  422.  
  423.              if ( NULL != SAR_cache_database_list->prev )
  424.                 SAR_cache_database_list = SAR_cache_database_list->prev;
  425.              
  426.              XP_ListRemoveObject(SAR_cache_database_list, db_info);
  427.          }
  428.         cache_freeExtCacheDBInfoObj(db_info);
  429.     }
  430.  
  431.     cache_SaveSARCacheInfo();
  432.  
  433.     SAR_cache_database_list = 0;
  434.     SARCacheIndexOpen = FALSE;
  435. }
  436.  
  437. MODULE_PRIVATE void
  438. CACHE_OpenAllSARCache()
  439. {
  440.     XP_File            fp;
  441.     XP_List            *tmpList;
  442.     ExtCacheDBInfo    *db_info,
  443.                     *tmpDB_info;
  444.     char            * filename,            /* The platform specific filename returned by WH_PlatformFileName */
  445.                     * tmpName;            /* The filename returned by WH_FileName */
  446.  
  447.     if (!SARCacheIndexOpen)
  448.     {
  449.         fp = XP_FileOpen("", xpSARCacheIndex, XP_FILE_READ);
  450.  
  451.         /* check to see if the open succeeds */
  452.         if (fp)
  453.             cache_ReadCacheInfo(fp, &SAR_cache_database_list, SARCACHE);
  454.         else
  455.             return;
  456.     }
  457.  
  458.     SARCacheIndexOpen = TRUE;
  459.  
  460.     if (!SAR_cache_database_list) return;
  461.  
  462.     tmpList = SAR_cache_database_list;
  463.     while(NULL != (db_info = (ExtCacheDBInfo *)XP_ListNextObject(tmpList)))
  464.     {
  465.         if ( !db_info->database )
  466.         {
  467.             tmpName = WH_FileName(db_info->filename, xpSARCache);
  468.             filename = WH_FilePlatformName(tmpName);
  469.  
  470.             /* Open or create the db file they specified */
  471.             db_info->database = dbopen(filename,
  472.                                            O_RDWR | O_CREAT,
  473.                                            0600,
  474.                                            DB_HASH,
  475.                                            0);
  476.  
  477.             /* check to see if the dbopen failed */
  478.             if ( NULL == db_info->database )
  479.             {
  480.                 CACHE_CloseCache(db_info);
  481.                 FREEIF(db_info);
  482.                 db_info = NULL;
  483.             }
  484.  
  485.             /* Do stuff to get the type, and name */
  486.             tmpDB_info = cache_GetSARCacheInfoFromDB(db_info);
  487.  
  488.             if ( !tmpDB_info ) return;
  489.  
  490.             /* Since they can access this one, fill in the cache name value */
  491.             db_info->DiskCacheSize       = tmpDB_info->DiskCacheSize;
  492.             db_info->NumberInDiskCache = tmpDB_info->NumberInDiskCache;
  493.             db_info->MaxSize           = tmpDB_info->MaxSize;
  494.             db_info->name               = XP_STRDUP(tmpDB_info->name);
  495.             db_info->logFile           = NULL;    
  496.  
  497.             cache_freeExtCacheDBInfoObj(tmpDB_info);
  498. #ifdef XP_WIN
  499.             FREEIF(filename);
  500. #endif
  501.         }
  502.     }    
  503.  
  504. }
  505.  
  506.  
  507. /*
  508.  * Closes the cache db
  509.  */
  510. PUBLIC int 
  511. CACHE_CloseCache(ExtCacheDBInfo *db)
  512. {
  513.     /* If there is no Cache Struct return */
  514.     if (!db) return 0;
  515.  
  516.     /* If there is no db return */
  517.     if (!db->database) return 0;
  518.  
  519.     if(-1 == (*db->database->close)(db->database))
  520.     {
  521.         TRACEMSG(("Error closing cache database"));
  522.  
  523.         return 0;
  524.     }
  525.  
  526.     db->database = 0;
  527.  
  528.     return SUCCESS;
  529. }
  530.  
  531. /*
  532.  * Closes the cache db
  533.  */
  534. PUBLIC void 
  535. CACHE_UpdateCache(ExtCacheDBInfo *db)
  536. {
  537.     if ( db )
  538.         cache_PutSARCacheInfoIntoDB(db);
  539. }
  540.  
  541.     
  542. /*
  543.  * Returns a handle to the desired persitent cache,
  544.  * It also adds this newly opened cache to the list
  545.  * of opened caches
  546.  */
  547. PUBLIC ExtCacheDBInfo * 
  548. CACHE_GetCache(ExtCacheDBInfo *db)
  549. {
  550.     XP_File            fp;
  551.     char            * filename,            /* The platform specific filename returned by WH_PlatformFileName */
  552.                     * tmpName;            /* The filename returned by WH_FileName */
  553.  
  554.     ExtCacheDBInfo    *db_info,
  555.                     *tmpDB_info;
  556.     XP_Bool            inIndex = FALSE,
  557.                     add2Index = FALSE;
  558.     XP_List            *tmpList;
  559.     uint32            maxSize;
  560.  
  561.     /* If there is no Cache Struct return */
  562.     if (!db) return NULL;
  563.  
  564. /* **************************************************************************************************
  565.        This is a hack.  It is a temp fix for bug 69098.  The plan is to go with this for 4.0 and
  566.        do the right thing in 4.1
  567. ************************************************************************************************** */
  568.     if ( -1 == db->type ) {
  569.         tmpName = WH_FileName(db->filename, xpSARCache);
  570. #ifndef XP_MAC
  571.         filename = WH_FilePlatformName(tmpName);
  572. #else
  573.         filename = tmpName;
  574. #endif
  575.  
  576.         /* Open or create the db file they specified */
  577.         db->database = dbopen(filename,
  578.                                        O_RDWR | O_CREAT,
  579.                                        0600,
  580.                                        DB_HASH,
  581.                                        0);
  582.         return db;
  583.     }
  584. /* **************************************************************************************************
  585.        The above was a hack.
  586. ************************************************************************************************** */
  587.  
  588.  
  589.     /* Set up the max size for the cache */
  590.     if (db->MaxSize < 0) {
  591.         maxSize = NET_GetDiskCacheSize();
  592.  
  593.         if (maxSize < MIN_MAX_SIZE)
  594.             maxSize = MIN_MAX_SIZE;
  595.     }
  596.     else {
  597.         maxSize = db->MaxSize;
  598.     }
  599.  
  600.     /* Kludge to prevent NULL writes to the Cache Index */
  601.     if ( db->path == NULL || *(db->path) == '\0' || *(db->path) == ' ')
  602.     {
  603.         db->path = XP_STRDUP("\\");
  604.     }
  605.  
  606.     /* If the Cache Index is not open, we can not see if the cache is open now can we */
  607.     if (!SARCacheIndexOpen)
  608.     {
  609.         fp = XP_FileOpen("", xpSARCacheIndex, XP_FILE_READ);
  610.  
  611.         /* check to see if the open succeeds */
  612.         if (fp)
  613.             cache_ReadCacheInfo(fp, &SAR_cache_database_list, SARCACHE);
  614.         else
  615.         {
  616.             /* I guess the index isn't there, let's make a new one */
  617.             SAR_cache_database_list = XP_ListNew();
  618.             if(!SAR_cache_database_list)
  619.                 return NULL;
  620.  
  621.             /* set the db_info values here since they will not be retrieved later */
  622.             db_info                          = (ExtCacheDBInfo *)XP_ALLOC(sizeof(ExtCacheDBInfo));
  623.             db_info->name                  = XP_STRDUP(db->name);
  624.             db_info->filename              = XP_STRDUP(db->filename);
  625.             db_info->path                  = XP_STRDUP(db->path);
  626.             db_info->queried_this_session = FALSE;
  627.             db_info->type                  = db->type;
  628.             db_info->database              = NULL;
  629.             db_info->DiskCacheSize          = 0;
  630.             db_info->NumberInDiskCache      = 0;
  631.             db_info->MaxSize              = maxSize;
  632.             db_info->logFile              = NULL;
  633.  
  634.             add2Index = TRUE;
  635.         }
  636.         SARCacheIndexOpen = TRUE;
  637.     }
  638.  
  639.     if (!SAR_cache_database_list) return NULL;
  640.  
  641.     /* If I have to add it, I already know it's not there */
  642.     if ( !add2Index )
  643.     {
  644.         tmpList = SAR_cache_database_list;
  645.         while( NULL != (db_info = (ExtCacheDBInfo *)XP_ListNextObject(tmpList)))
  646.         {
  647.             if(!XP_STRCMP(db->filename, db_info->filename) ) /* && !XP_STRCMP(db->path, db_info->path) ) */
  648.             {
  649.                 inIndex = TRUE;
  650.                 break;
  651.             }
  652.         }
  653.     }
  654.  
  655.     if (!inIndex && !add2Index)
  656.     {
  657.         /* We know nothing about this cache so add it */
  658.         db_info                          = (ExtCacheDBInfo *)XP_ALLOC(sizeof(ExtCacheDBInfo));
  659.         db_info->name                  = XP_STRDUP(db->name);
  660.         db_info->filename              = XP_STRDUP(db->filename);
  661.         db_info->path                  = XP_STRDUP(db->path);
  662.         db_info->queried_this_session = FALSE;
  663.         db_info->type                  = db->type;
  664.         db_info->database              = NULL;
  665.         db_info->DiskCacheSize          = 0;
  666.         db_info->NumberInDiskCache      = 0;
  667.         db_info->MaxSize              = maxSize;
  668.         db_info->logFile              = NULL;
  669.  
  670.         add2Index = TRUE;
  671.     }
  672.     else
  673.     {
  674.         /* if it is already open I am going to return the handle to it,
  675.            if it is not open I will return NULL since we have a name conflict */
  676.         if ((db_info!= NULL) && (db_info->database))
  677.         {
  678.             /* Do the meager name check to see if they can access this cache */
  679.             if ( XP_STRCMP(db->name, db_info->name) )
  680.             {
  681.                 db_info = NULL;
  682.             }
  683.  
  684.             return db_info;
  685.         }
  686.     }
  687.         
  688.     tmpName = WH_FileName(db->filename, xpSARCache);
  689. #ifndef XP_MAC
  690.     filename = WH_FilePlatformName(tmpName);
  691. #else
  692.     filename = tmpName;
  693. #endif
  694.  
  695.     if (!db_info)
  696.         return NULL ;
  697.  
  698.     /* Open or create the db file they specified */
  699.     db_info->database = dbopen(filename,
  700.                                    O_RDWR | O_CREAT,
  701.                                    0600,
  702.                                    DB_HASH,
  703.                                    0);
  704.  
  705.     /* check to see if the dbopen failed */
  706.     if ( NULL == db_info->database )
  707.     {
  708.         CACHE_CloseCache(db_info);
  709.         FREEIF(db_info);    
  710.         
  711.         db_info = NULL;
  712.  
  713.         return NULL;
  714.     }
  715.  
  716.     /* Do stuff to get the type, and name */
  717.     tmpDB_info = cache_GetSARCacheInfoFromDB(db_info);
  718.  
  719.     /* If tmpDB_info doesn't exist then this is a new cache */
  720.     if ( !tmpDB_info )
  721.     {
  722.         /* Since they can access this one, fill in the cache name value before it is saved */
  723.         db_info->name = XP_STRDUP(db->name);
  724.         cache_PutSARCacheInfoIntoDB(db_info);
  725.     }
  726.     else 
  727.     {
  728.         /* Do the meager name check to see if they can access this cache */
  729.         if ( XP_STRCMP(db->name, tmpDB_info->name) )
  730.         {
  731.             CACHE_CloseCache(db_info);
  732.             FREEIF(db_info);
  733.             
  734.             db_info = NULL;
  735.         }
  736.         else
  737.         {
  738.             /* Since they can access this one, fill in the cache name value */
  739.             db_info->name               = XP_STRDUP(db->name);
  740.             db_info->DiskCacheSize       = tmpDB_info->DiskCacheSize;
  741.             db_info->NumberInDiskCache = tmpDB_info->NumberInDiskCache;
  742.             db_info->MaxSize           = maxSize;
  743.             db_info->logFile           = NULL;    
  744.         }
  745.  
  746.         cache_freeExtCacheDBInfoObj(tmpDB_info);
  747.     }    
  748.  
  749.     if ( add2Index ) 
  750.     {
  751.         /* Since this is not in the index, add it */
  752.         XP_ListAddObject(SAR_cache_database_list, db_info);
  753.         cache_SaveSARCacheInfo();
  754.     }
  755.  
  756.     /* This might cause problems for FileName routins 
  757.     FREEIF(tmpName);
  758.     */
  759. #ifdef XP_WIN
  760.     FREEIF(filename);
  761. #endif
  762.  
  763.     if (db_info != NULL)
  764.         db_info->type  = db->type;
  765.  
  766.     /* free the struct they passed in, and have it point to the new 
  767.      * struct we will be using.
  768.      */
  769.     FREEIF(db);
  770.     db = db_info;
  771.  
  772.     return db_info;
  773. }
  774.  
  775. PUBLIC Bool
  776. CACHE_Put(char *filename, URL_Struct *url_s)
  777. {
  778.     net_CacheObject *cacheObject = XP_NEW(net_CacheObject);
  779.     XP_MEMSET(cacheObject, 0, sizeof(net_CacheObject));
  780.  
  781.     cacheObject->last_modified = url_s->last_modified;
  782.     cacheObject->content_length = url_s->content_length;
  783.     StrAllocCopy(cacheObject->filename, filename);
  784.     cacheObject->is_relative_path = TRUE;
  785.     StrAllocCopy(cacheObject->address, url_s->address);
  786.     StrAllocCopy(cacheObject->content_type, url_s->content_type);
  787.  
  788.     return NET_CacheStore(cacheObject, url_s, FALSE);
  789. }
  790.  
  791. PUBLIC char *
  792. CACHE_GetCachePath(char * name)
  793. {
  794.     char * tmpName, * filename;
  795.  
  796.     tmpName = WH_FileName(name, xpSARCache);
  797.     filename = WH_FilePlatformName(tmpName);
  798.  
  799.     return filename;
  800. }
  801.  
  802.  
  803. PUBLIC ExtCacheDBInfo * 
  804. CACHE_GetCacheStruct(char * path, char * filename, char * name)
  805. {
  806.     ExtCacheDBInfo * db_info;
  807.     XP_List            *tmpList;
  808.  
  809.     tmpList = SAR_cache_database_list;
  810.     while( NULL != (db_info = (ExtCacheDBInfo *)XP_ListNextObject(tmpList)))
  811.     {
  812.         if(!XP_STRCMP(path, db_info->path) && !XP_STRCMP(filename, db_info->filename) && !XP_STRCMP(name, db_info->name) )
  813.         {
  814.             return db_info;
  815.         }
  816.     }
  817.     
  818.     return NULL;
  819. }
  820.  
  821. /*
  822.  * New Cache version to allow for different files, and cache lists
  823.  */
  824. PRIVATE void
  825. cache_SaveCacheInfo(XP_File fp, XP_List *list_ptr, int type)
  826.     ExtCacheDBInfo *db_info;
  827.     int32 len = 0;
  828.  
  829.     if(!list_ptr)
  830.         return;
  831.  
  832.     if(!fp)
  833.         return;
  834.  
  835.     len = XP_FileWrite("# Netscape External Cache Index" LINEBREAK
  836.                  "# This is a generated file!  Do not edit." LINEBREAK
  837.                  LINEBREAK,
  838.                  -1, fp);
  839.     if (len < 0)
  840.     {
  841.         XP_FileClose(fp);
  842.         return;
  843.     }
  844.  
  845.     /* file format is:
  846.      *   Filename  <TAB> database_name
  847.      */
  848.      while((db_info = (ExtCacheDBInfo *)XP_ListNextObject(list_ptr)) != NULL)
  849.      {
  850.     
  851.         if( !db_info->filename && ( (type == EXTCACHE && !db_info->name) || (type == SARCACHE && !db_info->path) ) )
  852.             continue;
  853.  
  854.         len = XP_FileWrite(db_info->filename, -1, fp);
  855.         if (len < 0)
  856.         {
  857.             XP_FileClose(fp);
  858.             return;
  859.         }
  860.         XP_FileWrite("\t", -1, fp);
  861.  
  862.         if ( type == EXTCACHE )
  863.             XP_FileWrite(db_info->name, -1, fp);
  864.         else
  865.         {
  866.             if ( db_info->path == NULL || *(db_info->path) == '\0' || *(db_info->path) == ' ')
  867.             {
  868.                 XP_FileWrite("\\", -1, fp);
  869.             }
  870.             else
  871.             {
  872.                 XP_FileWrite(db_info->path, -1, fp);
  873.             }
  874.         }
  875.  
  876.         len = XP_FileWrite(LINEBREAK, -1, fp);
  877.         if (len < 0)
  878.         {
  879.             XP_FileClose(fp);
  880.             return;
  881.         }
  882.       }
  883.  
  884.     XP_FileClose(fp);
  885. }
  886.  
  887. PRIVATE void 
  888. cache_SaveSARCacheInfo(void)
  889. {    
  890.     XP_File fp;
  891.     XP_List *list_ptr;
  892.  
  893.     fp = XP_FileOpen("", xpSARCacheIndex, XP_FILE_WRITE);
  894.     list_ptr = SAR_cache_database_list;
  895.  
  896.     cache_SaveCacheInfo(fp, list_ptr, SARCACHE);
  897. }
  898.  
  899. /*
  900.  * New Cache version to allow for different files, and cache lists
  901.  */
  902. PRIVATE void
  903. cache_ReadCacheInfo(XP_File fp, XP_List **list_ptr, int type)
  904. {
  905.     ExtCacheDBInfo *new_db_info;
  906.     char buf[BUF_SIZE];
  907.     char *name;
  908.  
  909.     if(!*list_ptr)
  910.       {
  911.         *list_ptr = XP_ListNew();
  912.         if(!*list_ptr)
  913.             return;
  914.       }
  915.     
  916.     if(!fp)
  917.         return;
  918.  
  919.     /* file format is:
  920.      *   Filename  <TAB> database_name
  921.      */
  922.     while(XP_FileReadLine(buf, BUF_SIZE-1, fp))
  923.       {
  924.         if (*buf == 0 || *buf == '#' || *buf == CR || *buf == LF)
  925.           continue;
  926.  
  927.         /* remove /r and /n from the end of the line */
  928.         XP_StripLine(buf);
  929.  
  930.         name = XP_STRCHR(buf, '\t');
  931.  
  932.         if(!name)
  933.             continue;
  934.  
  935.         *name++ = '\0';
  936.  
  937.         new_db_info = XP_NEW(ExtCacheDBInfo);
  938.         if(!new_db_info)
  939.             return;
  940.  
  941.         XP_MEMSET(new_db_info, 0, sizeof(ExtCacheDBInfo));
  942.  
  943.         StrAllocCopy(new_db_info->filename, buf);
  944.  
  945.         if ( type == EXTCACHE )
  946.             StrAllocCopy(new_db_info->name, name);
  947.         else
  948.             StrAllocCopy(new_db_info->path, name);
  949.  
  950.         XP_ListAddObject(*list_ptr, new_db_info);
  951.       }
  952.     
  953.     XP_FileClose(fp);
  954. }
  955.  
  956. /*
  957.  * Delete the specified cache and all the files in it.
  958.  */
  959. PUBLIC int CACHE_EmptyCache(ExtCacheDBInfo *db)
  960. {
  961.     DBT data;
  962.     DBT key;
  963.     int ret;
  964.     char *filename;
  965.  
  966. #ifdef DEBUG_francis
  967.     printf("CACHE_EmptyCache()\n");
  968. #endif
  969.  
  970.     ret = (*db->database->seq)(db->database, &key, &data, R_FIRST);
  971.  
  972.     if( 0 != ret )
  973.       {
  974. #ifdef DEBUG_francis
  975.     printf("CACHE_EmptyCache(): 0 != ret\n");
  976. #endif
  977.  
  978.         return 0;
  979.   }
  980.  
  981.     do
  982.       {
  983.         filename = net_GetFilenameInCacheDBT(&data);     
  984.         if(filename)                                      
  985.           {                                                
  986. #ifdef DEBUG_francis
  987.     printf("CACHE_EmptyCache(): removing %s\n",filename);
  988. #endif
  989.  
  990.             TRACEMSG(("Removing file: %s due to disk"       
  991.                       " cache remove",filename));     
  992.             XP_FileRemove(filename, xpSARCache);            /* *X* What will happen if I pass this */
  993.             FREE(filename);                                 /*     a relative path */
  994.           }  
  995.       }
  996.     while(0 == (*db->database->seq)(db->database, &key, &data, R_NEXT));
  997.  
  998.     db->DiskCacheSize      = 0;
  999.     db->NumberInDiskCache = 0;
  1000.  
  1001. #ifdef DEBUG_francis
  1002.     printf("CACHE_EmptyCache(): success\n");
  1003. #endif
  1004.  
  1005.  
  1006.     return SUCCESS;
  1007. }
  1008.  
  1009. /*
  1010.  * Delete the specified cache and all the files in it.
  1011.  */
  1012. PUBLIC int CACHE_RemoveCache(ExtCacheDBInfo *db)
  1013. {
  1014.     int ret;
  1015.     ExtCacheDBInfo *db_info;
  1016.     XP_List            *tmpList;
  1017.  
  1018.     /* See if the database is open */
  1019.     if (!db->database) return 0;
  1020.  
  1021.     CACHE_EmptyCache(db);
  1022.     CACHE_CloseCache(db);
  1023.  
  1024.     /* Find the database object in my internal list */
  1025.     tmpList = SAR_cache_database_list;
  1026.     while(NULL != (db_info = (ExtCacheDBInfo *)XP_ListNextObject(tmpList)))
  1027.     {
  1028.         if(!XP_STRCMP(db->path, db_info->path) && !XP_STRCMP(db->filename, db_info->filename)) break;
  1029.     }
  1030.  
  1031.     /* Remove the cache from SAR_cache_database_list */
  1032.     if ( XP_ListRemoveObject(SAR_cache_database_list, db_info) )
  1033.         ret = XP_FileRemove(db->filename, xpSARCache);
  1034.  
  1035.     /* This was released in the call to CACHE_CloseCache above */
  1036.     db_info->database = 0;
  1037.  
  1038.     cache_freeExtCacheDBInfoObj(db_info);
  1039.  
  1040.     cache_SaveSARCacheInfo();
  1041.  
  1042.     return ret;
  1043. }
  1044.  
  1045. MODULE_PRIVATE int
  1046. CACHE_FindURLInCache(URL_Struct *URL_s, MWContext *ctxt)
  1047. {
  1048.     DBT *key;
  1049.     DBT data;
  1050.     net_CacheObject *found_cache_obj;
  1051.     ExtCacheDBInfo *db_ptr;
  1052.     int status;
  1053.     XP_StatStruct    stat_entry;
  1054.     char *filename=0;
  1055.     XP_List *list_ptr;
  1056.  
  1057.     /* larubbio */
  1058.     XP_FileType fileType;
  1059.  
  1060.     TRACEMSG(("Checking for URL in external cache"));
  1061.  
  1062.     /* zero the last modified date so that we don't
  1063.      * screw up the If-modified-since header by
  1064.      * having it in even when the document isn't
  1065.      * cached.
  1066.      */
  1067.     URL_s->last_modified = 0;
  1068.  
  1069.     if(!AtLeastOneOpenCache && !SARCacheIndexOpen)
  1070.       {
  1071.         TRACEMSG(("No External Cache databases open"));
  1072.          return(0); 
  1073.       }
  1074.  
  1075.     key = net_GenCacheDBKey(URL_s->address, 
  1076.                             URL_s->post_data, 
  1077.                             URL_s->post_data_size);
  1078.  
  1079.     status = 1;
  1080.  
  1081.     /* Search the external caches first */
  1082.     if (AtLeastOneOpenCache)
  1083.     {
  1084.         list_ptr = ext_cache_database_list;
  1085.         while((db_ptr = (ExtCacheDBInfo *)XP_ListNextObject(list_ptr)) != NULL)
  1086.           {
  1087.             if(db_ptr->database)
  1088.               {
  1089.                 TRACEMSG(("Searching databse: %s", db_ptr->name));
  1090.                 status = (*db_ptr->database->get)(db_ptr->database, key, &data, 0);
  1091.                 if(status == 0)
  1092.                 {
  1093.                     fileType = xpExtCache;
  1094.                     break;
  1095.                 }
  1096.               }
  1097.           }
  1098.     }
  1099.  
  1100.     /* Search the SAR caches next */
  1101.     if (SARCacheIndexOpen && status != 0)
  1102.     {
  1103.         list_ptr = SAR_cache_database_list;
  1104.         while((db_ptr = (ExtCacheDBInfo *)XP_ListNextObject(list_ptr)) != NULL)
  1105.         {
  1106.             if(db_ptr->database)
  1107.             {
  1108.                 TRACEMSG(("Searching databse: %s", db_ptr->name));
  1109.                 status = (*db_ptr->database->get)(db_ptr->database, key, &data, 0);
  1110.                 if(status == 0)
  1111.                 {
  1112.                    time_t cur_time = time(NULL);
  1113.  
  1114.                    /*
  1115.                     * larubbio: If were here, then the file must have
  1116.                     * been found in an external (CD or archive) cache.
  1117.                     * In order to prevent unnecessary network refresh,
  1118.                     * override the network check if the file has
  1119.                     * not already expired out of the cache and the call
  1120.                     * isnt being made from Java (so its not the Netcaster
  1121.                     * crawler).
  1122.                     */
  1123.                     if( (NULL == URL_s->SARCache) &&
  1124.                         ( (0 == URL_s->expires) || (cur_time < URL_s->expires) ))
  1125.                            URL_s->use_local_copy = 1;
  1126.  
  1127.                     fileType = xpSARCache;
  1128.                     URL_s->SARCache = db_ptr;
  1129.                     break;
  1130.                 }
  1131.             }
  1132.         }
  1133.     }
  1134.  
  1135.     if(status != 0)
  1136.     {
  1137.         TRACEMSG(("Key not found in any database"));
  1138.         net_FreeCacheDBTdata(key);
  1139.          return(0); 
  1140.     }
  1141.  
  1142.     found_cache_obj = net_Fast_DBDataToCacheStruct(&data);
  1143.  
  1144.     TRACEMSG(("mkextcache: found URL in cache!"));
  1145.  
  1146.     if(!found_cache_obj)
  1147.         return(0);
  1148.  
  1149.     /* copy in the cache file name
  1150.      */
  1151.     if(db_ptr->path 
  1152. #if REAL_TIME  /* use this for real */
  1153.         && found_cache_obj->is_relative_path
  1154. #endif
  1155.          )
  1156.       {
  1157.         if ( XP_STRCMP(db_ptr->path, "\\" ) )
  1158.             StrAllocCopy(filename, db_ptr->path);
  1159.  
  1160.         StrAllocCat(filename, found_cache_obj->filename);
  1161.       }
  1162.     else
  1163.       {
  1164.         StrAllocCopy(filename, found_cache_obj->filename);
  1165.       }
  1166.  
  1167.     /* make sure the file still exists
  1168.      * Looks like the new cache is ok since xpExtCache tells XP_Stat to use it's default
  1169.      * settings, which is what we want so I won't touch it.
  1170.      */
  1171.     if(XP_Stat(filename, &stat_entry, fileType) == -1)
  1172.       {
  1173.         /* file does not exist!!
  1174.          * remove the entry 
  1175.          */
  1176.         TRACEMSG(("Error! Cache file missing: %s", filename));
  1177.  
  1178.         net_FreeCacheDBTdata(key);
  1179.  
  1180.         FREE(filename);
  1181.  
  1182.         return(0);
  1183.             
  1184.       }
  1185.  
  1186.     /*
  1187.      * if the last accessed date is before the startup date set the
  1188.      * expiration date really low so that the URL is forced to be rechecked
  1189.      * again.  We don't just not return the URL as being in the
  1190.      * cache because we want to use "If-modified-since"
  1191.      *
  1192.      * This works correctly because mkhttp will zero the
  1193.      * expires field.
  1194.      *
  1195.      * if it's not an http url then just delete the entry
  1196.      * since we can't do an If-modified-since
  1197.      */
  1198.  
  1199.     /* since we can't set a last accessed time
  1200.      * we can't do the once per session thing.
  1201.      * Always assume EVERY TIME
  1202.      *
  1203.      *  if(found_cache_obj->last_accessed < NET_StartupTime
  1204.      *        && NET_CacheUseMethod != CU_NEVER_CHECK)
  1205.      */
  1206.     if(URL_s->use_local_copy || URL_s->history_num)
  1207.       {
  1208.         /* we already did an IMS get or it's coming out
  1209.          * of the history.
  1210.          * Set the expires to 0 so that we can now use the
  1211.          * object
  1212.          */
  1213.          URL_s->expires = 0;
  1214.       }
  1215.  
  1216.     else if(NET_CacheUseMethod != CU_NEVER_CHECK)
  1217.       {
  1218.         if(!strncasecomp(URL_s->address, "http", 4))
  1219.           {
  1220. #ifdef MOZ_OFFLINE
  1221.             if ( NET_IsOffline() )
  1222.             {
  1223.                 time_t cur_time = time(NULL);
  1224.  
  1225.                 if ( (0 == URL_s->expires) || (cur_time < URL_s->expires) )
  1226.                     URL_s->use_local_copy = 1;
  1227.             }
  1228. #endif /* MOZ_OFFLINE */
  1229.           }
  1230.         else
  1231.           {
  1232.             /* object has expired and cant use IMS. Don't return it */
  1233.  
  1234.             net_FreeCacheDBTdata(key);
  1235.             FREE(filename);
  1236.  
  1237.             return(0);
  1238.           }
  1239.       }
  1240.     else
  1241.       {
  1242.         /* otherwise use the normal expires date for CU_NEVER_CHECK */
  1243.          URL_s->expires = found_cache_obj->expires;
  1244.       }
  1245.  
  1246.     /* won't need the key anymore */
  1247.     net_FreeCacheDBTdata(key);
  1248.  
  1249.     URL_s->cache_file = filename;
  1250.  
  1251.     /* copy the contents of the URL struct so that the content type
  1252.      * and other stuff gets recorded
  1253.      */
  1254.     StrAllocCopy(URL_s->content_type,     found_cache_obj->content_type);
  1255.     StrAllocCopy(URL_s->charset,          found_cache_obj->charset);
  1256.     StrAllocCopy(URL_s->content_encoding, found_cache_obj->content_encoding);
  1257.     URL_s->content_length = found_cache_obj->content_length;
  1258.     URL_s->real_content_length = found_cache_obj->real_content_length;
  1259.      URL_s->last_modified  = found_cache_obj->last_modified;
  1260.      URL_s->is_netsite     = found_cache_obj->is_netsite;
  1261.  
  1262.     /* copy security info */
  1263.     URL_s->security_on             = found_cache_obj->security_on;
  1264.     URL_s->key_size                = found_cache_obj->key_size;
  1265.     URL_s->key_secret_size         = found_cache_obj->key_secret_size;
  1266.     StrAllocCopy(URL_s->key_cipher,  found_cache_obj->key_cipher);
  1267.  
  1268.     /* delete any existing certificate first */
  1269.     CERT_DestroyCertificate(URL_s->certificate);
  1270.     URL_s->certificate = NULL;
  1271.  
  1272.     if (found_cache_obj->certificate)
  1273.           URL_s->certificate =
  1274.             CERT_DupCertificate(found_cache_obj->certificate);
  1275.  
  1276.     TRACEMSG(("Cached copy is valid. returning method"));
  1277.  
  1278.     TRACEMSG(("Using Disk Copy"));
  1279.  
  1280.     URL_s->ext_cache_file = TRUE;
  1281.  
  1282.     return(FILE_CACHE_TYPE_URL);
  1283. }
  1284.  
  1285.  
  1286.  /* free the cache object
  1287.  */
  1288. MODULE_PRIVATE void cache_freeExtCacheDBInfoObj (ExtCacheDBInfo * cache_obj)
  1289. {
  1290.  
  1291.     FREEIF(cache_obj->database);
  1292.     FREEIF(cache_obj->filename);
  1293.     FREEIF(cache_obj->path);
  1294.     FREEIF(cache_obj->name);
  1295.  
  1296.     FREE(cache_obj);
  1297. }
  1298.  
  1299.  
  1300. PRIVATE ExtCacheDBInfo *
  1301. cache_GetSARCacheInfoFromDB(ExtCacheDBInfo *db_info)
  1302. {
  1303.     DBT key;
  1304.     DBT data;
  1305.  
  1306.     if(!db_info->database)
  1307.         return NULL;
  1308.  
  1309.     key.data = SAR_CACHE_INFO_STRING;
  1310.     key.size = XP_STRLEN(SAR_CACHE_INFO_STRING);
  1311.  
  1312.     if(0 == (*db_info->database->get)(db_info->database, &key, &data, 0))
  1313.     {
  1314.         /* convert it to a struct */
  1315.         return cache_DBDataToExtCacheDBInfoStruct(&data);
  1316.     }
  1317.  
  1318.     return(NULL);
  1319. }
  1320.  
  1321. /* Flushes the DB's contents to disk */
  1322. PUBLIC void
  1323. CACHE_FlushCache(ExtCacheDBInfo *db_info)
  1324. {
  1325.     (*db_info->database->sync)(db_info->database, 0);
  1326. }
  1327.  
  1328. PUBLIC void
  1329. CACHE_SaveCacheInfoToDB(ExtCacheDBInfo *db_info)
  1330. {
  1331.     cache_PutSARCacheInfoIntoDB(db_info);
  1332. }
  1333.  
  1334. PRIVATE int
  1335. cache_PutSARCacheInfoIntoDB(ExtCacheDBInfo *db_info)
  1336. {
  1337.     DBT key;
  1338.     DBT * data;
  1339.  
  1340.     if(!db_info->database)
  1341.         return 0;
  1342.  
  1343.     key.data = SAR_CACHE_INFO_STRING;
  1344.     key.size = XP_STRLEN(SAR_CACHE_INFO_STRING);
  1345.  
  1346.     data = cache_ExtCacheDBInfoStructToDBData(db_info);
  1347.  
  1348.     if(0 == (*db_info->database->put)(db_info->database, &key, data, 0))
  1349.     {
  1350.         /* Flush the db to disk */
  1351.         (*db_info->database->sync)(db_info->database, 0);
  1352.         return(SUCCESS);
  1353.     }
  1354.  
  1355.     return 0;
  1356. }
  1357.  
  1358. /* takes a cache object and returns a malloc'd 
  1359.  * (void *) suitible for passing in as a database
  1360.  * data storage object
  1361.  */
  1362. MODULE_PRIVATE DBT *
  1363. cache_ExtCacheDBInfoStructToDBData(ExtCacheDBInfo * old_obj)
  1364. {
  1365.     int32 len;
  1366.     char *cur_ptr;
  1367.     void *new_obj;
  1368.     int32 total_size;
  1369.     DBT *rv;
  1370.  
  1371.     rv = XP_NEW(DBT);
  1372.  
  1373.     if(!rv)
  1374.         return(NULL);
  1375.  
  1376.     total_size = sizeof(ExtCacheDBInfo);
  1377.  
  1378. #define ADD_STRING_SIZE(string) \
  1379. total_size += old_obj->string ? XP_STRLEN(old_obj->string)+1 : 0
  1380.  
  1381.     total_size += sizeof(NULL);
  1382.     ADD_STRING_SIZE(filename);
  1383.     ADD_STRING_SIZE(path);
  1384.     ADD_STRING_SIZE(name);
  1385.     total_size += sizeof(Bool);
  1386.     total_size += sizeof(uint32);
  1387.     total_size += sizeof(uint32);
  1388.     total_size += sizeof(uint32);
  1389.     total_size += sizeof(uint32);
  1390.  
  1391. #undef ADD_STRING_SIZE
  1392.     
  1393.     new_obj = XP_ALLOC(total_size * sizeof(char));
  1394.  
  1395.     if(!new_obj)
  1396.       {
  1397.         FREE(rv);
  1398.         return NULL;
  1399.       }
  1400.  
  1401.     XP_MEMSET(new_obj, 0, total_size * sizeof(char));
  1402.     /* VERY VERY IMPORTANT.  Whenever the
  1403.      * format of the record structure changes
  1404.       * you must verify that the byte positions    
  1405.      * in extcache.h are updated
  1406.      */
  1407.  
  1408. #define STUFF_STRING(string)                                     \
  1409. {                                                                 \
  1410.   len = (old_obj->string ? XP_STRLEN(old_obj->string)+1 : 0);    \
  1411.   COPY_INT32((void *)cur_ptr, &len);                            \
  1412.   cur_ptr = cur_ptr + sizeof(int32);                            \
  1413.   if(len)                                                        \
  1414.       XP_MEMCPY((void *)cur_ptr, old_obj->string, len);            \
  1415.   cur_ptr += len;                                                \
  1416. }
  1417.  
  1418. #define STUFF_NUMBER(number)                                     \
  1419. {                                                                 \
  1420.   COPY_INT32((void *)cur_ptr, &old_obj->number);                \
  1421.   cur_ptr = cur_ptr + sizeof(int32);                            \
  1422. }
  1423.  
  1424. #define STUFF_BOOL(bool_val)                                         \
  1425. {                                                                     \
  1426.   if(old_obj->bool_val)                                                \
  1427.     ((char *)(cur_ptr))[0] = 1;                                        \
  1428.   else                                                                \
  1429.     ((char *)(cur_ptr))[0] = 0;                                        \
  1430.   cur_ptr = cur_ptr + sizeof(char);                                    \
  1431. }
  1432.  
  1433.     cur_ptr = (char *)new_obj;
  1434.  
  1435.     /* put the total size of the struct into
  1436.      * the first field so that we have
  1437.      * a cross check against corruption
  1438.      */
  1439.       COPY_INT32((void *)cur_ptr, &total_size);
  1440.       cur_ptr = cur_ptr + sizeof(int32);
  1441.  
  1442.     STUFF_STRING(filename);
  1443.     STUFF_STRING(path);
  1444.     STUFF_STRING(name);
  1445.     STUFF_BOOL(queried_this_session);
  1446.     STUFF_NUMBER(type);
  1447.     STUFF_NUMBER(DiskCacheSize);
  1448.     STUFF_NUMBER(NumberInDiskCache);
  1449.     STUFF_NUMBER(MaxSize);
  1450.  
  1451. #undef STUFF_STRING
  1452. #undef STUFF_NUMBER
  1453. #undef STUFF_BOOL
  1454.  
  1455.     rv->data = new_obj;
  1456.     rv->size = total_size;
  1457.  
  1458.     return(rv);
  1459. }
  1460.  
  1461. /* takes a database storage object and returns a malloc'd
  1462.  * cache data object.  The cache object needs all of
  1463.  * it's parts free'd.
  1464.  *
  1465.  * returns NULL on parse error 
  1466.  */
  1467. MODULE_PRIVATE ExtCacheDBInfo *
  1468. cache_DBDataToExtCacheDBInfoStruct(DBT * db_obj)
  1469. {
  1470.     ExtCacheDBInfo * rv = XP_NEW(ExtCacheDBInfo);
  1471.     char * cur_ptr;
  1472.     char * max_ptr;
  1473.     uint32 len;
  1474.  
  1475.     if(!rv)
  1476.         return NULL;
  1477.  
  1478.     XP_MEMSET(rv, 0, sizeof(ExtCacheDBInfo));
  1479.  
  1480. /* if any strings are larger than this then
  1481.  * there was a serious database error
  1482.  */
  1483. #define MAX_HUGE_STRING_SIZE 10000
  1484.  
  1485. #define RETRIEVE_STRING(string)                    \
  1486. {                                                \
  1487.     if(cur_ptr > max_ptr)                       \
  1488.       {                                             \
  1489.         cache_freeExtCacheDBInfoObj(rv);        \
  1490.         return(NULL);                           \
  1491.       }                                            \
  1492.     COPY_INT32(&len, cur_ptr);                    \
  1493.     cur_ptr += sizeof(int32);                    \
  1494.     if(len)                                        \
  1495.       {                                            \
  1496.         if(len > MAX_HUGE_STRING_SIZE)            \
  1497.           {                                         \
  1498.             cache_freeExtCacheDBInfoObj(rv);    \
  1499.             return(NULL);                        \
  1500.           }                                        \
  1501.         rv->string = (char*)XP_ALLOC(len);        \
  1502.         if(!rv->string)                            \
  1503.           {                                         \
  1504.             cache_freeExtCacheDBInfoObj(rv);    \
  1505.             return(NULL);                        \
  1506.           }                                        \
  1507.         XP_MEMCPY(rv->string, cur_ptr, len);    \
  1508.         cur_ptr += len;                            \
  1509.       }                                            \
  1510. }                                            
  1511.  
  1512. #define RETRIEVE_NUMBER(number)                    \
  1513. {                                                \
  1514.     if(cur_ptr > max_ptr)                       \
  1515.         return(rv);                             \
  1516.     COPY_INT32(&rv->number, cur_ptr);            \
  1517.     cur_ptr += sizeof(int32);                    \
  1518. }
  1519.  
  1520. #define RETRIEVE_BOOL(bool)                \
  1521. {                                        \
  1522.   if(cur_ptr > max_ptr)                 \
  1523.     return(rv);                         \
  1524.   if(((char *)(cur_ptr))[0])            \
  1525.     rv->bool = TRUE;                    \
  1526.   else                                     \
  1527.     rv->bool = FALSE;                    \
  1528.   cur_ptr += sizeof(char);                \
  1529. }
  1530.  
  1531.     cur_ptr = (char *)db_obj->data;
  1532.  
  1533.     max_ptr = cur_ptr+db_obj->size;
  1534.  
  1535.     /* get the total size of the struct out of
  1536.      * the first field to check it
  1537.      */
  1538.     COPY_INT32(&len, cur_ptr);
  1539.     cur_ptr += sizeof(int32);
  1540.  
  1541.     if(len != db_obj->size)
  1542.       {
  1543.         TRACEMSG(("Size going in is not the same as size coming out"));
  1544.         FREE(rv);
  1545.         return(NULL);
  1546.       }
  1547.  
  1548.     RETRIEVE_STRING(filename);
  1549.     RETRIEVE_STRING(path);
  1550.     RETRIEVE_STRING(name);
  1551.     RETRIEVE_BOOL(queried_this_session);
  1552.     RETRIEVE_NUMBER(type);
  1553.     RETRIEVE_NUMBER(DiskCacheSize);
  1554.     RETRIEVE_NUMBER(NumberInDiskCache);
  1555.     RETRIEVE_NUMBER(MaxSize);
  1556.  
  1557.     return(rv);
  1558. }
  1559.  
  1560. #endif /* MOZILLA_CLIENT */
  1561.