|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* $LynxId: HTFile.c,v 1.151 2018/05/11 23:20:35 tom Exp $
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* File Access HTFile.c
|
|
Packit |
f574b8 |
* ===========
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* This is unix-specific code in general, with some VMS bits.
|
|
Packit |
f574b8 |
* These are routines for file access used by browsers.
|
|
Packit |
f574b8 |
* Development of this module for Unix DIRED_SUPPORT in Lynx
|
|
Packit |
f574b8 |
* regrettably has has been conducted in a manner with now
|
|
Packit |
f574b8 |
* creates a major impediment for hopes of adapting Lynx to
|
|
Packit |
f574b8 |
* a newer version of the library.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* History:
|
|
Packit |
f574b8 |
* Feb 91 Written Tim Berners-Lee CERN/CN
|
|
Packit |
f574b8 |
* Apr 91 vms-vms access included using DECnet syntax
|
|
Packit |
f574b8 |
* 26 Jun 92 (JFG) When running over DECnet, suppressed FTP.
|
|
Packit |
f574b8 |
* Fixed access bug for relative names on VMS.
|
|
Packit |
f574b8 |
* Sep 93 (MD) Access to VMS files allows sharing.
|
|
Packit |
f574b8 |
* 15 Nov 93 (MD) Moved HTVMSname to HTVMSUTILS.C
|
|
Packit |
f574b8 |
* 27 Dec 93 (FM) FTP now works with VMS hosts.
|
|
Packit |
f574b8 |
* FTP path must be Unix-style and cannot include
|
|
Packit |
f574b8 |
* the device or top directory.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#include <HTUtils.h>
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifndef VMS
|
|
Packit |
f574b8 |
#if defined(DOSPATH)
|
|
Packit |
f574b8 |
#undef LONG_LIST
|
|
Packit |
f574b8 |
#define LONG_LIST /* Define this for long style unix listings (ls -l),
|
|
Packit |
f574b8 |
the actual style is configurable from lynx.cfg */
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
/* #define NO_PARENT_DIR_REFERENCE */
|
|
Packit |
f574b8 |
/* Define this for no parent links */
|
|
Packit |
f574b8 |
#endif /* !VMS */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#if defined(DOSPATH)
|
|
Packit |
f574b8 |
#define HAVE_READDIR 1
|
|
Packit |
f574b8 |
#define USE_DIRENT
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#if defined(USE_DOS_DRIVES)
|
|
Packit |
f574b8 |
#include <HTDOS.h>
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#include <HTFile.h> /* Implemented here */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef VMS
|
|
Packit |
f574b8 |
#include <stat.h>
|
|
Packit |
f574b8 |
#endif /* VMS */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#if defined (USE_ZLIB) || defined (USE_BZLIB)
|
|
Packit |
f574b8 |
#include <GridText.h>
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define MULTI_SUFFIX ".multi" /* Extension for scanning formats */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#include <HTParse.h>
|
|
Packit |
f574b8 |
#include <HTTCP.h>
|
|
Packit |
f574b8 |
#ifndef DECNET
|
|
Packit |
f574b8 |
#include <HTFTP.h>
|
|
Packit |
f574b8 |
#endif /* !DECNET */
|
|
Packit |
f574b8 |
#include <HTAnchor.h>
|
|
Packit |
f574b8 |
#include <HTAtom.h>
|
|
Packit |
f574b8 |
#include <HTAAProt.h>
|
|
Packit |
f574b8 |
#include <HTFWriter.h>
|
|
Packit |
f574b8 |
#include <HTInit.h>
|
|
Packit |
f574b8 |
#include <HTBTree.h>
|
|
Packit |
f574b8 |
#include <HTAlert.h>
|
|
Packit |
f574b8 |
#include <HTCJK.h>
|
|
Packit |
f574b8 |
#include <UCDefs.h>
|
|
Packit |
f574b8 |
#include <UCMap.h>
|
|
Packit |
f574b8 |
#include <UCAux.h>
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#include <LYexit.h>
|
|
Packit |
f574b8 |
#include <LYCharSets.h>
|
|
Packit |
f574b8 |
#include <LYGlobalDefs.h>
|
|
Packit |
f574b8 |
#include <LYStrings.h>
|
|
Packit |
f574b8 |
#include <LYUtils.h>
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef USE_PRETTYSRC
|
|
Packit |
f574b8 |
# include <LYPrettySrc.h>
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#include <LYLeaks.h>
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
typedef struct _HTSuffix {
|
|
Packit |
f574b8 |
char *suffix;
|
|
Packit |
f574b8 |
HTAtom *rep;
|
|
Packit |
f574b8 |
HTAtom *encoding;
|
|
Packit |
f574b8 |
char *desc;
|
|
Packit |
f574b8 |
float quality;
|
|
Packit |
f574b8 |
} HTSuffix;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
typedef struct {
|
|
Packit |
f574b8 |
struct stat file_info;
|
|
Packit |
f574b8 |
char sort_tags;
|
|
Packit |
f574b8 |
char file_name[1]; /* on the end of the struct, since its length varies */
|
|
Packit |
f574b8 |
} DIRED;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifndef NGROUPS
|
|
Packit |
f574b8 |
#ifdef NGROUPS_MAX
|
|
Packit |
f574b8 |
#define NGROUPS NGROUPS_MAX
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
#define NGROUPS 32
|
|
Packit |
f574b8 |
#endif /* NGROUPS_MAX */
|
|
Packit |
f574b8 |
#endif /* NGROUPS */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifndef GETGROUPS_T
|
|
Packit |
f574b8 |
#define GETGROUPS_T int
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#include <HTML.h> /* For directory object building */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define PUTC(c) (*target->isa->put_character)(target, c)
|
|
Packit |
f574b8 |
#define PUTS(s) (*target->isa->put_string)(target, s)
|
|
Packit |
f574b8 |
#define START(e) (*target->isa->start_element)(target, e, 0, 0, -1, 0)
|
|
Packit |
f574b8 |
#define END(e) (*target->isa->end_element)(target, e, 0)
|
|
Packit |
f574b8 |
#define MAYBE_END(e) if (HTML_dtd.tags[e].contents != SGML_EMPTY) \
|
|
Packit |
f574b8 |
(*target->isa->end_element)(target, e, 0)
|
|
Packit |
f574b8 |
#define FREE_TARGET (*target->isa->_free)(target)
|
|
Packit |
f574b8 |
#define ABORT_TARGET (*targetClass._abort)(target, NULL);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
struct _HTStructured {
|
|
Packit |
f574b8 |
const HTStructuredClass *isa;
|
|
Packit |
f574b8 |
/* ... */
|
|
Packit |
f574b8 |
};
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Controlling globals.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
int HTDirAccess = HT_DIR_OK;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef DIRED_SUPPORT
|
|
Packit |
f574b8 |
int HTDirReadme = HT_DIR_README_NONE;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
int HTDirReadme = HT_DIR_README_TOP;
|
|
Packit |
f574b8 |
#endif /* DIRED_SUPPORT */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static const char *HTMountRoot = "/Net/"; /* Where to find mounts */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef VMS
|
|
Packit |
f574b8 |
static const char *HTCacheRoot = "/WWW$SCRATCH"; /* Where to cache things */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
static const char *HTCacheRoot = "/tmp/W3_Cache_"; /* Where to cache things */
|
|
Packit |
f574b8 |
#endif /* VMS */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static char s_no_suffix[] = "*";
|
|
Packit |
f574b8 |
static char s_unknown_suffix[] = "*.*";
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Suffix registration.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
static HTList *HTSuffixes = 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static HTSuffix no_suffix =
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
s_no_suffix, NULL, NULL, NULL, 1.0
|
|
Packit |
f574b8 |
};
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static HTSuffix unknown_suffix =
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
s_unknown_suffix, NULL, NULL, NULL, 1.0
|
|
Packit |
f574b8 |
};
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* To free up the suffixes at program exit.
|
|
Packit |
f574b8 |
* ----------------------------------------
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
#ifdef LY_FIND_LEAKS
|
|
Packit |
f574b8 |
static void free_suffixes(void);
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static char *FindSearch(const char *filename)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *result = 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if ((result = strchr(filename, '?')) == 0) {
|
|
Packit |
f574b8 |
result = strstr(filename, "%3F");
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef LONG_LIST
|
|
Packit |
f574b8 |
static char *FormatStr(char **bufp,
|
|
Packit |
f574b8 |
char *start,
|
|
Packit |
f574b8 |
const char *entry)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char fmt[512];
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (*start) {
|
|
Packit |
f574b8 |
sprintf(fmt, "%%%.*ss", (int) sizeof(fmt) - 3, start);
|
|
Packit |
f574b8 |
HTSprintf0(bufp, fmt, entry);
|
|
Packit |
f574b8 |
} else if (*bufp && !(entry && *entry)) {
|
|
Packit |
f574b8 |
**bufp = '\0';
|
|
Packit |
f574b8 |
} else if (entry) {
|
|
Packit |
f574b8 |
StrAllocCopy(*bufp, entry);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return *bufp;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static char *FormatSize(char **bufp,
|
|
Packit |
f574b8 |
char *start,
|
|
Packit |
f574b8 |
off_t entry)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char fmt[512];
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (*start) {
|
|
Packit |
f574b8 |
sprintf(fmt, "%%%.*s" PRI_off_t,
|
|
Packit |
f574b8 |
(int) sizeof(fmt) - DigitsOf(start) - 3, start);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
HTSprintf0(bufp, fmt, entry);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
sprintf(fmt, "%" PRI_off_t, CAST_off_t (entry));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrAllocCopy(*bufp, fmt);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return *bufp;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static char *FormatNum(char **bufp,
|
|
Packit |
f574b8 |
char *start,
|
|
Packit |
f574b8 |
int entry)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char fmt[512];
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (*start) {
|
|
Packit |
f574b8 |
sprintf(fmt, "%%%.*sd", (int) sizeof(fmt) - 3, start);
|
|
Packit |
f574b8 |
HTSprintf0(bufp, fmt, entry);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
sprintf(fmt, "%d", entry);
|
|
Packit |
f574b8 |
StrAllocCopy(*bufp, fmt);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return *bufp;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static void LYListFmtParse(const char *fmtstr,
|
|
Packit |
f574b8 |
DIRED * data,
|
|
Packit |
f574b8 |
char *file,
|
|
Packit |
f574b8 |
HTStructured * target,
|
|
Packit |
f574b8 |
char *tail)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char c;
|
|
Packit |
f574b8 |
char *s;
|
|
Packit |
f574b8 |
char *end;
|
|
Packit |
f574b8 |
char *start;
|
|
Packit |
f574b8 |
char *str = NULL;
|
|
Packit |
f574b8 |
char *buf = NULL;
|
|
Packit |
f574b8 |
char tmp[LY_MAXPATH];
|
|
Packit |
f574b8 |
char type;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifndef NOUSERS
|
|
Packit |
f574b8 |
const char *name;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
time_t now;
|
|
Packit |
f574b8 |
char *datestr;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef S_IFLNK
|
|
Packit |
f574b8 |
int len;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#define SEC_PER_YEAR (60 * 60 * 24 * 365)
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef _WINDOWS /* 1998/01/06 (Tue) 21:20:53 */
|
|
Packit |
f574b8 |
static const char *pbits[] =
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
"---", "--x", "-w-", "-wx",
|
|
Packit |
f574b8 |
"r--", "r-x", "rw-", "rwx",
|
|
Packit |
f574b8 |
0};
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define PBIT(a, n, s) pbits[((a) >> (n)) & 0x7]
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
static const char *pbits[] =
|
|
Packit |
f574b8 |
{"---", "--x", "-w-", "-wx",
|
|
Packit |
f574b8 |
"r--", "r-x", "rw-", "rwx", 0};
|
|
Packit |
f574b8 |
static const char *psbits[] =
|
|
Packit |
f574b8 |
{"--S", "--s", "-wS", "-ws",
|
|
Packit |
f574b8 |
"r-S", "r-s", "rwS", "rws", 0};
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define PBIT(a, n, s) (s) ? psbits[((a) >> (n)) & 0x7] : \
|
|
Packit |
f574b8 |
pbits[((a) >> (n)) & 0x7]
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#if defined(S_ISVTX) && !defined(_WINDOWS)
|
|
Packit |
f574b8 |
static const char *ptbits[] =
|
|
Packit |
f574b8 |
{"--T", "--t", "-wT", "-wt",
|
|
Packit |
f574b8 |
"r-T", "r-t", "rwT", "rwt", 0};
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define PTBIT(a, s) (s) ? ptbits[(a) & 0x7] : pbits[(a) & 0x7]
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
#define PTBIT(a, s) PBIT(a, 0, 0)
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (data->file_info.st_mode == 0)
|
|
Packit |
f574b8 |
fmtstr = " %a"; /* can't stat so just do anchor */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrAllocCopy(str, fmtstr);
|
|
Packit |
f574b8 |
s = str;
|
|
Packit |
f574b8 |
end = str + strlen(str);
|
|
Packit |
f574b8 |
while (*s) {
|
|
Packit |
f574b8 |
start = s;
|
|
Packit |
f574b8 |
while (*s) {
|
|
Packit |
f574b8 |
if (*s == '%') {
|
|
Packit |
f574b8 |
if (*(s + 1) == '%') /* literal % */
|
|
Packit |
f574b8 |
s++;
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
s++;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
/* s is positioned either at a % or at \0 */
|
|
Packit |
f574b8 |
*s = '\0';
|
|
Packit |
f574b8 |
if (s > start) { /* some literal chars. */
|
|
Packit |
f574b8 |
PUTS(start);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (s == end)
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
start = ++s;
|
|
Packit |
f574b8 |
while (isdigit(UCH(*s)) || *s == '.' || *s == '-' || *s == ' ' ||
|
|
Packit |
f574b8 |
*s == '#' || *s == '+' || *s == '\'')
|
|
Packit |
f574b8 |
s++;
|
|
Packit |
f574b8 |
c = *s; /* the format char. or \0 */
|
|
Packit |
f574b8 |
*s = '\0';
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
switch (c) {
|
|
Packit |
f574b8 |
case '\0':
|
|
Packit |
f574b8 |
PUTS(start);
|
|
Packit |
f574b8 |
continue;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
case 'A':
|
|
Packit |
f574b8 |
case 'a': /* anchor */
|
|
Packit |
f574b8 |
HTDirEntry(target, tail, data->file_name);
|
|
Packit |
f574b8 |
FormatStr(&buf, start, data->file_name);
|
|
Packit |
f574b8 |
PUTS(buf);
|
|
Packit |
f574b8 |
END(HTML_A);
|
|
Packit |
f574b8 |
*buf = '\0';
|
|
Packit |
f574b8 |
#ifdef S_IFLNK
|
|
Packit |
f574b8 |
if (c != 'A' && S_ISLNK(data->file_info.st_mode) &&
|
|
Packit |
f574b8 |
(len = (int) readlink(file, tmp, sizeof(tmp) - 1)) >= 0) {
|
|
Packit |
f574b8 |
PUTS(" -> ");
|
|
Packit |
f574b8 |
tmp[len] = '\0';
|
|
Packit |
f574b8 |
PUTS(tmp);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
case 'T': /* MIME type */
|
|
Packit |
f574b8 |
case 't': /* MIME type description */
|
|
Packit |
f574b8 |
if (S_ISDIR(data->file_info.st_mode)) {
|
|
Packit |
f574b8 |
if (c != 'T') {
|
|
Packit |
f574b8 |
FormatStr(&buf, start, ENTRY_IS_DIRECTORY);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
FormatStr(&buf, start, "");
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
const char *cp2;
|
|
Packit |
f574b8 |
HTFormat format;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
format = HTFileFormat(file, NULL, &cp2);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (c != 'T') {
|
|
Packit |
f574b8 |
if (cp2 == NULL) {
|
|
Packit |
f574b8 |
if (!StrNCmp(HTAtom_name(format),
|
|
Packit |
f574b8 |
"application", 11)) {
|
|
Packit |
f574b8 |
cp2 = HTAtom_name(format) + 12;
|
|
Packit |
f574b8 |
if (!StrNCmp(cp2, "x-", 2))
|
|
Packit |
f574b8 |
cp2 += 2;
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
cp2 = HTAtom_name(format);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
FormatStr(&buf, start, cp2);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
FormatStr(&buf, start, HTAtom_name(format));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
case 'd': /* date */
|
|
Packit |
f574b8 |
now = time(0);
|
|
Packit |
f574b8 |
datestr = ctime(&data->file_info.st_mtime);
|
|
Packit |
f574b8 |
if ((now - data->file_info.st_mtime) < SEC_PER_YEAR / 2)
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* MMM DD HH:MM
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
sprintf(tmp, "%.12s", datestr + 4);
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* MMM DD YYYY
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
sprintf(tmp, "%.7s %.4s ", datestr + 4,
|
|
Packit |
f574b8 |
datestr + 20);
|
|
Packit |
f574b8 |
FormatStr(&buf, start, tmp);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
case 's': /* size in bytes */
|
|
Packit |
f574b8 |
FormatSize(&buf, start, data->file_info.st_size);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
case 'K': /* size in Kilobytes but not for directories */
|
|
Packit |
f574b8 |
if (S_ISDIR(data->file_info.st_mode)) {
|
|
Packit |
f574b8 |
FormatStr(&buf, start, "");
|
|
Packit |
f574b8 |
StrAllocCat(buf, " ");
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
/* FALL THROUGH */
|
|
Packit |
f574b8 |
case 'k': /* size in Kilobytes */
|
|
Packit |
f574b8 |
FormatSize(&buf, start, ((data->file_info.st_size + 1023) / 1024));
|
|
Packit |
f574b8 |
StrAllocCat(buf, "K");
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
case 'p': /* unix-style permission bits */
|
|
Packit |
f574b8 |
switch (data->file_info.st_mode & S_IFMT) {
|
|
Packit |
f574b8 |
#if defined(_MSC_VER) && defined(_S_IFIFO)
|
|
Packit |
f574b8 |
case _S_IFIFO:
|
|
Packit |
f574b8 |
type = 'p';
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
case S_IFIFO:
|
|
Packit |
f574b8 |
type = 'p';
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
case S_IFCHR:
|
|
Packit |
f574b8 |
type = 'c';
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case S_IFDIR:
|
|
Packit |
f574b8 |
type = 'd';
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case S_IFREG:
|
|
Packit |
f574b8 |
type = '-';
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#ifdef S_IFBLK
|
|
Packit |
f574b8 |
case S_IFBLK:
|
|
Packit |
f574b8 |
type = 'b';
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef S_IFLNK
|
|
Packit |
f574b8 |
case S_IFLNK:
|
|
Packit |
f574b8 |
type = 'l';
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef S_IFSOCK
|
|
Packit |
f574b8 |
# ifdef S_IFIFO /* some older machines (e.g., apollo) have a conflict */
|
|
Packit |
f574b8 |
# if S_IFIFO != S_IFSOCK
|
|
Packit |
f574b8 |
case S_IFSOCK:
|
|
Packit |
f574b8 |
type = 's';
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
# endif
|
|
Packit |
f574b8 |
# else
|
|
Packit |
f574b8 |
case S_IFSOCK:
|
|
Packit |
f574b8 |
type = 's';
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
# endif
|
|
Packit |
f574b8 |
#endif /* S_IFSOCK */
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
type = '?';
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#ifdef _WINDOWS
|
|
Packit |
f574b8 |
sprintf(tmp, "%c%s", type,
|
|
Packit |
f574b8 |
PBIT(data->file_info.st_mode, 6, data->file_info.st_mode & S_IRWXU));
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
sprintf(tmp, "%c%s%s%s", type,
|
|
Packit |
f574b8 |
PBIT(data->file_info.st_mode, 6, data->file_info.st_mode & S_ISUID),
|
|
Packit |
f574b8 |
PBIT(data->file_info.st_mode, 3, data->file_info.st_mode & S_ISGID),
|
|
Packit |
f574b8 |
PTBIT(data->file_info.st_mode, data->file_info.st_mode & S_ISVTX));
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
FormatStr(&buf, start, tmp);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
case 'o': /* owner */
|
|
Packit |
f574b8 |
#ifndef NOUSERS
|
|
Packit |
f574b8 |
name = HTAA_UidToName((int) data->file_info.st_uid);
|
|
Packit |
f574b8 |
if (*name) {
|
|
Packit |
f574b8 |
FormatStr(&buf, start, name);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
FormatNum(&buf, start, (int) data->file_info.st_uid);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
case 'g': /* group */
|
|
Packit |
f574b8 |
#ifndef NOUSERS
|
|
Packit |
f574b8 |
name = HTAA_GidToName((int) data->file_info.st_gid);
|
|
Packit |
f574b8 |
if (*name) {
|
|
Packit |
f574b8 |
FormatStr(&buf, start, name);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
FormatNum(&buf, start, (int) data->file_info.st_gid);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
case 'l': /* link count */
|
|
Packit |
f574b8 |
FormatNum(&buf, start, (int) data->file_info.st_nlink);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
case '%': /* literal % with flags/width */
|
|
Packit |
f574b8 |
FormatStr(&buf, start, "%");
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
fprintf(stderr,
|
|
Packit |
f574b8 |
"Unknown format character `%c' in list format\n", c);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (buf)
|
|
Packit |
f574b8 |
PUTS(buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
s++;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
FREE(buf);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
FREE(str);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* LONG_LIST */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Define the representation associated with a file suffix.
|
|
Packit |
f574b8 |
* --------------------------------------------------------
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* Calling this with suffix set to "*" will set the default
|
|
Packit |
f574b8 |
* representation.
|
|
Packit |
f574b8 |
* Calling this with suffix set to "*.*" will set the default
|
|
Packit |
f574b8 |
* representation for unknown suffix files which contain a ".".
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* The encoding parameter can give a trivial (8bit, 7bit, binary)
|
|
Packit |
f574b8 |
* or real (gzip, compress) encoding.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* If filename suffix is already defined with the same encoding
|
|
Packit |
f574b8 |
* its previous definition is overridden.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
void HTSetSuffix5(const char *suffix,
|
|
Packit |
f574b8 |
const char *representation,
|
|
Packit |
f574b8 |
const char *encoding,
|
|
Packit |
f574b8 |
const char *desc,
|
|
Packit |
f574b8 |
double value)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
HTSuffix *suff;
|
|
Packit |
f574b8 |
BOOL trivial_enc = (BOOL) IsUnityEncStr(encoding);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (strcmp(suffix, s_no_suffix) == 0)
|
|
Packit |
f574b8 |
suff = &no_suffix;
|
|
Packit |
f574b8 |
else if (strcmp(suffix, s_unknown_suffix) == 0)
|
|
Packit |
f574b8 |
suff = &unknown_suffix;
|
|
Packit |
f574b8 |
else {
|
|
Packit |
f574b8 |
HTList *cur = HTSuffixes;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
while (NULL != (suff = (HTSuffix *) HTList_nextObject(cur))) {
|
|
Packit |
f574b8 |
if (suff->suffix && 0 == strcmp(suff->suffix, suffix) &&
|
|
Packit |
f574b8 |
((trivial_enc && IsUnityEnc(suff->encoding)) ||
|
|
Packit |
f574b8 |
(!trivial_enc && !IsUnityEnc(suff->encoding) &&
|
|
Packit |
f574b8 |
strcmp(encoding, HTAtom_name(suff->encoding)) == 0)))
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (!suff) { /* Not found -- create a new node */
|
|
Packit |
f574b8 |
suff = typecalloc(HTSuffix);
|
|
Packit |
f574b8 |
if (suff == NULL)
|
|
Packit |
f574b8 |
outofmem(__FILE__, "HTSetSuffix");
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (!HTSuffixes) {
|
|
Packit |
f574b8 |
HTSuffixes = HTList_new();
|
|
Packit |
f574b8 |
#ifdef LY_FIND_LEAKS
|
|
Packit |
f574b8 |
atexit(free_suffixes);
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
HTList_addObject(HTSuffixes, suff);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrAllocCopy(suff->suffix, suffix);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (representation)
|
|
Packit |
f574b8 |
suff->rep = HTAtom_for(representation);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Memory leak fixed.
|
|
Packit |
f574b8 |
* 05-28-94 Lynx 2-3-1 Garrett Arch Blythe
|
|
Packit |
f574b8 |
* Invariant code removed.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
suff->encoding = HTAtom_for(encoding);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrAllocCopy(suff->desc, desc);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
suff->quality = (float) value;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef LY_FIND_LEAKS
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Purpose: Free all added suffixes.
|
|
Packit |
f574b8 |
* Arguments: void
|
|
Packit |
f574b8 |
* Return Value: void
|
|
Packit |
f574b8 |
* Remarks/Portability/Dependencies/Restrictions:
|
|
Packit |
f574b8 |
* To be used at program exit.
|
|
Packit |
f574b8 |
* Revision History:
|
|
Packit |
f574b8 |
* 05-28-94 created Lynx 2-3-1 Garrett Arch Blythe
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
static void free_suffixes(void)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
HTSuffix *suff = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Loop through all suffixes.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
while (!HTList_isEmpty(HTSuffixes)) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Free off each item and its members if need be.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
suff = (HTSuffix *) HTList_removeLastObject(HTSuffixes);
|
|
Packit |
f574b8 |
FREE(suff->suffix);
|
|
Packit |
f574b8 |
FREE(suff->desc);
|
|
Packit |
f574b8 |
FREE(suff);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Free off the list itself.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
HTList_delete(HTSuffixes);
|
|
Packit |
f574b8 |
HTSuffixes = NULL;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* LY_FIND_LEAKS */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Make the cache file name for a W3 document.
|
|
Packit |
f574b8 |
* -------------------------------------------
|
|
Packit |
f574b8 |
* Make up a suitable name for saving the node in
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* E.g. /tmp/WWW_Cache_news/1234@cernvax.cern.ch
|
|
Packit |
f574b8 |
* /tmp/WWW_Cache_http/crnvmc/FIND/xx.xxx.xx
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* On exit:
|
|
Packit |
f574b8 |
* Returns a malloc'ed string which must be freed by the caller.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
char *HTCacheFileName(const char *name)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *acc_method = HTParse(name, "", PARSE_ACCESS);
|
|
Packit |
f574b8 |
char *host = HTParse(name, "", PARSE_HOST);
|
|
Packit |
f574b8 |
char *path = HTParse(name, "", PARSE_PATH + PARSE_PUNCTUATION);
|
|
Packit |
f574b8 |
char *result = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
HTSprintf0(&result, "%s/WWW/%s/%s%s", HTCacheRoot, acc_method, host, path);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
FREE(path);
|
|
Packit |
f574b8 |
FREE(acc_method);
|
|
Packit |
f574b8 |
FREE(host);
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Open a file for write, creating the path.
|
|
Packit |
f574b8 |
* -----------------------------------------
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
#ifdef NOT_IMPLEMENTED
|
|
Packit |
f574b8 |
static int HTCreatePath(const char *path)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
return -1;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* NOT_IMPLEMENTED */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Convert filename from URL-path syntax to local path format
|
|
Packit |
f574b8 |
* ----------------------------------------------------------
|
|
Packit |
f574b8 |
* Input name is assumed to be the URL-path of a local file
|
|
Packit |
f574b8 |
* URL, i.e. what comes after the "file://localhost".
|
|
Packit |
f574b8 |
* '#'-fragments to be treated as such must already be stripped.
|
|
Packit |
f574b8 |
* If expand_all is FALSE, unescape only escaped '/'. - kw
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* On exit:
|
|
Packit |
f574b8 |
* Returns a malloc'ed string which must be freed by the caller.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
char *HTURLPath_toFile(const char *name,
|
|
Packit |
f574b8 |
int expand_all,
|
|
Packit |
f574b8 |
int is_remote GCC_UNUSED)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *path = NULL;
|
|
Packit |
f574b8 |
char *result = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrAllocCopy(path, name);
|
|
Packit |
f574b8 |
if (expand_all)
|
|
Packit |
f574b8 |
HTUnEscape(path); /* Interpret all % signs */
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
HTUnEscapeSome(path, "/"); /* Interpret % signs for path delims */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "URLPath `%s' means path `%s'\n", name, path));
|
|
Packit |
f574b8 |
#if defined(USE_DOS_DRIVES)
|
|
Packit |
f574b8 |
StrAllocCopy(result, is_remote ? path : HTDOS_name(path));
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
StrAllocCopy(result, path);
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
FREE(path);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
/* Convert filenames between local and WWW formats.
|
|
Packit |
f574b8 |
* ------------------------------------------------
|
|
Packit |
f574b8 |
* Make up a suitable name for saving the node in
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* E.g. $(HOME)/WWW/news/1234@cernvax.cern.ch
|
|
Packit |
f574b8 |
* $(HOME)/WWW/http/crnvmc/FIND/xx.xxx.xx
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* On exit:
|
|
Packit |
f574b8 |
* Returns a malloc'ed string which must be freed by the caller.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
/* NOTE: Don't use this function if you know that the input is a URL path
|
|
Packit |
f574b8 |
rather than a full URL, use HTURLPath_toFile instead. Otherwise
|
|
Packit |
f574b8 |
this function will return the wrong thing for some unusual
|
|
Packit |
f574b8 |
paths (like ones containing "//", possibly escaped). - kw
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
char *HTnameOfFile_WWW(const char *name,
|
|
Packit |
f574b8 |
int WWW_prefix,
|
|
Packit |
f574b8 |
int expand_all)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *acc_method = HTParse(name, "", PARSE_ACCESS);
|
|
Packit |
f574b8 |
char *host = HTParse(name, "", PARSE_HOST);
|
|
Packit |
f574b8 |
char *path = HTParse(name, "", PARSE_PATH + PARSE_PUNCTUATION);
|
|
Packit |
f574b8 |
const char *home;
|
|
Packit |
f574b8 |
char *result = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (expand_all) {
|
|
Packit |
f574b8 |
HTUnEscape(path); /* Interpret all % signs */
|
|
Packit |
f574b8 |
} else
|
|
Packit |
f574b8 |
HTUnEscapeSome(path, "/"); /* Interpret % signs for path delims */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (0 == strcmp(acc_method, "file") /* local file */
|
|
Packit |
f574b8 |
||!*acc_method) { /* implicitly local? */
|
|
Packit |
f574b8 |
if ((0 == strcasecomp(host, HTHostName())) ||
|
|
Packit |
f574b8 |
(0 == strcasecomp(host, "localhost")) || !*host) {
|
|
Packit |
f574b8 |
CTRACE((tfp, "Node `%s' means path `%s'\n", name, path));
|
|
Packit |
f574b8 |
StrAllocCopy(result, HTSYS_name(path));
|
|
Packit |
f574b8 |
} else if (WWW_prefix) {
|
|
Packit |
f574b8 |
HTSprintf0(&result, "%s%s%s", "/Net/", host, path);
|
|
Packit |
f574b8 |
CTRACE((tfp, "Node `%s' means file `%s'\n", name, result));
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
StrAllocCopy(result, path);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} else if (WWW_prefix) { /* other access */
|
|
Packit |
f574b8 |
#ifdef VMS
|
|
Packit |
f574b8 |
if ((home = LYGetEnv("HOME")) == NULL)
|
|
Packit |
f574b8 |
home = HTCacheRoot;
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
home = HTVMS_wwwName(home);
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
#if defined(_WINDOWS) /* 1997/10/16 (Thu) 20:42:51 */
|
|
Packit |
f574b8 |
home = Home_Dir();
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
home = LYGetEnv("HOME");
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
if (home == NULL)
|
|
Packit |
f574b8 |
home = "/tmp";
|
|
Packit |
f574b8 |
#endif /* VMS */
|
|
Packit |
f574b8 |
HTSprintf0(&result, "%s/WWW/%s/%s%s", home, acc_method, host, path);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
StrAllocCopy(result, path);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
FREE(host);
|
|
Packit |
f574b8 |
FREE(path);
|
|
Packit |
f574b8 |
FREE(acc_method);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTnameOfFile_WWW(%s,%d,%d) = %s\n",
|
|
Packit |
f574b8 |
name, WWW_prefix, expand_all, result));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Make a WWW name from a full local path name.
|
|
Packit |
f574b8 |
* --------------------------------------------
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* Bugs:
|
|
Packit |
f574b8 |
* At present, only the names of two network root nodes are hand-coded
|
|
Packit |
f574b8 |
* in and valid for the NeXT only. This should be configurable in
|
|
Packit |
f574b8 |
* the general case.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
char *WWW_nameOfFile(const char *name)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *result = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef NeXT
|
|
Packit |
f574b8 |
if (0 == StrNCmp("/private/Net/", name, 13)) {
|
|
Packit |
f574b8 |
HTSprintf0(&result, "%s//%s", STR_FILE_URL, name + 13);
|
|
Packit |
f574b8 |
} else
|
|
Packit |
f574b8 |
#endif /* NeXT */
|
|
Packit |
f574b8 |
if (0 == StrNCmp(HTMountRoot, name, 5)) {
|
|
Packit |
f574b8 |
HTSprintf0(&result, "%s//%s", STR_FILE_URL, name + 5);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
HTSprintf0(&result, "%s//%s%s", STR_FILE_URL, HTHostName(), name);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
CTRACE((tfp, "File `%s'\n\tmeans node `%s'\n", name, result));
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Determine a suitable suffix, given the representation.
|
|
Packit |
f574b8 |
* ------------------------------------------------------
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* On entry,
|
|
Packit |
f574b8 |
* rep is the atomized MIME style representation
|
|
Packit |
f574b8 |
* enc is an encoding, trivial (8bit, binary, etc.) or gzip etc.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* On exit:
|
|
Packit |
f574b8 |
* Returns a pointer to a suitable suffix string if one has been
|
|
Packit |
f574b8 |
* found, else "".
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
const char *HTFileSuffix(HTAtom *rep,
|
|
Packit |
f574b8 |
const char *enc)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
HTSuffix *suff;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef FNAMES_8_3
|
|
Packit |
f574b8 |
HTSuffix *first_found = NULL;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
BOOL trivial_enc;
|
|
Packit |
f574b8 |
int n;
|
|
Packit |
f574b8 |
int i;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define NO_INIT /* don't init anymore since I do it in Lynx at startup */
|
|
Packit |
f574b8 |
#ifndef NO_INIT
|
|
Packit |
f574b8 |
if (!HTSuffixes)
|
|
Packit |
f574b8 |
HTFileInit();
|
|
Packit |
f574b8 |
#endif /* !NO_INIT */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
trivial_enc = (BOOL) IsUnityEncStr(enc);
|
|
Packit |
f574b8 |
n = HTList_count(HTSuffixes);
|
|
Packit |
f574b8 |
for (i = 0; i < n; i++) {
|
|
Packit |
f574b8 |
suff = (HTSuffix *) HTList_objectAt(HTSuffixes, i);
|
|
Packit |
f574b8 |
if (suff->rep == rep &&
|
|
Packit |
f574b8 |
#if defined(VMS) || defined(FNAMES_8_3)
|
|
Packit |
f574b8 |
/* Don't return a suffix whose first char is a dot, and which
|
|
Packit |
f574b8 |
has more dots or asterisks after that, for
|
|
Packit |
f574b8 |
these systems - kw */
|
|
Packit |
f574b8 |
(!suff->suffix || !suff->suffix[0] || suff->suffix[0] != '.' ||
|
|
Packit |
f574b8 |
(StrChr(suff->suffix + 1, '.') == NULL &&
|
|
Packit |
f574b8 |
StrChr(suff->suffix + 1, '*') == NULL)) &&
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
((trivial_enc && IsUnityEnc(suff->encoding)) ||
|
|
Packit |
f574b8 |
(!trivial_enc && !IsUnityEnc(suff->encoding) &&
|
|
Packit |
f574b8 |
strcmp(enc, HTAtom_name(suff->encoding)) == 0))) {
|
|
Packit |
f574b8 |
#ifdef FNAMES_8_3
|
|
Packit |
f574b8 |
if (suff->suffix && (strlen(suff->suffix) <= 4)) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* If length of suffix (including dot) is 4 or smaller, return
|
|
Packit |
f574b8 |
* this one even if we found a longer one earlier - kw
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
return suff->suffix;
|
|
Packit |
f574b8 |
} else if (!first_found) {
|
|
Packit |
f574b8 |
first_found = suff; /* remember this one */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
return suff->suffix; /* OK -- found */
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#ifdef FNAMES_8_3
|
|
Packit |
f574b8 |
if (first_found)
|
|
Packit |
f574b8 |
return first_found->suffix;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
return ""; /* Dunno */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Trim version from VMS filenames to avoid confusing comparisons.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
#ifdef VMS
|
|
Packit |
f574b8 |
static const char *VMS_trim_version(const char *filename)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
const char *result = filename;
|
|
Packit |
f574b8 |
const char *version = StrChr(filename, ';');
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (version != 0) {
|
|
Packit |
f574b8 |
static char *stripped;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrAllocCopy(stripped, filename);
|
|
Packit |
f574b8 |
stripped[version - filename] = '\0';
|
|
Packit |
f574b8 |
result = (const char *) stripped;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#define VMS_DEL_VERSION(name) name = VMS_trim_version(name)
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
#define VMS_DEL_VERSION(name) /* nothing */
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Determine file format from file name.
|
|
Packit |
f574b8 |
* -------------------------------------
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* This version will return the representation and also set
|
|
Packit |
f574b8 |
* a variable for the encoding.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* Encoding may be a unity encoding (binary, 8bit, etc.) or
|
|
Packit |
f574b8 |
* a content-coding like gzip, compress.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* It will handle for example x.txt, x.txt,Z, x.Z
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
HTFormat HTFileFormat(const char *filename,
|
|
Packit |
f574b8 |
HTAtom **pencoding,
|
|
Packit |
f574b8 |
const char **pdesc)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
HTSuffix *suff;
|
|
Packit |
f574b8 |
int n;
|
|
Packit |
f574b8 |
int i;
|
|
Packit |
f574b8 |
int lf;
|
|
Packit |
f574b8 |
char *search;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
VMS_DEL_VERSION(filename);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if ((search = FindSearch(filename)) != 0) {
|
|
Packit |
f574b8 |
char *newname = NULL;
|
|
Packit |
f574b8 |
HTFormat result;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrAllocCopy(newname, filename);
|
|
Packit |
f574b8 |
newname[((const char *) search) - filename] = '\0';
|
|
Packit |
f574b8 |
result = HTFileFormat(newname, pencoding, pdesc);
|
|
Packit |
f574b8 |
free(newname);
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (pencoding)
|
|
Packit |
f574b8 |
*pencoding = NULL;
|
|
Packit |
f574b8 |
if (pdesc)
|
|
Packit |
f574b8 |
*pdesc = NULL;
|
|
Packit |
f574b8 |
if (LYforce_HTML_mode) {
|
|
Packit |
f574b8 |
if (pencoding)
|
|
Packit |
f574b8 |
*pencoding = WWW_ENC_8BIT;
|
|
Packit |
f574b8 |
return WWW_HTML;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#ifndef NO_INIT
|
|
Packit |
f574b8 |
if (!HTSuffixes)
|
|
Packit |
f574b8 |
HTFileInit();
|
|
Packit |
f574b8 |
#endif /* !NO_INIT */
|
|
Packit |
f574b8 |
lf = (int) strlen(filename);
|
|
Packit |
f574b8 |
n = HTList_count(HTSuffixes);
|
|
Packit |
f574b8 |
for (i = 0; i < n; i++) {
|
|
Packit |
f574b8 |
int ls;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
suff = (HTSuffix *) HTList_objectAt(HTSuffixes, i);
|
|
Packit |
f574b8 |
ls = (int) strlen(suff->suffix);
|
|
Packit |
f574b8 |
if ((ls <= lf) && 0 == strcasecomp(suff->suffix, filename + lf - ls)) {
|
|
Packit |
f574b8 |
int j;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (pencoding)
|
|
Packit |
f574b8 |
*pencoding = suff->encoding;
|
|
Packit |
f574b8 |
if (pdesc)
|
|
Packit |
f574b8 |
*pdesc = suff->desc;
|
|
Packit |
f574b8 |
if (suff->rep) {
|
|
Packit |
f574b8 |
return suff->rep; /* OK -- found */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
for (j = 0; j < n; j++) { /* Got encoding, need representation */
|
|
Packit |
f574b8 |
int ls2;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
suff = (HTSuffix *) HTList_objectAt(HTSuffixes, j);
|
|
Packit |
f574b8 |
ls2 = (int) strlen(suff->suffix);
|
|
Packit |
f574b8 |
if ((ls + ls2 <= lf) &&
|
|
Packit |
f574b8 |
!strncasecomp(suff->suffix,
|
|
Packit |
f574b8 |
filename + lf - ls - ls2, ls2)) {
|
|
Packit |
f574b8 |
if (suff->rep) {
|
|
Packit |
f574b8 |
if (pdesc && !(*pdesc))
|
|
Packit |
f574b8 |
*pdesc = suff->desc;
|
|
Packit |
f574b8 |
if (pencoding && IsUnityEnc(*pencoding) &&
|
|
Packit |
f574b8 |
*pencoding != WWW_ENC_7BIT &&
|
|
Packit |
f574b8 |
!IsUnityEnc(suff->encoding))
|
|
Packit |
f574b8 |
*pencoding = suff->encoding;
|
|
Packit |
f574b8 |
return suff->rep;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* defaults tree */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
suff = (StrChr(filename, '.')
|
|
Packit |
f574b8 |
? (unknown_suffix.rep
|
|
Packit |
f574b8 |
? &unknown_suffix
|
|
Packit |
f574b8 |
: &no_suffix)
|
|
Packit |
f574b8 |
: &no_suffix);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Set default encoding unless found with suffix already.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (pencoding && !*pencoding) {
|
|
Packit |
f574b8 |
*pencoding = (suff->encoding
|
|
Packit |
f574b8 |
? suff->encoding
|
|
Packit |
f574b8 |
: HTAtom_for("binary"));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return suff->rep ? suff->rep : WWW_BINARY;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Revise the file format in relation to the Lynx charset. - FM
|
|
Packit |
f574b8 |
* -------------------------------------------------------
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* This checks the format associated with an anchor for
|
|
Packit |
f574b8 |
* an extended MIME Content-Type, and if a charset is
|
|
Packit |
f574b8 |
* indicated, sets Lynx up for proper handling in relation
|
|
Packit |
f574b8 |
* to the currently selected character set. - FM
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
HTFormat HTCharsetFormat(HTFormat format,
|
|
Packit |
f574b8 |
HTParentAnchor *anchor,
|
|
Packit |
f574b8 |
int default_LYhndl)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *cp = NULL, *cp1, *cp2, *cp3 = NULL, *cp4;
|
|
Packit |
f574b8 |
BOOL chartrans_ok = FALSE;
|
|
Packit |
f574b8 |
int chndl = -1;
|
|
Packit |
f574b8 |
const char *format_name = format->name;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
FREE(anchor->charset);
|
|
Packit |
f574b8 |
if (format_name == 0)
|
|
Packit |
f574b8 |
format_name = "";
|
|
Packit |
f574b8 |
StrAllocCopy(cp, format_name);
|
|
Packit |
f574b8 |
LYLowerCase(cp);
|
|
Packit |
f574b8 |
if (((cp1 = StrChr(cp, ';')) != NULL) &&
|
|
Packit |
f574b8 |
(cp2 = strstr(cp1, "charset")) != NULL) {
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTCharsetFormat: Extended MIME Content-Type is %s\n",
|
|
Packit |
f574b8 |
format_name));
|
|
Packit |
f574b8 |
cp2 += 7;
|
|
Packit |
f574b8 |
while (*cp2 == ' ' || *cp2 == '=')
|
|
Packit |
f574b8 |
cp2++;
|
|
Packit |
f574b8 |
StrAllocCopy(cp3, cp2); /* copy to mutilate more */
|
|
Packit |
f574b8 |
for (cp4 = cp3; (*cp4 != '\0' && *cp4 != '"' &&
|
|
Packit |
f574b8 |
*cp4 != ';' && *cp4 != ':' &&
|
|
Packit |
f574b8 |
!WHITE(*cp4)); cp4++) {
|
|
Packit |
f574b8 |
; /* do nothing */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
*cp4 = '\0';
|
|
Packit |
f574b8 |
cp4 = cp3;
|
|
Packit |
f574b8 |
chndl = UCGetLYhndl_byMIME(cp3);
|
|
Packit |
f574b8 |
if (UCCanTranslateFromTo(chndl, current_char_set)) {
|
|
Packit |
f574b8 |
chartrans_ok = YES;
|
|
Packit |
f574b8 |
*cp1 = '\0';
|
|
Packit |
f574b8 |
format = HTAtom_for(cp);
|
|
Packit |
f574b8 |
StrAllocCopy(anchor->charset, cp4);
|
|
Packit |
f574b8 |
HTAnchor_setUCInfoStage(anchor, chndl,
|
|
Packit |
f574b8 |
UCT_STAGE_MIME,
|
|
Packit |
f574b8 |
UCT_SETBY_MIME);
|
|
Packit |
f574b8 |
} else if (chndl < 0) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Got something but we don't recognize it.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
chndl = UCLYhndl_for_unrec;
|
|
Packit |
f574b8 |
if (chndl < 0)
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* UCLYhndl_for_unrec not defined :-( fallback to
|
|
Packit |
f574b8 |
* UCLYhndl_for_unspec which always valid.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
chndl = UCLYhndl_for_unspec; /* always >= 0 */
|
|
Packit |
f574b8 |
if (UCCanTranslateFromTo(chndl, current_char_set)) {
|
|
Packit |
f574b8 |
chartrans_ok = YES;
|
|
Packit |
f574b8 |
HTAnchor_setUCInfoStage(anchor, chndl,
|
|
Packit |
f574b8 |
UCT_STAGE_MIME,
|
|
Packit |
f574b8 |
UCT_SETBY_DEFAULT);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (chartrans_ok) {
|
|
Packit |
f574b8 |
LYUCcharset *p_in = HTAnchor_getUCInfoStage(anchor,
|
|
Packit |
f574b8 |
UCT_STAGE_MIME);
|
|
Packit |
f574b8 |
LYUCcharset *p_out = HTAnchor_setUCInfoStage(anchor,
|
|
Packit |
f574b8 |
current_char_set,
|
|
Packit |
f574b8 |
UCT_STAGE_HTEXT,
|
|
Packit |
f574b8 |
UCT_SETBY_DEFAULT);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (!p_out) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Try again.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
p_out = HTAnchor_getUCInfoStage(anchor, UCT_STAGE_HTEXT);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (!strcmp(p_in->MIMEname, "x-transparent")) {
|
|
Packit |
f574b8 |
HTPassEightBitRaw = TRUE;
|
|
Packit |
f574b8 |
HTAnchor_setUCInfoStage(anchor,
|
|
Packit |
f574b8 |
HTAnchor_getUCLYhndl(anchor,
|
|
Packit |
f574b8 |
UCT_STAGE_HTEXT),
|
|
Packit |
f574b8 |
UCT_STAGE_MIME,
|
|
Packit |
f574b8 |
UCT_SETBY_DEFAULT);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (!strcmp(p_out->MIMEname, "x-transparent")) {
|
|
Packit |
f574b8 |
HTPassEightBitRaw = TRUE;
|
|
Packit |
f574b8 |
HTAnchor_setUCInfoStage(anchor,
|
|
Packit |
f574b8 |
HTAnchor_getUCLYhndl(anchor,
|
|
Packit |
f574b8 |
UCT_STAGE_MIME),
|
|
Packit |
f574b8 |
UCT_STAGE_HTEXT,
|
|
Packit |
f574b8 |
UCT_SETBY_DEFAULT);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (p_in->enc != UCT_ENC_CJK) {
|
|
Packit |
f574b8 |
HTCJK = NOCJK;
|
|
Packit |
f574b8 |
if (!(p_in->codepoints &
|
|
Packit |
f574b8 |
UCT_CP_SUBSETOF_LAT1) &&
|
|
Packit |
f574b8 |
chndl == current_char_set) {
|
|
Packit |
f574b8 |
HTPassEightBitRaw = TRUE;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} else if (p_out->enc == UCT_ENC_CJK) {
|
|
Packit |
f574b8 |
Set_HTCJK(p_in->MIMEname, p_out->MIMEname);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Cannot translate. If according to some heuristic the given
|
|
Packit |
f574b8 |
* charset and the current display character both are likely to be
|
|
Packit |
f574b8 |
* like ISO-8859 in structure, pretend we have some kind of match.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
BOOL given_is_8859 = (BOOL) (!StrNCmp(cp4, "iso-8859-", 9) &&
|
|
Packit |
f574b8 |
isdigit(UCH(cp4[9])));
|
|
Packit |
f574b8 |
BOOL given_is_8859like = (BOOL) (given_is_8859 ||
|
|
Packit |
f574b8 |
!StrNCmp(cp4, "windows-", 8) ||
|
|
Packit |
f574b8 |
!StrNCmp(cp4, "cp12", 4) ||
|
|
Packit |
f574b8 |
!StrNCmp(cp4, "cp-12", 5));
|
|
Packit |
f574b8 |
BOOL given_and_display_8859like = (BOOL) (given_is_8859like &&
|
|
Packit |
f574b8 |
(strstr(LYchar_set_names[current_char_set],
|
|
Packit |
f574b8 |
"ISO-8859") ||
|
|
Packit |
f574b8 |
strstr(LYchar_set_names[current_char_set],
|
|
Packit |
f574b8 |
"windows-")));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (given_and_display_8859like) {
|
|
Packit |
f574b8 |
*cp1 = '\0';
|
|
Packit |
f574b8 |
format = HTAtom_for(cp);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (given_is_8859) {
|
|
Packit |
f574b8 |
cp1 = &cp4[10];
|
|
Packit |
f574b8 |
while (*cp1 &&
|
|
Packit |
f574b8 |
isdigit(UCH(*cp1)))
|
|
Packit |
f574b8 |
cp1++;
|
|
Packit |
f574b8 |
*cp1 = '\0';
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (given_and_display_8859like) {
|
|
Packit |
f574b8 |
StrAllocCopy(anchor->charset, cp4);
|
|
Packit |
f574b8 |
HTPassEightBitRaw = TRUE;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
HTAlert(*cp4 ? cp4 : anchor->charset);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
FREE(cp3);
|
|
Packit |
f574b8 |
} else if (cp1 != NULL) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* No charset parameter is present. Ignore all other parameters, as we
|
|
Packit |
f574b8 |
* do when charset is present. - FM
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
*cp1 = '\0';
|
|
Packit |
f574b8 |
format = HTAtom_for(cp);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
FREE(cp);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Set up defaults, if needed. - FM
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (!chartrans_ok && !anchor->charset && default_LYhndl >= 0) {
|
|
Packit |
f574b8 |
HTAnchor_setUCInfoStage(anchor, default_LYhndl,
|
|
Packit |
f574b8 |
UCT_STAGE_MIME,
|
|
Packit |
f574b8 |
UCT_SETBY_DEFAULT);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
HTAnchor_copyUCInfoStage(anchor,
|
|
Packit |
f574b8 |
UCT_STAGE_PARSER,
|
|
Packit |
f574b8 |
UCT_STAGE_MIME,
|
|
Packit |
f574b8 |
-1);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return format;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Get various pieces of meta info from file name.
|
|
Packit |
f574b8 |
* -----------------------------------------------
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* LYGetFileInfo fills in information that can be determined without
|
|
Packit |
f574b8 |
* an actual (new) access to the filesystem, based on current suffix
|
|
Packit |
f574b8 |
* and character set configuration. If the file has been loaded and
|
|
Packit |
f574b8 |
* parsed before (with the same URL generated here!) and the anchor
|
|
Packit |
f574b8 |
* is still around, some results may be influenced by that (in
|
|
Packit |
f574b8 |
* particular, charset info from a META tag - this is not actually
|
|
Packit |
f574b8 |
* tested!).
|
|
Packit |
f574b8 |
* The caller should not keep pointers to the returned objects around
|
|
Packit |
f574b8 |
* for too long, the valid lifetimes vary. In particular, the returned
|
|
Packit |
f574b8 |
* charset string should be copied if necessary. If return of the
|
|
Packit |
f574b8 |
* file_anchor is requested, that one can be used to retrieve
|
|
Packit |
f574b8 |
* additional bits of info that are stored in the anchor object and
|
|
Packit |
f574b8 |
* are not covered here; as usual, don't keep pointers to the
|
|
Packit |
f574b8 |
* file_anchor longer than necessary since the object may disappear
|
|
Packit |
f574b8 |
* through HTuncache_current_document or at the next document load.
|
|
Packit |
f574b8 |
* - kw
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
void LYGetFileInfo(const char *filename,
|
|
Packit |
f574b8 |
HTParentAnchor **pfile_anchor,
|
|
Packit |
f574b8 |
HTFormat *pformat,
|
|
Packit |
f574b8 |
HTAtom **pencoding,
|
|
Packit |
f574b8 |
const char **pdesc,
|
|
Packit |
f574b8 |
const char **pcharset,
|
|
Packit |
f574b8 |
int *pfile_cs)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *Afn;
|
|
Packit |
f574b8 |
char *Aname = NULL;
|
|
Packit |
f574b8 |
HTFormat format;
|
|
Packit |
f574b8 |
HTAtom *myEnc = NULL;
|
|
Packit |
f574b8 |
HTParentAnchor *file_anchor;
|
|
Packit |
f574b8 |
const char *file_csname;
|
|
Packit |
f574b8 |
int file_cs;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Convert filename to URL. Note that it is always supposed to be a
|
|
Packit |
f574b8 |
* filename, not maybe-filename-maybe-URL, so we don't use
|
|
Packit |
f574b8 |
* LYFillLocalFileURL and LYEnsureAbsoluteURL. - kw
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
Afn = HTEscape(filename, URL_PATH);
|
|
Packit |
f574b8 |
LYLocalFileToURL(&Aname, Afn);
|
|
Packit |
f574b8 |
file_anchor = HTAnchor_findSimpleAddress(Aname);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
format = HTFileFormat(filename, &myEnc, pdesc);
|
|
Packit |
f574b8 |
format = HTCharsetFormat(format, file_anchor, UCLYhndl_HTFile_for_unspec);
|
|
Packit |
f574b8 |
file_cs = HTAnchor_getUCLYhndl(file_anchor, UCT_STAGE_MIME);
|
|
Packit |
f574b8 |
file_csname = file_anchor->charset;
|
|
Packit |
f574b8 |
if (!file_csname) {
|
|
Packit |
f574b8 |
if (file_cs >= 0)
|
|
Packit |
f574b8 |
file_csname = LYCharSet_UC[file_cs].MIMEname;
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
file_csname = "display character set";
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
CTRACE((tfp, "GetFileInfo: '%s' is a%s %s %s file, charset=%s (%d).\n",
|
|
Packit |
f574b8 |
filename,
|
|
Packit |
f574b8 |
((myEnc && *HTAtom_name(myEnc) == '8') ? "n" : myEnc ? "" :
|
|
Packit |
f574b8 |
*HTAtom_name(format) == 'a' ? "n" : ""),
|
|
Packit |
f574b8 |
myEnc ? HTAtom_name(myEnc) : "",
|
|
Packit |
f574b8 |
HTAtom_name(format),
|
|
Packit |
f574b8 |
file_csname,
|
|
Packit |
f574b8 |
file_cs));
|
|
Packit |
f574b8 |
FREE(Afn);
|
|
Packit |
f574b8 |
FREE(Aname);
|
|
Packit |
f574b8 |
if (pfile_anchor)
|
|
Packit |
f574b8 |
*pfile_anchor = file_anchor;
|
|
Packit |
f574b8 |
if (pformat)
|
|
Packit |
f574b8 |
*pformat = format;
|
|
Packit |
f574b8 |
if (pencoding)
|
|
Packit |
f574b8 |
*pencoding = myEnc;
|
|
Packit |
f574b8 |
if (pcharset)
|
|
Packit |
f574b8 |
*pcharset = file_csname;
|
|
Packit |
f574b8 |
if (pfile_cs)
|
|
Packit |
f574b8 |
*pfile_cs = file_cs;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Determine value from file name.
|
|
Packit |
f574b8 |
* -------------------------------
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
float HTFileValue(const char *filename)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
HTSuffix *suff;
|
|
Packit |
f574b8 |
int n;
|
|
Packit |
f574b8 |
int i;
|
|
Packit |
f574b8 |
int lf = (int) strlen(filename);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifndef NO_INIT
|
|
Packit |
f574b8 |
if (!HTSuffixes)
|
|
Packit |
f574b8 |
HTFileInit();
|
|
Packit |
f574b8 |
#endif /* !NO_INIT */
|
|
Packit |
f574b8 |
n = HTList_count(HTSuffixes);
|
|
Packit |
f574b8 |
for (i = 0; i < n; i++) {
|
|
Packit |
f574b8 |
int ls;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
suff = (HTSuffix *) HTList_objectAt(HTSuffixes, i);
|
|
Packit |
f574b8 |
ls = (int) strlen(suff->suffix);
|
|
Packit |
f574b8 |
if ((ls <= lf) && 0 == strcmp(suff->suffix, filename + lf - ls)) {
|
|
Packit |
f574b8 |
CTRACE((tfp, "File: Value of %s is %.3f\n",
|
|
Packit |
f574b8 |
filename, suff->quality));
|
|
Packit |
f574b8 |
return suff->quality; /* OK -- found */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return (float) 0.3; /* Dunno! */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Determine compression type from file name, by looking at its suffix.
|
|
Packit |
f574b8 |
* Sets as side-effect a pointer to the "dot" that begins the suffix.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
CompressFileType HTCompressFileType(const char *filename,
|
|
Packit |
f574b8 |
const char *dots,
|
|
Packit |
f574b8 |
int *rootlen)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
CompressFileType result = cftNone;
|
|
Packit |
f574b8 |
char *search;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if ((search = FindSearch(filename)) != 0) {
|
|
Packit |
f574b8 |
char *newname = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrAllocCopy(newname, filename);
|
|
Packit |
f574b8 |
newname[((const char *) search) - filename] = '\0';
|
|
Packit |
f574b8 |
result = HTCompressFileType(newname, dots, rootlen);
|
|
Packit |
f574b8 |
free(newname);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
size_t len;
|
|
Packit |
f574b8 |
const char *ftype;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
VMS_DEL_VERSION(filename);
|
|
Packit |
f574b8 |
len = strlen(filename);
|
|
Packit |
f574b8 |
ftype = filename + len;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if ((len > 4)
|
|
Packit |
f574b8 |
&& !strcasecomp((ftype - 3), "bz2")
|
|
Packit |
f574b8 |
&& StrChr(dots, ftype[-4]) != 0) {
|
|
Packit |
f574b8 |
result = cftBzip2;
|
|
Packit |
f574b8 |
ftype -= 4;
|
|
Packit |
f574b8 |
} else if ((len > 3)
|
|
Packit |
f574b8 |
&& !strcasecomp((ftype - 2), "gz")
|
|
Packit |
f574b8 |
&& StrChr(dots, ftype[-3]) != 0) {
|
|
Packit |
f574b8 |
result = cftGzip;
|
|
Packit |
f574b8 |
ftype -= 3;
|
|
Packit |
f574b8 |
} else if ((len > 3)
|
|
Packit |
f574b8 |
&& !strcasecomp((ftype - 2), "zz")
|
|
Packit |
f574b8 |
&& StrChr(dots, ftype[-3]) != 0) {
|
|
Packit |
f574b8 |
result = cftDeflate;
|
|
Packit |
f574b8 |
ftype -= 3;
|
|
Packit |
f574b8 |
} else if ((len > 2)
|
|
Packit |
f574b8 |
&& !strcmp((ftype - 1), "Z")
|
|
Packit |
f574b8 |
&& StrChr(dots, ftype[-2]) != 0) {
|
|
Packit |
f574b8 |
result = cftCompress;
|
|
Packit |
f574b8 |
ftype -= 2;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
*rootlen = (int) (ftype - filename);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTCompressFileType(%s) returns %d:%s\n",
|
|
Packit |
f574b8 |
filename, (int) result, filename + *rootlen));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Determine expected file-suffix from the compression method.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
const char *HTCompressTypeToSuffix(CompressFileType method)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
const char *result = "";
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
switch (method) {
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
case cftNone:
|
|
Packit |
f574b8 |
result = "";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftGzip:
|
|
Packit |
f574b8 |
result = ".gz";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftCompress:
|
|
Packit |
f574b8 |
result = ".Z";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftBzip2:
|
|
Packit |
f574b8 |
result = ".bz2";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftDeflate:
|
|
Packit |
f574b8 |
result = ".zz";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Determine compression encoding from the compression method.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
const char *HTCompressTypeToEncoding(CompressFileType method)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
const char *result = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
switch (method) {
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
case cftNone:
|
|
Packit |
f574b8 |
result = NULL;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftGzip:
|
|
Packit |
f574b8 |
result = "gzip";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftCompress:
|
|
Packit |
f574b8 |
result = "compress";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftBzip2:
|
|
Packit |
f574b8 |
result = "bzip2";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftDeflate:
|
|
Packit |
f574b8 |
result = "deflate";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Check if the token from "Content-Encoding" corresponds to a compression
|
|
Packit |
f574b8 |
* type. RFC 2068 (and cut/paste into RFC 2616) lists these:
|
|
Packit |
f574b8 |
* gzip
|
|
Packit |
f574b8 |
* compress
|
|
Packit |
f574b8 |
* deflate
|
|
Packit |
f574b8 |
* as well as "identity" (but that does nothing).
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
CompressFileType HTEncodingToCompressType(const char *coding)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
CompressFileType result = cftNone;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (coding == NULL) {
|
|
Packit |
f574b8 |
result = cftNone;
|
|
Packit |
f574b8 |
} else if (!strcasecomp(coding, "gzip") ||
|
|
Packit |
f574b8 |
!strcasecomp(coding, "x-gzip")) {
|
|
Packit |
f574b8 |
result = cftGzip;
|
|
Packit |
f574b8 |
} else if (!strcasecomp(coding, "compress") ||
|
|
Packit |
f574b8 |
!strcasecomp(coding, "x-compress")) {
|
|
Packit |
f574b8 |
result = cftCompress;
|
|
Packit |
f574b8 |
} else if (!strcasecomp(coding, "bzip2") ||
|
|
Packit |
f574b8 |
!strcasecomp(coding, "x-bzip2")) {
|
|
Packit |
f574b8 |
result = cftBzip2;
|
|
Packit |
f574b8 |
} else if (!strcasecomp(coding, "deflate") ||
|
|
Packit |
f574b8 |
!strcasecomp(coding, "x-deflate")) {
|
|
Packit |
f574b8 |
result = cftDeflate;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CompressFileType HTContentTypeToCompressType(const char *ct)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
CompressFileType method = cftNone;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (ct == NULL) {
|
|
Packit |
f574b8 |
method = cftNone;
|
|
Packit |
f574b8 |
} else if (!strncasecomp(ct, "application/gzip", 16) ||
|
|
Packit |
f574b8 |
!strncasecomp(ct, "application/x-gzip", 18)) {
|
|
Packit |
f574b8 |
method = cftGzip;
|
|
Packit |
f574b8 |
} else if (!strncasecomp(ct, "application/compress", 20) ||
|
|
Packit |
f574b8 |
!strncasecomp(ct, "application/x-compress", 22)) {
|
|
Packit |
f574b8 |
method = cftCompress;
|
|
Packit |
f574b8 |
} else if (!strncasecomp(ct, "application/bzip2", 17) ||
|
|
Packit |
f574b8 |
!strncasecomp(ct, "application/x-bzip2", 19)) {
|
|
Packit |
f574b8 |
method = cftBzip2;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return method;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Check the anchor's content_type and content_encoding elements for a gzip or
|
|
Packit |
f574b8 |
* Unix compressed file -FM, TD
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
CompressFileType HTContentToCompressType(HTParentAnchor *anchor)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
CompressFileType method = cftNone;
|
|
Packit |
f574b8 |
const char *ct = HTAnchor_content_type(anchor);
|
|
Packit |
f574b8 |
const char *ce = HTAnchor_content_encoding(anchor);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (ct != 0) {
|
|
Packit |
f574b8 |
method = HTContentTypeToCompressType(ct);
|
|
Packit |
f574b8 |
} else if (ce != 0) {
|
|
Packit |
f574b8 |
method = HTEncodingToCompressType(ce);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return method;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Determine write access to a file.
|
|
Packit |
f574b8 |
* ---------------------------------
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* On exit:
|
|
Packit |
f574b8 |
* Returns YES if file can be accessed and can be written to.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* Bugs:
|
|
Packit |
f574b8 |
* 1. No code for non-unix systems.
|
|
Packit |
f574b8 |
* 2. Isn't there a quicker way?
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
BOOL HTEditable(const char *filename GCC_UNUSED)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
#ifndef NO_GROUPS
|
|
Packit |
f574b8 |
GETGROUPS_T groups[NGROUPS];
|
|
Packit |
f574b8 |
uid_t myUid;
|
|
Packit |
f574b8 |
int ngroups; /* The number of groups */
|
|
Packit |
f574b8 |
struct stat fileStatus;
|
|
Packit |
f574b8 |
int i;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (stat(filename, &fileStatus)) /* Get details of filename */
|
|
Packit |
f574b8 |
return NO; /* Can't even access file! */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
ngroups = getgroups(NGROUPS, groups); /* Groups to which I belong */
|
|
Packit |
f574b8 |
myUid = geteuid(); /* Get my user identifier */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (TRACE) {
|
|
Packit |
f574b8 |
int i2;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
fprintf(tfp,
|
|
Packit |
f574b8 |
"File mode is 0%o, uid=%d, gid=%d. My uid=%d, %d groups (",
|
|
Packit |
f574b8 |
(unsigned int) fileStatus.st_mode,
|
|
Packit |
f574b8 |
(int) fileStatus.st_uid,
|
|
Packit |
f574b8 |
(int) fileStatus.st_gid,
|
|
Packit |
f574b8 |
(int) myUid,
|
|
Packit |
f574b8 |
(int) ngroups);
|
|
Packit |
f574b8 |
for (i2 = 0; i2 < ngroups; i2++)
|
|
Packit |
f574b8 |
fprintf(tfp, " %d", (int) groups[i2]);
|
|
Packit |
f574b8 |
fprintf(tfp, ")\n");
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (fileStatus.st_mode & 0002) /* I can write anyway? */
|
|
Packit |
f574b8 |
return YES;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if ((fileStatus.st_mode & 0200) /* I can write my own file? */
|
|
Packit |
f574b8 |
&&(fileStatus.st_uid == myUid))
|
|
Packit |
f574b8 |
return YES;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (fileStatus.st_mode & 0020) /* Group I am in can write? */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
for (i = 0; i < ngroups; i++) {
|
|
Packit |
f574b8 |
if (groups[i] == fileStatus.st_gid)
|
|
Packit |
f574b8 |
return YES;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
CTRACE((tfp, "\tFile is not editable.\n"));
|
|
Packit |
f574b8 |
#endif /* NO_GROUPS */
|
|
Packit |
f574b8 |
return NO; /* If no excuse, can't do */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Make a save stream.
|
|
Packit |
f574b8 |
* -------------------
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* The stream must be used for writing back the file.
|
|
Packit |
f574b8 |
* @@@ no backup done
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
HTStream *HTFileSaveStream(HTParentAnchor *anchor)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
const char *addr = anchor->address;
|
|
Packit |
f574b8 |
char *localname = HTLocalName(addr);
|
|
Packit |
f574b8 |
FILE *fp = fopen(localname, BIN_W);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
FREE(localname);
|
|
Packit |
f574b8 |
if (!fp)
|
|
Packit |
f574b8 |
return NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return HTFWriter_new(fp);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Output one directory entry.
|
|
Packit |
f574b8 |
* ---------------------------
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
void HTDirEntry(HTStructured * target, const char *tail, const char *entry)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *relative = NULL;
|
|
Packit |
f574b8 |
char *stripped = NULL;
|
|
Packit |
f574b8 |
char *escaped = NULL;
|
|
Packit |
f574b8 |
int len;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (entry == NULL)
|
|
Packit |
f574b8 |
entry = "";
|
|
Packit |
f574b8 |
StrAllocCopy(escaped, entry);
|
|
Packit |
f574b8 |
LYTrimPathSep(escaped);
|
|
Packit |
f574b8 |
if (strcmp(escaped, "..") != 0) {
|
|
Packit |
f574b8 |
stripped = escaped;
|
|
Packit |
f574b8 |
escaped = HTEscape(stripped, URL_XPALPHAS);
|
|
Packit |
f574b8 |
if (((len = (int) strlen(escaped)) > 2) &&
|
|
Packit |
f574b8 |
escaped[(len - 3)] == '%' &&
|
|
Packit |
f574b8 |
escaped[(len - 2)] == '2' &&
|
|
Packit |
f574b8 |
TOUPPER(escaped[(len - 1)]) == 'F') {
|
|
Packit |
f574b8 |
escaped[(len - 3)] = '\0';
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (isEmpty(tail)) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Handle extra slash at end of path.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
HTStartAnchor(target, NULL, (escaped[0] != '\0' ? escaped : "/"));
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* If empty tail, gives absolute ref below.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
relative = 0;
|
|
Packit |
f574b8 |
HTSprintf0(&relative, "%s%s%s",
|
|
Packit |
f574b8 |
tail,
|
|
Packit |
f574b8 |
(*escaped != '\0' ? "/" : ""),
|
|
Packit |
f574b8 |
escaped);
|
|
Packit |
f574b8 |
HTStartAnchor(target, NULL, relative);
|
|
Packit |
f574b8 |
FREE(relative);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
FREE(stripped);
|
|
Packit |
f574b8 |
FREE(escaped);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static BOOL view_structured(HTFormat format_out)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
BOOL result = FALSE;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef USE_PRETTYSRC
|
|
Packit |
f574b8 |
if (psrc_view
|
|
Packit |
f574b8 |
|| (format_out == HTAtom_for("www/dump")))
|
|
Packit |
f574b8 |
result = TRUE;
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
if (format_out == WWW_SOURCE)
|
|
Packit |
f574b8 |
result = TRUE;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Write a DOCTYPE to the given stream if we happen to want to see the
|
|
Packit |
f574b8 |
* source view, or are dumping source. This is not needed when the source
|
|
Packit |
f574b8 |
* is not visible, since the document is rendered from a HTStructured object.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
void HTStructured_doctype(HTStructured * target, HTFormat format_out)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
if (view_structured(format_out))
|
|
Packit |
f574b8 |
PUTS("\n");
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void HTStructured_meta(HTStructured * target, HTFormat format_out)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
if (view_structured(format_out))
|
|
Packit |
f574b8 |
PUTS("
|
|
Packit |
f574b8 |
"; charset=iso-8859-1\">\n");
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
/* Output parent directory entry.
|
|
Packit |
f574b8 |
* ------------------------------
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* This gives the TITLE and H1 header, and also a link
|
|
Packit |
f574b8 |
* to the parent directory if appropriate.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* On exit:
|
|
Packit |
f574b8 |
* Returns TRUE if an "Up to <parent>" link was not created
|
|
Packit |
f574b8 |
* for a readable local directory because LONG_LIST is defined
|
|
Packit |
f574b8 |
* and NO_PARENT_DIR_REFERENCE is not defined, so that the
|
|
Packit |
f574b8 |
* calling function should use LYListFmtParse() to create a link
|
|
Packit |
f574b8 |
* to the parent directory. Otherwise, it returns FALSE. - FM
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
BOOL HTDirTitles(HTStructured * target, HTParentAnchor *anchor,
|
|
Packit |
f574b8 |
HTFormat format_out,
|
|
Packit |
f574b8 |
int tildeIsTop)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
const char *logical = anchor->address;
|
|
Packit |
f574b8 |
char *path = HTParse(logical, "", PARSE_PATH + PARSE_PUNCTUATION);
|
|
Packit |
f574b8 |
char *current;
|
|
Packit |
f574b8 |
char *cp = NULL;
|
|
Packit |
f574b8 |
BOOL need_parent_link = FALSE;
|
|
Packit |
f574b8 |
int i;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#if defined(USE_DOS_DRIVES)
|
|
Packit |
f574b8 |
BOOL local_link = (strlen(logical) > 18
|
|
Packit |
f574b8 |
&& !strncasecomp(logical, "file://localhost/", 17)
|
|
Packit |
f574b8 |
&& LYIsDosDrive(logical + 17));
|
|
Packit |
f574b8 |
BOOL is_remote = !local_link;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
#define is_remote TRUE
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Check tildeIsTop for treating home directory as Welcome (assume the
|
|
Packit |
f574b8 |
* tilde is not followed by a username). - FM
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (tildeIsTop && !StrNCmp(path, "/~", 2)) {
|
|
Packit |
f574b8 |
if (path[2] == '\0') {
|
|
Packit |
f574b8 |
path[1] = '\0';
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
for (i = 0; path[(i + 2)]; i++) {
|
|
Packit |
f574b8 |
path[i] = path[(i + 2)];
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
path[i] = '\0';
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Trim out the ;type= parameter, if present. - FM
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if ((cp = strrchr(path, ';')) != NULL) {
|
|
Packit |
f574b8 |
if (!strncasecomp((cp + 1), "type=", 5)) {
|
|
Packit |
f574b8 |
if (TOUPPER(*(cp + 6)) == 'D' ||
|
|
Packit |
f574b8 |
TOUPPER(*(cp + 6)) == 'A' ||
|
|
Packit |
f574b8 |
TOUPPER(*(cp + 6)) == 'I')
|
|
Packit |
f574b8 |
*cp = '\0';
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
cp = NULL;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
current = LYPathLeaf(path); /* last part or "" */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *printable = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef DIRED_SUPPORT
|
|
Packit |
f574b8 |
printable = HTURLPath_toFile(((!strncasecomp(path, "/%2F", 4)) /* "//" ? */
|
|
Packit |
f574b8 |
? (path + 1)
|
|
Packit |
f574b8 |
: path),
|
|
Packit |
f574b8 |
TRUE,
|
|
Packit |
f574b8 |
is_remote);
|
|
Packit |
f574b8 |
if (0 == strncasecomp(printable, "/vmsysu:", 8) ||
|
|
Packit |
f574b8 |
0 == strncasecomp(printable, "/anonymou.", 10)) {
|
|
Packit |
f574b8 |
StrAllocCopy(cp, (printable + 1));
|
|
Packit |
f574b8 |
StrAllocCopy(printable, cp);
|
|
Packit |
f574b8 |
FREE(cp);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
StrAllocCopy(printable, current);
|
|
Packit |
f574b8 |
HTUnEscape(printable);
|
|
Packit |
f574b8 |
#endif /* DIRED_SUPPORT */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
HTStructured_doctype(target, format_out);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
START(HTML_HEAD);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
START(HTML_TITLE);
|
|
Packit |
f574b8 |
PUTS(*printable ? printable : WELCOME_MSG);
|
|
Packit |
f574b8 |
PUTS(SEGMENT_DIRECTORY);
|
|
Packit |
f574b8 |
END(HTML_TITLE);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
HTStructured_meta(target, format_out);
|
|
Packit |
f574b8 |
END(HTML_HEAD);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
START(HTML_BODY);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef DIRED_SUPPORT
|
|
Packit |
f574b8 |
START(HTML_H2);
|
|
Packit |
f574b8 |
PUTS(*printable ? SEGMENT_CURRENT_DIR : "");
|
|
Packit |
f574b8 |
PUTS(*printable ? printable : WELCOME_MSG);
|
|
Packit |
f574b8 |
END(HTML_H2);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
START(HTML_H1);
|
|
Packit |
f574b8 |
PUTS(*printable ? printable : WELCOME_MSG);
|
|
Packit |
f574b8 |
END(HTML_H1);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
#endif /* DIRED_SUPPORT */
|
|
Packit |
f574b8 |
if (((0 == strncasecomp(printable, "vmsysu:", 7)) &&
|
|
Packit |
f574b8 |
(cp = StrChr(printable, '.')) != NULL &&
|
|
Packit |
f574b8 |
StrChr(cp, '/') == NULL) ||
|
|
Packit |
f574b8 |
(0 == strncasecomp(printable, "anonymou.", 9) &&
|
|
Packit |
f574b8 |
StrChr(printable, '/') == NULL)) {
|
|
Packit |
f574b8 |
FREE(printable);
|
|
Packit |
f574b8 |
FREE(path);
|
|
Packit |
f574b8 |
return (need_parent_link);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
FREE(printable);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifndef NO_PARENT_DIR_REFERENCE
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Make link back to parent directory.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (current - path > 0
|
|
Packit |
f574b8 |
&& LYIsPathSep(current[-1])
|
|
Packit |
f574b8 |
&& current[0] != '\0') { /* was a slash AND something else too */
|
|
Packit |
f574b8 |
char *parent = NULL;
|
|
Packit |
f574b8 |
char *relative = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
current[-1] = '\0';
|
|
Packit |
f574b8 |
parent = strrchr(path, '/'); /* penultimate slash */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if ((parent &&
|
|
Packit |
f574b8 |
(!strcmp(parent, "/..") ||
|
|
Packit |
f574b8 |
!strncasecomp(parent, "/%2F", 4))) ||
|
|
Packit |
f574b8 |
!strncasecomp(current, "%2F", 3)) {
|
|
Packit |
f574b8 |
FREE(path);
|
|
Packit |
f574b8 |
return (need_parent_link);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
relative = 0;
|
|
Packit |
f574b8 |
HTSprintf0(&relative, "%s/..", current);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#if defined(DOSPATH) || defined(__EMX__)
|
|
Packit |
f574b8 |
if (local_link) {
|
|
Packit |
f574b8 |
if (parent != 0 && strlen(parent) == 3) {
|
|
Packit |
f574b8 |
StrAllocCat(relative, "/.");
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} else
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#if !defined (VMS)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* On Unix, if it's not ftp and the directory cannot be read, don't
|
|
Packit |
f574b8 |
* put out a link.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* On VMS, this problem is dealt with internally by
|
|
Packit |
f574b8 |
* HTVMSBrowseDir().
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
DIR *dp = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (LYisLocalFile(logical)) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* We need an absolute file path for the opendir. We also need
|
|
Packit |
f574b8 |
* to unescape for this test. Don't worry about %2F now, they
|
|
Packit |
f574b8 |
* presumably have been dealt with above, and shouldn't appear
|
|
Packit |
f574b8 |
* for local files anyway... Assume OS / filesystem will just
|
|
Packit |
f574b8 |
* ignore superfluous slashes. - KW
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
char *fullparentpath = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Path has been shortened above.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
StrAllocCopy(fullparentpath, *path ? path : "/");
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Guard against weirdness.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (0 == strcmp(current, "..")) {
|
|
Packit |
f574b8 |
StrAllocCat(fullparentpath, "/../..");
|
|
Packit |
f574b8 |
} else if (0 == strcmp(current, ".")) {
|
|
Packit |
f574b8 |
StrAllocCat(fullparentpath, "/..");
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
HTUnEscape(fullparentpath);
|
|
Packit |
f574b8 |
if ((dp = opendir(fullparentpath)) == NULL) {
|
|
Packit |
f574b8 |
FREE(fullparentpath);
|
|
Packit |
f574b8 |
FREE(relative);
|
|
Packit |
f574b8 |
FREE(path);
|
|
Packit |
f574b8 |
return (need_parent_link);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
closedir(dp);
|
|
Packit |
f574b8 |
FREE(fullparentpath);
|
|
Packit |
f574b8 |
#ifdef LONG_LIST
|
|
Packit |
f574b8 |
need_parent_link = TRUE;
|
|
Packit |
f574b8 |
FREE(path);
|
|
Packit |
f574b8 |
FREE(relative);
|
|
Packit |
f574b8 |
return (need_parent_link);
|
|
Packit |
f574b8 |
#endif /* LONG_LIST */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* !VMS */
|
|
Packit |
f574b8 |
HTStartAnchor(target, "", relative);
|
|
Packit |
f574b8 |
FREE(relative);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
PUTS(SEGMENT_UP_TO);
|
|
Packit |
f574b8 |
if (parent) {
|
|
Packit |
f574b8 |
if ((0 == strcmp(current, ".")) ||
|
|
Packit |
f574b8 |
(0 == strcmp(current, ".."))) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Should not happen, but if it does, at least avoid giving
|
|
Packit |
f574b8 |
* misleading info. - KW
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
PUTS("..");
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
char *printable = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrAllocCopy(printable, parent + 1);
|
|
Packit |
f574b8 |
HTUnEscape(printable);
|
|
Packit |
f574b8 |
PUTS(printable);
|
|
Packit |
f574b8 |
FREE(printable);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
PUTC('/');
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
END(HTML_A);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* !NO_PARENT_DIR_REFERENCE */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
FREE(path);
|
|
Packit |
f574b8 |
return (need_parent_link);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#if defined HAVE_READDIR
|
|
Packit |
f574b8 |
/* Send README file.
|
|
Packit |
f574b8 |
* -----------------
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* If a README file exists, then it is inserted into the document here.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
static void do_readme(HTStructured * target, const char *localname)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
FILE *fp;
|
|
Packit |
f574b8 |
char *readme_file_name = NULL;
|
|
Packit |
f574b8 |
int ch;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
HTSprintf0(&readme_file_name, "%s/%s", localname, HT_DIR_README_FILE);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
fp = fopen(readme_file_name, "r");
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (fp) {
|
|
Packit |
f574b8 |
START(HTML_PRE);
|
|
Packit |
f574b8 |
while ((ch = fgetc(fp)) != EOF) {
|
|
Packit |
f574b8 |
PUTC((char) ch);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
END(HTML_PRE);
|
|
Packit |
f574b8 |
HTDisplayPartial();
|
|
Packit |
f574b8 |
fclose(fp);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
FREE(readme_file_name);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define DIRED_BLOK(obj) (((DIRED *)(obj))->sort_tags)
|
|
Packit |
f574b8 |
#define DIRED_NAME(obj) (((DIRED *)(obj))->file_name)
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define NM_cmp(a,b) ((a) < (b) ? -1 : ((a) > (b) ? 1 : 0))
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#if defined(LONG_LIST) && defined(DIRED_SUPPORT)
|
|
Packit |
f574b8 |
static const char *file_type(const char *path)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
const char *type;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
while (*path == '.')
|
|
Packit |
f574b8 |
++path;
|
|
Packit |
f574b8 |
type = StrChr(path, '.');
|
|
Packit |
f574b8 |
if (type == NULL)
|
|
Packit |
f574b8 |
type = "";
|
|
Packit |
f574b8 |
return type;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* LONG_LIST && DIRED_SUPPORT */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static int dired_cmp(void *a, void *b)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
DIRED *p = (DIRED *) a;
|
|
Packit |
f574b8 |
DIRED *q = (DIRED *) b;
|
|
Packit |
f574b8 |
int code = p->sort_tags - q->sort_tags;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#if defined(LONG_LIST) && defined(DIRED_SUPPORT)
|
|
Packit |
f574b8 |
if (code == 0) {
|
|
Packit |
f574b8 |
switch (dir_list_order) {
|
|
Packit |
f574b8 |
case ORDER_BY_SIZE:
|
|
Packit |
f574b8 |
code = -NM_cmp(p->file_info.st_size, q->file_info.st_size);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case ORDER_BY_DATE:
|
|
Packit |
f574b8 |
code = -NM_cmp(p->file_info.st_mtime, q->file_info.st_mtime);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case ORDER_BY_MODE:
|
|
Packit |
f574b8 |
code = NM_cmp(p->file_info.st_mode, q->file_info.st_mode);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case ORDER_BY_USER:
|
|
Packit |
f574b8 |
code = NM_cmp(p->file_info.st_uid, q->file_info.st_uid);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case ORDER_BY_GROUP:
|
|
Packit |
f574b8 |
code = NM_cmp(p->file_info.st_gid, q->file_info.st_gid);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case ORDER_BY_TYPE:
|
|
Packit |
f574b8 |
code = AS_cmp(file_type(p->file_name), file_type(q->file_name));
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
code = 0;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* LONG_LIST && DIRED_SUPPORT */
|
|
Packit |
f574b8 |
if (code == 0)
|
|
Packit |
f574b8 |
code = AS_cmp(p->file_name, q->file_name);
|
|
Packit |
f574b8 |
#if 0
|
|
Packit |
f574b8 |
CTRACE((tfp, "dired_cmp(%d) ->%d\n\t%c:%s (%s)\n\t%c:%s (%s)\n",
|
|
Packit |
f574b8 |
dir_list_order,
|
|
Packit |
f574b8 |
code,
|
|
Packit |
f574b8 |
p->sort_tags, p->file_name, file_type(p->file_name),
|
|
Packit |
f574b8 |
q->sort_tags, q->file_name, file_type(q->file_name)));
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
return code;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static int print_local_dir(DIR *dp, char *localname,
|
|
Packit |
f574b8 |
HTParentAnchor *anchor,
|
|
Packit |
f574b8 |
HTFormat format_out,
|
|
Packit |
f574b8 |
HTStream *sink)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
HTStructured *target; /* HTML object */
|
|
Packit |
f574b8 |
HTBTree *bt;
|
|
Packit |
f574b8 |
HTStructuredClass targetClass;
|
|
Packit |
f574b8 |
STRUCT_DIRENT *dirbuf;
|
|
Packit |
f574b8 |
char *pathname = NULL;
|
|
Packit |
f574b8 |
char *tail = NULL;
|
|
Packit |
f574b8 |
const char *p;
|
|
Packit |
f574b8 |
char *tmpfilename = NULL;
|
|
Packit |
f574b8 |
BOOL need_parent_link = FALSE;
|
|
Packit |
f574b8 |
BOOL preformatted = FALSE;
|
|
Packit |
f574b8 |
int status;
|
|
Packit |
f574b8 |
struct stat *actual_info;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef DISP_PARTIAL
|
|
Packit |
f574b8 |
int num_of_entries = 0; /* lines counter */
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef S_IFLNK
|
|
Packit |
f574b8 |
struct stat link_info;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "print_local_dir() started\n"));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
pathname = HTParse(anchor->address, "",
|
|
Packit |
f574b8 |
PARSE_PATH + PARSE_PUNCTUATION);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if ((p = strrchr(pathname, '/')) == NULL)
|
|
Packit |
f574b8 |
p = "/";
|
|
Packit |
f574b8 |
StrAllocCopy(tail, (p + 1));
|
|
Packit |
f574b8 |
FREE(pathname);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (UCLYhndl_HTFile_for_unspec >= 0) {
|
|
Packit |
f574b8 |
HTAnchor_setUCInfoStage(anchor,
|
|
Packit |
f574b8 |
UCLYhndl_HTFile_for_unspec,
|
|
Packit |
f574b8 |
UCT_STAGE_PARSER,
|
|
Packit |
f574b8 |
UCT_SETBY_DEFAULT);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
target = HTML_new(anchor, format_out, sink);
|
|
Packit |
f574b8 |
targetClass = *target->isa; /* Copy routine entry points */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* The need_parent_link flag will be set if an "Up to <parent>" link was
|
|
Packit |
f574b8 |
* not created for a readable parent in HTDirTitles() because LONG_LIST is
|
|
Packit |
f574b8 |
* defined and NO_PARENT_DIR_REFERENCE is not defined so that need we to
|
|
Packit |
f574b8 |
* create the link via an LYListFmtParse() call. - FM
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
need_parent_link = HTDirTitles(target, anchor, format_out, FALSE);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef DIRED_SUPPORT
|
|
Packit |
f574b8 |
if (!isLYNXCGI(anchor->address)) {
|
|
Packit |
f574b8 |
HTAnchor_setFormat(anchor, WWW_DIRED);
|
|
Packit |
f574b8 |
lynx_edit_mode = TRUE;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* DIRED_SUPPORT */
|
|
Packit |
f574b8 |
if (HTDirReadme == HT_DIR_README_TOP)
|
|
Packit |
f574b8 |
do_readme(target, localname);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
bt = HTBTree_new(dired_cmp);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
_HTProgress(READING_DIRECTORY);
|
|
Packit |
f574b8 |
status = HT_LOADED; /* assume we don't get interrupted */
|
|
Packit |
f574b8 |
while ((dirbuf = readdir(dp)) != NULL) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* While there are directory entries to be read...
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
DIRED *data = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef STRUCT_DIRENT__D_INO
|
|
Packit |
f574b8 |
if (dirbuf->d_ino == 0)
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* If the entry is not being used, skip it.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
continue;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Skip self, parent if handled in HTDirTitles() or if
|
|
Packit |
f574b8 |
* NO_PARENT_DIR_REFERENCE is not defined, and any dot files if
|
|
Packit |
f574b8 |
* no_dotfiles is set or show_dotfiles is not set. - FM
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (!strcmp(dirbuf->d_name, ".") /* self */ ||
|
|
Packit |
f574b8 |
(!strcmp(dirbuf->d_name, "..") /* parent */ &&
|
|
Packit |
f574b8 |
need_parent_link == FALSE) ||
|
|
Packit |
f574b8 |
((strcmp(dirbuf->d_name, "..")) &&
|
|
Packit |
f574b8 |
(dirbuf->d_name[0] == '.' &&
|
|
Packit |
f574b8 |
(no_dotfiles || !show_dotfiles))))
|
|
Packit |
f574b8 |
continue;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrAllocCopy(tmpfilename, localname);
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* If filename is not root directory, add trailing separator.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
LYAddPathSep(&tmpfilename);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrAllocCat(tmpfilename, dirbuf->d_name);
|
|
Packit |
f574b8 |
data = (DIRED *) malloc(sizeof(DIRED) + strlen(dirbuf->d_name) + 4);
|
|
Packit |
f574b8 |
if (data == NULL) {
|
|
Packit |
f574b8 |
status = HT_PARTIAL_CONTENT;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
LYTrimPathSep(tmpfilename);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
actual_info = &(data->file_info);
|
|
Packit |
f574b8 |
#ifdef S_IFLNK
|
|
Packit |
f574b8 |
if (lstat(tmpfilename, actual_info) < 0) {
|
|
Packit |
f574b8 |
actual_info->st_mode = 0;
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
if (S_ISLNK(actual_info->st_mode)) {
|
|
Packit |
f574b8 |
actual_info = &link_info;
|
|
Packit |
f574b8 |
if (stat(tmpfilename, actual_info) < 0)
|
|
Packit |
f574b8 |
actual_info->st_mode = 0;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
if (stat(tmpfilename, actual_info) < 0)
|
|
Packit |
f574b8 |
actual_info->st_mode = 0;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
strcpy(data->file_name, dirbuf->d_name);
|
|
Packit |
f574b8 |
#ifndef DIRED_SUPPORT
|
|
Packit |
f574b8 |
if (S_ISDIR(actual_info->st_mode)) {
|
|
Packit |
f574b8 |
data->sort_tags = 'D';
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
data->sort_tags = 'F';
|
|
Packit |
f574b8 |
/* D & F to have first directories, then files */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
if (S_ISDIR(actual_info->st_mode)) {
|
|
Packit |
f574b8 |
if (dir_list_style == MIXED_STYLE) {
|
|
Packit |
f574b8 |
data->sort_tags = ' ';
|
|
Packit |
f574b8 |
LYAddPathSep0(data->file_name);
|
|
Packit |
f574b8 |
} else if (!strcmp(dirbuf->d_name, "..")) {
|
|
Packit |
f574b8 |
data->sort_tags = 'A';
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
data->sort_tags = 'D';
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} else if (dir_list_style == MIXED_STYLE) {
|
|
Packit |
f574b8 |
data->sort_tags = ' ';
|
|
Packit |
f574b8 |
} else if (dir_list_style == FILES_FIRST) {
|
|
Packit |
f574b8 |
data->sort_tags = 'C';
|
|
Packit |
f574b8 |
/* C & D to have first files, then directories */
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
data->sort_tags = 'F';
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* !DIRED_SUPPORT */
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Sort dirname in the tree bt.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
HTBTree_add(bt, data);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef DISP_PARTIAL
|
|
Packit |
f574b8 |
/* optimize for expensive operation: */
|
|
Packit |
f574b8 |
if (num_of_entries % (partial_threshold > 0 ?
|
|
Packit |
f574b8 |
partial_threshold : display_lines) == 0) {
|
|
Packit |
f574b8 |
if (HTCheckForInterrupt()) {
|
|
Packit |
f574b8 |
status = HT_PARTIAL_CONTENT;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
num_of_entries++;
|
|
Packit |
f574b8 |
#endif /* DISP_PARTIAL */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
} /* end while directory entries left to read */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (status != HT_PARTIAL_CONTENT)
|
|
Packit |
f574b8 |
_HTProgress(OPERATION_OK);
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
CTRACE((tfp, "Reading the directory interrupted by user\n"));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Run through tree printing out in order.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
HTBTElement *next_element = HTBTree_next(bt, NULL);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* pick up the first element of the list */
|
|
Packit |
f574b8 |
int num_of_entries_output = 0; /* lines counter */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char state;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* I for initial (.. file),
|
|
Packit |
f574b8 |
D for directory file,
|
|
Packit |
f574b8 |
F for file */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef DIRED_SUPPORT
|
|
Packit |
f574b8 |
char test;
|
|
Packit |
f574b8 |
#endif /* DIRED_SUPPORT */
|
|
Packit |
f574b8 |
state = 'I';
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
while (next_element != NULL) {
|
|
Packit |
f574b8 |
DIRED *entry;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifndef DISP_PARTIAL
|
|
Packit |
f574b8 |
if (num_of_entries_output % HTMAX(display_lines, 10) == 0) {
|
|
Packit |
f574b8 |
if (HTCheckForInterrupt()) {
|
|
Packit |
f574b8 |
_HTProgress(TRANSFER_INTERRUPTED);
|
|
Packit |
f574b8 |
status = HT_PARTIAL_CONTENT;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
StrAllocCopy(tmpfilename, localname);
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* If filename is not root directory.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
LYAddPathSep(&tmpfilename);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
entry = (DIRED *) (HTBTree_object(next_element));
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Append the current entry's filename to the path.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
StrAllocCat(tmpfilename, entry->file_name);
|
|
Packit |
f574b8 |
HTSimplify(tmpfilename);
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Output the directory entry.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (strcmp(DIRED_NAME(HTBTree_object(next_element)), "..")) {
|
|
Packit |
f574b8 |
#ifdef DIRED_SUPPORT
|
|
Packit |
f574b8 |
test =
|
|
Packit |
f574b8 |
(char) (DIRED_BLOK(HTBTree_object(next_element))
|
|
Packit |
f574b8 |
== 'D' ? 'D' : 'F');
|
|
Packit |
f574b8 |
if (state != test) {
|
|
Packit |
f574b8 |
#ifndef LONG_LIST
|
|
Packit |
f574b8 |
if (dir_list_style == FILES_FIRST) {
|
|
Packit |
f574b8 |
if (state == 'F') {
|
|
Packit |
f574b8 |
END(HTML_DIR);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} else if (dir_list_style != MIXED_STYLE)
|
|
Packit |
f574b8 |
if (state == 'D') {
|
|
Packit |
f574b8 |
END(HTML_DIR);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* !LONG_LIST */
|
|
Packit |
f574b8 |
state =
|
|
Packit |
f574b8 |
(char) (DIRED_BLOK(HTBTree_object(next_element))
|
|
Packit |
f574b8 |
== 'D' ? 'D' : 'F');
|
|
Packit |
f574b8 |
if (preformatted) {
|
|
Packit |
f574b8 |
END(HTML_PRE);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
preformatted = FALSE;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
START(HTML_H2);
|
|
Packit |
f574b8 |
if (dir_list_style != MIXED_STYLE) {
|
|
Packit |
f574b8 |
START(HTML_EM);
|
|
Packit |
f574b8 |
PUTS(state == 'D'
|
|
Packit |
f574b8 |
? LABEL_SUBDIRECTORIES
|
|
Packit |
f574b8 |
: LABEL_FILES);
|
|
Packit |
f574b8 |
END(HTML_EM);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
END(HTML_H2);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
#ifndef LONG_LIST
|
|
Packit |
f574b8 |
START(HTML_DIR);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
#endif /* !LONG_LIST */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
if (state != DIRED_BLOK(HTBTree_object(next_element))) {
|
|
Packit |
f574b8 |
#ifndef LONG_LIST
|
|
Packit |
f574b8 |
if (state == 'D') {
|
|
Packit |
f574b8 |
END(HTML_DIR);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* !LONG_LIST */
|
|
Packit |
f574b8 |
state =
|
|
Packit |
f574b8 |
(char) (DIRED_BLOK(HTBTree_object(next_element))
|
|
Packit |
f574b8 |
== 'D' ? 'D' : 'F');
|
|
Packit |
f574b8 |
if (preformatted) {
|
|
Packit |
f574b8 |
END(HTML_PRE);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
preformatted = FALSE;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
START(HTML_H2);
|
|
Packit |
f574b8 |
START(HTML_EM);
|
|
Packit |
f574b8 |
PUTS(state == 'D'
|
|
Packit |
f574b8 |
? LABEL_SUBDIRECTORIES
|
|
Packit |
f574b8 |
: LABEL_FILES);
|
|
Packit |
f574b8 |
END(HTML_EM);
|
|
Packit |
f574b8 |
END(HTML_H2);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
#ifndef LONG_LIST
|
|
Packit |
f574b8 |
START(HTML_DIR);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
#endif /* !LONG_LIST */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* DIRED_SUPPORT */
|
|
Packit |
f574b8 |
#ifndef LONG_LIST
|
|
Packit |
f574b8 |
START(HTML_LI);
|
|
Packit |
f574b8 |
#endif /* !LONG_LIST */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (!preformatted) {
|
|
Packit |
f574b8 |
START(HTML_PRE);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
preformatted = TRUE;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#ifdef LONG_LIST
|
|
Packit |
f574b8 |
LYListFmtParse(list_format, entry, tmpfilename, target, tail);
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
HTDirEntry(target, tail, entry->file_name);
|
|
Packit |
f574b8 |
PUTS(entry->file_name);
|
|
Packit |
f574b8 |
END(HTML_A);
|
|
Packit |
f574b8 |
MAYBE_END(HTML_LI);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
#endif /* LONG_LIST */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
next_element = HTBTree_next(bt, next_element);
|
|
Packit |
f574b8 |
/* pick up the next element of the list;
|
|
Packit |
f574b8 |
if none, return NULL */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* optimize for expensive operation: */
|
|
Packit |
f574b8 |
#ifdef DISP_PARTIAL
|
|
Packit |
f574b8 |
if (num_of_entries_output %
|
|
Packit |
f574b8 |
((partial_threshold > 0)
|
|
Packit |
f574b8 |
? partial_threshold
|
|
Packit |
f574b8 |
: display_lines) == 0) {
|
|
Packit |
f574b8 |
/* num_of_entries, num_of_entries_output... */
|
|
Packit |
f574b8 |
HTDisplayPartial();
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (HTCheckForInterrupt()) {
|
|
Packit |
f574b8 |
_HTProgress(TRANSFER_INTERRUPTED);
|
|
Packit |
f574b8 |
status = HT_PARTIAL_CONTENT;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
num_of_entries_output++;
|
|
Packit |
f574b8 |
#endif /* DISP_PARTIAL */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
} /* end while next_element */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (status == HT_LOADED) {
|
|
Packit |
f574b8 |
if (state == 'I') {
|
|
Packit |
f574b8 |
START(HTML_P);
|
|
Packit |
f574b8 |
PUTS("Empty Directory");
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#ifndef LONG_LIST
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
END(HTML_DIR);
|
|
Packit |
f574b8 |
#endif /* !LONG_LIST */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} /* end printing out the tree in order */
|
|
Packit |
f574b8 |
if (preformatted) {
|
|
Packit |
f574b8 |
END(HTML_PRE);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
END(HTML_BODY);
|
|
Packit |
f574b8 |
PUTC('\n');
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
FREE(tmpfilename);
|
|
Packit |
f574b8 |
FREE(tail);
|
|
Packit |
f574b8 |
HTBTreeAndObject_free(bt);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (status == HT_LOADED) {
|
|
Packit |
f574b8 |
if (HTDirReadme == HT_DIR_README_BOTTOM)
|
|
Packit |
f574b8 |
do_readme(target, localname);
|
|
Packit |
f574b8 |
FREE_TARGET;
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
ABORT_TARGET;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
HTFinishDisplayPartial();
|
|
Packit |
f574b8 |
return status; /* document loaded, maybe partial */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* HAVE_READDIR */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifndef VMS
|
|
Packit |
f574b8 |
int HTStat(const char *filename,
|
|
Packit |
f574b8 |
struct stat *data)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
int result = -1;
|
|
Packit |
f574b8 |
size_t len = strlen(filename);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (len != 0 && LYIsPathSep(filename[len - 1])) {
|
|
Packit |
f574b8 |
char *temp_name = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
HTSprintf0(&temp_name, "%s.", filename);
|
|
Packit |
f574b8 |
result = HTStat(temp_name, data);
|
|
Packit |
f574b8 |
FREE(temp_name);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
result = stat(filename, data);
|
|
Packit |
f574b8 |
#ifdef _WINDOWS
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Someone claims that stat() doesn't give the proper result for a
|
|
Packit |
f574b8 |
* directory on Windows.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (result == -1
|
|
Packit |
f574b8 |
&& access(filename, 0) == 0) {
|
|
Packit |
f574b8 |
data->st_mode = S_IFDIR;
|
|
Packit |
f574b8 |
result = 0;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#if defined(USE_ZLIB) || defined(USE_BZLIB)
|
|
Packit |
f574b8 |
static BOOL sniffStream(FILE *fp, char *buffer, size_t needed)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
long offset = ftell(fp);
|
|
Packit |
f574b8 |
BOOL result = FALSE;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (offset >= 0) {
|
|
Packit |
f574b8 |
if (fread(buffer, sizeof(char), needed, fp) == needed) {
|
|
Packit |
f574b8 |
result = TRUE;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (fseek(fp, offset, SEEK_SET) < 0) {
|
|
Packit |
f574b8 |
CTRACE((tfp, "error seeking in stream\n"));
|
|
Packit |
f574b8 |
result = FALSE;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef USE_ZLIB
|
|
Packit |
f574b8 |
static BOOL isGzipStream(FILE *fp)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char buffer[3];
|
|
Packit |
f574b8 |
BOOL result;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (sniffStream(fp, buffer, sizeof(buffer))
|
|
Packit |
f574b8 |
&& !MemCmp(buffer, "\037\213", sizeof(buffer) - 1)) {
|
|
Packit |
f574b8 |
result = TRUE;
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
CTRACE((tfp, "not a gzip-stream\n"));
|
|
Packit |
f574b8 |
result = FALSE;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Strictly speaking, DEFLATE has no header bytes. But decode what we can,
|
|
Packit |
f574b8 |
* (to eliminate the one "reserved" pattern) and provide a trace. See RFC-1951
|
|
Packit |
f574b8 |
* discussion of BFINAL and BTYPE.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
static BOOL isDeflateStream(FILE *fp)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char buffer[3];
|
|
Packit |
f574b8 |
BOOL result = FALSE;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (sniffStream(fp, buffer, sizeof(buffer))) {
|
|
Packit |
f574b8 |
int bit1 = ((buffer[0] >> 0) & 1);
|
|
Packit |
f574b8 |
int bit2 = ((buffer[0] >> 1) & 1);
|
|
Packit |
f574b8 |
int bit3 = ((buffer[0] >> 2) & 1);
|
|
Packit |
f574b8 |
int btype = ((bit3 << 1) + bit2);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (!MemCmp(buffer, "\170\234", sizeof(buffer) - 1)) {
|
|
Packit |
f574b8 |
result = TRUE;
|
|
Packit |
f574b8 |
CTRACE((tfp, "isDeflate: assume zlib-wrapped deflate\n"));
|
|
Packit |
f574b8 |
} else if (btype == 3) {
|
|
Packit |
f574b8 |
CTRACE((tfp, "isDeflate: not a deflate-stream\n"));
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
CTRACE((tfp, "isDeflate: %send block, %s compression\n",
|
|
Packit |
f574b8 |
(bit1 ? "" : "non-"),
|
|
Packit |
f574b8 |
(btype == 0
|
|
Packit |
f574b8 |
? "no"
|
|
Packit |
f574b8 |
: (btype == 1
|
|
Packit |
f574b8 |
? "static Huffman"
|
|
Packit |
f574b8 |
: "dynamic Huffman"))));
|
|
Packit |
f574b8 |
result = TRUE;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef USE_BZLIB
|
|
Packit |
f574b8 |
static BOOL isBzip2Stream(FILE *fp)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char buffer[6];
|
|
Packit |
f574b8 |
BOOL result;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (sniffStream(fp, buffer, sizeof(buffer))
|
|
Packit |
f574b8 |
&& !MemCmp(buffer, "BZh", 3)
|
|
Packit |
f574b8 |
&& isdigit(UCH(buffer[3]))
|
|
Packit |
f574b8 |
&& isdigit(UCH(buffer[4]))) {
|
|
Packit |
f574b8 |
result = TRUE;
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
CTRACE((tfp, "not a bzip2-stream\n"));
|
|
Packit |
f574b8 |
result = FALSE;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef VMS
|
|
Packit |
f574b8 |
#define FOPEN_MODE(bin) "r", "shr=put", "shr=upd"
|
|
Packit |
f574b8 |
#define DOT_STRING "._-" /* FIXME: should we check if suffix is after ']' or ':' ? */
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
#define FOPEN_MODE(bin) (bin ? BIN_R : "r")
|
|
Packit |
f574b8 |
#define DOT_STRING "."
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static int decompressAndParse(HTParentAnchor *anchor,
|
|
Packit |
f574b8 |
HTFormat format_out,
|
|
Packit |
f574b8 |
HTStream *sink,
|
|
Packit |
f574b8 |
char *nodename GCC_UNUSED,
|
|
Packit |
f574b8 |
char *filename,
|
|
Packit |
f574b8 |
HTAtom *myEncoding,
|
|
Packit |
f574b8 |
HTFormat format,
|
|
Packit |
f574b8 |
int *statusp)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
HTAtom *encoding = 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef USE_ZLIB
|
|
Packit |
f574b8 |
FILE *zzfp = 0;
|
|
Packit |
f574b8 |
gzFile gzfp = 0;
|
|
Packit |
f574b8 |
#endif /* USE_ZLIB */
|
|
Packit |
f574b8 |
#ifdef USE_BZLIB
|
|
Packit |
f574b8 |
BZFILE *bzfp = 0;
|
|
Packit |
f574b8 |
#endif /* USE_ZLIB */
|
|
Packit |
f574b8 |
#if defined(USE_ZLIB) || defined(USE_BZLIB)
|
|
Packit |
f574b8 |
CompressFileType internal_decompress = cftNone;
|
|
Packit |
f574b8 |
BOOL failed_decompress = NO;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
int rootlen = 0;
|
|
Packit |
f574b8 |
char *localname = filename;
|
|
Packit |
f574b8 |
int bin;
|
|
Packit |
f574b8 |
FILE *fp;
|
|
Packit |
f574b8 |
int result = FALSE;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef VMS
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Assume that the file is in Unix-style syntax if it contains a '/' after
|
|
Packit |
f574b8 |
* the leading one. @@
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
localname = (StrChr(localname + 1, '/')
|
|
Packit |
f574b8 |
? HTVMS_name(nodename, localname)
|
|
Packit |
f574b8 |
: localname + 1);
|
|
Packit |
f574b8 |
#endif /* VMS */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
bin = HTCompressFileType(filename, ".", &rootlen) != cftNone;
|
|
Packit |
f574b8 |
fp = fopen(localname, FOPEN_MODE(bin));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef VMS
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* If the file wasn't VMS syntax, then perhaps it is Ultrix.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (!fp) {
|
|
Packit |
f574b8 |
char *ultrixname = 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTLoadFile: Can't open as %s\n", localname));
|
|
Packit |
f574b8 |
HTSprintf0(&ultrixname, "%s::\"%s\"", nodename, filename);
|
|
Packit |
f574b8 |
fp = fopen(ultrixname, FOPEN_MODE(bin));
|
|
Packit |
f574b8 |
if (!fp) {
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTLoadFile: Can't open as %s\n", ultrixname));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
FREE(ultrixname);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* VMS */
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTLoadFile: Opening `%s' gives %p\n", localname, (void *) fp));
|
|
Packit |
f574b8 |
if (fp) { /* Good! */
|
|
Packit |
f574b8 |
if (HTEditable(localname)) {
|
|
Packit |
f574b8 |
HTAtom *put = HTAtom_for("PUT");
|
|
Packit |
f574b8 |
HTList *methods = HTAnchor_methods(anchor);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (HTList_indexOf(methods, put) == (-1)) {
|
|
Packit |
f574b8 |
HTList_addObject(methods, put);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Fake a Content-Encoding for compressed files. - FM
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (!IsUnityEnc(myEncoding)) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* We already know from the call to HTFileFormat that
|
|
Packit |
f574b8 |
* this is a compressed file, no need to look at the filename
|
|
Packit |
f574b8 |
* again. - kw
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
#if defined(USE_ZLIB) || defined(USE_BZLIB)
|
|
Packit |
f574b8 |
CompressFileType method = HTEncodingToCompressType(HTAtom_name(myEncoding));
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define isDOWNLOAD(m) (strcmp(format_out->name, "www/download") && (method == m))
|
|
Packit |
f574b8 |
#ifdef USE_ZLIB
|
|
Packit |
f574b8 |
if (isDOWNLOAD(cftGzip)) {
|
|
Packit |
f574b8 |
if (isGzipStream(fp)) {
|
|
Packit |
f574b8 |
fclose(fp);
|
|
Packit |
f574b8 |
fp = 0;
|
|
Packit |
f574b8 |
gzfp = gzopen(localname, BIN_R);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTLoadFile: gzopen of `%s' gives %p\n",
|
|
Packit |
f574b8 |
localname, (void *) gzfp));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
internal_decompress = cftGzip;
|
|
Packit |
f574b8 |
} else if (isDOWNLOAD(cftDeflate)) {
|
|
Packit |
f574b8 |
if (isDeflateStream(fp)) {
|
|
Packit |
f574b8 |
zzfp = fp;
|
|
Packit |
f574b8 |
fp = 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTLoadFile: zzopen of `%s' gives %p\n",
|
|
Packit |
f574b8 |
localname, (void *) zzfp));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
internal_decompress = cftDeflate;
|
|
Packit |
f574b8 |
} else
|
|
Packit |
f574b8 |
#endif /* USE_ZLIB */
|
|
Packit |
f574b8 |
#ifdef USE_BZLIB
|
|
Packit |
f574b8 |
if (isDOWNLOAD(cftBzip2)) {
|
|
Packit |
f574b8 |
if (isBzip2Stream(fp)) {
|
|
Packit |
f574b8 |
fclose(fp);
|
|
Packit |
f574b8 |
fp = 0;
|
|
Packit |
f574b8 |
bzfp = BZ2_bzopen(localname, BIN_R);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTLoadFile: bzopen of `%s' gives %p\n",
|
|
Packit |
f574b8 |
localname, bzfp));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
internal_decompress = cftBzip2;
|
|
Packit |
f574b8 |
} else
|
|
Packit |
f574b8 |
#endif /* USE_BZLIB */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
StrAllocCopy(anchor->content_type, format->name);
|
|
Packit |
f574b8 |
StrAllocCopy(anchor->content_encoding, HTAtom_name(myEncoding));
|
|
Packit |
f574b8 |
format = HTAtom_for("www/compressed");
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
CompressFileType cft = HTCompressFileType(localname, DOT_STRING, &rootlen);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (cft != cftNone) {
|
|
Packit |
f574b8 |
char *cp = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrAllocCopy(cp, localname);
|
|
Packit |
f574b8 |
cp[rootlen] = '\0';
|
|
Packit |
f574b8 |
format = HTFileFormat(cp, &encoding, NULL);
|
|
Packit |
f574b8 |
FREE(cp);
|
|
Packit |
f574b8 |
format = HTCharsetFormat(format, anchor,
|
|
Packit |
f574b8 |
UCLYhndl_HTFile_for_unspec);
|
|
Packit |
f574b8 |
StrAllocCopy(anchor->content_type, format->name);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
switch (cft) {
|
|
Packit |
f574b8 |
case cftCompress:
|
|
Packit |
f574b8 |
StrAllocCopy(anchor->content_encoding, "x-compress");
|
|
Packit |
f574b8 |
format = HTAtom_for("www/compressed");
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftDeflate:
|
|
Packit |
f574b8 |
StrAllocCopy(anchor->content_encoding, "x-deflate");
|
|
Packit |
f574b8 |
#ifdef USE_ZLIB
|
|
Packit |
f574b8 |
if (strcmp(format_out->name, "www/download") != 0) {
|
|
Packit |
f574b8 |
if (isDeflateStream(fp)) {
|
|
Packit |
f574b8 |
zzfp = fp;
|
|
Packit |
f574b8 |
fp = 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTLoadFile: zzopen of `%s' gives %p\n",
|
|
Packit |
f574b8 |
localname, (void *) zzfp));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
internal_decompress = cftDeflate;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#else /* USE_ZLIB */
|
|
Packit |
f574b8 |
format = HTAtom_for("www/compressed");
|
|
Packit |
f574b8 |
#endif /* USE_ZLIB */
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftGzip:
|
|
Packit |
f574b8 |
StrAllocCopy(anchor->content_encoding, "x-gzip");
|
|
Packit |
f574b8 |
#ifdef USE_ZLIB
|
|
Packit |
f574b8 |
if (strcmp(format_out->name, "www/download") != 0) {
|
|
Packit |
f574b8 |
if (isGzipStream(fp)) {
|
|
Packit |
f574b8 |
fclose(fp);
|
|
Packit |
f574b8 |
fp = 0;
|
|
Packit |
f574b8 |
gzfp = gzopen(localname, BIN_R);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTLoadFile: gzopen of `%s' gives %p\n",
|
|
Packit |
f574b8 |
localname, (void *) gzfp));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
internal_decompress = cftGzip;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#else /* USE_ZLIB */
|
|
Packit |
f574b8 |
format = HTAtom_for("www/compressed");
|
|
Packit |
f574b8 |
#endif /* USE_ZLIB */
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftBzip2:
|
|
Packit |
f574b8 |
StrAllocCopy(anchor->content_encoding, "x-bzip2");
|
|
Packit |
f574b8 |
#ifdef USE_BZLIB
|
|
Packit |
f574b8 |
if (strcmp(format_out->name, "www/download") != 0) {
|
|
Packit |
f574b8 |
if (isBzip2Stream(fp)) {
|
|
Packit |
f574b8 |
fclose(fp);
|
|
Packit |
f574b8 |
fp = 0;
|
|
Packit |
f574b8 |
bzfp = BZ2_bzopen(localname, BIN_R);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTLoadFile: bzopen of `%s' gives %p\n",
|
|
Packit |
f574b8 |
localname, bzfp));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
internal_decompress = cftBzip2;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#else /* USE_BZLIB */
|
|
Packit |
f574b8 |
format = HTAtom_for("www/compressed");
|
|
Packit |
f574b8 |
#endif /* USE_BZLIB */
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftNone:
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#if defined(USE_ZLIB) || defined(USE_BZLIB)
|
|
Packit |
f574b8 |
if (internal_decompress != cftNone) {
|
|
Packit |
f574b8 |
switch (internal_decompress) {
|
|
Packit |
f574b8 |
#ifdef USE_ZLIB
|
|
Packit |
f574b8 |
case cftDeflate:
|
|
Packit |
f574b8 |
failed_decompress = (BOOLEAN) (zzfp == NULL);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftCompress:
|
|
Packit |
f574b8 |
case cftGzip:
|
|
Packit |
f574b8 |
failed_decompress = (BOOLEAN) (gzfp == NULL);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef USE_BZLIB
|
|
Packit |
f574b8 |
case cftBzip2:
|
|
Packit |
f574b8 |
failed_decompress = (BOOLEAN) (bzfp == NULL);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
failed_decompress = YES;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (failed_decompress) {
|
|
Packit |
f574b8 |
*statusp = HTLoadError(NULL,
|
|
Packit |
f574b8 |
-(HT_ERROR),
|
|
Packit |
f574b8 |
FAILED_OPEN_COMPRESSED_FILE);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
char *sugfname = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (anchor->SugFname) {
|
|
Packit |
f574b8 |
StrAllocCopy(sugfname, anchor->SugFname);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
char *anchor_path = HTParse(anchor->address, "",
|
|
Packit |
f574b8 |
PARSE_PATH + PARSE_PUNCTUATION);
|
|
Packit |
f574b8 |
char *lastslash;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
HTUnEscape(anchor_path);
|
|
Packit |
f574b8 |
lastslash = strrchr(anchor_path, '/');
|
|
Packit |
f574b8 |
if (lastslash)
|
|
Packit |
f574b8 |
StrAllocCopy(sugfname, lastslash + 1);
|
|
Packit |
f574b8 |
FREE(anchor_path);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
FREE(anchor->content_encoding);
|
|
Packit |
f574b8 |
if (sugfname && *sugfname)
|
|
Packit |
f574b8 |
HTCheckFnameForCompression(&sugfname, anchor,
|
|
Packit |
f574b8 |
TRUE);
|
|
Packit |
f574b8 |
if (sugfname && *sugfname)
|
|
Packit |
f574b8 |
StrAllocCopy(anchor->SugFname, sugfname);
|
|
Packit |
f574b8 |
FREE(sugfname);
|
|
Packit |
f574b8 |
#ifdef USE_BZLIB
|
|
Packit |
f574b8 |
if (bzfp)
|
|
Packit |
f574b8 |
*statusp = HTParseBzFile(format, format_out,
|
|
Packit |
f574b8 |
anchor,
|
|
Packit |
f574b8 |
bzfp, sink);
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef USE_ZLIB
|
|
Packit |
f574b8 |
if (gzfp)
|
|
Packit |
f574b8 |
*statusp = HTParseGzFile(format, format_out,
|
|
Packit |
f574b8 |
anchor,
|
|
Packit |
f574b8 |
gzfp, sink);
|
|
Packit |
f574b8 |
else if (zzfp)
|
|
Packit |
f574b8 |
*statusp = HTParseZzFile(format, format_out,
|
|
Packit |
f574b8 |
anchor,
|
|
Packit |
f574b8 |
zzfp, sink);
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} else
|
|
Packit |
f574b8 |
#endif /* USE_ZLIB || USE_BZLIB */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
*statusp = HTParseFile(format, format_out, anchor, fp, sink);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (fp != 0) {
|
|
Packit |
f574b8 |
fclose(fp);
|
|
Packit |
f574b8 |
fp = 0;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
result = TRUE;
|
|
Packit |
f574b8 |
} /* If successful open */
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Load a document.
|
|
Packit |
f574b8 |
* ----------------
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* On entry:
|
|
Packit |
f574b8 |
* addr must point to the fully qualified hypertext reference.
|
|
Packit |
f574b8 |
* This is the physical address of the file
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* On exit:
|
|
Packit |
f574b8 |
* returns <0 Error has occurred.
|
|
Packit |
f574b8 |
* HTLOADED OK
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
int HTLoadFile(const char *addr,
|
|
Packit |
f574b8 |
HTParentAnchor *anchor,
|
|
Packit |
f574b8 |
HTFormat format_out,
|
|
Packit |
f574b8 |
HTStream *sink)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *filename = NULL;
|
|
Packit |
f574b8 |
char *acc_method = NULL;
|
|
Packit |
f574b8 |
HTFormat format;
|
|
Packit |
f574b8 |
char *nodename = NULL;
|
|
Packit |
f574b8 |
char *newname = NULL; /* Simplified name of file */
|
|
Packit |
f574b8 |
HTAtom *myEncoding = NULL; /* enc of this file, may be gzip etc. */
|
|
Packit |
f574b8 |
int status = -1;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifndef DISABLE_FTP
|
|
Packit |
f574b8 |
char *ftp_newhost;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef VMS
|
|
Packit |
f574b8 |
struct stat stat_info;
|
|
Packit |
f574b8 |
#endif /* VMS */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Reduce the filename to a basic form (hopefully unique!).
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
StrAllocCopy(newname, addr);
|
|
Packit |
f574b8 |
filename = HTParse(newname, "", PARSE_PATH | PARSE_PUNCTUATION);
|
|
Packit |
f574b8 |
nodename = HTParse(newname, "", PARSE_HOST);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* If access is ftp, or file is on another host, invoke ftp now.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
acc_method = HTParse(newname, "", PARSE_ACCESS);
|
|
Packit |
f574b8 |
if (strcmp("ftp", acc_method) == 0 ||
|
|
Packit |
f574b8 |
(!LYSameHostname("localhost", nodename) &&
|
|
Packit |
f574b8 |
!LYSameHostname(nodename, HTHostName()))) {
|
|
Packit |
f574b8 |
status = -1;
|
|
Packit |
f574b8 |
FREE(newname);
|
|
Packit |
f574b8 |
FREE(filename);
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
FREE(acc_method);
|
|
Packit |
f574b8 |
#ifndef DISABLE_FTP
|
|
Packit |
f574b8 |
ftp_newhost = HTParse(addr, "", PARSE_HOST);
|
|
Packit |
f574b8 |
if (strcmp(ftp_lasthost, ftp_newhost))
|
|
Packit |
f574b8 |
ftp_local_passive = ftp_passive;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
status = HTFTPLoad(addr, anchor, format_out, sink);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (ftp_passive == ftp_local_passive) {
|
|
Packit |
f574b8 |
if ((status >= 400) || (status < 0)) {
|
|
Packit |
f574b8 |
ftp_local_passive = (BOOLEAN) !ftp_passive;
|
|
Packit |
f574b8 |
status = HTFTPLoad(addr, anchor, format_out, sink);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
free(ftp_lasthost);
|
|
Packit |
f574b8 |
ftp_lasthost = ftp_newhost;
|
|
Packit |
f574b8 |
#endif /* DISABLE_FTP */
|
|
Packit |
f574b8 |
return status;
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
FREE(newname);
|
|
Packit |
f574b8 |
FREE(acc_method);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#if defined(VMS) || defined(USE_DOS_DRIVES)
|
|
Packit |
f574b8 |
HTUnEscape(filename);
|
|
Packit |
f574b8 |
#endif /* VMS */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Determine the format and encoding mapped to any suffix.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (anchor->content_type && anchor->content_encoding) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* If content_type and content_encoding are BOTH already set in the
|
|
Packit |
f574b8 |
* anchor object, we believe it and don't try to derive format and
|
|
Packit |
f574b8 |
* encoding from the filename. - kw
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
format = HTAtom_for(anchor->content_type);
|
|
Packit |
f574b8 |
myEncoding = HTAtom_for(anchor->content_encoding);
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
int default_UCLYhndl = UCLYhndl_HTFile_for_unspec;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (force_old_UCLYhndl_on_reload) {
|
|
Packit |
f574b8 |
force_old_UCLYhndl_on_reload = FALSE;
|
|
Packit |
f574b8 |
default_UCLYhndl = forced_UCLYhdnl;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
format = HTFileFormat(filename, &myEncoding, NULL);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Check the format for an extended MIME charset value, and act on it
|
|
Packit |
f574b8 |
* if present. Otherwise, assume what is indicated by the last
|
|
Packit |
f574b8 |
* parameter (fallback will effectively be UCLYhndl_for_unspec, by
|
|
Packit |
f574b8 |
* default ISO-8859-1). - kw
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
format = HTCharsetFormat(format, anchor, default_UCLYhndl);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef VMS
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Check to see if the 'filename' is in fact a directory. If it is create
|
|
Packit |
f574b8 |
* a new hypertext object containing a list of files and subdirectories
|
|
Packit |
f574b8 |
* contained in the directory. All of these are links to the directories
|
|
Packit |
f574b8 |
* or files listed.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (HTStat(filename, &stat_info) == -1) {
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTLoadFile: Can't stat %s\n", filename));
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
if (S_ISDIR(stat_info.st_mode)) {
|
|
Packit |
f574b8 |
if (HTDirAccess == HT_DIR_FORBID) {
|
|
Packit |
f574b8 |
FREE(filename);
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
return HTLoadError(sink, 403, DISALLOWED_DIR_SCAN);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (HTDirAccess == HT_DIR_SELECTIVE) {
|
|
Packit |
f574b8 |
char *enable_file_name = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
HTSprintf0(&enable_file_name, "%s/%s", filename, HT_DIR_ENABLE_FILE);
|
|
Packit |
f574b8 |
if (HTStat(enable_file_name, &stat_info) == -1) {
|
|
Packit |
f574b8 |
FREE(filename);
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
FREE(enable_file_name);
|
|
Packit |
f574b8 |
return HTLoadError(sink, 403, DISALLOWED_SELECTIVE_ACCESS);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
FREE(filename);
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
return HTVMSBrowseDir(addr, anchor, format_out, sink);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (decompressAndParse(anchor,
|
|
Packit |
f574b8 |
format_out,
|
|
Packit |
f574b8 |
sink,
|
|
Packit |
f574b8 |
nodename,
|
|
Packit |
f574b8 |
filename,
|
|
Packit |
f574b8 |
myEncoding,
|
|
Packit |
f574b8 |
format,
|
|
Packit |
f574b8 |
&status)) {
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
FREE(filename);
|
|
Packit |
f574b8 |
return status;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
FREE(filename);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#else /* not VMS: */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
FREE(filename);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* For unix, we try to translate the name into the name of a transparently
|
|
Packit |
f574b8 |
* mounted file.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* Not allowed in secure (HTClientHost) situations. TBL 921019
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
#ifndef NO_UNIX_IO
|
|
Packit |
f574b8 |
/* Need protection here for telnet server but not httpd server. */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (!HTSecure) { /* try local file system */
|
|
Packit |
f574b8 |
char *localname = HTLocalName(addr);
|
|
Packit |
f574b8 |
struct stat dir_info;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef HAVE_READDIR
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Multiformat handling.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* If needed, scan directory to find a good file. Bug: We don't stat
|
|
Packit |
f574b8 |
* the file to find the length.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if ((strlen(localname) > strlen(MULTI_SUFFIX)) &&
|
|
Packit |
f574b8 |
(0 == strcmp(localname + strlen(localname) - strlen(MULTI_SUFFIX),
|
|
Packit |
f574b8 |
MULTI_SUFFIX))) {
|
|
Packit |
f574b8 |
DIR *dp = 0;
|
|
Packit |
f574b8 |
BOOL forget_multi = NO;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
STRUCT_DIRENT *dirbuf;
|
|
Packit |
f574b8 |
float best = (float) NO_VALUE_FOUND; /* So far best is bad */
|
|
Packit |
f574b8 |
HTFormat best_rep = NULL; /* Set when rep found */
|
|
Packit |
f574b8 |
HTAtom *best_enc = NULL;
|
|
Packit |
f574b8 |
char *best_name = NULL; /* Best dir entry so far */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *base = strrchr(localname, '/');
|
|
Packit |
f574b8 |
size_t baselen = 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (!base || base == localname) {
|
|
Packit |
f574b8 |
forget_multi = YES;
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
*base++ = '\0'; /* Just got directory name */
|
|
Packit |
f574b8 |
baselen = strlen(base) - strlen(MULTI_SUFFIX);
|
|
Packit |
f574b8 |
base[baselen] = '\0'; /* Chop off suffix */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
dp = opendir(localname);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (forget_multi || !dp) {
|
|
Packit |
f574b8 |
FREE(localname);
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
return HTLoadError(sink, 500, FAILED_DIR_SCAN);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
while ((dirbuf = readdir(dp)) != NULL) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* While there are directory entries to be read...
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
#ifdef STRUCT_DIRENT__D_INO
|
|
Packit |
f574b8 |
if (dirbuf->d_ino == 0)
|
|
Packit |
f574b8 |
continue; /* if the entry is not being used, skip it */
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
if (strlen(dirbuf->d_name) > baselen && /* Match? */
|
|
Packit |
f574b8 |
!StrNCmp(dirbuf->d_name, base, baselen)) {
|
|
Packit |
f574b8 |
HTAtom *enc;
|
|
Packit |
f574b8 |
HTFormat rep = HTFileFormat(dirbuf->d_name, &enc, NULL);
|
|
Packit |
f574b8 |
float filevalue = HTFileValue(dirbuf->d_name);
|
|
Packit |
f574b8 |
float value = HTStackValue(rep, format_out,
|
|
Packit |
f574b8 |
filevalue,
|
|
Packit |
f574b8 |
0L /* @@@@@@ */ );
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (value <= 0.0) {
|
|
Packit |
f574b8 |
int rootlen = 0;
|
|
Packit |
f574b8 |
const char *atomname = NULL;
|
|
Packit |
f574b8 |
CompressFileType cft =
|
|
Packit |
f574b8 |
HTCompressFileType(dirbuf->d_name, ".", &rootlen);
|
|
Packit |
f574b8 |
char *cp = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
enc = NULL;
|
|
Packit |
f574b8 |
if (cft != cftNone) {
|
|
Packit |
f574b8 |
StrAllocCopy(cp, dirbuf->d_name);
|
|
Packit |
f574b8 |
cp[rootlen] = '\0';
|
|
Packit |
f574b8 |
format = HTFileFormat(cp, NULL, NULL);
|
|
Packit |
f574b8 |
FREE(cp);
|
|
Packit |
f574b8 |
value = HTStackValue(format, format_out,
|
|
Packit |
f574b8 |
filevalue, 0L);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
switch (cft) {
|
|
Packit |
f574b8 |
case cftCompress:
|
|
Packit |
f574b8 |
atomname = "application/x-compressed";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftGzip:
|
|
Packit |
f574b8 |
atomname = "application/x-gzip";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftDeflate:
|
|
Packit |
f574b8 |
atomname = "application/x-deflate";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftBzip2:
|
|
Packit |
f574b8 |
atomname = "application/x-bzip2";
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case cftNone:
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (atomname != NULL) {
|
|
Packit |
f574b8 |
value = HTStackValue(format, format_out,
|
|
Packit |
f574b8 |
filevalue, 0L);
|
|
Packit |
f574b8 |
if (value <= 0.0) {
|
|
Packit |
f574b8 |
format = HTAtom_for(atomname);
|
|
Packit |
f574b8 |
value = HTStackValue(format, format_out,
|
|
Packit |
f574b8 |
filevalue, 0L);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (value <= 0.0) {
|
|
Packit |
f574b8 |
format = HTAtom_for("www/compressed");
|
|
Packit |
f574b8 |
value = HTStackValue(format, format_out,
|
|
Packit |
f574b8 |
filevalue, 0L);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (value < NO_VALUE_FOUND) {
|
|
Packit |
f574b8 |
CTRACE((tfp,
|
|
Packit |
f574b8 |
"HTLoadFile: value of presenting %s is %f\n",
|
|
Packit |
f574b8 |
HTAtom_name(rep), value));
|
|
Packit |
f574b8 |
if (value > best) {
|
|
Packit |
f574b8 |
best_rep = rep;
|
|
Packit |
f574b8 |
best_enc = enc;
|
|
Packit |
f574b8 |
best = value;
|
|
Packit |
f574b8 |
StrAllocCopy(best_name, dirbuf->d_name);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} /* if best so far */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
/* if match */
|
|
Packit |
f574b8 |
} /* end while directory entries left to read */
|
|
Packit |
f574b8 |
closedir(dp);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (best_rep) {
|
|
Packit |
f574b8 |
format = best_rep;
|
|
Packit |
f574b8 |
myEncoding = best_enc;
|
|
Packit |
f574b8 |
base[-1] = '/'; /* Restore directory name */
|
|
Packit |
f574b8 |
base[0] = '\0';
|
|
Packit |
f574b8 |
StrAllocCat(localname, best_name);
|
|
Packit |
f574b8 |
FREE(best_name);
|
|
Packit |
f574b8 |
} else { /* If not found suitable file */
|
|
Packit |
f574b8 |
FREE(localname);
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
return HTLoadError(sink, 403, FAILED_NO_REPRESENTATION);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
/*NOTREACHED */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
/* if multi suffix */
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Check to see if the 'localname' is in fact a directory. If it is
|
|
Packit |
f574b8 |
* create a new hypertext object containing a list of files and
|
|
Packit |
f574b8 |
* subdirectories contained in the directory. All of these are links
|
|
Packit |
f574b8 |
* to the directories or files listed. NB This assumes the existence
|
|
Packit |
f574b8 |
* of a type 'STRUCT_DIRENT', which will hold the directory entry, and
|
|
Packit |
f574b8 |
* a type 'DIR' which is used to point to the current directory being
|
|
Packit |
f574b8 |
* read.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
#if defined(USE_DOS_DRIVES)
|
|
Packit |
f574b8 |
if (strlen(localname) == 2 && LYIsDosDrive(localname))
|
|
Packit |
f574b8 |
LYAddPathSep(&localname);
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
if (HTStat(localname, &dir_info) == -1) /* get file information */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
/* if can't read file information */
|
|
Packit |
f574b8 |
CTRACE((tfp, "HTLoadFile: can't stat %s\n", localname));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
} else { /* Stat was OK */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (S_ISDIR(dir_info.st_mode)) {
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* If localname is a directory.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
DIR *dp;
|
|
Packit |
f574b8 |
struct stat file_info;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "%s is a directory\n", localname));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Check directory access. Selective access means only those
|
|
Packit |
f574b8 |
* directories containing a marker file can be browsed.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (HTDirAccess == HT_DIR_FORBID) {
|
|
Packit |
f574b8 |
FREE(localname);
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
return HTLoadError(sink, 403, DISALLOWED_DIR_SCAN);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (HTDirAccess == HT_DIR_SELECTIVE) {
|
|
Packit |
f574b8 |
char *enable_file_name = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
HTSprintf0(&enable_file_name, "%s/%s", localname, HT_DIR_ENABLE_FILE);
|
|
Packit |
f574b8 |
if (stat(enable_file_name, &file_info) != 0) {
|
|
Packit |
f574b8 |
FREE(localname);
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
FREE(enable_file_name);
|
|
Packit |
f574b8 |
return HTLoadError(sink, 403, DISALLOWED_SELECTIVE_ACCESS);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CTRACE((tfp, "Opening directory %s\n", localname));
|
|
Packit |
f574b8 |
dp = opendir(localname);
|
|
Packit |
f574b8 |
if (!dp) {
|
|
Packit |
f574b8 |
FREE(localname);
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
return HTLoadError(sink, 403, FAILED_DIR_UNREADABLE);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Directory access is allowed and possible.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
status = print_local_dir(dp, localname,
|
|
Packit |
f574b8 |
anchor, format_out, sink);
|
|
Packit |
f574b8 |
closedir(dp);
|
|
Packit |
f574b8 |
FREE(localname);
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
return status; /* document loaded, maybe partial */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
/* end if localname is a directory */
|
|
Packit |
f574b8 |
if (S_ISREG(dir_info.st_mode)) {
|
|
Packit |
f574b8 |
#ifdef LONG_MAX
|
|
Packit |
f574b8 |
if (dir_info.st_size <= LONG_MAX)
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
anchor->content_length = (long) dir_info.st_size;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
} /* end if file stat worked */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* End of directory reading section
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
#endif /* HAVE_READDIR */
|
|
Packit |
f574b8 |
if (decompressAndParse(anchor,
|
|
Packit |
f574b8 |
format_out,
|
|
Packit |
f574b8 |
sink,
|
|
Packit |
f574b8 |
nodename,
|
|
Packit |
f574b8 |
localname,
|
|
Packit |
f574b8 |
myEncoding,
|
|
Packit |
f574b8 |
format,
|
|
Packit |
f574b8 |
&status)) {
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
FREE(localname);
|
|
Packit |
f574b8 |
return status;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
FREE(localname);
|
|
Packit |
f574b8 |
} /* local unix file system */
|
|
Packit |
f574b8 |
#endif /* !NO_UNIX_IO */
|
|
Packit |
f574b8 |
#endif /* VMS */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifndef DECNET
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Now, as transparently mounted access has failed, we try FTP.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Deal with case-sensitivity differences on VMS versus Unix.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
#ifdef VMS
|
|
Packit |
f574b8 |
if (strcasecomp(nodename, HTHostName()) != 0)
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
if (strcmp(nodename, HTHostName()) != 0)
|
|
Packit |
f574b8 |
#endif /* VMS */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
status = -1;
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
if (StrNCmp(addr, "file://localhost", 16)) {
|
|
Packit |
f574b8 |
/* never go to ftp site when URL
|
|
Packit |
f574b8 |
* is file://localhost
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
#ifndef DISABLE_FTP
|
|
Packit |
f574b8 |
status = HTFTPLoad(addr, anchor, format_out, sink);
|
|
Packit |
f574b8 |
#endif /* DISABLE_FTP */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return status;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
FREE(nodename);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
#endif /* !DECNET */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* All attempts have failed.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
CTRACE((tfp, "Can't open `%s', errno=%d\n", addr, SOCKET_ERRNO));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return HTLoadError(sink, 403, FAILED_FILE_UNREADABLE);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static const char *program_paths[pp_Last];
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Given a program number, return its path
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
const char *HTGetProgramPath(ProgramPaths code)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
const char *result = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (code > ppUnknown && code < pp_Last)
|
|
Packit |
f574b8 |
result = program_paths[code];
|
|
Packit |
f574b8 |
return result;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Store a program's path. The caller must allocate the string used for 'path',
|
|
Packit |
f574b8 |
* since HTInitProgramPaths() may free it.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
void HTSetProgramPath(ProgramPaths code, const char *path)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
if (code > ppUnknown && code < pp_Last) {
|
|
Packit |
f574b8 |
program_paths[code] = isEmpty(path) ? 0 : path;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Reset the list of known program paths to the ones that are compiled-in
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
void HTInitProgramPaths(BOOL init)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
ProgramPaths code;
|
|
Packit |
f574b8 |
int n;
|
|
Packit |
f574b8 |
const char *path;
|
|
Packit |
f574b8 |
const char *test;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
for (n = (int) ppUnknown + 1; n < (int) pp_Last; ++n) {
|
|
Packit |
f574b8 |
switch (code = (ProgramPaths) n) {
|
|
Packit |
f574b8 |
#ifdef BZIP2_PATH
|
|
Packit |
f574b8 |
case ppBZIP2:
|
|
Packit |
f574b8 |
path = BZIP2_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef CHMOD_PATH
|
|
Packit |
f574b8 |
case ppCHMOD:
|
|
Packit |
f574b8 |
path = CHMOD_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef COMPRESS_PATH
|
|
Packit |
f574b8 |
case ppCOMPRESS:
|
|
Packit |
f574b8 |
path = COMPRESS_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef COPY_PATH
|
|
Packit |
f574b8 |
case ppCOPY:
|
|
Packit |
f574b8 |
path = COPY_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef CSWING_PATH
|
|
Packit |
f574b8 |
case ppCSWING:
|
|
Packit |
f574b8 |
path = CSWING_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef GZIP_PATH
|
|
Packit |
f574b8 |
case ppGZIP:
|
|
Packit |
f574b8 |
path = GZIP_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef INFLATE_PATH
|
|
Packit |
f574b8 |
case ppINFLATE:
|
|
Packit |
f574b8 |
path = INFLATE_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef INSTALL_PATH
|
|
Packit |
f574b8 |
case ppINSTALL:
|
|
Packit |
f574b8 |
path = INSTALL_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef MKDIR_PATH
|
|
Packit |
f574b8 |
case ppMKDIR:
|
|
Packit |
f574b8 |
path = MKDIR_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef MV_PATH
|
|
Packit |
f574b8 |
case ppMV:
|
|
Packit |
f574b8 |
path = MV_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef RLOGIN_PATH
|
|
Packit |
f574b8 |
case ppRLOGIN:
|
|
Packit |
f574b8 |
path = RLOGIN_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef RM_PATH
|
|
Packit |
f574b8 |
case ppRM:
|
|
Packit |
f574b8 |
path = RM_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef RMDIR_PATH
|
|
Packit |
f574b8 |
case ppRMDIR:
|
|
Packit |
f574b8 |
path = RMDIR_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef SETFONT_PATH
|
|
Packit |
f574b8 |
case ppSETFONT:
|
|
Packit |
f574b8 |
path = SETFONT_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef TAR_PATH
|
|
Packit |
f574b8 |
case ppTAR:
|
|
Packit |
f574b8 |
path = TAR_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef TELNET_PATH
|
|
Packit |
f574b8 |
case ppTELNET:
|
|
Packit |
f574b8 |
path = TELNET_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef TN3270_PATH
|
|
Packit |
f574b8 |
case ppTN3270:
|
|
Packit |
f574b8 |
path = TN3270_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef TOUCH_PATH
|
|
Packit |
f574b8 |
case ppTOUCH:
|
|
Packit |
f574b8 |
path = TOUCH_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef UNCOMPRESS_PATH
|
|
Packit |
f574b8 |
case ppUNCOMPRESS:
|
|
Packit |
f574b8 |
path = UNCOMPRESS_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef UNZIP_PATH
|
|
Packit |
f574b8 |
case ppUNZIP:
|
|
Packit |
f574b8 |
path = UNZIP_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef UUDECODE_PATH
|
|
Packit |
f574b8 |
case ppUUDECODE:
|
|
Packit |
f574b8 |
path = UUDECODE_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef ZCAT_PATH
|
|
Packit |
f574b8 |
case ppZCAT:
|
|
Packit |
f574b8 |
path = ZCAT_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
#ifdef ZIP_PATH
|
|
Packit |
f574b8 |
case ppZIP:
|
|
Packit |
f574b8 |
path = ZIP_PATH;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
#endif
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
path = NULL;
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
test = HTGetProgramPath(code);
|
|
Packit |
f574b8 |
if (test != NULL && test != path) {
|
|
Packit |
f574b8 |
free(DeConst(test));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (init) {
|
|
Packit |
f574b8 |
HTSetProgramPath(code, path);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Protocol descriptors
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
#ifdef GLOBALDEF_IS_MACRO
|
|
Packit |
f574b8 |
#define _HTFILE_C_1_INIT { "ftp", HTLoadFile, 0 }
|
|
Packit |
f574b8 |
GLOBALDEF(HTProtocol, HTFTP, _HTFILE_C_1_INIT);
|
|
Packit |
f574b8 |
#define _HTFILE_C_2_INIT { "file", HTLoadFile, HTFileSaveStream }
|
|
Packit |
f574b8 |
GLOBALDEF(HTProtocol, HTFile, _HTFILE_C_2_INIT);
|
|
Packit |
f574b8 |
#else
|
|
Packit |
f574b8 |
GLOBALDEF HTProtocol HTFTP =
|
|
Packit |
f574b8 |
{"ftp", HTLoadFile, 0};
|
|
Packit |
f574b8 |
GLOBALDEF HTProtocol HTFile =
|
|
Packit |
f574b8 |
{"file", HTLoadFile, HTFileSaveStream};
|
|
Packit |
f574b8 |
#endif /* GLOBALDEF_IS_MACRO */
|