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.
 
 
 
 
 
 

1252 lines
33 KiB

/*
This file was derived from the libwww code, version 2.15, from CERN.
A number of modifications have been made by Spyglass.
Copyright 1995 Spyglass, Inc.
All Rights Reserved
[email protected]
*/
/*****************************************************************************
Included Files
*****************************************************************************/
#include "all.h"
/*****************************************************************************
Constants and Structures
*****************************************************************************/
#define PUTS(s) (*target->isa->put_string)(target, s)
#define START(e) (*target->isa->start_element)(target, e, 0, 0)
#define END(e) (*target->isa->end_element)(target, e)
struct _HTStructured
{
CONST HTStructuredClass *isa;
/* ... */
};
struct _HTStream
{
CONST HTStreamClass *isa;
/* ... */
};
/*****************************************************************************
More Constants
*****************************************************************************/
#define STATE_FILE_STREAMINIT (STATE_OTHER + 1)
#define STATE_FILE_COPYING (STATE_OTHER + 2)
#ifdef FEATURE_LOCAL_DIRECTORY
int HTLoadDir (struct Mwin *tw, HTRequest *request, char *pszLocalname);
#endif
/*****************************************************************************
Private prototypes
*****************************************************************************/
#ifdef MAC
extern struct Viewer_Info *
PREF_GetViewerInfoBy_FileType
(OSType reqType);
#endif
static int
HTLoadFile_TryFTP
(struct Mwin *tw,
struct Data_LoadFile* pData,
char *addr);
int
HTLoadFile_Async_SetFileInfo
(struct Mwin* tw,
struct Data_LoadFile* pData,
char* pszURL,
char** pszLocalname);
int
HTLoadFile_Async_Init
(struct Mwin *tw,
void **ppInfo,
int openType);
int
HTLoadFile_Async_File_Copy
(struct Mwin *tw,
struct Data_LoadFile *pData);
int
HTLoadFile_Async_File_StreamInit
(struct Mwin *tw,
struct Data_LoadFile *pData);
int
HTLoadFile_Async_Abort
(struct Mwin *tw,
struct Data_LoadFile *pData);
/*****************************************************************************
Code
*****************************************************************************/
/*****************************************************************************
HTFileFormat
*****************************************************************************/
PUBLIC HTFormat HTFileFormat(CONST char *filename, HTAtom *pencoding, HTAtom *planguage)
{
char *p;
CONST char *pslash;
if (planguage)
{
*planguage = 0; /* note that this isn't supported at all yet */
}
pslash = strrchr(filename, '/');
if (pslash)
{
pslash++;
/* the filename passed in was a URL. pslash now points to the basename */
}
else
{
pslash = filename;
}
p = strrchr(pslash, '.');
/* In the case of an HTTP/0.9 server, we have to assume that the root page
(e.g. "http://www.foo.com/") is HTML even though it doesn't have a
filename, let alone an extension. */
#ifndef _GIBRALTAR
//
// Without any extention at all, we assume html
//
if (p || *pslash == '\0')
#endif // _GIBRALTAR
{
//////////////////////////////////////////////////////////////////////
//
// ((q - szSuff) < 32) below causes the NULL char
// to be written one past the boundary!!!!
//
//char szSuff[32];
char szSuff[SUFF_BUF_LEN + 1];
char *q;
struct Viewer_Info *pvi = NULL;
if (p)
{
szSuff[0] = 0;
p++; /* skip the dot */
q = szSuff;
while (*p && (*p != '/') && ((q - szSuff) < SUFF_BUF_LEN))
{
*q++ = *p++;
}
*q = 0;
XX_DMsg(DBG_WWW, ("HTFileFormat: Looking for extension %s... ", szSuff));
pvi = PREF_GetViewerInfoBy_Suffix(szSuff);
}
else
{
pvi = PREF_GetViewerInfoBy_Suffix("html");
}
if (pvi)
{
XX_DMsg(DBG_WWW, ("found! MIME=%s\n", HTAtom_name(pvi->atomMIMEType)));
if (pencoding)
*pencoding = pvi->atomEncoding;
return pvi->atomMIMEType;
}
XX_DMsg(DBG_WWW, ("Suffix not found.\n"));
if (pencoding)
*pencoding = 0;
return WWW_BINARY;
}
#ifndef _GIBRALTAR
else
{
if (pencoding)
*pencoding = HTAtom_for("8bit");
return WWW_PLAINTEXT;
}
#endif // _GIBRALTAR
}
/*****************************************************************************
HTContentToEncoding
*****************************************************************************/
PUBLIC HTAtom HTContentToEncoding(HTAtom content_type)
{
struct Viewer_Info *pvi;
pvi = PREF_GetViewerInfoBy_MIMEAtom(content_type);
if (pvi)
{
return pvi->atomEncoding;
}
else
{
return HTAtom_for("binary");
}
}
/*****************************************************************************
HTFileSuffix
*****************************************************************************/
PUBLIC CONST char *HTFileSuffix(HTAtom rep)
{
struct Viewer_Info *pvi;
static char szSuff[SUFF_BUF_LEN + 1];
int i;
char *p;
pvi = PREF_GetViewerInfoBy_MIMEAtom(rep);
if (pvi && pvi->nSuffixes)
{
for (i=0; i<pvi->nSuffixes; i++)
{
PREF_GetSuffix(szSuff, pvi, i);
p = szSuff;
if (*p == '.')
{
p++;
}
#ifdef UNIX
if (strlen(p) >= 4) /* we prefer our suffixes long */
#else
if (strlen(p) <= 3)
#endif
{
return szSuff;
}
}
/*
A suffix could not be found. Just return the first one
*/
if (0 > PREF_GetSuffix(szSuff, pvi, 0))
return NULL;
return szSuff;
}
else
{
return NULL;
}
}
/*****************************************************************************
HTLocalName
*****************************************************************************/
/* Convert filenames between local and WWW formats
** -----------------------------------------------
** Make up a suitable name for saving the node in
**
** E.g. $(HOME)/WWW/news/[email protected]
** $(HOME)/WWW/http/crnvmc/FIND/xx.xxx.xx
**
** On exit,
** returns a GTR_MALLOC'ed string which must be freed by the caller.
*/
PUBLIC char *HTLocalName(CONST char *name)
{
char *host = HTParse(name, "", PARSE_HOST);
int iLoc;
#ifdef WIN32
int iSlash;
#endif
if (!host || !*host || (0 == strcasecomp(host, HTHostName())) ||
(0 == strcasecomp(host, "localhost")))
{
char *path;
if (host)
{
GTR_FREE(host);
}
path = HTParse(name, "", PARSE_PATH + PARSE_PUNCTUATION);
#ifdef MAC
#define SLASH ':'
/* Convert slashes to colons before we unescape */
for (iLoc = 0; path[iLoc]; iLoc++)
{
if (path[iLoc] == '/')
path[iLoc] = SLASH;
}
#endif
HTUnEscape (path); /* Interpret % signs */
/*
BEGIN NCSA Copy-Paste
*/
#ifdef WIN32
#define SLASH '\\'
if ( (path[0] == '/') && (strchr(path, ':') || strchr(path, '|')) )
{
char *shuffle = path; // We have drive spec - strip leading slash
while (*shuffle && (*(shuffle + 1)))
{
*shuffle = *(shuffle + 1);
shuffle++;
}
*shuffle = 0;
}
iSlash = 0;
for (iLoc = 0; iLoc < strlen(path); iLoc++)
{
if (path[iLoc] == '|')
path[iLoc] = ':';
else if (path[iLoc] == '/')
{
path[iLoc] = SLASH;
iSlash++;
}
else if (path[iLoc] == SLASH)
iSlash++;
}
if ((path[strlen(path) - 1] == SLASH) && (iSlash > 1))
path[strlen(path) - 1] = 0;
#endif
#ifdef MAC
/*
Remove initial colon. Note that this could cause a problem with a
relative path name, if a person were so foolish as to enter one.
*/
if (path[0] == ':')
memmove(path, path + 1, strlen(path));
#endif
/*
END NCSA Copy-Paste
*/
XX_DMsg(DBG_WWW, ("Node `%s' means path `%s'\n", name, path));
return (path);
}
else
{
GTR_FREE(host);
return NULL;
}
}
//
// Adjust local file name -- if it's relative to the document
// it's embedded in (and that doc is a 'file:' itself),
// adjust it to be an absolute reference
//
// Note: this may return a newly allocate a new string and free the old one
// so the input string must have been malloc'ed
//
static char *AdjustLocalNameIfRelative( struct Mwin *tw, char *localname )
{
char *retval = localname;
if ( tw && tw->w3doc && tw->w3doc->szActualURL )
{
char *p = tw->w3doc->szActualURL;
if ( _strnicmp( p, "file:", 5 ) == 0 )
{
char *s;
p += 5; // move past 'file:'
if ( s = strrchr( p, '\\' ) )
{
s++; // move past the last slash
if ( localname[0] && localname[0] != '\\' && localname[1] != ':' ) // is it relative?
{
char *newlocalname = (char *) GTR_MALLOC( (s-p) + strlen(localname) + 1);
if ( newlocalname )
{
//
// Build absolute local name
//
strncpy( newlocalname, p, (s-p) );
strcpy( newlocalname + (s-p), localname );
GTR_FREE( localname );
retval = newlocalname;
}
}
}
}
}
return retval;
}
/*****************************************************************************
HTDirEntry
Output one directory entry
*****************************************************************************/
PUBLIC void HTDirEntry(HTStructured * target, CONST char *tail, CONST char *entry, BOOL isdir)
{
char *relative;
char *escaped = HTEscape(entry, URL_XPALPHAS, '\0');
char buf[_MAX_PATH+5];
/* If empty tail, gives absolute ref below */
relative = (char *) GTR_MALLOC(strlen(tail) + strlen(escaped) + 2);
if (relative)
{
sprintf(relative, "%s/%s", tail, escaped);
HTStartAnchor(target, NULL, relative);
GTR_FREE(relative);
}
else
{
ERR_ReportError(NULL, SID_ERR_OUT_OF_MEMORY, NULL, NULL);
}
GTR_FREE(escaped);
if (isdir)
{
sprintf (buf, "< %s > ", entry);
PUTS(buf);
}
else
PUTS(entry);
END(HTML_A);
}
/*****************************************************************************
HTDirTitles
Output parent directory entry
This gives the TITLE and H1 header, and also a link
to the parent directory if appropriate.
*****************************************************************************/
PUBLIC void HTDirTitles(HTStructured * target, CONST char *szURL, BOOL bLocal)
{
char *path;
char *current;
if (bLocal)
path = GTR_strdup (szURL);
else
path = HTParse(szURL, "", PARSE_PATH + PARSE_PUNCTUATION);
current = strrchr(path, '/'); /* last part or "" */
if (current)
{
char *printable = NULL;
printable = GTR_strdup((current+1));
if (!bLocal)
HTUnEscape(printable);
START(HTML_TITLE);
if (*printable)
{
PUTS(printable);
//PUTS(" directory");
PUTS(GTR_GetString(SID_INF_DIRECTORY));
}
else
{
/* PUTS("Welcome"); */
//PUTS("Top Level Directory");
PUTS(GTR_GetString(SID_INF_TOP_LEVEL_DIRECTORY));
}
END(HTML_TITLE);
START(HTML_H1);
//PUTS(*printable ? printable : "Top Level");
PUTS(*printable ? printable : GTR_GetString(SID_INF_TOP_LEVEL));
END(HTML_H1);
GTR_FREE(printable);
}
/* Make link back to parent directory */
if (current && current[1])
{ /* was a slash AND something else too */
char *parent;
char *relative;
*current++ = 0;
parent = strrchr(path, '/'); /* penultimate slash */
relative = (char *) GTR_MALLOC(strlen(current) + 4);
if (relative)
{
sprintf(relative, "%s/..", current);
HTStartAnchor(target, "", relative);
GTR_FREE(relative);
}
else
{
ERR_ReportError(NULL, SID_ERR_OUT_OF_MEMORY, NULL, NULL);
}
//PUTS("Up to ");
PUTS(GTR_GetString(SID_INF_UP_TO));
if (parent)
{
char *printable = NULL;
printable = GTR_strdup((parent+1));
if (!bLocal)
HTUnEscape(printable);
PUTS(printable);
GTR_FREE(printable);
}
else
{
PUTS("/");
}
END(HTML_A);
}
if (path)
GTR_FREE(path);
}
/*****************************************************************************
HTLoadFile_Async_SetFileInfo
*****************************************************************************/
int
HTLoadFile_Async_SetFileInfo
(struct Mwin* tw,
struct Data_LoadFile* pData,
char* pszURL,
char** pszLocalname)
{
char *pszFilename;
HTFormat format;
HTAtom encoding;
HTAtom language;
char *myhost = HTParse (pszURL, "", PARSE_HOST);
if (myhost)
{
if (*myhost)
{
GTR_FREE (myhost); /* be a good boy and clean up memory before we leave */
return HTLoadFile_TryFTP (tw, pData, pszURL);
}
GTR_FREE (myhost); /* memory cleanup */
}
/* Reduce the filename to a basic form (hopefully unique!) */
pszFilename = HTParse (pszURL, "", PARSE_PATH | PARSE_PUNCTUATION);
*pszLocalname = HTLocalName (pszURL);
if (!*pszLocalname)
{ /* No localname */
*pData->pStatus = -403;
ERR_ReportError (tw, SID_ERR_FILE_NOT_FOUND_S, pData->request->destination->szActualURL, NULL);
return STATE_DONE;
}
/* take care of the case where we have been given (via ShowFile event) the MIMEtype */
if (tw && tw->SDI_MimeType != 0)
{
struct Viewer_Info* pvi = NULL;
pvi = PREF_GetViewerInfoBy_MIMEAtom (tw->SDI_MimeType);
if (pvi)
{
format = pvi->atomMIMEType;
encoding = pvi->atomEncoding;
language = 0;
goto GotIt;
}
}
#ifdef MAC
{ /* see if we can figure out the type ourselves from the fileTYPE */
struct Viewer_Info* pvi = NULL;
Str255 spMacFilename;
FInfo fndrInfo;
strncpy (spMacFilename, *pszLocalname, sizeof (Str255));
c2pstr (spMacFilename);
if (GetFInfo (spMacFilename, 0, &fndrInfo) == noErr)
{
if (fndrInfo.fdType == 'TEXT')
{ /* TEXT is inconclusive, check based on extension */
format = HTFileFormat (pszFilename, &encoding, &language);
if (format == WWW_BINARY)
{
pvi = PREF_GetViewerInfoBy_MIMEAtom (WWW_PLAINTEXT);
}
}
else
{
pvi = PREF_GetViewerInfoBy_FileType (fndrInfo.fdType);
}
if (pvi)
{
format = pvi->atomMIMEType;
encoding = pvi->atomEncoding;
language = 0;
}
}
if (!pvi)
format = HTFileFormat (pszFilename, &encoding, &language);
}
#else
format = HTFileFormat (pszFilename, &encoding, &language);
#endif
GotIt:
/* memory cleanup */
if (pszFilename)
{
GTR_FREE (pszFilename);
pszFilename = NULL;
}
pData->request->content_type = format;
pData->request->content_encoding = encoding;
pData->request->content_language = language;
return STATE_INIT;
} /* HTLoadFile_Async_SetFileInfo */
/*****************************************************************************
HTLoadFile_Async_Init
NOTES:
Since we are reading a local file, we record that fact in the
request structure. If this request happens to end up in the
FileWriter class, that class can avoid writing a temp file
and simply read this file directly.
It is the responsibility of FileWriter to make sure that this
filename is not marked for deletion as a temporary file.
It is the responsibility of the caller (loaddoc.c) to make sure
that this string gets freed.
The "openType" parameter is used to determine if we are opening a local
file, or handling a "cache" file. This was done to condense the dcache
code with this code, since there was considerable overlap in functionality.
0 = open local
1 = dcache
other = undefined
[der: 5/24/95]
*****************************************************************************/
int
HTLoadFile_Async_Init
(struct Mwin *tw,
void **ppInfo,
int openType)
{
struct Params_InitStream* pis;
struct Params_LoadAsync* pParams;
struct Data_LoadFile* pData;
char *pszURL;
char *pszLocalname;
pParams = *ppInfo;
/****************************************/
/* this code copied from FTP_DoInit() to remove trailing slash */
/* this line fixed the infinite looping bug */
if (openType == 0) /* local file rather than dcache */
{
char *name;
name = pParams->request->destination->szActualURL;
if (!name || !*name)
{
*pParams->pStatus = HT_INTERNAL;
return STATE_DONE;
}
/* It's common for someone to enter an invalid directory URL which
ends in a slash ("ftp://foo.com/pub/mac/"), so make sure this
isn't malformed like that. */
{
char *filename;
char *p = NULL;
char buf[MAX_URL_STRING];
filename = HTParse(name, "", PARSE_PATH + PARSE_PUNCTUATION);
if (filename)
p = strrchr(filename, '/');
if (p && !*(p+1) && p != filename)
{
/* The URL was, in fact, malformed. I told you it was common. */
/* Fix up the URL and try again. */
p = strrchr(name, '/');
strncpy(buf, name, p - name);
buf[p - name] = '\0';
Dest_UpdateActual(pParams->request->destination, buf);
*pParams->pStatus = HT_REDIRECTION_ON_FLY;
GTR_FREE(filename);
return STATE_DONE;
}
GTR_FREE(filename);
}
}
/****************************************/
pData = GTR_CALLOC(sizeof(*pData), 1);
if (!pData)
{ /* out of memory error! */
ERR_ReportError(tw, SID_ERR_OUT_OF_MEMORY, NULL, NULL);
return STATE_ABORT;
}
pData->request = pParams->request;
pData->pStatus = pParams->pStatus;
*ppInfo = pData;
GTR_FREE(pParams);
if (!pData->request)
{
*pData->pStatus = HT_INTERNAL;
return STATE_DONE;
}
pData->request->content_length = 0;
pData->iTotalBytes = 0;
pszURL = pData->request->destination->szActualURL;
/* get the local name, MIMEtype, encoding, etc... info for this URL */
switch (openType)
{
case 0: /* open local */
if (HTLoadFile_Async_SetFileInfo (tw, pData, pszURL, &pszLocalname) == STATE_DONE)
return STATE_DONE;
break;
case 1:
if (HTLoadDCache_Async_SetFileInfo (tw, pData, pszURL, &pszLocalname) == STATE_DONE)
return STATE_DONE;
break;
default:
/* guano case here -- we should never get here */
*pData->pStatus = -403;
ERR_ReportError(tw, SID_ERR_FILE_NOT_FOUND_S, pData->request->destination->szActualURL, NULL);
return STATE_DONE;
break;
}
if (tw)
tw->SDI_MimeType = 0; /* clear this now */
/****************************************/
#ifdef FEATURE_LOCAL_DIRECTORY
if (Dir_IsDirectory (pszLocalname))
{
*pData->pStatus = HTLoadDir (tw, pData->request, pszLocalname);
return STATE_DONE;
}
#endif
/* open the file */
pData->fp = fopen (pszLocalname, "rb");
if (!pData->fp)
{ /* unable to open the file */
GTR_FREE (pszLocalname);
pszLocalname = NULL;
pData->request->szLocalFileName = NULL;
*pData->pStatus = -403;
ERR_ReportError(tw, SID_ERR_FILE_NOT_FOUND_S, pData->request->destination->szActualURL, NULL);
return STATE_DONE;
}
pData->request->szLocalFileName = GTR_strdup (pszLocalname);
GTR_FREE (pszLocalname);
pszLocalname = NULL;
/* get the length of the data */
if (0 == fseek(pData->fp, 0, SEEK_END))
{
pData->request->content_length = ftell(pData->fp);
if (pData->request->content_length < 0)
{
pData->request->content_length = 0;
}
fseek(pData->fp, 0, SEEK_SET);
}
/* set the stream */
pData->stream = HTStreamStack(tw, pData->request->content_type, pData->request);
if (!pData->stream)
{
*pData->pStatus = -501;
return STATE_DONE;
}
/* Ignore CRLF if necessary */
if (!(pData->request->iFlags & HTREQ_BINARY) &&
((pData->request->content_encoding == HTAtom_for("7bit") ||
pData->request->content_encoding == HTAtom_for("8bit"))))
{
pData->stream = HTNetToText(pData->stream);
}
HTSetStreamStatus (tw, pData->stream, pData->request);
if (!pData->stream->isa->init_Async)
{
return STATE_FILE_COPYING;
}
else
{ /* the stream has an async initialization function */
pis = GTR_CALLOC (sizeof (*pis), 1);
if (!pis)
{ /* HEY - THE FILE SEEMS TO BE LEFT OPEN HERE!!! [der: 4/25/95] */
ERR_ReportError(tw, SID_ERR_OUT_OF_MEMORY, NULL, NULL);
return STATE_ABORT;
}
pis->me = pData->stream;
pis->request = pData->request;
pis->pResult = pData->pStatus;
Async_DoCall (pData->stream->isa->init_Async, pis);
return STATE_FILE_STREAMINIT;
}
} /* HTLoadFile_Async_Init */
/*****************************************************************************
HTLoadFile_Async_File_Copy
NOTE: This function also used by dcache functions
*****************************************************************************/
int
HTLoadFile_Async_File_Copy
(struct Mwin *tw,
struct Data_LoadFile *pData)
{
char input_buffer[INPUT_BUFFER_SIZE];
BOOL bError = FALSE;
BOOL bDone = FALSE;
int iNumBytesRead;
iNumBytesRead = fread(input_buffer, 1, INPUT_BUFFER_SIZE, pData->fp);
if (iNumBytesRead == 0)
{ /* EOF or error */
bDone = TRUE;
if (ferror(pData->fp) != 0)
{
bError = TRUE;
}
}
else
{
pData->iTotalBytes += iNumBytesRead;
if (pData->request->content_length)
{
WAIT_SetTherm (tw, pData->iTotalBytes);
}
if (!(*pData->stream->isa->put_block)(pData->stream, input_buffer, iNumBytesRead))
{
bError = TRUE;
bDone = TRUE;
}
}
if (!bDone && !bError)
{
return STATE_FILE_COPYING;
}
/* close the file */
fclose(pData->fp);
pData->fp = NULL;
/* cleanup -- abort (error) or free (success) */
if (bError)
{
(*pData->stream->isa->abort)(pData->stream, 0);
pData->stream = NULL;
*pData->pStatus = -1;
}
else
{
(*pData->stream->isa->free)(pData->stream);
pData->stream = NULL;
*pData->pStatus = HT_LOADED;
}
return STATE_DONE;
}
/*****************************************************************************
HTLoadFile_Async_File_StreamInit
NOTE: This function also used by dcache functions
*****************************************************************************/
int
HTLoadFile_Async_File_StreamInit
(struct Mwin *tw,
struct Data_LoadFile *pData)
{
if (*pData->pStatus < 0)
{
(*pData->stream->isa->abort)(pData->stream, 0);
return STATE_DONE;
}
if (*pData->pStatus == 0)
{ /*
This only happens if the async init function told us we were already
done. In other words, only FileWriter should do this, and only when
request->szLocalFileName is true.
*/
fclose(pData->fp);
pData->fp = NULL;
(*pData->stream->isa->free)(pData->stream);
pData->stream = NULL;
*pData->pStatus = HT_LOADED;
return STATE_DONE;
}
return HTLoadFile_Async_File_Copy (tw, pData);
}
/*****************************************************************************
HTLoadFile_Async_Abort
NOTE: This function also used by dcache functions
*****************************************************************************/
int
HTLoadFile_Async_Abort
(struct Mwin *tw,
struct Data_LoadFile *pData)
{
/* allow the stream to abort */
if (pData->stream)
{
(*pData->stream->isa->abort)(pData->stream, HTERROR_CANCELLED);
}
/* close the file if we opened it */
if (pData->fp)
{
fclose(pData->fp);
}
*pData->pStatus = -1;
return STATE_DONE;
}
/*****************************************************************************
HTLoadFile_Async
This is a pretty pathetic async version -
once it starts copying it just keeps going.
*****************************************************************************/
PRIVATE int HTLoadFile_Async(struct Mwin *tw, int nState, void **ppInfo)
{
int result;
struct Data_LoadFile *pData;
pData = *ppInfo;
switch (nState)
{
case STATE_INIT:
result = HTLoadFile_Async_Init (tw, ppInfo, 0);
break;
case STATE_FILE_STREAMINIT:
result = HTLoadFile_Async_File_StreamInit (tw, pData);
break;
case STATE_FILE_COPYING:
result = HTLoadFile_Async_File_Copy (tw, pData);
break;
case STATE_ABORT:
result = HTLoadFile_Async_Abort (tw, pData);
break;
default:
XX_Assert((0), ("Function called with illegal state: %d", nState));
result = STATE_DONE;
break;
}
return result;
}
/*****************************************************************************
HTLoadFile_TryFTP
*****************************************************************************/
static int
HTLoadFile_TryFTP
(struct Mwin *tw,
struct Data_LoadFile* pData,
char *addr)
{
char* newname = GTR_MALLOC(strlen(addr));
if (!newname)
{
ERR_ReportError(tw, SID_ERR_OUT_OF_MEMORY, NULL, NULL);
return STATE_ABORT;
}
strcpy(newname, "ftp:");
strcat(newname, addr + 5);
Dest_UpdateActual(pData->request->destination, newname);
GTR_FREE(newname);
*pData->pStatus = HT_REDIRECTION_ON_FLY;
return STATE_DONE;
}
static void file_MakeSizeString1 (char *buf, int nSize)
{
if (nSize >= 0)
{
if (nSize < 999)
{
sprintf(buf, "%ld", (long) nSize);
}
else if (nSize < 9999)
{
sprintf(buf, "%ld,%03ld", (long) nSize / 1000, (long) nSize % 1000);
}
else if (nSize < (999 * 1024))
{
sprintf(buf, "%ld", (long) nSize / 1024);
}
else
{
sprintf (buf, "%ld.%ld", (long) nSize / (1024 * 1024),
(long) (nSize / (1024 * 1024 / 10)) % 10);
}
}
else
{
strcpy(buf, "(unknown size?)");
}
}
static void file_MakeSizeString2(char *buf, int nSize)
{
if (nSize >= 0)
{
if (nSize < 999)
{
strcpy(buf, "bytes");
}
else if (nSize < 9999)
{
strcpy(buf, "bytes");
}
else if (nSize < (999 * 1024))
{
strcpy(buf, "KB");
}
else
{
strcpy (buf, "MB");
}
}
else
{
strcpy (buf, "unknown size");
}
}
#ifdef FEATURE_LOCAL_DIRECTORY
/*
** This function will read a directory and display
** the sorted entries in a <TABLE>
**
** Calls Dir_OpenDirectory() reading functions
** Calls HTML_new() to create the output
*/
int HTLoadDir (struct Mwin *tw, HTRequest *request, char *pszLocalname)
{
HTStructured *target;
int i;
#ifdef HTLOADDIR_USE_TABLE
char size_buf1[100];
char size_buf2[100];
#endif
char buf[_MAX_PATH+100];
HTBTree *bt; /* btree for sorting elements */
HTBTElement *ele;
CONST char *hrvalues[HTML_HR_ATTRIBUTES];
BOOL hrpresent[HTML_HR_ATTRIBUTES];
#ifdef HTLOADDIR_USE_TABLE
CONST char *tvalues[HTML_TABLE_ATTRIBUTES];
BOOL tpresent[HTML_TABLE_ATTRIBUTES];
CONST char *tdvalues[HTML_TD_ATTRIBUTES];
BOOL tdpresent[HTML_TD_ATTRIBUTES];
CONST char *trvalues[HTML_TR_ATTRIBUTES];
BOOL trpresent[HTML_TR_ATTRIBUTES];
#endif
void *dp; /* opendirectory private data */
HT_DirEntry *dir_ent;
char *p;
/****************************************/
/****************************************/
target = HTML_new (tw, request, NULL, WWW_HTML,
request->output_format, request->output_stream);
GTR_strncpy (buf, pszLocalname, _MAX_PATH);
p = buf + strlen(buf) - 1;
if (*p == '/')
*p = '\0';
HTDirTitles (target, buf, 1);
if (!(dp = Dir_OpenDirectory (buf)))
return HT_ERROR;
if (NULL == (bt = HTBTree_new ((HTComparer) strcasecomp)))
{
Dir_CloseDirectory (dp);
return HT_ERROR;
}
for (i = 0 ; i < HTML_HR_ATTRIBUTES ; i++)
hrpresent[i] = 0;
#ifdef HTLOADDIR_USE_TABLE
for (i = 0 ; i < HTML_TABLE_ATTRIBUTES ; i++)
tpresent[i] = 0;
for (i = 0 ; i < HTML_TD_ATTRIBUTES ; i++)
tdpresent[i] = 0;
for (i = 0 ; i < HTML_TR_ATTRIBUTES ; i++)
trpresent[i] = 0;
#endif
while ( Dir_NextEntry (dp,
dir_ent = (HT_DirEntry *)GTR_CALLOC (1, sizeof (*dir_ent))))
{
if ( dir_ent && dir_ent->name[0] && (strcmp (dir_ent->name, ".") && strcmp (dir_ent->name, "..")) )
HTBTree_add (bt, dir_ent);
}
(*target->isa->start_element) (target, HTML_HR, hrpresent, hrvalues);
#ifdef HTLOADDIR_USE_TABLE
tvalues[HTML_TABLE_CELLSPACING] = "50";
tpresent[HTML_TABLE_CELLSPACING] = 1;
/* start table */
(*target->isa->start_element) (target, HTML_TABLE, tpresent, tvalues);
#else
START (HTML_DIR);
#endif
for (ele = HTBTree_next(bt, NULL); ele != NULL; ele = HTBTree_next(bt, ele))
{
dir_ent = (HT_DirEntry *) HTBTree_object (ele);
#ifdef HTLOADDIR_USE_TABLE
/* Row */
(*target->isa->start_element) (target, HTML_TR, trpresent, trvalues);
/* Data Cell for directory info */
(*target->isa->start_element) (target, HTML_TD, tdpresent, tdvalues);
if (dir_ent->type & HTDIR_DIR)
//PUTS ("<DIR> ");
PUTS(GTR_GetString(SID_INF_DIR));
/* Column 2: file name */
(*target->isa->start_element) (target, HTML_TD, tdpresent, tdvalues);
HTDirEntry (target, request->destination->szActualURL, (CONST char *) dir_ent->name, 0);
/* toss in a couple colums for space */
(*target->isa->start_element) (target, HTML_TD, tdpresent, tdvalues);
(*target->isa->start_element) (target, HTML_TD, tdpresent, tdvalues);
/* size number */
tdvalues[HTML_TD_ALIGN] = "right";
tdpresent[HTML_TD_ALIGN] = 1;
(*target->isa->start_element) (target, HTML_TD, tdpresent, tdvalues);
file_MakeSizeString1 (size_buf1, dir_ent->size);
PUTS (size_buf1);
/* size units */
tdvalues[HTML_TD_ALIGN] = "left";
tdpresent[HTML_TD_ALIGN] = 1;
(*target->isa->start_element) (target, HTML_TD, tdpresent, tdvalues);
file_MakeSizeString2 (size_buf2, dir_ent->size);
PUTS (size_buf2);
tdpresent[HTML_TD_ALIGN] = 0; /* reset just in case */
END (HTML_TD);
END (HTML_TR);
#else
START (HTML_LI);
HTDirEntry (target, request->destination->szActualURL,
(CONST char *) dir_ent->name, 0);
#endif /* HTLOADDIR_USE_TABLE */
}
#ifdef HTLOADDIR_USE_TABLE
END (HTML_TABLE);
#else
END (HTML_DIR);
#endif
(*target->isa->free) (target); /* clean up stream */
HTBTreeAndObject_free (bt); /* free btree AND dir_ent's */
Dir_CloseDirectory (dp); /* close directory */
return HT_LOADED;
}
#endif /* FEATURE_LOCAL_DIRECTORY */
/*****************************************************************************
Protocol descriptors
*****************************************************************************/
GLOBALDEF PUBLIC HTProtocol HTFile ={"file", NULL, HTLoadFile_Async};