Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

557 lines
12 KiB

/*
Enhanced NCSA Mosaic from Spyglass
"Guitar"
Copyright 1994 Spyglass, Inc.
All Rights Reserved
Author(s):
Eric W. Sink [email protected]
Jim Seidman [email protected]
Scott Piette [email protected]
*/
#include "all.h"
far struct hash_table gGlobalHistory;
extern void GTR_RefreshHistory(void);
#ifdef FEATURE_OPTIONS_MENU
struct hash_table gSessionHistory;
#endif
static BOOL bGHistLoading;
static int GHist_Add_NoSession(char *url, char *title, time_t tm);
#define TITLE_LEN 512
struct _HTStructured
{
CONST HTStructuredClass *isa;
CONST SGML_dtd *dtd;
BOOL bInAnchor;
char href[MAX_URL_STRING + 1];
char title[TITLE_LEN + 1]; /* TODO check for overflow */
int lenTitle;
char base_url[MAX_URL_STRING + 1];
time_t tm;
};
/* Flush Buffer
*/
PRIVATE void HTGHist_flush(HTStructured * me)
{
}
/* Character handling
*/
PRIVATE void HTGHist_put_character(HTStructured * me, char c)
{
switch (c)
{
case '\n':
case '\t':
case '\r':
c = ' ';
break;
default:
break;
}
if (me->bInAnchor && (me->lenTitle < TITLE_LEN))
{
me->title[me->lenTitle++] = c;
}
}
/* String handling
*/
PRIVATE void HTGHist_put_string(HTStructured * me, CONST char *s)
{
}
PRIVATE void HTGHist_write(HTStructured * me, CONST char *s, int l)
{
}
/* Start Element
*/
PRIVATE void HTGHist_start_element(HTStructured * me, int element_number, CONST BOOL * present, CONST char **value)
{
switch (element_number)
{
case HTML_A:
{
if (present[HTML_A_HREF])
{
GTR_strncpy(me->href, value[HTML_A_HREF], MAX_URL_STRING);
HTSimplify(me->href);
}
if (value[HTML_A_NAME])
me->tm = atol(value[HTML_A_NAME]);
else
me->tm = 0;
memset(me->title, 0, TITLE_LEN + 1);
me->lenTitle = 0;
me->bInAnchor = TRUE;
break;
}
}
}
/* End Element
*/
PRIVATE void HTGHist_end_element(HTStructured * me, int element_number)
{
char *full_address;
char mycopy[MAX_URL_STRING + 1];
char *stripped;
switch (element_number)
{
case HTML_A:
/*
First get the full URL
*/
GTR_strncpy(mycopy, me->href, MAX_URL_STRING);
stripped = HTStrip(mycopy);
full_address = HTParse(stripped,
me->base_url,
PARSE_ACCESS | PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION | PARSE_ANCHOR);
GHist_Add_NoSession(full_address, me->title, me->tm);
GTR_FREE(full_address);
break;
}
}
/* Expanding entities
*/
PRIVATE void HTGHist_put_entity(HTStructured * me, int entity_number)
{
}
/* Free an HTML object
*/
PRIVATE void HTGHist_free(HTStructured * me)
{
GTR_FREE(me);
}
PRIVATE void HTGHist_abort(HTStructured * me, HTError e)
{
HTGHist_free(me);
}
/* Structured Object Class
*/
PRIVATE CONST HTStructuredClass HTGlobalHistory = /* As opposed to print etc */
{
"HTMLToGlobalHistory",
HTGHist_free,
HTGHist_abort,
HTGHist_put_character, HTGHist_put_string, HTGHist_write,
HTGHist_start_element, HTGHist_end_element,
HTGHist_put_entity, NULL, NULL
};
/* HTConverter from HTML to internal global history structure
*/
PUBLIC HTStream *HTMLToGlobalHistory(struct Mwin *tw, HTRequest * request, void *param, HTFormat input_format, HTFormat output_format, HTStream * output_stream)
{
HTStructured *me = (HTStructured *) GTR_CALLOC(1, sizeof(*me));
if (me)
{
GTR_strncpy(me->base_url, request->destination->szActualURL, MAX_URL_STRING);
me->bInAnchor = FALSE;
me->isa = (HTStructuredClass *) & HTGlobalHistory;
me->dtd = &HTMLP_dtd;
return SGML_new(tw, &HTMLP_dtd, me, request);
}
else
{
return NULL;
}
}
#ifdef FEATURE_OPTIONS_MENU
void SessionHist_Init(void)
{
Hash_Init(&gSessionHistory);
}
void SessionHist_Destroy(void)
{
Hash_FreeContents(&gGlobalHistory);
}
void SessionHist_Sort(void)
{
Hash_SortByDataDescending(&gSessionHistory);
}
int SessionHist_Export(char *file, char *szDate)
{
int count;
char *s1;
char *s2;
time_t then;
time_t now;
FILE *fp;
int i;
SessionHist_Sort();
now = time(NULL);
fp = fopen(file, "w");
if (!fp)
{
return -1;
}
fprintf(fp, GTR_GetString(SID_INF_SESSION_HISTORY));
fprintf(fp, GTR_GetString(SID_INF_SESSION_HISTORY_FOR_DATE_S), szDate);
count = Hash_Count(&gSessionHistory);
#ifdef MAC
if (count > 32767)
count = 32767;
#endif
for (i = 0; i < count; i++)
{
Hash_GetIndexedEntry(&gSessionHistory, i, &s1, &s2, (void **) &then);
fprintf(fp, "<a href=\"%s\" name=\"%lu\">%s</a><p>\n", s1, (unsigned long) then, s2);
}
fclose(fp);
return 0;
}
void SessionHist_SaveToDisk(HWND hWnd)
{
char buf[_MAX_PATH];
time_t now;
struct tm *ptm;
char szDate[255+1];
now = time(NULL);
ptm = localtime(&now);
strftime(szDate, 255, "%A %B %d, %Y %I:%M:%S %p", ptm);
strftime(buf, 12, "HS%m%d%y.HTM", ptm);
buf[12] = 0;
if (DlgSaveAs_RunDialog(hWnd, NULL, buf, 1, GTR_GetString(SID_DLG_SAVE_SESSION_HISTORY_TITLE)) < 0)
{
return;
}
if (SessionHist_Export(buf, szDate) < 0)
{
/*ERR_ReportError(errCantSaveFile, buf, "");*/
}
}
#endif /* FEATURE_OPTIONS_MENU */
struct Params_GHist_Load {
HTRequest *request;
/* Used internally */
int status;
};
static int GHist_Load_Async(struct Mwin *tw, int nState, void **ppInfo)
{
struct Params_GHist_Load *pParams;
struct Params_LoadAsync *p2;
pParams = *ppInfo;
switch (nState)
{
case STATE_INIT:
p2 = GTR_MALLOC(sizeof(*p2));
p2->request = pParams->request;
p2->pStatus = &pParams->status;
bGHistLoading = TRUE;
Async_DoCall(HTLoadDocument_Async, p2);
return STATE_OTHER;
case STATE_OTHER:
case STATE_ABORT:
bGHistLoading = FALSE;
Dest_DestroyDest(pParams->request->destination);
HTRequest_delete(pParams->request);
return STATE_DONE;
}
XX_Assert((0), ("Function called with illegal state: %d", nState));
return STATE_DONE;
}
void GHist_Init(void)
{
HTRequest *request;
char url[MAX_URL_STRING + 1];
struct Params_GHist_Load *phll;
struct DestInfo *pDest;
#ifdef WIN32
char path[_MAX_PATH];
PREF_GetPathToHistoryFile(path);
FixPathName(path);
strcpy(url, "file:///");
strcat(url, path);
#endif
#ifdef MAC
#include "resequ.h"
Str255 filename;
strcpy (url, "file:///");
strcat (url, vv_Application);
GetIndString (filename, OEM_FILES_STR_LIST, OEM_HISTNAME_STR);
p2cstr (filename);
strcat (url, " ");
strcat (url, filename);
PathNameFromDirID (MacGlobals.prefFldrDirID, MacGlobals.prefFldrVRefNum, url + 8);
FixPathName (url + 8);
#endif
#ifdef UNIX
/*
** the gPrefs.szGlobHistFile is
** guaranteed to be loaded w/ a full path name to a history file.
** (that is once InitPrefences() has been called) -dpg
*/
strcpy (url, "file://");
strcat (url, gPrefs.szGlobHistFile);
#endif
Hash_Init(&gGlobalHistory);
pDest = Dest_CreateDest(url);
if (pDest)
{
request = HTRequest_new();
HTFormatInit(request->conversions);
request->output_format = HTAtom_for("www/global_history");
request->destination = pDest;
phll = GTR_MALLOC(sizeof(*phll));
phll->request = request;
Async_StartThread(GHist_Load_Async, phll, NULL);
}
}
void GHist_Sort(void)
{
Hash_SortByDataDescending(&gGlobalHistory);
}
int GHist_Export(char *file, int history_expire_days)
{
int count;
char *s1;
char *s2;
time_t then;
time_t now;
int age;
FILE *fp;
int i;
BOOL bKeep;
GHist_Sort();
now = time(NULL);
fp = fopen(file, "w");
if (!fp)
{
return -1;
}
fprintf(fp, GTR_GetString(SID_INF_GLOBAL_HISTORY));
fprintf(fp, GTR_GetString(SID_INF_GLOBAL_HISTORY_PAGE));
count = Hash_Count(&gGlobalHistory);
#ifdef MAC
if (count > 16338)
count = 16338;
#endif
for (i = 0; i < count; i++)
{
Hash_GetIndexedEntry(&gGlobalHistory, i, &s1, &s2, (void **) &then);
if (history_expire_days == 0)
{
/*
If expire == 0, don't save anything
*/
bKeep = FALSE;
}
else if (history_expire_days > 0)
{
age = (now - then) / (24 * 60 * 60);
if (age > history_expire_days)
bKeep = FALSE;
else
bKeep = TRUE;
}
else
{
/*
If expire < 0, then keep everything
*/
bKeep = TRUE;
}
if (bKeep)
{
fprintf(fp, "<a href=\"%s\" name=\"%lu\">%s</a><p>\n", s1, (unsigned long) then, s2);
}
}
fclose(fp);
return 0;
}
int GHist_SaveToDisk(void)
{
char path[_MAX_PATH];
int status;
#ifdef MAC
strcpy(path, vv_Application);
strcat(path, " History.html");
PathNameFromDirID(MacGlobals.prefFldrDirID, MacGlobals.prefFldrVRefNum, path);
#endif
#ifdef WIN32
PREF_GetPathToHistoryFile(path);
#endif
#ifdef UNIX
/* for unix, history file is a complete path. */
strcpy (path, gPrefs.szGlobHistFile);
#endif
/** If the history file has not completely loaded then **/
/** do not continue **/
if (bGHistLoading)
return 0;
status = GHist_Export(path, gPrefs.history_expire_days);
#ifdef MAC
if (!status)
{
short tempWD;
(void) makevwd (MacGlobals.prefFldrVRefNum, MacGlobals.prefFldrDirID, &tempWD); /* make a WD for it */
MakeGuitarFile (tempWD, path);
}
#endif
return status;
}
void GHist_Destroy(void)
{
Hash_FreeContents(&gGlobalHistory);
}
void GHist_DeleteIndexedItem(int ndx)
{
Hash_DeleteIndexedEntry(&gGlobalHistory, ndx);
}
static int GHist_Add_NoSession(char *url, char *title, time_t tm)
{
int ndx;
time_t old_tm;
int err;
if (title)
{
while (isspace((unsigned char)*title))
{
title++;
}
}
if (!title || !*title)
{
title = url;
}
ndx = Hash_Find(&gGlobalHistory, url, NULL, (void **) &old_tm);
if (ndx >= 0)
{
Hash_DeleteIndexedEntry(&gGlobalHistory, ndx);
}
XX_DMsg(DBG_HIST, ("Adding to global history: %s\n", url));
err = Hash_Add(&gGlobalHistory, url, title, (void *) tm);
return err;
}
int GHist_Add(char *url, char *title, time_t tm)
{
int err;
if (title)
{
while (isspace((unsigned char)*title))
{
title++;
}
}
if (!title || !*title)
{
title = url;
}
err = GHist_Add_NoSession(url, title, tm);
/* TODO deal with err */
#ifdef FEATURE_OPTIONS_MENU
{
int ndx;
time_t old_tm;
ndx = Hash_Find(&gSessionHistory, url, NULL, (void **) &old_tm);
if (ndx >= 0)
{
Hash_DeleteIndexedEntry(&gSessionHistory, ndx);
}
err = Hash_Add(&gSessionHistory, url, title, (void *) tm);
}
#endif /* FEATURE_OPTIONS_MENU */
GTR_RefreshHistory();
return err;
}