home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / modules / rdf / src / hist2rdf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  17.1 KB  |  605 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. /* 
  20.    This file implements History support for the rdf data model.
  21.    For more information on this file, contact rjc or guha 
  22.    For more information on RDF, look at the RDF section of www.mozilla.org
  23. */
  24.  
  25. #include "hist2rdf.h"
  26. #include "remstore.h"
  27.  
  28.  
  29.     /* extern declarations */
  30. void GH_DeleteHistoryItem (char * url);
  31. PR_PUBLIC_API(void) updateNewHistItem (DBT *key, DBT *data);    /* XXX this should be elsewhere */
  32.  
  33.  
  34.     /* externs */
  35. extern    char    *profileDirURL;
  36. extern    char    *gGlobalHistoryURL;
  37.  
  38.  
  39.     /* external string references in allxpstr */
  40. extern    int    RDF_WEEKOF, RDF_WITHINLASTHOUR, RDF_TODAY, RDF_DAY_0;
  41. extern    int    RDF_RELATEDLINKSNAME;
  42.  
  43.  
  44.     /* globals */
  45. PLHashTable     *hostHash = 0;
  46. RDF grdf = NULL;
  47. RDFT gHistoryStore = 0;
  48. PRBool ByDateOpened = 0;
  49.  
  50.  
  51.  
  52. char    *prefixList[] = {
  53.     "about:", "javascript:", "livescript:", "mailbox:", "mailto:",
  54.     "mocha:", "news:", "pop3", "snews:", "view-source", "wysiwyg:", NULL
  55.     };
  56.  
  57. char    *suffixList[] = {
  58.     ".gif", ".jpg", ".jpeg", ".xbm", ".pfr", ".class", ".tmp", ".js", ".rdf", 
  59.     ".mcf", ".mco", NULL
  60.     };
  61.  
  62. char   *intermediateList[] = {
  63.         ".gif", ".GIF",  NULL
  64.     };
  65.  
  66.  
  67.  
  68. void
  69. collateHistory (RDF r, RDF_Resource u, PRBool byDateFlag)
  70. {
  71.   HASHINFO hash = { 4*1024, 0, 0, 0, 0, 0};
  72.   DBT key, data;
  73.   time_t    last,first,numaccess;
  74.   PRBool firstOne = 0;
  75.   DB* db = CallDBOpenUsingFileURL(gGlobalHistoryURL,  O_RDONLY ,0600,
  76.                                   DB_HASH, &hash);
  77.   grdf = r;
  78.   if (db != NULL)    {
  79.     if (!byDateFlag) {
  80.       hostHash = PL_NewHashTable(500, idenHash, PL_CompareValues,  PL_CompareValues,  null, null);
  81.     } else ByDateOpened = 1;
  82.     while (0 ==   (*db->seq)(db, &key, &data, (firstOne ? R_NEXT : R_FIRST))) {
  83.       char* title =    ((char*)data.data + 16);                /* title */
  84.       char* url =      (char*)key.data;                       /* url */
  85.       int32 flag = (int32)*((char*)data.data + 3*sizeof(int32));
  86.       firstOne = 1;
  87. #ifdef XP_UNIX
  88.       if ((/*1 == flag &&*/ displayHistoryItem((char*)key.data))) {
  89. #else
  90.       if (1 == flag && displayHistoryItem((char*)key.data)) {
  91. #endif
  92.     COPY_INT32(&last, (time_t *)((char *)data.data));
  93.     COPY_INT32(&first, (time_t *)((char *)data.data + 4));
  94.     COPY_INT32(&numaccess, (time_t *)((char *)data.data + 8));
  95.  
  96.     collateOneHist(r, u,url,title, last, first, numaccess, byDateFlag);
  97.       }
  98.     }
  99.     (*db->close)(db);
  100.   }
  101. }
  102.  
  103.  
  104.  
  105. void
  106. collateOneHist (RDF r, RDF_Resource u, char* url, char* title, time_t lastAccessDate,
  107.         time_t firstAccessDate, uint32 numAccesses, PRBool byDateFlag)
  108. {
  109.   RDF_Resource        hostUnit, urlUnit;
  110.   char* existingName = NULL;
  111.   if (startsWith("404", title)) return;
  112.   urlUnit  = HistCreate(url, 1);
  113.   existingName = nlocalStoreGetSlotValue(gLocalStore, urlUnit, gCoreVocab->RDF_name, RDF_STRING_TYPE, 0, 1);
  114.   if (existingName == NULL) {
  115.   if (title[0] != '\0')  remoteAddName(urlUnit, title);      
  116.   } else freeMem(existingName);
  117.   if (byDateFlag) {
  118.     hostUnit = hostUnitOfDate(r, u, lastAccessDate);
  119.   } else {
  120.     hostUnit = hostUnitOfURL(r, u, urlUnit, title); 
  121.   }
  122.   
  123.   if (hostUnit == NULL) return;
  124.  
  125.   
  126.   if (hostUnit != urlUnit) remoteAddParent(urlUnit, hostUnit);
  127.   remoteStoreAdd(gRemoteStore, urlUnit, gWebData->RDF_lastVisitDate,
  128.          (void *)lastAccessDate, RDF_INT_TYPE, 1);
  129.   remoteStoreAdd(gRemoteStore, urlUnit, gWebData->RDF_firstVisitDate,
  130.          (void *)firstAccessDate, RDF_INT_TYPE, 1);
  131.   if (numAccesses==0)    ++numAccesses;
  132.   remoteStoreAdd(gRemoteStore, urlUnit, gWebData->RDF_numAccesses,
  133.          (void *)numAccesses, RDF_INT_TYPE, 1);
  134. }
  135.  
  136.  
  137.  
  138. RDF_Resource
  139. hostUnitOfURL (RDF r, RDF_Resource top, RDF_Resource nu, char* title)
  140. {
  141.   char host[100];
  142.   char* url =  resourceID(nu);
  143.   int16 s1, s2, s3;
  144.   RDF_Resource hostResource, existing;
  145.   if (strlen(url) > 100) return NULL;
  146.   if (startsWith("file", url)) {
  147.     return RDF_GetResource(NULL, "Local Files", 1);
  148.   } else { 
  149.     memset(host, '\0', 100);
  150.     s1 = charSearch(':', url)+3;
  151.     s2 = charSearch('/', &url[s1]);
  152.     s3 = charSearch(':', &url[s1]);
  153.     if (s2 == -1) s2 = strlen(url)-s1;
  154.     if ((s3 != -1) && (s2 > s3)) s2 = s3;
  155.     if (startsWith("www", &url[s1])) {s1 = s1+4; s2 = s2-4;}
  156.     if (s2<1) return(NULL);
  157.     memcpy((char*)host, &url[s1], s2);
  158.     host[0] = toupper(host[0]);
  159.     hostResource = RDF_GetResource(NULL, host, 1);
  160.     setContainerp(hostResource, 1);
  161.     setResourceType(hostResource, HISTORY_RT);
  162.     existing = PL_HashTableLookup(hostHash, hostResource);
  163.     if (existing != NULL) {
  164.       if (existing == nu) {
  165.     return existing;
  166.       } else if (existing == top) {
  167.     return hostResource;
  168.       } else {
  169.     remoteStoreRemove(gRemoteStore, existing, gCoreVocab->RDF_parent, top, RDF_RESOURCE_TYPE);
  170.     histAddParent(existing, hostResource);
  171.     histAddParent(hostResource, top);
  172.     PL_HashTableAdd(hostHash, hostResource, top);
  173.     return hostResource;
  174.       }
  175.     } else {
  176.     PL_HashTableAdd(hostHash, hostResource, nu);
  177.     histAddParent(nu, top);
  178.     return nu;
  179.     }
  180.   }
  181. }
  182.  
  183.  
  184.  
  185. void
  186. hourRange(char *buffer, struct tm *theTm)
  187. {
  188.     char        *startHourStr="AM",*endHourStr="AM";
  189.  
  190.     if (theTm->tm_hour > 0 && theTm->tm_hour < 12) {
  191.       sprintf(buffer, "AM");
  192.     } else  {
  193.       sprintf(buffer, "PM");
  194.     } 
  195. }
  196.  
  197.  
  198.  
  199. RDF_Resource
  200. hostUnitOfDate (RDF r, RDF_Resource u, time_t lastAccessDate)
  201. {
  202.     RDF_Resource        node = NULL, parentNode;
  203. /*
  204.     RDF_Resources        std;
  205. */
  206.     time_t            now, tempTime;
  207.     struct tm        *T,nowStruct, dateStruct;
  208.     char            hourBuffer[128], dayBuffer[128], weekBuffer[128];
  209.     char            bigBuffer[1024];
  210.     int            numDays;
  211.  
  212.     /* NOTE: localtime uses a single static buffer, so MUST copy contents out */
  213.  
  214.     time((time_t *)&now);
  215.     if ((T = localtime(&now)) == NULL)    return(NULL);
  216.     nowStruct = *T;
  217.  
  218.     if ((T = localtime(&lastAccessDate)) == NULL)    return(NULL);
  219.     dateStruct = *T;
  220.  
  221.     bigBuffer[0] = hourBuffer[0] = dayBuffer[0] = weekBuffer[0] = 0;
  222.  
  223.     if (now < (lastAccessDate + SECS_IN_HOUR))        /* within the last hour */
  224.     {
  225.         strcpy(hourBuffer, XP_GetString(RDF_WITHINLASTHOUR));
  226.     }
  227.     else if ((nowStruct.tm_year == dateStruct.tm_year) &&    /* some time today */
  228.         (nowStruct.tm_yday == dateStruct.tm_yday))
  229.     {
  230.         strcpy(dayBuffer, XP_GetString(RDF_TODAY));
  231.         hourRange(hourBuffer, &dateStruct);
  232.     }
  233.     else                            /* check if within last week */
  234.     {
  235.         numDays = 7;
  236.         do
  237.         {
  238.             now -= SECS_IN_DAY;
  239.             if ((T = localtime(&now)) == NULL)    return(NULL);
  240.             nowStruct = *T;
  241.             if ((nowStruct.tm_year == dateStruct.tm_year) &&
  242.                 (nowStruct.tm_yday == dateStruct.tm_yday))
  243.             {
  244.                 sprintf(dayBuffer, "%d/%d - %s",
  245.                     (uint) dateStruct.tm_mon + 1,    (uint)dateStruct.tm_mday,
  246.                     XP_GetString(RDF_DAY_0 + nowStruct.tm_wday));
  247.                 hourRange(hourBuffer, &dateStruct);
  248.                 break;
  249.             }
  250.         } while (numDays-- > 0);
  251.  
  252.         if (dayBuffer[0] == '\0')                /* older than a week */
  253.         {
  254.             tempTime = lastAccessDate;
  255.             numDays = dateStruct.tm_wday;
  256.             while (numDays-- > 0)
  257.             {
  258.                 tempTime -= SECS_IN_DAY;
  259.             }
  260.             if ((T = localtime(&tempTime)) == NULL)    return(NULL);
  261.             dateStruct = *T;
  262. #ifdef    XP_MAC
  263.             /* Mac epoch according to localtime is 1904 */
  264.             PR_snprintf(weekBuffer, sizeof(weekBuffer)-1, XP_GetString(RDF_WEEKOF), (uint)dateStruct.tm_mon + 1,
  265.                 (int)dateStruct.tm_mday, (uint)dateStruct.tm_year + 1904);
  266. #else
  267.             PR_snprintf(weekBuffer, sizeof(weekBuffer)-1, XP_GetString(RDF_WEEKOF), (uint)dateStruct.tm_mon + 1,
  268.                 (int)dateStruct.tm_mday, (uint)dateStruct.tm_year + 1900);
  269. #endif
  270.  
  271.             if ((T = localtime(&lastAccessDate)) == NULL)    return(NULL);
  272.             dateStruct = *T;
  273.  
  274. #ifdef    XP_MAC
  275.             /* Mac epoch according to localtime is 1904 */
  276.             sprintf(dayBuffer, "%s - %d/%d/%d",
  277.                 XP_GetString(RDF_DAY_0 + dateStruct.tm_wday), (uint) dateStruct.tm_mon + 1,
  278.                 (uint)dateStruct.tm_mday, (uint)dateStruct.tm_year + 1904);
  279. #else
  280.             sprintf(dayBuffer, "%s - %d/%d/%d",
  281.                 XP_GetString(RDF_DAY_0 + dateStruct.tm_wday), (uint) dateStruct.tm_mon + 1,
  282.                 (uint)dateStruct.tm_mday, (uint)dateStruct.tm_year + 1900);
  283. #endif
  284.             hourRange(hourBuffer, &dateStruct);
  285.         }
  286.     }
  287.     parentNode = u;
  288.  
  289.     if (weekBuffer[0] != '\0')
  290.     {
  291.         if ((node = RDF_GetResource(NULL, weekBuffer, false)) == NULL)
  292.         {
  293.             if ((node = RDF_GetResource(NULL, weekBuffer, true)) == NULL)    return(NULL);
  294.         }
  295.         setContainerp(node, 1);
  296.         setResourceType(node, HISTORY_RT);
  297.         remoteStoreAdd(gRemoteStore, node, gCoreVocab->RDF_parent,
  298.                 parentNode, RDF_RESOURCE_TYPE, 1);
  299.         remoteStoreAdd(gRemoteStore, node, gCoreVocab->RDF_name,
  300.                 copyString(weekBuffer), RDF_STRING_TYPE, 1);
  301.         parentNode = node;
  302.     }
  303.     if (dayBuffer[0] != '\0')
  304.     {
  305.       sprintf(bigBuffer, "%d/%d",  (uint) dateStruct.tm_mon + 1,
  306.           (uint)dateStruct.tm_mday);
  307.  
  308.  
  309.         if ((node = RDF_GetResource(NULL, bigBuffer, false)) == NULL)
  310.         {
  311.             if ((node = RDF_GetResource(NULL, bigBuffer, true)) == NULL)    return(NULL);
  312.         }
  313.         setContainerp(node, 1);
  314.         setResourceType(node, HISTORY_RT);
  315.         histAddParent(node, parentNode);
  316.         sprintf(bigBuffer,"%s - %s",weekBuffer,dayBuffer);
  317.         remoteStoreAdd(gRemoteStore, node, gCoreVocab->RDF_name,
  318.                 copyString(dayBuffer), RDF_STRING_TYPE, 1);
  319.         parentNode = node;
  320.     }
  321.     if (hourBuffer[0] == 'W')
  322.     {
  323.         sprintf(bigBuffer, "%s", hourBuffer);
  324.  
  325.         if ((node = RDF_GetResource(NULL, bigBuffer, false)) == NULL)
  326.         {
  327.             if ((node = RDF_GetResource(NULL, bigBuffer, true)) == NULL)    return(NULL);
  328.         }
  329.         setContainerp(node, 1);
  330.         setResourceType(node, HISTORY_RT);
  331.         remoteStoreAdd(gRemoteStore, node, gCoreVocab->RDF_parent,
  332.                 parentNode, RDF_RESOURCE_TYPE, 1);
  333.         remoteStoreAdd(gRemoteStore, node, gCoreVocab->RDF_name,
  334.                 copyString(hourBuffer), RDF_STRING_TYPE, 1);
  335.         parentNode = node;
  336.     }
  337.     return (node);
  338. }
  339.  
  340.  
  341.  
  342. void
  343. deleteCurrentSitemaps (char *address)
  344. {
  345.   RDF_Resource          children[40];
  346.   int16                n = 0;
  347.   RDF_Cursor c = remoteStoreGetSlotValues(gRemoteStore, gNavCenter->RDF_Sitemaps, gCoreVocab->RDF_parent, 
  348.                 RDF_RESOURCE_TYPE,1, 1);
  349.   RDF_Resource child;
  350.   while (c && (child = remoteStoreNextValue(gRemoteStore, c))) {
  351.     children[n++] = child;
  352.   }
  353.   remoteStoreDisposeCursor(gRemoteStore, c);
  354.   n--;
  355.   while (n > -1) {
  356.     remoteStoreRemove(gRemoteStore, children[n--], 
  357.               gCoreVocab->RDF_parent, gNavCenter->RDF_Sitemaps, RDF_RESOURCE_TYPE);
  358.   }
  359. }
  360.  
  361.  
  362.  
  363. PR_PUBLIC_API(void)
  364. updateNewHistItem (DBT *key, DBT *data)
  365. {
  366.   time_t    last,first,numaccess;
  367.   int32 flg = (int32)*((char*)data->data + 3*sizeof(int32));
  368.   if (!displayHistoryItem((char*)key->data)) return;
  369.   if (grdf != NULL) {
  370.     COPY_INT32(&last, (time_t *)((char *)data->data));
  371.     COPY_INT32(&first, (time_t *)((char *)data->data + 4));
  372.     COPY_INT32(&numaccess, (time_t *)((char *)data->data + 8));
  373.     
  374.     if (hostHash) collateOneHist(grdf, gNavCenter->RDF_HistoryBySite, 
  375.                  (char*)key->data,                        /* url */
  376.                  ((char*)data->data + 16),                /* title */
  377.                  last, first, numaccess, 0);
  378.     if (ByDateOpened) collateOneHist(grdf, gNavCenter->RDF_HistoryByDate, 
  379.                      (char*)key->data,                        /* url */
  380.                      ((char*)data->data + 16),                /* title */
  381.                      last, first, numaccess, 1);
  382.   }
  383.  
  384. }
  385.  
  386.  
  387.  
  388. /** History clustering utils **/
  389.  
  390.  
  391.  
  392. PRBool
  393. displayHistoryItem (char* url)
  394. {
  395.   int            x;
  396.   x=0;
  397.   while (prefixList[x]) {
  398.     if (startsWith(prefixList[x++], url))   return 0;
  399.   }
  400.   x=0;
  401.   while (suffixList[x]) {
  402.     if (endsWith(suffixList[x++], url))     return 0;
  403.   }
  404.   x=0;
  405.   while (intermediateList[x]) {
  406.     if (strstr(url, intermediateList[x++])) return 0;
  407.   }
  408.   return 1;
  409. }
  410.  
  411.  
  412.  
  413. RDF_Resource
  414. HistCreate (char* url, PRBool createp)
  415. {
  416.   size_t size = strlen(url);
  417.   char* nurl = getMem(size+8);
  418.   RDF_Resource ans;
  419.   if (charSearch(':', url) == -1) {    
  420.     if (url[size-1] == '/') {
  421.       sprintf(nurl, "http://%s", url);
  422.       nurl[strlen(nurl)-1] = '\0';
  423.     } else {
  424.     sprintf(nurl, "http://%s/", url);
  425.     }
  426.   } else {
  427.     if (url[size-1] == '/') {
  428.       memcpy(nurl, url, size-1);
  429.     } else {
  430.       sprintf(nurl, "%s/", url);
  431.     }
  432.   }
  433.   ans = RDF_GetResource(NULL, nurl, 0);
  434.   if (ans != NULL) {
  435.     freeMem(nurl);
  436.     return ans;
  437.   } 
  438.   freeMem(nurl);
  439.   ans = RDF_GetResource(NULL, url, createp);
  440.  
  441.   if (ans != NULL) {
  442.     return ans;
  443.   } else {
  444.     return NULL;
  445.   }
  446. }
  447.  
  448.  
  449.  
  450. Assertion
  451. histAddParent (RDF_Resource child, RDF_Resource parent)
  452. {
  453.   Assertion nextAs, prevAs, newAs; 
  454.   RDF_Resource s = gCoreVocab->RDF_parent;
  455.   RDF_ValueType type = RDF_RESOURCE_TYPE;
  456.   nextAs = prevAs = child->rarg1;
  457.   while (nextAs != null) {
  458.     if (asEqual(nextAs, child, s, parent, type)) return null;
  459.     prevAs = nextAs;
  460.     nextAs = nextAs->next;
  461.   }
  462.   newAs = makeNewAssertion(child, s, parent, type, 1);
  463.   if (prevAs == null) {
  464.     child->rarg1 = newAs;
  465.   } else {
  466.     prevAs->next = newAs;
  467.   }
  468.   nextAs = prevAs = parent->rarg2;
  469.   if (nextAs == NULL) {
  470.     parent->rarg2 = newAs;
  471.   } else {
  472.     PRBool added = 0;
  473.     while (nextAs != null) {
  474.         char* nid =  resourceID(nextAs->u);
  475.       if (strcmp( resourceID(child),  resourceID(nextAs->u)) > 0) {
  476.     if (prevAs == nextAs) {
  477.       newAs->invNext = prevAs;
  478.       parent->rarg2  = newAs;
  479.       added = 1;
  480.       break;
  481.       } else {
  482.         newAs->invNext = nextAs;        
  483.         prevAs->invNext = newAs;
  484.         added = 1;
  485.         break;
  486.       }
  487.       } 
  488.       prevAs = nextAs;
  489.       nextAs = nextAs->invNext;
  490.     }
  491.     if (!added) prevAs->invNext = newAs;
  492.   }
  493.   sendNotifications2(gHistoryStore, RDF_ASSERT_NOTIFY, child, s, parent, type, 1);
  494.   /* XXX have to mark the entire subtree XXX */
  495.   /*  sendNotifications(gRemoteStore->rdf, RDF_ASSERT_NOTIFY, child, s, parent, type, 1); */
  496. }
  497.  
  498.  
  499.  
  500. PRBool
  501. historyUnassert (RDFT hst,  RDF_Resource u, RDF_Resource s, void* v, 
  502.                RDF_ValueType type)
  503. {
  504.   if ((type == RDF_RESOURCE_TYPE) && (resourceType((RDF_Resource)v) == HISTORY_RT) &&
  505.       (s == gCoreVocab->RDF_parent)) {
  506.     RDF_Resource parents[5];
  507.     int8 n = 0;
  508.     Assertion as = u->rarg1;
  509.     memset(parents, '\0', 5 * sizeof(RDF_Resource));
  510.     while (as) {
  511.       if ((as->type == RDF_RESOURCE_TYPE) && (as->s == gCoreVocab->RDF_parent) && 
  512.       (resourceType((RDF_Resource)as->value) == HISTORY_RT) && (n < 5)) {
  513.     parents[n++] = (RDF_Resource)as->value;
  514.       }
  515.       as = as->next;
  516.     }
  517.     GH_DeleteHistoryItem ( resourceID(u));
  518.     while (n > 0) {
  519.         n = n - 1;
  520.         if (parents[n]) {
  521.             Assertion nas = remoteStoreRemove (gRemoteStore, u, gCoreVocab->RDF_parent, 
  522.                  parents[n], RDF_RESOURCE_TYPE);
  523.             freeMem(nas);
  524.         } 
  525.     }
  526.     return 1;
  527.   }
  528.   return 0;
  529. }
  530.  
  531.  
  532.  
  533. RDF_Cursor
  534. historyStoreGetSlotValuesInt (RDFT mcf, RDF_Resource u, RDF_Resource s, RDF_ValueType type,  
  535.                      PRBool inversep, PRBool tv)
  536. {
  537.     if ((type == RDF_RESOURCE_TYPE) && (resourceType(u) == HISTORY_RT) && inversep &&
  538.     (s == gCoreVocab->RDF_parent)) {
  539.       return remoteStoreGetSlotValuesInt(mcf, u, s, type, inversep, tv);
  540.     } else {
  541.       return NULL;
  542.     }
  543. }
  544.  
  545.  
  546.  
  547. PRBool
  548. historyStoreHasAssertion (RDFT mcf, RDF_Resource u, RDF_Resource s, void* v, RDF_ValueType type, PRBool tv)
  549. {
  550.   if ((s == gCoreVocab->RDF_parent) && (type == RDF_RESOURCE_TYPE) && (resourceType((RDF_Resource)v) == HISTORY_RT))
  551.     {
  552.       remoteStoreHasAssertionInt(mcf, u, s, v, type, tv);
  553.     } else {
  554.       return 0;
  555.     }
  556. }
  557.  
  558.  
  559.  
  560. RDFT
  561. MakeHistoryStore (char* url)
  562. {
  563.   if (startsWith("rdf:history", url)) {
  564.     if (gHistoryStore == 0) {
  565.       RDFT ntr = (RDFT)getMem(sizeof(struct RDF_TranslatorStruct));
  566.       ntr->assert = NULL;
  567.       ntr->unassert = historyUnassert;
  568.       ntr->getSlotValue = remoteStoreGetSlotValue;
  569.       ntr->getSlotValues = historyStoreGetSlotValuesInt;
  570.       ntr->hasAssertion = historyStoreHasAssertion;
  571.       ntr->nextValue = remoteStoreNextValue;
  572.       ntr->disposeCursor = remoteStoreDisposeCursor;
  573.       gHistoryStore = ntr;
  574.       ntr->url = copyString(url);
  575.       return ntr;
  576.     } else return gHistoryStore;
  577.   } else return NULL;
  578. }
  579.  
  580.  
  581.  
  582.  
  583. void
  584. dumpHist ()
  585. {
  586.   FILE *fp = fopen("history.txt", "w");
  587.   HASHINFO hash = { 4*1024, 0, 0, 0, 0, 0};
  588.   DBT key, data;
  589.   PRBool firstOne = 0;
  590.   DB* db = CallDBOpenUsingFileURL(gGlobalHistoryURL,  O_RDONLY ,0600,
  591.                                   DB_HASH, &hash);
  592.  
  593.   if (db != NULL)    {
  594.     while (0 ==   (*db->seq)(db, &key, &data, (firstOne ? R_NEXT : R_FIRST))) {
  595.       firstOne = 1;
  596.       if ((1 == (int32)*((char*)data.data + 3*sizeof(uint32)) && 
  597.        displayHistoryItem((char*)key.data))) {
  598.     fprintf(fp, "%s\n", (char*)key.data);
  599.       }
  600.     }
  601.   }
  602.   fclose(fp);
  603.   (*db->close)(db);
  604. }
  605.