home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libnet / extcache.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  20.9 KB  |  911 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.  
  19. /* Please leave outside of ifdef for window precompiled headers */
  20. #include "mkutils.h"
  21.  
  22. #ifdef MOZILLA_CLIENT
  23.  
  24. /* Publicly released Netscape cache access routines.
  25.  *
  26.  * These routines are shared between the netscape executable
  27.  * and the programs released as a cache developers kit.
  28.  *
  29.  * Created: Lou Montulli <montulli@netscape.com>, July-95.
  30.  * Modifications/Addition: Gagan Saksena, 97
  31.  */
  32.  
  33. #ifndef EXT_DB_ROUTINES
  34. #include "cert.h"
  35. #include "sechash.h"
  36. #endif
  37.  
  38. #include "extcache.h"  /* include this for everything */
  39.  
  40. #ifdef EXT_DB_ROUTINES
  41.  
  42. #include <fcntl.h>
  43. #include <sys/stat.h>
  44. #include <assert.h>
  45.  
  46. typedef struct {
  47.     int32 len;
  48.     char *data;
  49. } SECItem;
  50.  
  51. #ifdef _sgi
  52. #include <sys/endian.h>
  53. #endif /* _sgi */
  54.  
  55.  
  56. /* URL methods
  57.  */
  58.  #define URL_GET_METHOD  0
  59.  #define URL_POST_METHOD 1
  60.  #define URL_HEAD_METHOD 2
  61.  
  62. #endif /* DB_STORE */
  63.  
  64.  
  65. MODULE_PRIVATE DBT *
  66. net_CacheDBTDup(DBT *obj)
  67. {
  68.     DBT * rv = XP_NEW(DBT);
  69.  
  70.     if(!rv)
  71.         return(NULL);
  72.  
  73.     rv->size = obj->size;
  74.     rv->data = XP_ALLOC(rv->size);
  75.  
  76.     if(!rv->data)
  77.       {
  78.         FREE(rv);
  79.         return(NULL);
  80.       }
  81.  
  82.     XP_MEMCPY(rv->data, obj->data, rv->size);
  83.  
  84.     return(rv);
  85.  
  86. }
  87.  
  88. /* free the cache object
  89.  */
  90. MODULE_PRIVATE void net_freeCacheObj (net_CacheObject * cache_obj)
  91. {
  92.  
  93.     FREEIF(cache_obj->address);
  94.     FREEIF(cache_obj->post_data);
  95.     FREEIF(cache_obj->post_headers);
  96.     FREEIF(cache_obj->content_type);
  97.     FREEIF(cache_obj->charset);
  98.     FREEIF(cache_obj->content_encoding);
  99.     FREEIF(cache_obj->page_services_url);
  100.     FREEIF(cache_obj->filename);
  101.     
  102. #ifndef EXT_DB_ROUTINES
  103.     if ( cache_obj->certificate ) {
  104.         CERT_DestroyCertificate(cache_obj->certificate);
  105.     }
  106. #endif
  107.     
  108.     FREE(cache_obj);
  109. }
  110.  
  111. /* returns true if this DBT looks like a valid
  112.  * entry.  It looks at the checksum and the
  113.  * version number to see if it's valid
  114.  */
  115. #define MAX_VALID_DBT_SIZE 10000
  116.  
  117. MODULE_PRIVATE Bool
  118. net_IsValidCacheDBT(DBT *obj)
  119. {
  120.     char *cur_ptr, *max_ptr;
  121.     uint32 len;
  122.  
  123.     if(!obj || obj->size < 9 || obj->size > MAX_VALID_DBT_SIZE)
  124.         return(FALSE);
  125.  
  126.     cur_ptr = (char *)obj->data;
  127.     max_ptr = cur_ptr+obj->size;
  128.  
  129.     /* get the total size of the struct out of
  130.      * the first field to check it
  131.      */
  132.     COPY_INT32(&len, cur_ptr);
  133.     cur_ptr += sizeof(int32);
  134.  
  135.     if(len != obj->size)
  136.       {
  137.         TRACEMSG(("Size going in is not the same as size coming out"));
  138.         return(FALSE);
  139.       }
  140.  
  141.     /* get the version number of the written structure
  142.      */
  143.     if(cur_ptr > max_ptr)
  144.         return(FALSE);
  145.     COPY_INT32(&len, cur_ptr);
  146.     cur_ptr += sizeof(int32);
  147.  
  148.     if(len != CACHE_FORMAT_VERSION)
  149.       {
  150.         TRACEMSG(("Version of cache structure is wrong!: %d", len));
  151.         return(FALSE);
  152.       }
  153.  
  154.     /* looks good to me... */
  155.     return(TRUE);
  156. }
  157.  
  158.  
  159. /* takes a cache object and returns a malloc'd 
  160.  * (void *) suitible for passing in as a database
  161.  * data storage object
  162.  */
  163. MODULE_PRIVATE DBT *
  164. net_CacheStructToDBData(net_CacheObject * old_obj)
  165. {
  166.     int32 len;
  167.     char *cur_ptr;
  168.     void *new_obj;
  169.     int32 total_size;
  170.     DBT *rv;
  171.  
  172.     rv = XP_NEW(DBT);
  173.  
  174.     if(!rv)
  175.         return(NULL);
  176.  
  177.     total_size = sizeof(net_CacheObject);
  178.  
  179. #define ADD_STRING_SIZE(string) \
  180. total_size += old_obj->string ? XP_STRLEN(old_obj->string)+1 : 0
  181.  
  182.     ADD_STRING_SIZE(address);
  183.     total_size += old_obj->post_data_size+1;
  184.     ADD_STRING_SIZE(post_headers);
  185.     ADD_STRING_SIZE(content_type);
  186.     ADD_STRING_SIZE(content_encoding);
  187.     ADD_STRING_SIZE(charset);
  188.     ADD_STRING_SIZE(filename);
  189.     ADD_STRING_SIZE(key_cipher);
  190.     total_size += sizeof(uint32); /* certificate length */
  191.     ADD_STRING_SIZE(page_services_url);
  192.  
  193. #ifndef EXT_DB_ROUTINES
  194.     if ( old_obj->certificate ) {
  195.         total_size += old_obj->certificate->derCert.len;
  196.     }
  197. #endif
  198.  
  199. #undef ADD_STRING_SIZE
  200.     
  201.     new_obj = XP_ALLOC(total_size * sizeof(char));
  202.  
  203.     if(!new_obj)
  204.       {
  205.         FREE(rv);
  206.         return NULL;
  207.       }
  208.  
  209.     XP_MEMSET(new_obj, 0, total_size * sizeof(char));
  210.  
  211.     /*
  212.      * order is:
  213.      * int32    size of the entire structure;
  214.      *
  215.      * int32    version of the structure format (CACHE_FORMAT_VERSION)
  216.      *
  217.      * time_t                  last_modified;
  218.      * time_t                  last_accessed;
  219.      * time_t                  expires;
  220.      * uint32                  content_length;
  221.      * Bool                    is_netsite;
  222.      *
  223.       * time_t                  lock_date;
  224.      *
  225.      * char                  * filename;
  226.      * int32                   filename_len;
  227.      *
  228.      * int32                   security_on;
  229.      * int32                   key_size;
  230.      * int32                   key_secret_size;             
  231.      * char                  * key_cipher;
  232.      *
  233.      * struct SECCertificateStr *certificate;
  234.      *
  235.      * int32                   method;
  236.      *
  237.      * # don't store address, or post_data stuff
  238.      * # char                  * address;
  239.      * # uint32                  post_data_size;
  240.      * # char                  * post_data;
  241.      *
  242.      * char                  * post_headers;
  243.      * char                  * content_type;
  244.      * char                  * content_encoding;
  245.      * char                  * charset;
  246.      *
  247.      * Bool                    incomplete_file;
  248.      * uint32                  total_content_length;
  249.      *
  250.      * char                  * page_services_url;
  251.       * 
  252.      * string lengths all include null terminators
  253.      * all integer constants are stored as 4 bytes
  254.      * all booleans are stored as one byte
  255.      */
  256.  
  257.     /* VERY VERY IMPORTANT.  Whenever the
  258.      * format of the record structure changes
  259.       * you must verify that the byte positions    
  260.      * in extcache.h are updated
  261.      */
  262.  
  263. #define STUFF_STRING(string)                                     \
  264. {                                                                 \
  265.   len = (old_obj->string ? XP_STRLEN(old_obj->string)+1 : 0);    \
  266.   COPY_INT32((void *)cur_ptr, &len);                            \
  267.   cur_ptr = cur_ptr + sizeof(int32);                            \
  268.   if(len)                                                        \
  269.       XP_MEMCPY((void *)cur_ptr, old_obj->string, len);            \
  270.   cur_ptr += len;                                                \
  271. }
  272.  
  273. #define STUFF_NUMBER(number)                                     \
  274. {                                                                 \
  275.   COPY_INT32((void *)cur_ptr, &old_obj->number);                \
  276.   cur_ptr = cur_ptr + sizeof(int32);                            \
  277. }
  278.  
  279. #define STUFF_TIMET(number)                                     \
  280. {                                                                 \
  281.   COPY_INT32((void *)cur_ptr, &old_obj->number);                \
  282.   cur_ptr = cur_ptr + sizeof(time_t);                            \
  283. }
  284.  
  285. #define STUFF_BOOL(bool_val)                                         \
  286. {                                                                     \
  287.   if(old_obj->bool_val)                                                \
  288.     ((char *)(cur_ptr))[0] = 1;                                        \
  289.   else                                                                \
  290.     ((char *)(cur_ptr))[0] = 0;                                        \
  291.   cur_ptr = cur_ptr + sizeof(char);                                    \
  292. }
  293.  
  294.     cur_ptr = (char *)new_obj;
  295.  
  296.     /* put the total size of the struct into
  297.      * the first field so that we have
  298.      * a cross check against corruption
  299.      */
  300.       COPY_INT32((void *)cur_ptr, &total_size);
  301.       cur_ptr = cur_ptr + sizeof(int32);
  302.  
  303.     /* put the version number of the structure
  304.      * format that we are using
  305.      * By using a version string when writting
  306.      * we can support backwards compatibility
  307.      * in our reading code
  308.      * (use "len" as a temp variable)
  309.      */
  310.     len = CACHE_FORMAT_VERSION;
  311.       COPY_INT32((void *)cur_ptr, &len);
  312.       cur_ptr = cur_ptr + sizeof(int32);
  313.  
  314.     STUFF_TIMET(last_modified);
  315.     STUFF_TIMET(last_accessed);
  316.     STUFF_TIMET(expires);
  317.     STUFF_NUMBER(content_length);
  318.     STUFF_BOOL(is_netsite);
  319.  
  320.     STUFF_TIMET(lock_date);
  321.  
  322.     STUFF_STRING(filename);
  323.     STUFF_NUMBER(filename_len);
  324.  
  325.     STUFF_BOOL(is_relative_path);
  326.  
  327.     STUFF_NUMBER(security_on);
  328.     STUFF_NUMBER(key_size);
  329.     STUFF_NUMBER(key_secret_size);
  330.     STUFF_STRING(key_cipher);
  331.  
  332. #ifndef EXT_DB_ROUTINES
  333.     /* save the certificate */
  334.     if ( old_obj->certificate ) {
  335.         len = old_obj->certificate->derCert.len;
  336.         COPY_INT32((void *)cur_ptr, &len);
  337.         cur_ptr = cur_ptr + sizeof(int32);
  338.  
  339.         XP_MEMCPY((void *)cur_ptr, old_obj->certificate->derCert.data, len);
  340.         cur_ptr += len;
  341.     } else {
  342. #else
  343.     {
  344. #endif
  345.         len = 0;
  346.         COPY_INT32((void *)cur_ptr, &len);
  347.         cur_ptr = cur_ptr + sizeof(int32);
  348.     }
  349.  
  350.     STUFF_NUMBER(method);
  351.  
  352. #ifdef STORE_ADDRESS_AND_POST_DATA
  353.  
  354.     STUFF_STRING(address);
  355.     STUFF_NUMBER(post_data_size);
  356.     
  357.     /* post_data 
  358.      * this is special since it not necessarily a string
  359.      */
  360.     if(old_obj->post_data_size)
  361.       {
  362.         XP_MEMCPY(cur_ptr, old_obj->post_data, old_obj->post_data_size+1);
  363.         cur_ptr += old_obj->post_data_size+1;
  364.       }
  365.  
  366. #endif /* STORE_ADDRESS_AND_POST_DATA */
  367.  
  368.     STUFF_STRING(post_headers);
  369.  
  370.     STUFF_STRING(content_type);
  371.     STUFF_STRING(content_encoding);
  372.     STUFF_STRING(charset);
  373.  
  374.     STUFF_BOOL(incomplete_file);
  375.     STUFF_NUMBER(real_content_length);
  376.  
  377.     STUFF_STRING(page_services_url);
  378.  
  379. #undef STUFF_STRING
  380. #undef STUFF_NUMBER
  381. #undef STUFF_BOOL
  382.  
  383.     rv->data = new_obj;
  384.     rv->size = total_size;
  385.  
  386.     return(rv);
  387.  
  388. }
  389.  
  390. /* takes a database storage object and returns a malloc'd
  391.  * cache data object.  The cache object needs all of
  392.  * it's parts free'd.
  393.  *
  394.  * returns NULL on parse error 
  395.  */
  396. MODULE_PRIVATE net_CacheObject *
  397. net_DBDataToCacheStruct(DBT * db_obj)
  398. {
  399.     net_CacheObject * rv = XP_NEW(net_CacheObject);
  400.     char * cur_ptr;
  401.     char * max_ptr;
  402.     uint32 len;
  403.     int32 version;
  404.     SECItem seccert;
  405.  
  406.     if(!rv)
  407.         return NULL;
  408.  
  409.     XP_MEMSET(rv, 0, sizeof(net_CacheObject));
  410.  
  411. /* if any strings are larger than this then
  412.  * there was a serious database error
  413.  */
  414. #define MAX_HUGE_STRING_SIZE 10000
  415.  
  416. #define RETRIEVE_STRING(string)                    \
  417. {                                                \
  418.     if(cur_ptr > max_ptr)                       \
  419.       {                                             \
  420.         net_freeCacheObj(rv);                     \
  421.         return(NULL);                           \
  422.       }                                            \
  423.     COPY_INT32(&len, cur_ptr);                    \
  424.     cur_ptr += sizeof(int32);                    \
  425.     if(len)                                        \
  426.       {                                            \
  427.         if(len > MAX_HUGE_STRING_SIZE)            \
  428.           {                                         \
  429.             net_freeCacheObj(rv);                \
  430.             return(NULL);                        \
  431.           }                                        \
  432.         rv->string = (char*)XP_ALLOC(len);        \
  433.         if(!rv->string)                            \
  434.           {                                         \
  435.             net_freeCacheObj(rv);                \
  436.             return(NULL);                        \
  437.           }                                        \
  438.         XP_MEMCPY(rv->string, cur_ptr, len);    \
  439.         cur_ptr += len;                            \
  440.       }                                            \
  441. }                                            
  442.  
  443. #define RETRIEVE_NUMBER(number)                    \
  444. {                                                \
  445.     if(cur_ptr > max_ptr)                       \
  446.         return(rv);                             \
  447.     COPY_INT32(&rv->number, cur_ptr);            \
  448.     cur_ptr += sizeof(int32);                    \
  449. }
  450.  
  451. #define RETRIEVE_TIMET(number)                    \
  452. {                                                \
  453.     if(cur_ptr > max_ptr)                       \
  454.         return(rv);                             \
  455.     COPY_INT32(&rv->number, cur_ptr);            \
  456.     cur_ptr += sizeof(time_t);                    \
  457. }
  458.  
  459. #define RETRIEVE_BOOL(bool)                \
  460. {                                        \
  461.   if(cur_ptr > max_ptr)                 \
  462.     return(rv);                         \
  463.   if(((char *)(cur_ptr))[0])            \
  464.     rv->bool = TRUE;                    \
  465.   else                                     \
  466.     rv->bool = FALSE;                    \
  467.   cur_ptr += sizeof(char);                \
  468. }
  469.  
  470.     cur_ptr = (char *)db_obj->data;
  471.  
  472.     max_ptr = cur_ptr+db_obj->size;
  473.  
  474.     /* get the total size of the struct out of
  475.      * the first field to check it
  476.      */
  477.     COPY_INT32(&len, cur_ptr);
  478.     cur_ptr += sizeof(int32);
  479.  
  480.     if(len != db_obj->size)
  481.       {
  482.         TRACEMSG(("Size going in is not the same as size coming out"));
  483.         FREE(rv);
  484.         return(NULL);
  485.       }
  486.  
  487.     /* get the version number of the written structure
  488.      */
  489.     if(cur_ptr > max_ptr)
  490.         return(rv);
  491.     COPY_INT32(&version, cur_ptr);
  492.     cur_ptr += sizeof(int32);
  493.  
  494.     if(version != CACHE_FORMAT_VERSION)
  495.       {
  496.         TRACEMSG(("Version of cache structure is wrong!: %d", version));
  497.         FREE(rv);
  498.         return(NULL);
  499.       }
  500.  
  501.     RETRIEVE_TIMET(last_modified);
  502.     RETRIEVE_TIMET(last_accessed);
  503.     RETRIEVE_TIMET(expires);
  504.     RETRIEVE_NUMBER(content_length);
  505.     RETRIEVE_BOOL(is_netsite);
  506.  
  507.     RETRIEVE_TIMET(lock_date);
  508.  
  509.     RETRIEVE_STRING(filename);
  510.     RETRIEVE_NUMBER(filename_len);
  511.  
  512.     RETRIEVE_BOOL(is_relative_path);
  513.  
  514.     RETRIEVE_NUMBER(security_on);
  515.     RETRIEVE_NUMBER(key_size);
  516.     RETRIEVE_NUMBER(key_secret_size);
  517.     RETRIEVE_STRING(key_cipher);
  518.  
  519.     /* certificate length */
  520.     if(cur_ptr > max_ptr)
  521.         return(rv);
  522.     COPY_INT32(&len, cur_ptr);
  523.     cur_ptr += sizeof(int32);
  524.  
  525.     seccert.len = len;
  526.  
  527.     if ( len ) {
  528.         /* copy certificate */
  529.         if(cur_ptr > max_ptr)
  530.             return(rv);
  531.  
  532.         seccert.data = (unsigned char *)XP_ALLOC(len);
  533.         if ( !seccert.data )
  534.             return(rv);
  535.  
  536.         XP_MEMCPY(seccert.data, cur_ptr, len);
  537.         cur_ptr += len;
  538.  
  539. #ifndef EXT_DB_ROUTINES
  540.         rv->certificate = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
  541.                                                   &seccert, NULL, PR_FALSE,
  542.                                                   PR_TRUE);
  543.         XP_FREE(seccert.data);
  544. #endif
  545.     }
  546.  
  547.     RETRIEVE_NUMBER(method);
  548.  
  549. #ifdef STORE_ADDRESS_AND_POST_DATA
  550.  
  551.     RETRIEVE_STRING(address);
  552.     RETRIEVE_NUMBER(post_data_size);
  553.     
  554.     /* post_data 
  555.      * this is special since it not necessarily a string
  556.      */
  557.     if(rv->post_data_size)
  558.       {
  559.         rv->post_data = XP_ALLOC(rv->post_data_size+1);
  560.         if(rv->post_data)
  561.             XP_MEMCPY(rv->post_data, cur_ptr, rv->post_data_size+1);
  562.         cur_ptr += rv->post_data_size+1;
  563.       }
  564.  
  565. #endif /* STORE_ADDRESS_AND_POST_DATA */
  566.  
  567.     RETRIEVE_STRING(post_headers);
  568.  
  569.     RETRIEVE_STRING(content_type);
  570.     RETRIEVE_STRING(content_encoding);
  571.     RETRIEVE_STRING(charset);
  572.  
  573.     RETRIEVE_BOOL(incomplete_file);
  574.     RETRIEVE_NUMBER(real_content_length);
  575.  
  576.     RETRIEVE_STRING(page_services_url);
  577. #undef RETRIEVE_STRING
  578. #undef RETRIEVE_NUMBER
  579. #undef RETRIEVE_BOOL
  580.  
  581.     return(rv);
  582. }
  583.  
  584. #if defined(DEBUG) && defined(UNIX)
  585. int
  586. cache_test_me()
  587. {
  588.  
  589.     net_CacheObject test;
  590.     net_CacheObject *rv;
  591.     int32 total_size;
  592.     DBT *db_obj;
  593.  
  594.     XP_MEMSET(&test, 0, sizeof(net_CacheObject));
  595.     StrAllocCopy(test.address, "test1");
  596.     db_obj = net_CacheStructToDBData(&test);
  597.     rv = net_DBDataToCacheStruct(db_obj);
  598.     printf("test1: %s\n", rv->address);
  599.  
  600.     XP_MEMSET(&test, 0, sizeof(net_CacheObject));
  601.     StrAllocCopy(test.address, "test2");
  602.     StrAllocCopy(test.charset, "test2");
  603.     db_obj = net_CacheStructToDBData(&test);
  604.     rv = net_DBDataToCacheStruct(db_obj);
  605.     printf("test2: %s    %s\n", rv->address, rv->charset);
  606.  
  607.     XP_MEMSET(&test, 0, sizeof(net_CacheObject));
  608.     StrAllocCopy(test.address, "test3");
  609.     StrAllocCopy(test.charset, "test3");
  610.     StrAllocCopy(test.key_cipher, "test3");
  611.     test.content_length = 3 ;
  612.     test.method = 3 ;
  613.     test.is_netsite = 3 ;
  614.     db_obj = net_CacheStructToDBData(&test);
  615.     rv = net_DBDataToCacheStruct(db_obj);
  616.     printf("test3: %s    %s    %s    %d    %d    %s\n", 
  617.             rv->address, rv->charset, rv->key_cipher,
  618.             rv->content_length, rv->method, 
  619.             (rv->is_netsite == 3 ? "TRUE" : "FALSE"));
  620.  
  621. }
  622. #endif
  623.  
  624. /* generates a key for use in the cache database
  625.  * from a CacheObject struct
  626.  * 
  627.  * Key is based on the address and the post_data
  628.  *
  629.  * looks like:
  630.  *  size checksum | size of address | ADDRESS | size of post data | POST DATA
  631.  */
  632. MODULE_PRIVATE DBT *
  633. net_GenCacheDBKey(char *address, char *post_data, int32 post_data_size)
  634. {
  635.     DBT *rv = XP_NEW(DBT);
  636.     char *hash;
  637.     char *data_ptr;
  638.     int32 str_len;
  639.     int32 size;
  640.  
  641. #define MD5_HASH_SIZE 16 /* always 16 due to md5 hash type */
  642.     
  643.     if(!rv)
  644.         return(NULL);
  645.     
  646.     if(!address)
  647.       {
  648.         XP_ASSERT(0);
  649.         rv->size = 0;
  650.         return(rv);
  651.       } 
  652.  
  653.     hash = XP_STRCHR(address, '#');
  654.  
  655.     /* don't include '#' in a key */
  656.     if(hash)
  657.         *hash = '\0';
  658.  
  659.     str_len = XP_STRLEN(address)+1;
  660.  
  661.     size  = sizeof(int32);  /* for check sum */
  662.     size += sizeof(int32);  /* for size of address */
  663.     size += str_len;        /* for address string */
  664.     size += sizeof(int32);  /* for size of post_data */
  665.  
  666.     if(post_data_size)
  667.         size += MD5_HASH_SIZE;
  668.  
  669.     rv->size = size;
  670.     rv->data = XP_ALLOC(size);
  671.  
  672.     if(!rv->data)
  673.       {
  674.         FREE(rv);
  675.         return NULL;
  676.       }
  677.  
  678.     data_ptr = (char *) rv->data;
  679.  
  680.     /* put in the checksum size */
  681.     COPY_INT32(data_ptr, &size);
  682.     data_ptr = data_ptr + sizeof(int32);
  683.     
  684.     /* put in the size of the address string */
  685.     COPY_INT32(data_ptr, &str_len);
  686.     data_ptr = data_ptr + sizeof(int32);
  687.  
  688.     /* put in the address string data */
  689.     XP_MEMCPY(data_ptr, address, str_len);
  690.     data_ptr = data_ptr + str_len;
  691.  
  692.     /* set the address back to it's original form */
  693.     if(hash)
  694.         *hash = '#';
  695.  
  696.     /* put in the size of the post data */
  697.     if(post_data_size)
  698.       {
  699.         int32 size_of_md5 = MD5_HASH_SIZE;
  700.         unsigned char post_data_hash[MD5_HASH_SIZE];
  701.  
  702.         MD5_HashBuf(post_data_hash, (unsigned char*)post_data, post_data_size);
  703.  
  704.         COPY_INT32(data_ptr, &size_of_md5);
  705.         data_ptr = data_ptr + sizeof(int32);
  706.  
  707.         /* put in the post data if there is any */
  708.         XP_MEMCPY(data_ptr, post_data_hash, sizeof(post_data_hash));
  709.       }
  710.     else
  711.       {
  712.         COPY_INT32(data_ptr, &post_data_size);
  713.         data_ptr = data_ptr + sizeof(int32);
  714.       }
  715.  
  716.     return(rv);
  717. }
  718.  
  719. /* returns a static string that contains the
  720.  * URL->address of the key
  721.  * 
  722.  * returns NULL on error
  723.  */
  724. MODULE_PRIVATE char *
  725. net_GetAddressFromCacheKey(DBT *key)
  726. {
  727.     uint32 size;
  728.     char *data;
  729.  
  730.     /* check for minimum size */
  731.     if(key->size < 10)
  732.         return(NULL);
  733.  
  734.     /* validate size checksum */
  735.     data = (char *)key->data;
  736.     COPY_INT32(&size, data);
  737.     data += sizeof(int32);
  738.  
  739.     if(size != key->size)
  740.         return(NULL);
  741.  
  742.     /* get size of address string */
  743.     COPY_INT32(&size, data);
  744.     data += sizeof(int32);
  745.  
  746.     /* make sure it's a valid c string */
  747.     if(data[size] != '\0')
  748.         return(NULL);
  749.         
  750.     /* it's valid return it */
  751.     return(data);
  752. }
  753.  
  754.  
  755. /* checks a date within a DBT struct so
  756.  * that we don't have to convert it into a CacheObject
  757.  *
  758.  * This works because of the fixed length record format
  759.  * of the first part of the specific DBT format I'm
  760.  * using
  761.  * 
  762.  * returns 0 on error
  763.  */
  764. MODULE_PRIVATE time_t 
  765. net_GetTimeInCacheDBT(DBT *data, int byte_position)
  766. {
  767.     time_t date;
  768.     char *ptr = (char *)data->data;
  769.  
  770.     if(data->size < byte_position+sizeof(time_t))
  771.         return(0);
  772.  
  773.     if(!net_IsValidCacheDBT(data))
  774.         return(0);
  775.  
  776.     COPY_INT32(&date, ptr+byte_position);
  777.  
  778.     /* TRACEMSG(("Got date from cache DBT: %d", date)); */
  779.     
  780.     return(date);
  781.  
  782. }
  783.  
  784. /* Sets a date within a DBT struct so
  785.  * that we don't have to convert it into a CacheObject
  786.  *
  787.  * This works because of the fixed length record format
  788.  * of the first part of the specific DBT format I'm
  789.  * using
  790.  * 
  791.  * returns 0 on error
  792.  */
  793. MODULE_PRIVATE void
  794. net_SetTimeInCacheDBT(DBT *data, int byte_position, time_t date)
  795. {
  796.     char *ptr = (char *)data->data;
  797.  
  798.     if(data->size < byte_position+sizeof(time_t))
  799.         return;
  800.  
  801.     if(!net_IsValidCacheDBT(data))
  802.         return;
  803.  
  804.     COPY_INT32(ptr+byte_position, &date);
  805.  
  806.     return;
  807.  
  808. }
  809.  
  810. /* Gets the filename within a cache DBT struct so
  811.  * that we don't have to convert it into a CacheObject
  812.  *
  813.  * This works because of the fixed length record format
  814.  * of the first part of the specific DBT format I'm
  815.  * using
  816.  *
  817.  * returns NULL on error
  818.  */
  819. #define MAX_FILE_SIZE 2048
  820. MODULE_PRIVATE char *
  821. net_GetFilenameInCacheDBT(DBT *data)
  822. {
  823.     int32 size;
  824.     char *rv;
  825.     char *ptr = (char*)data->data;
  826.  
  827.     if(data->size < FILENAME_BYTE_POSITION)
  828.         return(NULL);
  829.  
  830.     if(!net_IsValidCacheDBT(data))
  831.         return(0);
  832.  
  833.     COPY_INT32(&size, ptr+FILENAME_SIZE_BYTE_POSITION);
  834.  
  835.     if(data->size < FILENAME_BYTE_POSITION+size 
  836.         || size > MAX_FILE_SIZE)
  837.         return(NULL);
  838.  
  839.     rv = (char *)XP_ALLOC(size);
  840.     if(!rv)
  841.         return(NULL);
  842.     XP_MEMCPY(rv, ptr+FILENAME_BYTE_POSITION, size);
  843.  
  844.     TRACEMSG(("Got filename: %s from DBT", rv));
  845.  
  846.     return(rv);
  847. }
  848.  
  849. /* Gets a int32 within a DBT struct so
  850.  * that we don't have to convert it into a CacheObject
  851.  *
  852.  * This works because of the fixed length record format
  853.  * of the first part of the specific DBT format I'm
  854.  * using
  855.  *
  856.  * returns 0 on error
  857.  */
  858. MODULE_PRIVATE time_t
  859. net_GetInt32InCacheDBT(DBT *data, int byte_position)
  860. {
  861.     int32 num;
  862.     char *ptr = (char *)data->data;
  863.  
  864.     if(!net_IsValidCacheDBT(data))
  865.         return(0);
  866.  
  867.     if(data->size < byte_position+sizeof(time_t))
  868.         return(0);
  869.  
  870.     COPY_INT32(&num, ptr+byte_position);
  871.  
  872.     /* TRACEMSG(("Got int32 from cache DBT: %d", num)); */
  873.    
  874.     return(num);
  875.  
  876. }
  877.  
  878. MODULE_PRIVATE void
  879. net_FreeCacheDBTdata(DBT *stuff)
  880. {
  881.     if(stuff)
  882.       {
  883.         FREE(stuff->data);
  884.         FREE(stuff);
  885.       }
  886. }
  887.  
  888. /* takes a database storage object and returns an un-malloc'd
  889.  * cache data object. The structure returned has pointers
  890.  * directly into the database memory and are only valid
  891.  * until the next call to any database function
  892.  *
  893.  * do not free anything returned by this structure
  894.  */
  895. MODULE_PRIVATE net_CacheObject *
  896. net_Fast_DBDataToCacheStruct(DBT *obj)
  897. {
  898.     static net_CacheObject *rv=0;
  899.  
  900.     /* free any previous one */
  901.     if(rv)
  902.         net_freeCacheObj(rv);
  903.  
  904.     rv = net_DBDataToCacheStruct(obj);
  905.  
  906.     return(rv);
  907.  
  908. }
  909.  
  910. #endif /* MOZILLA_CLIENT */
  911.