Blame src/HTInit.c

Packit f574b8
/*
Packit f574b8
 * $LynxId: HTInit.c,v 1.90 2018/03/05 22:35:07 tom Exp $
Packit f574b8
 *
Packit f574b8
 *		Configuration-specific Initialization		HTInit.c
Packit f574b8
 *		----------------------------------------
Packit f574b8
 */
Packit f574b8
Packit f574b8
/*	Define a basic set of suffixes and presentations
Packit f574b8
 *	------------------------------------------------
Packit f574b8
 */
Packit f574b8
Packit f574b8
#include <HTUtils.h>
Packit f574b8
Packit f574b8
/* Implements:
Packit f574b8
*/
Packit f574b8
#include <HTInit.h>
Packit f574b8
Packit f574b8
#include <HTML.h>
Packit f574b8
#include <HTPlain.h>
Packit f574b8
#include <HTMLGen.h>
Packit f574b8
#include <HTFile.h>
Packit f574b8
#include <HTFormat.h>
Packit f574b8
#include <HTMIME.h>
Packit f574b8
#include <HTWSRC.h>
Packit f574b8
Packit f574b8
#include <HTSaveToFile.h>	/* LJM */
Packit f574b8
#include <LYStrings.h>
Packit f574b8
#include <LYUtils.h>
Packit f574b8
#include <LYGlobalDefs.h>
Packit f574b8
Packit f574b8
#include <LYexit.h>
Packit f574b8
#include <LYLeaks.h>
Packit f574b8
Packit f574b8
#define CTrace(p) CTRACE2(TRACE_CFG, p)
Packit f574b8
Packit f574b8
static int HTLoadTypesConfigFile(char *fn, AcceptMedia media);
Packit f574b8
static int HTLoadExtensionsConfigFile(char *fn);
Packit f574b8
Packit f574b8
#define SET_SUFFIX1(suffix, description, type) \
Packit f574b8
	HTSetSuffix(suffix, description, type, 1.0)
Packit f574b8
Packit f574b8
#define SET_SUFFIX5(suffix, mimetype, type, description) \
Packit f574b8
       HTSetSuffix5(suffix, mimetype, type, description, 1.0)
Packit f574b8
Packit f574b8
#define SET_PRESENT(mimetype, command, quality, delay) \
Packit f574b8
  HTSetPresentation(mimetype, command, 0, quality, delay, 0.0, 0L, media)
Packit f574b8
Packit f574b8
#define SET_EXTERNL(rep_in, rep_out, command, quality) \
Packit f574b8
    HTSetConversion(rep_in, rep_out, command, quality, 3.0, 0.0, 0L, mediaEXT)
Packit f574b8
Packit f574b8
#define SET_INTERNL(rep_in, rep_out, command, quality) \
Packit f574b8
    HTSetConversion(rep_in, rep_out, command, quality, 0.0, 0.0, 0L, mediaINT)
Packit f574b8
Packit f574b8
void HTFormatInit(void)
Packit f574b8
{
Packit f574b8
    AcceptMedia media = mediaEXT;
Packit f574b8
Packit f574b8
    CTrace((tfp, "HTFormatInit\n"));
Packit f574b8
#ifdef NeXT
Packit f574b8
    SET_PRESENT("application/postscript", "open %s", 1.0, 2.0);
Packit f574b8
    SET_PRESENT("image/x-tiff", "open %s", 2.0, 2.0);
Packit f574b8
    SET_PRESENT("image/tiff", "open %s", 1.0, 2.0);
Packit f574b8
    SET_PRESENT("audio/basic", "open %s", 1.0, 2.0);
Packit f574b8
    SET_PRESENT("*", "open %s", 1.0, 0.0);
Packit f574b8
#else
Packit f574b8
    if (LYgetXDisplay() != 0) {	/* Must have X11 */
Packit f574b8
	SET_PRESENT("application/postscript", "ghostview %s&", 1.0, 3.0);
Packit f574b8
	if (non_empty(XLoadImageCommand)) {
Packit f574b8
	    /* *INDENT-OFF* */
Packit f574b8
	    SET_PRESENT("image/gif",	   XLoadImageCommand, 1.0, 3.0);
Packit f574b8
	    SET_PRESENT("image/x-xbm",	   XLoadImageCommand, 1.0, 3.0);
Packit f574b8
	    SET_PRESENT("image/x-xbitmap", XLoadImageCommand, 1.0, 3.0);
Packit f574b8
	    SET_PRESENT("image/x-png",	   XLoadImageCommand, 2.0, 3.0);
Packit f574b8
	    SET_PRESENT("image/png",	   XLoadImageCommand, 1.0, 3.0);
Packit f574b8
	    SET_PRESENT("image/x-rgb",	   XLoadImageCommand, 1.0, 3.0);
Packit f574b8
	    SET_PRESENT("image/x-tiff",	   XLoadImageCommand, 2.0, 3.0);
Packit f574b8
	    SET_PRESENT("image/tiff",	   XLoadImageCommand, 1.0, 3.0);
Packit f574b8
	    SET_PRESENT("image/jpeg",	   XLoadImageCommand, 1.0, 3.0);
Packit f574b8
	    /* *INDENT-ON* */
Packit f574b8
Packit f574b8
	}
Packit f574b8
	SET_PRESENT("video/mpeg", "mpeg_play %s &", 1.0, 3.0);
Packit f574b8
Packit f574b8
    }
Packit f574b8
#endif
Packit f574b8
Packit f574b8
#ifdef EXEC_SCRIPTS
Packit f574b8
    /* set quality to 999.0 for protected exec applications */
Packit f574b8
#ifndef VMS
Packit f574b8
    SET_PRESENT("application/x-csh", "csh %s", 999.0, 3.0);
Packit f574b8
    SET_PRESENT("application/x-sh", "sh %s", 999.0, 3.0);
Packit f574b8
    SET_PRESENT("application/x-ksh", "ksh %s", 999.0, 3.0);
Packit f574b8
#else
Packit f574b8
    SET_PRESENT("application/x-VMS_script", "@%s", 999.0, 3.0);
Packit f574b8
#endif /* not VMS */
Packit f574b8
#endif /* EXEC_SCRIPTS */
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Add our header handlers.
Packit f574b8
     */
Packit f574b8
    SET_INTERNL("message/x-http-redirection", "*", HTMIMERedirect, 2.0);
Packit f574b8
    SET_INTERNL("message/x-http-redirection", "www/present", HTMIMERedirect, 2.0);
Packit f574b8
    SET_INTERNL("message/x-http-redirection", "www/debug", HTMIMERedirect, 1.0);
Packit f574b8
    SET_INTERNL("www/mime", "www/present", HTMIMEConvert, 1.0);
Packit f574b8
    SET_INTERNL("www/mime", "www/download", HTMIMEConvert, 1.0);
Packit f574b8
    SET_INTERNL("www/mime", "www/source", HTMIMEConvert, 1.0);
Packit f574b8
    SET_INTERNL("www/mime", "www/dump", HTMIMEConvert, 1.0);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Add our compressed file handlers.
Packit f574b8
     */
Packit f574b8
    SET_INTERNL("www/compressed", "www/download", HTCompressed, 1.0);
Packit f574b8
    SET_INTERNL("www/compressed", "www/present", HTCompressed, 1.0);
Packit f574b8
    SET_INTERNL("www/compressed", "www/source", HTCompressed, 1.0);
Packit f574b8
    SET_INTERNL("www/compressed", "www/dump", HTCompressed, 1.0);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * The following support some content types seen here/there:
Packit f574b8
     */
Packit f574b8
    SET_INTERNL("application/html", "text/x-c", HTMLToC, 0.5);
Packit f574b8
    SET_INTERNL("application/html", STR_PLAINTEXT, HTMLToPlain, 0.5);
Packit f574b8
    SET_INTERNL("application/html", "www/present", HTMLPresent, 2.0);
Packit f574b8
    SET_INTERNL("application/html", "www/source", HTPlainPresent, 1.0);
Packit f574b8
    SET_INTERNL("application/xml", "www/present", HTMLPresent, 2.0);
Packit f574b8
    SET_INTERNL("application/x-wais-source", "www/source", HTPlainPresent, 1.0);
Packit f574b8
    SET_INTERNL("application/x-wais-source", "www/present", HTWSRCConvert, 2.0);
Packit f574b8
    SET_INTERNL("application/x-wais-source", "www/download", HTWSRCConvert, 1.0);
Packit f574b8
    SET_INTERNL("application/x-wais-source", "www/dump", HTWSRCConvert, 1.0);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Save all unknown mime types to disk.
Packit f574b8
     */
Packit f574b8
    SET_EXTERNL("www/source", "www/present", HTSaveToFile, 1.0);
Packit f574b8
    SET_EXTERNL("www/source", "www/source", HTSaveToFile, 1.0);
Packit f574b8
    SET_EXTERNL("www/source", "www/download", HTSaveToFile, 1.0);
Packit f574b8
    SET_EXTERNL("www/source", "*", HTSaveToFile, 1.0);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Output all www/dump presentations to stdout.
Packit f574b8
     */
Packit f574b8
    SET_EXTERNL("www/source", "www/dump", HTDumpToStdout, 1.0);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Other internal types, which must precede the "www/present" entries
Packit f574b8
     * below (otherwise, they will be filtered out in HTFilterPresentations()).
Packit f574b8
     */
Packit f574b8
    SET_INTERNL("text/css", STR_PLAINTEXT, HTMLToPlain, 0.5);
Packit f574b8
    SET_INTERNL(STR_HTML, STR_PLAINTEXT, HTMLToPlain, 0.5);
Packit f574b8
    SET_INTERNL(STR_HTML, "text/x-c", HTMLToC, 0.5);
Packit f574b8
    SET_INTERNL(STR_HTML, "www/source", HTPlainPresent, 1.0);
Packit f574b8
    SET_INTERNL(STR_PLAINTEXT, "www/source", HTPlainPresent, 1.0);
Packit f574b8
    SET_INTERNL("text/sgml", "www/source", HTPlainPresent, 1.0);
Packit f574b8
    SET_INTERNL("text/x-sgml", "www/source", HTPlainPresent, 1.0);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Now add our basic conversions.  These include the types which will
Packit f574b8
     * be listed in a "Accept:" line sent to a server.  These criteria are
Packit f574b8
     * used in HTFilterPresentations() to select acceptable types:
Packit f574b8
     *
Packit f574b8
     * a) input is not "www/mime" or "www/compressed"
Packit f574b8
     * b) output is "www/present"
Packit f574b8
     * c) quality is in the range 0.0 to 1.0, i.e., excludes the 2.0's.
Packit f574b8
     *
Packit f574b8
     * For reference:
Packit f574b8
     * RFC 1874 - text/sgml
Packit f574b8
     * RFC 2046 - text/plain
Packit f574b8
     * RFC 2318 - text/css
Packit f574b8
     * RFC 3023 - text/xml
Packit f574b8
     * obsolete - text/x-sgml
Packit f574b8
     *
Packit f574b8
     * as well as
Packit f574b8
     * http://www.iana.org/assignments/media-types/media-types.xhtml
Packit f574b8
     *
Packit f574b8
     * and
Packit f574b8
     * http://www.w3.org/TR/xhtml-media-types/
Packit f574b8
     *
Packit f574b8
     * which describes
Packit f574b8
     * application/xhtml+xml
Packit f574b8
     * text/html
Packit f574b8
     */
Packit f574b8
    SET_INTERNL("application/xhtml+xml", "www/present", HTMLPresent, 1.0);
Packit f574b8
    SET_INTERNL("text/css", "www/present", HTPlainPresent, 1.0);
Packit f574b8
    SET_INTERNL(STR_HTML, "www/present", HTMLPresent, 1.0);
Packit f574b8
    SET_INTERNL(STR_PLAINTEXT, "www/present", HTPlainPresent, 1.0);
Packit f574b8
    SET_INTERNL("text/sgml", "www/present", HTMLPresent, 1.0);
Packit f574b8
    SET_INTERNL("text/x-sgml", "www/present", HTMLPresent, 2.0);
Packit f574b8
    SET_INTERNL("text/xml", "www/present", HTMLPresent, 2.0);
Packit f574b8
Packit f574b8
    if (LYisAbsPath(global_type_map)) {
Packit f574b8
	/* These should override the default types as necessary.  */
Packit f574b8
	HTLoadTypesConfigFile(global_type_map, mediaSYS);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Load the local maps.
Packit f574b8
     */
Packit f574b8
    if (IsOurFile(LYAbsOrHomePath(&personal_type_map))
Packit f574b8
	&& LYCanReadFile(personal_type_map)) {
Packit f574b8
	/* These should override everything else. */
Packit f574b8
	HTLoadTypesConfigFile(personal_type_map, mediaUSR);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Put text/html and text/plain at beginning of list.  - kw
Packit f574b8
     */
Packit f574b8
    HTReorderPresentation(WWW_PLAINTEXT, WWW_PRESENT);
Packit f574b8
    HTReorderPresentation(WWW_HTML, WWW_PRESENT);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Analyze the list, and set 'get_accept' for those whose representations
Packit f574b8
     * are not redundant.
Packit f574b8
     */
Packit f574b8
    HTFilterPresentations();
Packit f574b8
}
Packit f574b8
Packit f574b8
void HTPreparsedFormatInit(void)
Packit f574b8
{
Packit f574b8
    CTrace((tfp, "HTPreparsedFormatInit\n"));
Packit f574b8
    if (LYPreparsedSource) {
Packit f574b8
	SET_INTERNL(STR_HTML, "www/source", HTMLParsedPresent, 1.0);
Packit f574b8
	SET_INTERNL(STR_HTML, "www/dump", HTMLParsedPresent, 1.0);
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
/* Some of the following is taken from: */
Packit f574b8
Packit f574b8
/*
Packit f574b8
Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
Packit f574b8
Packit f574b8
Permission to use, copy, modify, and distribute this material
Packit f574b8
for any purpose and without fee is hereby granted, provided
Packit f574b8
that the above copyright notice and this permission notice
Packit f574b8
appear in all copies, and that the name of Bellcore not be
Packit f574b8
used in advertising or publicity pertaining to this
Packit f574b8
material without the specific, prior written permission
Packit f574b8
of an authorized representative of Bellcore.  BELLCORE
Packit f574b8
MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
Packit f574b8
OF THIS MATERIAL FOR ANY PURPOSE.  IT IS PROVIDED "AS IS",
Packit f574b8
WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
Packit f574b8
*/
Packit f574b8
/******************************************************
Packit f574b8
    Metamail -- A tool to help diverse mail readers
Packit f574b8
                cope with diverse multimedia mail formats.
Packit f574b8
Packit f574b8
    Author:  Nathaniel S. Borenstein, Bellcore
Packit f574b8
Packit f574b8
 ******************************************************* */
Packit f574b8
Packit f574b8
struct MailcapEntry {
Packit f574b8
    char *contenttype;
Packit f574b8
    char *command;
Packit f574b8
    char *testcommand;
Packit f574b8
    int needsterminal;
Packit f574b8
    int copiousoutput;
Packit f574b8
    int needtofree;
Packit f574b8
    char *label;
Packit f574b8
    char *printcommand;
Packit f574b8
    char *nametemplate;
Packit f574b8
    float quality;
Packit f574b8
    long int maxbytes;
Packit f574b8
};
Packit f574b8
Packit f574b8
static int ExitWithError(const char *txt);
Packit f574b8
static int PassesTest(struct MailcapEntry *mc);
Packit f574b8
Packit f574b8
static char *GetCommand(char *s, char **t)
Packit f574b8
{
Packit f574b8
    char *s2;
Packit f574b8
    int quoted = 0;
Packit f574b8
Packit f574b8
    s = LYSkipBlanks(s);
Packit f574b8
    /* marca -- added + 1 for error case -- oct 24, 1993. */
Packit f574b8
    s2 = typeMallocn(char, strlen(s) * 2 + 1);	/* absolute max, if all % signs */
Packit f574b8
Packit f574b8
    if (!s2)
Packit f574b8
	ExitWithError(MEMORY_EXHAUSTED_ABORT);
Packit f574b8
Packit f574b8
    *t = s2;
Packit f574b8
    while (non_empty(s)) {
Packit f574b8
	if (quoted) {
Packit f574b8
	    if (*s == '%')
Packit f574b8
		*s2++ = '%';	/* Quote through next level, ugh! */
Packit f574b8
Packit f574b8
	    *s2++ = *s++;
Packit f574b8
	    quoted = 0;
Packit f574b8
	} else {
Packit f574b8
	    if (*s == ';') {
Packit f574b8
		*s2 = '\0';
Packit f574b8
		return (++s);
Packit f574b8
	    }
Packit f574b8
	    if (*s == ESCAPE) {
Packit f574b8
		quoted = 1;
Packit f574b8
		++s;
Packit f574b8
	    } else {
Packit f574b8
		*s2++ = *s++;
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    *s2 = '\0';
Packit f574b8
    return (NULL);
Packit f574b8
}
Packit f574b8
Packit f574b8
/* no leading or trailing space, all lower case */
Packit f574b8
static char *Cleanse(char *s)
Packit f574b8
{
Packit f574b8
    LYTrimLeading(s);
Packit f574b8
    LYTrimTrailing(s);
Packit f574b8
    LYLowerCase(s);
Packit f574b8
    return (s);
Packit f574b8
}
Packit f574b8
Packit f574b8
/* remove unnecessary (unquoted) blanks in a shell command */
Packit f574b8
static void TrimCommand(char *command)
Packit f574b8
{
Packit f574b8
    LYTrimTrailing(command);
Packit f574b8
#ifdef UNIX
Packit f574b8
    {
Packit f574b8
	char *s = command;
Packit f574b8
	char *d = command;
Packit f574b8
	int ch;
Packit f574b8
	int c0 = ' ';
Packit f574b8
	BOOL escape = FALSE;
Packit f574b8
	BOOL dquote = FALSE;
Packit f574b8
	BOOL squote = FALSE;
Packit f574b8
Packit f574b8
	while ((ch = *s++) != '\0') {
Packit f574b8
	    if (escape) {
Packit f574b8
		escape = FALSE;
Packit f574b8
	    } else if (squote) {
Packit f574b8
		if (ch == SQUOTE)
Packit f574b8
		    squote = FALSE;
Packit f574b8
	    } else if (dquote) {
Packit f574b8
		switch (ch) {
Packit f574b8
		case DQUOTE:
Packit f574b8
		    dquote = FALSE;
Packit f574b8
		    break;
Packit f574b8
		case ESCAPE:
Packit f574b8
		    escape = TRUE;
Packit f574b8
		    break;
Packit f574b8
		}
Packit f574b8
	    } else {
Packit f574b8
		switch (ch) {
Packit f574b8
		case DQUOTE:
Packit f574b8
		    dquote = TRUE;
Packit f574b8
		    break;
Packit f574b8
		case SQUOTE:
Packit f574b8
		    squote = TRUE;
Packit f574b8
		    break;
Packit f574b8
		}
Packit f574b8
	    }
Packit f574b8
	    if (!escape && !dquote && !squote) {
Packit f574b8
		if (ch == '\t')
Packit f574b8
		    ch = ' ';
Packit f574b8
		if (ch == ' ') {
Packit f574b8
		    if (c0 == ' ')
Packit f574b8
			continue;
Packit f574b8
		}
Packit f574b8
	    }
Packit f574b8
	    *d++ = (char) ch;
Packit f574b8
	    c0 = ch;
Packit f574b8
	}
Packit f574b8
	*d = '\0';
Packit f574b8
    }
Packit f574b8
#endif
Packit f574b8
}
Packit f574b8
Packit f574b8
static int ProcessMailcapEntry(FILE *fp, struct MailcapEntry *mc, AcceptMedia media)
Packit f574b8
{
Packit f574b8
    size_t rawentryalloc = 2000, len, need;
Packit f574b8
    char *rawentry, *s, *t;
Packit f574b8
    char *LineBuf = NULL;
Packit f574b8
Packit f574b8
    rawentry = (char *) malloc(rawentryalloc);
Packit f574b8
    if (!rawentry)
Packit f574b8
	ExitWithError(MEMORY_EXHAUSTED_ABORT);
Packit f574b8
Packit f574b8
    *rawentry = '\0';
Packit f574b8
    while (LYSafeGets(&LineBuf, fp) != 0) {
Packit f574b8
	LYTrimNewline(LineBuf);
Packit f574b8
	if (LineBuf[0] == '#' || LineBuf[0] == '\0')
Packit f574b8
	    continue;
Packit f574b8
	len = strlen(LineBuf);
Packit f574b8
	need = len + strlen(rawentry) + 1;
Packit f574b8
	if (need > rawentryalloc) {
Packit f574b8
	    rawentryalloc += (2000 + need);
Packit f574b8
	    rawentry = typeRealloc(char, rawentry, rawentryalloc);
Packit f574b8
Packit f574b8
	    if (!rawentry)
Packit f574b8
		ExitWithError(MEMORY_EXHAUSTED_ABORT);
Packit f574b8
	}
Packit f574b8
	if (len > 0 && LineBuf[len - 1] == ESCAPE) {
Packit f574b8
	    LineBuf[len - 1] = '\0';
Packit f574b8
	    strcat(rawentry, LineBuf);
Packit f574b8
	} else {
Packit f574b8
	    strcat(rawentry, LineBuf);
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    FREE(LineBuf);
Packit f574b8
Packit f574b8
    t = s = LYSkipBlanks(rawentry);
Packit f574b8
    if (!*s) {
Packit f574b8
	/* totally blank entry -- quietly ignore */
Packit f574b8
	FREE(rawentry);
Packit f574b8
	return (0);
Packit f574b8
    }
Packit f574b8
    s = StrChr(rawentry, ';');
Packit f574b8
    if (s == NULL) {
Packit f574b8
	CTrace((tfp,
Packit f574b8
		"ProcessMailcapEntry: Ignoring invalid mailcap entry: %s\n",
Packit f574b8
		rawentry));
Packit f574b8
	FREE(rawentry);
Packit f574b8
	return (0);
Packit f574b8
    }
Packit f574b8
    *s++ = '\0';
Packit f574b8
    if (!strncasecomp(t, STR_HTML, 9) ||
Packit f574b8
	!strncasecomp(t, STR_PLAINTEXT, 10)) {
Packit f574b8
	--s;
Packit f574b8
	*s = ';';
Packit f574b8
	CTrace((tfp, "ProcessMailcapEntry: Ignoring mailcap entry: %s\n",
Packit f574b8
		rawentry));
Packit f574b8
	FREE(rawentry);
Packit f574b8
	return (0);
Packit f574b8
    }
Packit f574b8
    LYRemoveBlanks(rawentry);
Packit f574b8
    LYLowerCase(rawentry);
Packit f574b8
Packit f574b8
    mc->needsterminal = 0;
Packit f574b8
    mc->copiousoutput = 0;
Packit f574b8
    mc->needtofree = 1;
Packit f574b8
    mc->testcommand = NULL;
Packit f574b8
    mc->label = NULL;
Packit f574b8
    mc->printcommand = NULL;
Packit f574b8
    mc->contenttype = NULL;
Packit f574b8
    StrAllocCopy(mc->contenttype, rawentry);
Packit f574b8
    mc->quality = (float) 1.0;
Packit f574b8
    mc->maxbytes = 0;
Packit f574b8
    t = GetCommand(s, &mc->command);
Packit f574b8
    if (!t) {
Packit f574b8
	goto assign_presentation;
Packit f574b8
    }
Packit f574b8
    s = LYSkipBlanks(t);
Packit f574b8
    while (s) {
Packit f574b8
	char *arg, *eq, *mallocd_string;
Packit f574b8
Packit f574b8
	t = GetCommand(s, &mallocd_string);
Packit f574b8
	arg = mallocd_string;
Packit f574b8
	eq = StrChr(arg, '=');
Packit f574b8
	if (eq) {
Packit f574b8
	    *eq++ = '\0';
Packit f574b8
	    eq = LYSkipBlanks(eq);
Packit f574b8
	}
Packit f574b8
	if (non_empty(arg)) {
Packit f574b8
	    arg = Cleanse(arg);
Packit f574b8
	    if (!strcmp(arg, "needsterminal")) {
Packit f574b8
		mc->needsterminal = 1;
Packit f574b8
	    } else if (!strcmp(arg, "copiousoutput")) {
Packit f574b8
		mc->copiousoutput = 1;
Packit f574b8
	    } else if (eq && !strcmp(arg, "test")) {
Packit f574b8
		mc->testcommand = NULL;
Packit f574b8
		StrAllocCopy(mc->testcommand, eq);
Packit f574b8
		TrimCommand(mc->testcommand);
Packit f574b8
		CTrace((tfp, "ProcessMailcapEntry: Found testcommand:%s\n",
Packit f574b8
			mc->testcommand));
Packit f574b8
	    } else if (eq && !strcmp(arg, "description")) {
Packit f574b8
		mc->label = eq;	/* ignored */
Packit f574b8
	    } else if (eq && !strcmp(arg, "label")) {
Packit f574b8
		mc->label = eq;	/* ignored: bogus old name for description */
Packit f574b8
	    } else if (eq && !strcmp(arg, "print")) {
Packit f574b8
		mc->printcommand = eq;	/* ignored */
Packit f574b8
	    } else if (eq && !strcmp(arg, "textualnewlines")) {
Packit f574b8
		/* no support for now.  What does this do anyways? */
Packit f574b8
		/* ExceptionalNewline(mc->contenttype, atoi(eq)); */
Packit f574b8
	    } else if (eq && !strcmp(arg, "q")) {
Packit f574b8
		mc->quality = (float) atof(eq);
Packit f574b8
		if (mc->quality > 0.000 && mc->quality < 0.001)
Packit f574b8
		    mc->quality = (float) 0.001;
Packit f574b8
	    } else if (eq && !strcmp(arg, "mxb")) {
Packit f574b8
		mc->maxbytes = atol(eq);
Packit f574b8
		if (mc->maxbytes < 0)
Packit f574b8
		    mc->maxbytes = 0;
Packit f574b8
	    } else if (strcmp(arg, "notes")) {	/* IGNORE notes field */
Packit f574b8
		if (*arg)
Packit f574b8
		    CTrace((tfp,
Packit f574b8
			    "ProcessMailcapEntry: Ignoring mailcap flag '%s'.\n",
Packit f574b8
			    arg));
Packit f574b8
	    }
Packit f574b8
Packit f574b8
	}
Packit f574b8
	FREE(mallocd_string);
Packit f574b8
	s = t;
Packit f574b8
    }
Packit f574b8
Packit f574b8
  assign_presentation:
Packit f574b8
    FREE(rawentry);
Packit f574b8
Packit f574b8
    if (PassesTest(mc)) {
Packit f574b8
	CTrace((tfp, "ProcessMailcapEntry Setting up conversion %s : %s\n",
Packit f574b8
		mc->contenttype, mc->command));
Packit f574b8
	HTSetPresentation(mc->contenttype,
Packit f574b8
			  mc->command,
Packit f574b8
			  mc->testcommand,
Packit f574b8
			  mc->quality,
Packit f574b8
			  3.0, 0.0, mc->maxbytes, media);
Packit f574b8
    }
Packit f574b8
    FREE(mc->command);
Packit f574b8
    FREE(mc->testcommand);
Packit f574b8
    FREE(mc->contenttype);
Packit f574b8
Packit f574b8
    return (1);
Packit f574b8
}
Packit f574b8
Packit f574b8
#define L_CURL '{'
Packit f574b8
#define R_CURL '}'
Packit f574b8
Packit f574b8
static const char *LYSkipQuoted(const char *s)
Packit f574b8
{
Packit f574b8
    int escaped = 0;
Packit f574b8
Packit f574b8
    ++s;			/* skip first quote */
Packit f574b8
    while (*s != 0) {
Packit f574b8
	if (escaped) {
Packit f574b8
	    escaped = 0;
Packit f574b8
	} else if (*s == ESCAPE) {
Packit f574b8
	    escaped = 1;
Packit f574b8
	} else if (*s == DQUOTE) {
Packit f574b8
	    ++s;
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
	++s;
Packit f574b8
    }
Packit f574b8
    return s;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*
Packit f574b8
 * Note: the tspecials[] here are those defined for Content-Type header, so
Packit f574b8
 * this function is not really general-purpose.
Packit f574b8
 */
Packit f574b8
static const char *LYSkipToken(const char *s)
Packit f574b8
{
Packit f574b8
    static const char tspecials[] = "\"()<>@,;:\\/[]?.=";
Packit f574b8
Packit f574b8
    while (*s != '\0' && !WHITE(*s) && StrChr(tspecials, *s) == 0) {
Packit f574b8
	++s;
Packit f574b8
    }
Packit f574b8
    return s;
Packit f574b8
}
Packit f574b8
Packit f574b8
static const char *LYSkipValue(const char *s)
Packit f574b8
{
Packit f574b8
    if (*s == DQUOTE)
Packit f574b8
	s = LYSkipQuoted(s);
Packit f574b8
    else
Packit f574b8
	s = LYSkipToken(s);
Packit f574b8
    return s;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*
Packit f574b8
 * Copy the value from the source, dequoting if needed.
Packit f574b8
 */
Packit f574b8
static char *LYCopyValue(const char *s)
Packit f574b8
{
Packit f574b8
    const char *t;
Packit f574b8
    char *result = 0;
Packit f574b8
    int j, k;
Packit f574b8
Packit f574b8
    if (*s == DQUOTE) {
Packit f574b8
	t = LYSkipQuoted(s);
Packit f574b8
	StrAllocCopy(result, s + 1);
Packit f574b8
	result[t - s - 2] = '\0';
Packit f574b8
	for (j = k = 0;; ++j, ++k) {
Packit f574b8
	    if (result[j] == ESCAPE) {
Packit f574b8
		++j;
Packit f574b8
	    }
Packit f574b8
	    if ((result[k] = result[j]) == '\0')
Packit f574b8
		break;
Packit f574b8
	}
Packit f574b8
    } else {
Packit f574b8
	t = LYSkipToken(s);
Packit f574b8
	StrAllocCopy(result, s);
Packit f574b8
	result[t - s] = '\0';
Packit f574b8
    }
Packit f574b8
    return result;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*
Packit f574b8
 * The "Content-Type:" field, contains zero or more parameters after a ';'.
Packit f574b8
 * Return the value of the named parameter, or null.
Packit f574b8
 */
Packit f574b8
static char *LYGetContentType(const char *name,
Packit f574b8
			      const char *params)
Packit f574b8
{
Packit f574b8
    char *result = 0;
Packit f574b8
Packit f574b8
    if (params != 0) {
Packit f574b8
	if (name != 0) {
Packit f574b8
	    size_t length = strlen(name);
Packit f574b8
	    const char *test = StrChr(params, ';');	/* skip type/subtype */
Packit f574b8
	    const char *next;
Packit f574b8
Packit f574b8
	    while (test != 0) {
Packit f574b8
		BOOL found = FALSE;
Packit f574b8
Packit f574b8
		++test;		/* skip the ';' */
Packit f574b8
		test = LYSkipCBlanks(test);
Packit f574b8
		next = LYSkipToken(test);
Packit f574b8
		if ((next - test) == (int) length
Packit f574b8
		    && !StrNCmp(test, name, length)) {
Packit f574b8
		    found = TRUE;
Packit f574b8
		}
Packit f574b8
		test = LYSkipCBlanks(next);
Packit f574b8
		if (*test == '=') {
Packit f574b8
		    ++test;
Packit f574b8
		    test = LYSkipCBlanks(test);
Packit f574b8
		    if (found) {
Packit f574b8
			result = LYCopyValue(test);
Packit f574b8
			break;
Packit f574b8
		    } else {
Packit f574b8
			test = LYSkipValue(test);
Packit f574b8
		    }
Packit f574b8
		    test = LYSkipCBlanks(test);
Packit f574b8
		}
Packit f574b8
		if (*test != ';') {
Packit f574b8
		    break;	/* we're lost */
Packit f574b8
		}
Packit f574b8
	    }
Packit f574b8
	} else {		/* return the content-type */
Packit f574b8
	    StrAllocCopy(result, params);
Packit f574b8
	    *LYSkipNonBlanks(result) = '\0';
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    return result;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*
Packit f574b8
 * Check if the command uses a "%s" substitution.  We need to know this, to
Packit f574b8
 * decide when to create temporary files, etc.
Packit f574b8
 */
Packit f574b8
BOOL LYMailcapUsesPctS(const char *controlstring)
Packit f574b8
{
Packit f574b8
    BOOL result = FALSE;
Packit f574b8
    const char *from;
Packit f574b8
    const char *next;
Packit f574b8
    int prefixed = 0;
Packit f574b8
    int escaped = 0;
Packit f574b8
Packit f574b8
    for (from = controlstring; *from != '\0'; from++) {
Packit f574b8
	if (escaped) {
Packit f574b8
	    escaped = 0;
Packit f574b8
	} else if (*from == ESCAPE) {
Packit f574b8
	    escaped = 1;
Packit f574b8
	} else if (prefixed) {
Packit f574b8
	    prefixed = 0;
Packit f574b8
	    switch (*from) {
Packit f574b8
	    case '%':		/* not defined */
Packit f574b8
	    case 'n':
Packit f574b8
	    case 'F':
Packit f574b8
	    case 't':
Packit f574b8
		break;
Packit f574b8
	    case 's':
Packit f574b8
		result = TRUE;
Packit f574b8
		break;
Packit f574b8
	    case L_CURL:
Packit f574b8
		next = StrChr(from, R_CURL);
Packit f574b8
		if (next != 0) {
Packit f574b8
		    from = next;
Packit f574b8
		    break;
Packit f574b8
		}
Packit f574b8
		/* FALLTHRU */
Packit f574b8
	    default:
Packit f574b8
		break;
Packit f574b8
	    }
Packit f574b8
	} else if (*from == '%') {
Packit f574b8
	    prefixed = 1;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    return result;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*
Packit f574b8
 * Build the command string for testing or executing a mailcap entry.
Packit f574b8
 * If a substitution from the Content-Type header is requested but no
Packit f574b8
 * parameters are available, return -1, otherwise 0.
Packit f574b8
 *
Packit f574b8
 * This does not support multipart %n or %F (does this apply to lynx?)
Packit f574b8
 */
Packit f574b8
static int BuildCommand(HTChunk *cmd,
Packit f574b8
			const char *controlstring,
Packit f574b8
			const char *TmpFileName,
Packit f574b8
			const char *params)
Packit f574b8
{
Packit f574b8
    int result = 0;
Packit f574b8
    size_t TmpFileLen = strlen(TmpFileName);
Packit f574b8
    const char *from;
Packit f574b8
    const char *next;
Packit f574b8
    char *name, *value;
Packit f574b8
    int prefixed = 0;
Packit f574b8
    int escaped = 0;
Packit f574b8
Packit f574b8
    for (from = controlstring; *from != '\0'; from++) {
Packit f574b8
	if (escaped) {
Packit f574b8
	    escaped = 0;
Packit f574b8
	    HTChunkPutc(cmd, UCH(*from));
Packit f574b8
	} else if (*from == ESCAPE) {
Packit f574b8
	    escaped = 1;
Packit f574b8
	} else if (prefixed) {
Packit f574b8
	    prefixed = 0;
Packit f574b8
	    switch (*from) {
Packit f574b8
	    case '%':		/* not defined */
Packit f574b8
		HTChunkPutc(cmd, UCH(*from));
Packit f574b8
		break;
Packit f574b8
	    case 'n':
Packit f574b8
		/* FALLTHRU */
Packit f574b8
	    case 'F':
Packit f574b8
		CTrace((tfp, "BuildCommand: Bad mailcap \"test\" clause: %s\n",
Packit f574b8
			controlstring));
Packit f574b8
		break;
Packit f574b8
	    case 't':
Packit f574b8
		if ((value = LYGetContentType(NULL, params)) != 0) {
Packit f574b8
		    HTChunkPuts(cmd, value);
Packit f574b8
		    FREE(value);
Packit f574b8
		}
Packit f574b8
		break;
Packit f574b8
	    case 's':
Packit f574b8
		if (TmpFileLen) {
Packit f574b8
		    HTChunkPuts(cmd, TmpFileName);
Packit f574b8
		}
Packit f574b8
		break;
Packit f574b8
	    case L_CURL:
Packit f574b8
		next = StrChr(from, R_CURL);
Packit f574b8
		if (next != 0) {
Packit f574b8
		    if (params != 0) {
Packit f574b8
			++from;
Packit f574b8
			name = 0;
Packit f574b8
			HTSprintf0(&name, "%.*s", (int) (next - from), from);
Packit f574b8
			if ((value = LYGetContentType(name, params)) != 0) {
Packit f574b8
			    HTChunkPuts(cmd, value);
Packit f574b8
			    FREE(value);
Packit f574b8
			} else if (name) {
Packit f574b8
			    if (!strcmp(name, "charset")) {
Packit f574b8
				HTChunkPuts(cmd, "ISO-8859-1");
Packit f574b8
			    } else {
Packit f574b8
				CTrace((tfp, "BuildCommand no value for %s\n", name));
Packit f574b8
			    }
Packit f574b8
			}
Packit f574b8
			FREE(name);
Packit f574b8
		    } else {
Packit f574b8
			result = -1;
Packit f574b8
		    }
Packit f574b8
		    from = next;
Packit f574b8
		    break;
Packit f574b8
		}
Packit f574b8
		/* FALLTHRU */
Packit f574b8
	    default:
Packit f574b8
		CTrace((tfp,
Packit f574b8
			"BuildCommand: Ignoring unrecognized format code in mailcap file '%%%c'.\n",
Packit f574b8
			*from));
Packit f574b8
		break;
Packit f574b8
	    }
Packit f574b8
	} else if (*from == '%') {
Packit f574b8
	    prefixed = 1;
Packit f574b8
	} else {
Packit f574b8
	    HTChunkPutc(cmd, UCH(*from));
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    HTChunkTerminate(cmd);
Packit f574b8
    return result;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*
Packit f574b8
 * Build the mailcap test-command and execute it.  This is only invoked when
Packit f574b8
 * we cannot tell just by looking at the command if it would succeed.
Packit f574b8
 *
Packit f574b8
 * Returns 0 for success, -1 for error and 1 for deferred.
Packit f574b8
 */
Packit f574b8
int LYTestMailcapCommand(const char *testcommand,
Packit f574b8
			 const char *params)
Packit f574b8
{
Packit f574b8
    int result;
Packit f574b8
    char TmpFileName[LY_MAXPATH];
Packit f574b8
    HTChunk *expanded = 0;
Packit f574b8
Packit f574b8
    if (LYMailcapUsesPctS(testcommand)) {
Packit f574b8
	if (LYOpenTemp(TmpFileName, HTML_SUFFIX, "w") == 0)
Packit f574b8
	    ExitWithError(CANNOT_OPEN_TEMP);
Packit f574b8
	LYCloseTemp(TmpFileName);
Packit f574b8
    } else {
Packit f574b8
	/* We normally don't need a temp file name - kw */
Packit f574b8
	TmpFileName[0] = '\0';
Packit f574b8
    }
Packit f574b8
    expanded = HTChunkCreate(1024);
Packit f574b8
    if (BuildCommand(expanded, testcommand, TmpFileName, params) != 0) {
Packit f574b8
	result = 1;
Packit f574b8
	CTrace((tfp, "PassesTest: Deferring test command: %s\n", expanded->data));
Packit f574b8
    } else {
Packit f574b8
	CTrace((tfp, "PassesTest: Executing test command: %s\n", expanded->data));
Packit f574b8
	if ((result = LYSystem(expanded->data)) != 0) {
Packit f574b8
	    result = -1;
Packit f574b8
	    CTrace((tfp, "PassesTest: Test failed!\n"));
Packit f574b8
	} else {
Packit f574b8
	    CTrace((tfp, "PassesTest: Test passed!\n"));
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    HTChunkFree(expanded);
Packit f574b8
    (void) LYRemoveTemp(TmpFileName);
Packit f574b8
Packit f574b8
    return result;
Packit f574b8
}
Packit f574b8
Packit f574b8
char *LYMakeMailcapCommand(const char *command,
Packit f574b8
			   const char *params,
Packit f574b8
			   const char *filename)
Packit f574b8
{
Packit f574b8
    HTChunk *expanded = 0;
Packit f574b8
    char *result = 0;
Packit f574b8
Packit f574b8
    expanded = HTChunkCreate(1024);
Packit f574b8
    BuildCommand(expanded, command, filename, params);
Packit f574b8
    StrAllocCopy(result, expanded->data);
Packit f574b8
    HTChunkFree(expanded);
Packit f574b8
    return result;
Packit f574b8
}
Packit f574b8
Packit f574b8
#define RTR_forget      0
Packit f574b8
#define RTR_lookup      1
Packit f574b8
#define RTR_add         2
Packit f574b8
Packit f574b8
static int RememberTestResult(int mode, char *cmd, int result)
Packit f574b8
{
Packit f574b8
    struct cmdlist_s {
Packit f574b8
	char *cmd;
Packit f574b8
	int result;
Packit f574b8
	struct cmdlist_s *next;
Packit f574b8
    };
Packit f574b8
    static struct cmdlist_s *cmdlist = NULL;
Packit f574b8
    struct cmdlist_s *cur;
Packit f574b8
Packit f574b8
    switch (mode) {
Packit f574b8
    case RTR_forget:
Packit f574b8
	while (cmdlist) {
Packit f574b8
	    cur = cmdlist->next;
Packit f574b8
	    FREE(cmdlist->cmd);
Packit f574b8
	    FREE(cmdlist);
Packit f574b8
	    cmdlist = cur;
Packit f574b8
	}
Packit f574b8
	break;
Packit f574b8
    case RTR_lookup:
Packit f574b8
	for (cur = cmdlist; cur; cur = cur->next)
Packit f574b8
	    if (!strcmp(cmd, cur->cmd))
Packit f574b8
		return cur->result;
Packit f574b8
	return -1;
Packit f574b8
    case RTR_add:
Packit f574b8
	cur = typecalloc(struct cmdlist_s);
Packit f574b8
Packit f574b8
	if (cur == NULL)
Packit f574b8
	    outofmem(__FILE__, "RememberTestResult");
Packit f574b8
Packit f574b8
	cur->next = cmdlist;
Packit f574b8
	StrAllocCopy(cur->cmd, cmd);
Packit f574b8
	cur->result = result;
Packit f574b8
	cmdlist = cur;
Packit f574b8
	break;
Packit f574b8
    }
Packit f574b8
    return 0;
Packit f574b8
}
Packit f574b8
Packit f574b8
/* FIXME: this sometimes used caseless comparison, e.g., strcasecomp */
Packit f574b8
#define SameCommand(tst,ref) !strcmp(tst,ref)
Packit f574b8
Packit f574b8
static int PassesTest(struct MailcapEntry *mc)
Packit f574b8
{
Packit f574b8
    int result;
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     *  Make sure we have a command
Packit f574b8
     */
Packit f574b8
    if (!mc->testcommand)
Packit f574b8
	return (1);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     *  Save overhead of system() calls by faking these. - FM
Packit f574b8
     */
Packit f574b8
    if (SameCommand(mc->testcommand, "test \"$DISPLAY\"") ||
Packit f574b8
	SameCommand(mc->testcommand, "test \"$DISPLAY\" != \"\"") ||
Packit f574b8
	SameCommand(mc->testcommand, "test -n \"$DISPLAY\"")) {
Packit f574b8
	FREE(mc->testcommand);
Packit f574b8
	CTrace((tfp, "PassesTest: Testing for XWINDOWS environment.\n"));
Packit f574b8
	if (LYgetXDisplay() != NULL) {
Packit f574b8
	    CTrace((tfp, "PassesTest: Test passed!\n"));
Packit f574b8
	    return (0 == 0);
Packit f574b8
	} else {
Packit f574b8
	    CTrace((tfp, "PassesTest: Test failed!\n"));
Packit f574b8
	    return (-1 == 0);
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    if (SameCommand(mc->testcommand, "test -z \"$DISPLAY\"")) {
Packit f574b8
	FREE(mc->testcommand);
Packit f574b8
	CTrace((tfp, "PassesTest: Testing for NON_XWINDOWS environment.\n"));
Packit f574b8
	if (LYgetXDisplay() == NULL) {
Packit f574b8
	    CTrace((tfp, "PassesTest: Test passed!\n"));
Packit f574b8
	    return (0 == 0);
Packit f574b8
	} else {
Packit f574b8
	    CTrace((tfp, "PassesTest: Test failed!\n"));
Packit f574b8
	    return (-1 == 0);
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     *  Why do anything but return success for this one! - FM
Packit f574b8
     */
Packit f574b8
    if (SameCommand(mc->testcommand, "test -n \"$LYNX_VERSION\"")) {
Packit f574b8
	FREE(mc->testcommand);
Packit f574b8
	CTrace((tfp, "PassesTest: Testing for LYNX environment.\n"));
Packit f574b8
	CTrace((tfp, "PassesTest: Test passed!\n"));
Packit f574b8
	return (0 == 0);
Packit f574b8
    } else
Packit f574b8
	/*
Packit f574b8
	 *  ... or failure for this one! - FM
Packit f574b8
	 */
Packit f574b8
    if (SameCommand(mc->testcommand, "test -z \"$LYNX_VERSION\"")) {
Packit f574b8
	FREE(mc->testcommand);
Packit f574b8
	CTrace((tfp, "PassesTest: Testing for non-LYNX environment.\n"));
Packit f574b8
	CTrace((tfp, "PassesTest: Test failed!\n"));
Packit f574b8
	return (-1 == 0);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    result = RememberTestResult(RTR_lookup, mc->testcommand, 0);
Packit f574b8
    if (result == -1) {
Packit f574b8
	result = LYTestMailcapCommand(mc->testcommand, NULL);
Packit f574b8
	RememberTestResult(RTR_add, mc->testcommand, result ? 1 : 0);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     *  Free the test command as well since
Packit f574b8
     *  we wont be needing it anymore.
Packit f574b8
     */
Packit f574b8
    if (result != 1)
Packit f574b8
	FREE(mc->testcommand);
Packit f574b8
Packit f574b8
    if (result < 0) {
Packit f574b8
	CTrace((tfp, "PassesTest: Test failed!\n"));
Packit f574b8
    } else if (result == 0) {
Packit f574b8
	CTrace((tfp, "PassesTest: Test passed!\n"));
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return (result >= 0);
Packit f574b8
}
Packit f574b8
Packit f574b8
static int ProcessMailcapFile(char *file, AcceptMedia media)
Packit f574b8
{
Packit f574b8
    struct MailcapEntry mc;
Packit f574b8
    FILE *fp;
Packit f574b8
Packit f574b8
    CTrace((tfp, "ProcessMailcapFile: Loading file '%s'.\n",
Packit f574b8
	    file));
Packit f574b8
    if ((fp = fopen(file, TXT_R)) == NULL) {
Packit f574b8
	CTrace((tfp, "ProcessMailcapFile: Could not open '%s'.\n",
Packit f574b8
		file));
Packit f574b8
	return (-1 == 0);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    while (fp && !feof(fp)) {
Packit f574b8
	ProcessMailcapEntry(fp, &mc, media);
Packit f574b8
    }
Packit f574b8
    LYCloseInput(fp);
Packit f574b8
    RememberTestResult(RTR_forget, NULL, 0);
Packit f574b8
    return (0 == 0);
Packit f574b8
}
Packit f574b8
Packit f574b8
static int ExitWithError(const char *txt)
Packit f574b8
{
Packit f574b8
    if (txt)
Packit f574b8
	fprintf(tfp, "Lynx: %s\n", txt);
Packit f574b8
    exit_immediately(EXIT_FAILURE);
Packit f574b8
    return (-1);
Packit f574b8
}
Packit f574b8
Packit f574b8
/* Reverse the entries from each mailcap after it has been read, so that
Packit f574b8
 * earlier entries have precedence.  Set to 0 to get traditional lynx
Packit f574b8
 * behavior, which means that the last match wins. - kw */
Packit f574b8
static int reverse_mailcap = 1;
Packit f574b8
Packit f574b8
static int HTLoadTypesConfigFile(char *fn, AcceptMedia media)
Packit f574b8
{
Packit f574b8
    int result = 0;
Packit f574b8
    HTList *saved = HTPresentations;
Packit f574b8
Packit f574b8
    if (reverse_mailcap) {	/* temporarily hide existing list */
Packit f574b8
	HTPresentations = NULL;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    result = ProcessMailcapFile(fn, media);
Packit f574b8
Packit f574b8
    if (reverse_mailcap) {
Packit f574b8
	if (result && HTPresentations) {
Packit f574b8
	    HTList_reverse(HTPresentations);
Packit f574b8
	    HTList_appendList(HTPresentations, saved);
Packit f574b8
	    FREE(saved);
Packit f574b8
	} else {
Packit f574b8
	    HTPresentations = saved;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    return result;
Packit f574b8
}
Packit f574b8
Packit f574b8
/* ------------------------------------------------------------------------ */
Packit f574b8
/* ------------------------------------------------------------------------ */
Packit f574b8
/* ------------------------------------------------------------------------ */
Packit f574b8
Packit f574b8
/*	Define a basic set of suffixes
Packit f574b8
 *	------------------------------
Packit f574b8
 *
Packit f574b8
 *	The LAST suffix for a type is that used for temporary files
Packit f574b8
 *	of that type.
Packit f574b8
 *	The quality is an apriori bias as to whether the file should be
Packit f574b8
 *	used.  Not that different suffixes can be used to represent files
Packit f574b8
 *	which are of the same format but are originals or regenerated,
Packit f574b8
 *	with different values.
Packit f574b8
 */
Packit f574b8
/*
Packit f574b8
 * Additional notes:  the encoding parameter may be taken into account when
Packit f574b8
 * looking for a match; for that purpose "7bit", "8bit", and "binary" are
Packit f574b8
 * equivalent.
Packit f574b8
 *
Packit f574b8
 * Use of mixed case and of pseudo MIME types with embedded spaces should be
Packit f574b8
 * avoided.  It was once necessary for getting the fancy strings into type
Packit f574b8
 * labels in FTP directory listings, but that can now be done with the
Packit f574b8
 * description field (using HTSetSuffix5).  AFAIK the only effect of such
Packit f574b8
 * "fancy" (and mostly invalid) types that cannot be reproduced by using a
Packit f574b8
 * description fields is some statusline messages in SaveToFile (HTFWriter.c). 
Packit f574b8
 * And showing the user an invalid MIME type as the 'Content-type:' is not such
Packit f574b8
 * a hot idea anyway, IMO.  Still, if you want it, it is still possible (even
Packit f574b8
 * in lynx.cfg now), but use of it in the defaults below has been reduced.
Packit f574b8
 *
Packit f574b8
 * Case variations rely on peculiar behavior of HTAtom.c for matching.  They
Packit f574b8
 * lead to surprising behavior, Lynx retains the case of a string in the form
Packit f574b8
 * first encountered after starting up.  So while later suffix rules generally
Packit f574b8
 * override or modify earlier ones, the case used for a MIME time is determined
Packit f574b8
 * by the first suffix rule (or other occurrence).  Matching in HTAtom_for is
Packit f574b8
 * effectively case insensitive, except for the first character of the string
Packit f574b8
 * which is treated as case-sensitive by the hash function there; best not to
Packit f574b8
 * rely on that, rather convert MIME types to lowercase on input as is already
Packit f574b8
 * done in most places (And HTAtom could become consistently case-sensitive, as
Packit f574b8
 * in newer W3C libwww).
Packit f574b8
 *  - kw 1999-10-12
Packit f574b8
 */
Packit f574b8
void HTFileInit(void)
Packit f574b8
{
Packit f574b8
#ifdef BUILTIN_SUFFIX_MAPS
Packit f574b8
    if (LYUseBuiltinSuffixes) {
Packit f574b8
	CTrace((tfp, "HTFileInit: Loading default (HTInit) extension maps.\n"));
Packit f574b8
Packit f574b8
	/* default suffix interpretation */
Packit f574b8
	SET_SUFFIX1("*", STR_PLAINTEXT, "8bit");
Packit f574b8
	SET_SUFFIX1("*.*", STR_PLAINTEXT, "8bit");
Packit f574b8
Packit f574b8
#ifdef EXEC_SCRIPTS
Packit f574b8
	/*
Packit f574b8
	 * define these extensions for exec scripts.
Packit f574b8
	 */
Packit f574b8
#ifndef VMS
Packit f574b8
	/* for csh exec links */
Packit f574b8
	HTSetSuffix(".csh", "application/x-csh", "8bit", 0.8);
Packit f574b8
	HTSetSuffix(".sh", "application/x-sh", "8bit", 0.8);
Packit f574b8
	HTSetSuffix(".ksh", "application/x-ksh", "8bit", 0.8);
Packit f574b8
#else
Packit f574b8
	HTSetSuffix(".com", "application/x-VMS_script", "8bit", 0.8);
Packit f574b8
#endif /* !VMS */
Packit f574b8
#endif /* EXEC_SCRIPTS */
Packit f574b8
Packit f574b8
	/*
Packit f574b8
	 * Some of the old incarnation of the mappings is preserved and can be had
Packit f574b8
	 * by defining TRADITIONAL_SUFFIXES.  This is for some cases where I felt
Packit f574b8
	 * the old rules might be preferred by someone, for some reason.  It's not
Packit f574b8
	 * done consistently.  A lot more of this stuff could probably be changed
Packit f574b8
	 * too or omitted, now that nearly the equivalent functionality is
Packit f574b8
	 * available in lynx.cfg.  - kw 1999-10-12
Packit f574b8
	 */
Packit f574b8
	/* *INDENT-OFF* */
Packit f574b8
	SET_SUFFIX1(".saveme",	"application/x-Binary",		"binary");
Packit f574b8
	SET_SUFFIX1(".dump",	"application/x-Binary",		"binary");
Packit f574b8
	SET_SUFFIX1(".bin",	"application/x-Binary",		"binary");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".arc",	"application/x-Compressed",	"binary");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".alpha-exe", "application/x-Executable",	"binary");
Packit f574b8
	SET_SUFFIX1(".alpha_exe", "application/x-Executable",	"binary");
Packit f574b8
	SET_SUFFIX1(".AXP-exe", "application/x-Executable",	"binary");
Packit f574b8
	SET_SUFFIX1(".AXP_exe", "application/x-Executable",	"binary");
Packit f574b8
	SET_SUFFIX1(".VAX-exe", "application/x-Executable",	"binary");
Packit f574b8
	SET_SUFFIX1(".VAX_exe", "application/x-Executable",	"binary");
Packit f574b8
	SET_SUFFIX5(".exe",	STR_BINARY,			"binary", "Executable");
Packit f574b8
Packit f574b8
#ifdef TRADITIONAL_SUFFIXES
Packit f574b8
	SET_SUFFIX1(".exe.Z",	"application/x-Comp. Executable", "binary");
Packit f574b8
	SET_SUFFIX1(".Z",	"application/UNIX Compressed",	"binary");
Packit f574b8
	SET_SUFFIX1(".tar_Z",	"application/UNIX Compr. Tar",	"binary");
Packit f574b8
	SET_SUFFIX1(".tar.Z",	"application/UNIX Compr. Tar",	"binary");
Packit f574b8
#else
Packit f574b8
	SET_SUFFIX5(".Z",	"application/x-compress",	"binary", "UNIX Compressed");
Packit f574b8
	SET_SUFFIX5(".Z",	NULL,				"compress", "UNIX Compressed");
Packit f574b8
	SET_SUFFIX5(".exe.Z",	STR_BINARY,			"compress", "Executable");
Packit f574b8
	SET_SUFFIX5(".tar_Z",	"application/x-tar",		"compress", "UNIX Compr. Tar");
Packit f574b8
	SET_SUFFIX5(".tar.Z",	"application/x-tar",		"compress", "UNIX Compr. Tar");
Packit f574b8
#endif
Packit f574b8
Packit f574b8
#ifdef TRADITIONAL_SUFFIXES
Packit f574b8
	SET_SUFFIX1("-gz",	"application/GNU Compressed",	"binary");
Packit f574b8
	SET_SUFFIX1("_gz",	"application/GNU Compressed",	"binary");
Packit f574b8
	SET_SUFFIX1(".gz",	"application/GNU Compressed",	"binary");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".tar.gz",	"application/x-tar",		"binary", "GNU Compr. Tar");
Packit f574b8
	SET_SUFFIX5(".tgz",	"application/x-tar",		"gzip", "GNU Compr. Tar");
Packit f574b8
#else
Packit f574b8
	SET_SUFFIX5("-gz",	"application/x-gzip",		"binary", "GNU Compressed");
Packit f574b8
	SET_SUFFIX5("_gz",	"application/x-gzip",		"binary", "GNU Compressed");
Packit f574b8
	SET_SUFFIX5(".gz",	"application/x-gzip",		"binary", "GNU Compressed");
Packit f574b8
	SET_SUFFIX5("-gz",	NULL,				"gzip", "GNU Compressed");
Packit f574b8
	SET_SUFFIX5("_gz",	NULL,				"gzip", "GNU Compressed");
Packit f574b8
	SET_SUFFIX5(".gz",	NULL,				"gzip", "GNU Compressed");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".tar.gz",	"application/x-tar",		"gzip", "GNU Compr. Tar");
Packit f574b8
	SET_SUFFIX5(".tgz",	"application/x-tar",		"gzip", "GNU Compr. Tar");
Packit f574b8
#endif
Packit f574b8
Packit f574b8
#ifdef TRADITIONAL_SUFFIXES
Packit f574b8
	SET_SUFFIX1(".src",	"application/x-WAIS-source",	"8bit");
Packit f574b8
	SET_SUFFIX1(".wsrc",	"application/x-WAIS-source",	"8bit");
Packit f574b8
#else
Packit f574b8
	SET_SUFFIX5(".wsrc",	"application/x-wais-source",	"8bit", "WAIS-source");
Packit f574b8
#endif
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".zip",	"application/zip",		"binary", "Zip File");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".zz",	"application/x-deflate",	"binary");
Packit f574b8
	SET_SUFFIX1(".zz",	"application/deflate",		"binary");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".bz2",	"application/x-bzip2",		"binary");
Packit f574b8
	SET_SUFFIX1(".bz2",	"application/bzip2",		"binary");
Packit f574b8
Packit f574b8
#ifdef TRADITIONAL_SUFFIXES
Packit f574b8
	SET_SUFFIX1(".uu",	"application/x-UUencoded",	"8bit");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".hqx",	"application/x-Binhex",		"8bit");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".o",	"application/x-Prog. Object",	"binary");
Packit f574b8
	SET_SUFFIX1(".a",	"application/x-Prog. Library",	"binary");
Packit f574b8
#else
Packit f574b8
	SET_SUFFIX5(".uu",	"application/x-uuencoded",	"7bit", "UUencoded");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".hqx",	"application/mac-binhex40",	"8bit", "Mac BinHex");
Packit f574b8
Packit f574b8
	HTSetSuffix5(".o",	STR_BINARY,			"binary", "Prog. Object", 0.5);
Packit f574b8
	HTSetSuffix5(".a",	STR_BINARY,			"binary", "Prog. Library", 0.5);
Packit f574b8
	HTSetSuffix5(".so",	STR_BINARY,			"binary", "Shared Lib", 0.5);
Packit f574b8
#endif
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".oda",	"application/oda",		"binary", "ODA");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".pdf",	"application/pdf",		"binary", "PDF");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".eps",	"application/postscript",	"8bit", "Postscript");
Packit f574b8
	SET_SUFFIX5(".ai",	"application/postscript",	"8bit", "Postscript");
Packit f574b8
	SET_SUFFIX5(".ps",	"application/postscript",	"8bit", "Postscript");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".rtf",	"application/rtf",		"8bit", "RTF");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".dvi",	"application/x-dvi",		"8bit", "DVI");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".hdf",	"application/x-hdf",		"8bit", "HDF");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".cdf",	"application/x-netcdf",		"8bit");
Packit f574b8
	SET_SUFFIX1(".nc",	"application/x-netcdf",		"8bit");
Packit f574b8
Packit f574b8
#ifdef TRADITIONAL_SUFFIXES
Packit f574b8
	SET_SUFFIX1(".latex",	"application/x-Latex",		"8bit");
Packit f574b8
	SET_SUFFIX1(".tex",	"application/x-Tex",		"8bit");
Packit f574b8
	SET_SUFFIX1(".texinfo", "application/x-Texinfo",	"8bit");
Packit f574b8
	SET_SUFFIX1(".texi",	"application/x-Texinfo",	"8bit");
Packit f574b8
#else
Packit f574b8
	SET_SUFFIX5(".latex",	"application/x-latex",		"8bit", "LaTeX");
Packit f574b8
	SET_SUFFIX5(".tex",	"text/x-tex",			"8bit", "TeX");
Packit f574b8
	SET_SUFFIX5(".texinfo", "application/x-texinfo",	"8bit", "Texinfo");
Packit f574b8
	SET_SUFFIX5(".texi",	"application/x-texinfo",	"8bit", "Texinfo");
Packit f574b8
#endif
Packit f574b8
Packit f574b8
#ifdef TRADITIONAL_SUFFIXES
Packit f574b8
	SET_SUFFIX1(".t",	"application/x-Troff",		"8bit");
Packit f574b8
	SET_SUFFIX1(".tr",	"application/x-Troff",		"8bit");
Packit f574b8
	SET_SUFFIX1(".roff",	"application/x-Troff",		"8bit");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".man",	"application/x-Troff-man",	"8bit");
Packit f574b8
	SET_SUFFIX1(".me",	"application/x-Troff-me",	"8bit");
Packit f574b8
	SET_SUFFIX1(".ms",	"application/x-Troff-ms",	"8bit");
Packit f574b8
#else
Packit f574b8
	SET_SUFFIX5(".t",	"application/x-troff",		"8bit", "Troff");
Packit f574b8
	SET_SUFFIX5(".tr",	"application/x-troff",		"8bit", "Troff");
Packit f574b8
	SET_SUFFIX5(".roff",	"application/x-troff",		"8bit", "Troff");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".man",	"application/x-troff-man",	"8bit", "Man Page");
Packit f574b8
	SET_SUFFIX5(".me",	"application/x-troff-me",	"8bit", "Troff me");
Packit f574b8
	SET_SUFFIX5(".ms",	"application/x-troff-ms",	"8bit", "Troff ms");
Packit f574b8
#endif
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".zoo",	"application/x-Zoo File",	"binary");
Packit f574b8
Packit f574b8
#if defined(TRADITIONAL_SUFFIXES) || defined(VMS)
Packit f574b8
	SET_SUFFIX1(".bak",	"application/x-VMS BAK File",	"binary");
Packit f574b8
	SET_SUFFIX1(".bkp",	"application/x-VMS BAK File",	"binary");
Packit f574b8
	SET_SUFFIX1(".bck",	"application/x-VMS BAK File",	"binary");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".bkp_gz",	STR_BINARY,			"gzip", "GNU BAK File");
Packit f574b8
	SET_SUFFIX5(".bkp-gz",	STR_BINARY,			"gzip", "GNU BAK File");
Packit f574b8
	SET_SUFFIX5(".bck_gz",	STR_BINARY,			"gzip", "GNU BAK File");
Packit f574b8
	SET_SUFFIX5(".bck-gz",	STR_BINARY,			"gzip", "GNU BAK File");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".bkp-Z",	STR_BINARY,			"compress", "Comp. BAK File");
Packit f574b8
	SET_SUFFIX5(".bkp_Z",	STR_BINARY,			"compress", "Comp. BAK File");
Packit f574b8
	SET_SUFFIX5(".bck-Z",	STR_BINARY,			"compress", "Comp. BAK File");
Packit f574b8
	SET_SUFFIX5(".bck_Z",	STR_BINARY,			"compress", "Comp. BAK File");
Packit f574b8
#else
Packit f574b8
	HTSetSuffix5(".bak",	NULL,				"binary", "Backup", 0.5);
Packit f574b8
	SET_SUFFIX5(".bkp",	STR_BINARY,			"binary", "VMS BAK File");
Packit f574b8
	SET_SUFFIX5(".bck",	STR_BINARY,			"binary", "VMS BAK File");
Packit f574b8
#endif
Packit f574b8
Packit f574b8
#if defined(TRADITIONAL_SUFFIXES) || defined(VMS)
Packit f574b8
	SET_SUFFIX1(".hlb",	"application/x-VMS Help Libr.", "binary");
Packit f574b8
	SET_SUFFIX1(".olb",	"application/x-VMS Obj. Libr.", "binary");
Packit f574b8
	SET_SUFFIX1(".tlb",	"application/x-VMS Text Libr.", "binary");
Packit f574b8
	SET_SUFFIX1(".obj",	"application/x-VMS Prog. Obj.", "binary");
Packit f574b8
	SET_SUFFIX1(".decw$book", "application/x-DEC BookReader", "binary");
Packit f574b8
	SET_SUFFIX1(".mem",	"application/x-RUNOFF-MANUAL", "8bit");
Packit f574b8
#else
Packit f574b8
	SET_SUFFIX5(".hlb",	STR_BINARY,			"binary", "VMS Help Libr.");
Packit f574b8
	SET_SUFFIX5(".olb",	STR_BINARY,			"binary", "VMS Obj. Libr.");
Packit f574b8
	SET_SUFFIX5(".tlb",	STR_BINARY,			"binary", "VMS Text Libr.");
Packit f574b8
	SET_SUFFIX5(".obj",	STR_BINARY,			"binary", "Prog. Object");
Packit f574b8
	SET_SUFFIX5(".decw$book", STR_BINARY,			"binary", "DEC BookReader");
Packit f574b8
	SET_SUFFIX5(".mem",	"text/x-runoff-manual",		"8bit", "RUNOFF-MANUAL");
Packit f574b8
#endif
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".vsd",	"application/visio",		"binary");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".lha",	"application/x-lha",		"binary", "lha File");
Packit f574b8
	SET_SUFFIX5(".lzh",	"application/x-lzh",		"binary", "lzh File");
Packit f574b8
	SET_SUFFIX5(".sea",	"application/x-sea",		"binary", "sea File");
Packit f574b8
#ifdef TRADITIONAL_SUFFIXES
Packit f574b8
	SET_SUFFIX5(".sit",	"application/x-sit",		"binary", "sit File");
Packit f574b8
#else
Packit f574b8
	SET_SUFFIX5(".sit",	"application/x-stuffit",	"binary", "StuffIt");
Packit f574b8
#endif
Packit f574b8
	SET_SUFFIX5(".dms",	"application/x-dms",		"binary", "dms File");
Packit f574b8
	SET_SUFFIX5(".iff",	"application/x-iff",		"binary", "iff File");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".bcpio",	"application/x-bcpio",		"binary");
Packit f574b8
	SET_SUFFIX1(".cpio",	"application/x-cpio",		"binary");
Packit f574b8
Packit f574b8
#ifdef TRADITIONAL_SUFFIXES
Packit f574b8
	SET_SUFFIX1(".gtar",	"application/x-gtar",		"binary");
Packit f574b8
#endif
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".shar",	"application/x-shar",		"8bit");
Packit f574b8
	SET_SUFFIX1(".share",	"application/x-share",		"8bit");
Packit f574b8
Packit f574b8
#ifdef TRADITIONAL_SUFFIXES
Packit f574b8
	SET_SUFFIX1(".sh",	"application/x-sh",		"8bit"); /* xtra */
Packit f574b8
#endif
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".sv4cpio", "application/x-sv4cpio",	"binary");
Packit f574b8
	SET_SUFFIX1(".sv4crc",	"application/x-sv4crc",		"binary");
Packit f574b8
Packit f574b8
	SET_SUFFIX5(".tar",	"application/x-tar",		"binary", "Tar File");
Packit f574b8
	SET_SUFFIX1(".ustar",	"application/x-ustar",		"binary");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".snd",	"audio/basic",			"binary");
Packit f574b8
	SET_SUFFIX1(".au",	"audio/basic",			"binary");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".aifc",	"audio/x-aiff",			"binary");
Packit f574b8
	SET_SUFFIX1(".aif",	"audio/x-aiff",			"binary");
Packit f574b8
	SET_SUFFIX1(".aiff",	"audio/x-aiff",			"binary");
Packit f574b8
	SET_SUFFIX1(".wav",	"audio/x-wav",			"binary");
Packit f574b8
	SET_SUFFIX1(".midi",	"audio/midi",			"binary");
Packit f574b8
	SET_SUFFIX1(".mod",	"audio/mod",			"binary");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".gif",	"image/gif",			"binary");
Packit f574b8
	SET_SUFFIX1(".ief",	"image/ief",			"binary");
Packit f574b8
	SET_SUFFIX1(".jfif",	"image/jpeg",			"binary"); /* xtra */
Packit f574b8
	SET_SUFFIX1(".jfif-tbnl", "image/jpeg",			"binary"); /* xtra */
Packit f574b8
	SET_SUFFIX1(".jpe",	"image/jpeg",			"binary");
Packit f574b8
	SET_SUFFIX1(".jpg",	"image/jpeg",			"binary");
Packit f574b8
	SET_SUFFIX1(".jpeg",	"image/jpeg",			"binary");
Packit f574b8
	SET_SUFFIX1(".tif",	"image/tiff",			"binary");
Packit f574b8
	SET_SUFFIX1(".tiff",	"image/tiff",			"binary");
Packit f574b8
	SET_SUFFIX1(".ham",	"image/ham",			"binary");
Packit f574b8
	SET_SUFFIX1(".ras",	"image/x-cmu-rast",		"binary");
Packit f574b8
	SET_SUFFIX1(".pnm",	"image/x-portable-anymap",	"binary");
Packit f574b8
	SET_SUFFIX1(".pbm",	"image/x-portable-bitmap",	"binary");
Packit f574b8
	SET_SUFFIX1(".pgm",	"image/x-portable-graymap",	"binary");
Packit f574b8
	SET_SUFFIX1(".ppm",	"image/x-portable-pixmap",	"binary");
Packit f574b8
	SET_SUFFIX1(".png",	"image/png",			"binary");
Packit f574b8
	SET_SUFFIX1(".rgb",	"image/x-rgb",			"binary");
Packit f574b8
	SET_SUFFIX1(".xbm",	"image/x-xbitmap",		"binary");
Packit f574b8
	SET_SUFFIX1(".xpm",	"image/x-xpixmap",		"binary");
Packit f574b8
	SET_SUFFIX1(".xwd",	"image/x-xwindowdump",		"binary");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".rtx",	"text/richtext",		"8bit");
Packit f574b8
	SET_SUFFIX1(".tsv",	"text/tab-separated-values",	"8bit");
Packit f574b8
	SET_SUFFIX1(".etx",	"text/x-setext",		"8bit");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".mpg",	"video/mpeg",			"binary");
Packit f574b8
	SET_SUFFIX1(".mpe",	"video/mpeg",			"binary");
Packit f574b8
	SET_SUFFIX1(".mpeg",	"video/mpeg",			"binary");
Packit f574b8
	SET_SUFFIX1(".mov",	"video/quicktime",		"binary");
Packit f574b8
	SET_SUFFIX1(".qt",	"video/quicktime",		"binary");
Packit f574b8
	SET_SUFFIX1(".avi",	"video/x-msvideo",		"binary");
Packit f574b8
	SET_SUFFIX1(".movie",	"video/x-sgi-movie",		"binary");
Packit f574b8
	SET_SUFFIX1(".mv",	"video/x-sgi-movie",		"binary");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".mime",	"message/rfc822",		"8bit");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".c",	STR_PLAINTEXT,			"8bit");
Packit f574b8
	SET_SUFFIX1(".cc",	STR_PLAINTEXT,			"8bit");
Packit f574b8
	SET_SUFFIX1(".c++",	STR_PLAINTEXT,			"8bit");
Packit f574b8
	SET_SUFFIX1(".css",	STR_PLAINTEXT,			"8bit");
Packit f574b8
	SET_SUFFIX1(".h",	STR_PLAINTEXT,			"8bit");
Packit f574b8
	SET_SUFFIX1(".pl",	STR_PLAINTEXT,			"8bit");
Packit f574b8
	SET_SUFFIX1(".text",	STR_PLAINTEXT,			"8bit");
Packit f574b8
	SET_SUFFIX1(".txt",	STR_PLAINTEXT,			"8bit");
Packit f574b8
Packit f574b8
	SET_SUFFIX1(".php",	STR_HTML,			"8bit");
Packit f574b8
	SET_SUFFIX1(".php3",	STR_HTML,			"8bit");
Packit f574b8
	SET_SUFFIX1(".html3",	STR_HTML,			"8bit");
Packit f574b8
	SET_SUFFIX1(".ht3",	STR_HTML,			"8bit");
Packit f574b8
	SET_SUFFIX1(".phtml",	STR_HTML,			"8bit");
Packit f574b8
	SET_SUFFIX1(".shtml",	STR_HTML,			"8bit");
Packit f574b8
	SET_SUFFIX1(".sht",	STR_HTML,			"8bit");
Packit f574b8
	SET_SUFFIX1(".htmlx",	STR_HTML,			"8bit");
Packit f574b8
	SET_SUFFIX1(".htm",	STR_HTML,			"8bit");
Packit f574b8
	SET_SUFFIX1(".html",	STR_HTML,			"8bit");
Packit f574b8
	/* *INDENT-ON* */
Packit f574b8
Packit f574b8
    } else {			/* LYSuffixRules */
Packit f574b8
	/*
Packit f574b8
	 * Note that even .html -> text/html, .htm -> text/html are omitted if
Packit f574b8
	 * default maps are compiled in but then skipped because of a
Packit f574b8
	 * configuration file directive.  Whoever changes the config file in
Packit f574b8
	 * this way can easily also add the SUFFIX rules there.  - kw
Packit f574b8
	 */
Packit f574b8
	CTrace((tfp,
Packit f574b8
		"HTFileInit: Skipping all default (HTInit) extension maps!\n"));
Packit f574b8
    }				/* LYSuffixRules */
Packit f574b8
Packit f574b8
#else /* BUILTIN_SUFFIX_MAPS */
Packit f574b8
Packit f574b8
    CTrace((tfp,
Packit f574b8
	    "HTFileInit: Default (HTInit) extension maps not compiled in.\n"));
Packit f574b8
    /*
Packit f574b8
     * The following two are still used if BUILTIN_SUFFIX_MAPS was undefined. 
Packit f574b8
     * Without one of them, lynx would always need to have a mapping specified
Packit f574b8
     * in a lynx.cfg or mime.types file to be usable for local HTML files at
Packit f574b8
     * all.  That includes many of the generated user interface pages.  - kw
Packit f574b8
     */
Packit f574b8
    SET_SUFFIX1(".htm", STR_HTML, "8bit");
Packit f574b8
    SET_SUFFIX1(".html", STR_HTML, "8bit");
Packit f574b8
#endif /* BUILTIN_SUFFIX_MAPS */
Packit f574b8
Packit f574b8
    if (LYisAbsPath(global_extension_map)) {
Packit f574b8
	/* These should override the default extensions as necessary. */
Packit f574b8
	HTLoadExtensionsConfigFile(global_extension_map);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Load the local maps.
Packit f574b8
     */
Packit f574b8
    if (IsOurFile(LYAbsOrHomePath(&personal_extension_map))
Packit f574b8
	&& LYCanReadFile(personal_extension_map)) {
Packit f574b8
	/* These should override everything else. */
Packit f574b8
	HTLoadExtensionsConfigFile(personal_extension_map);
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
/* -------------------- Extension config file reading --------------------- */
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *  The following is lifted from NCSA httpd 1.0a1, by Rob McCool;
Packit f574b8
 *  NCSA httpd is in the public domain, as is this code.
Packit f574b8
 *
Packit f574b8
 *  Modified Oct 97 - KW
Packit f574b8
 */
Packit f574b8
Packit f574b8
#define MAX_STRING_LEN 256
Packit f574b8
Packit f574b8
static int HTGetLine(char *s, int n, FILE *f)
Packit f574b8
{
Packit f574b8
    register int i = 0, r;
Packit f574b8
Packit f574b8
    if (!f)
Packit f574b8
	return (1);
Packit f574b8
Packit f574b8
    while (1) {
Packit f574b8
	r = fgetc(f);
Packit f574b8
	s[i] = (char) r;
Packit f574b8
Packit f574b8
	if (s[i] == CR) {
Packit f574b8
	    r = fgetc(f);
Packit f574b8
	    if (r == LF)
Packit f574b8
		s[i] = (char) r;
Packit f574b8
	    else if (r != EOF)
Packit f574b8
		ungetc(r, f);
Packit f574b8
	}
Packit f574b8
Packit f574b8
	if ((r == EOF) || (s[i] == LF) || (s[i] == CR) || (i == (n - 1))) {
Packit f574b8
	    s[i] = '\0';
Packit f574b8
	    return (feof(f) ? 1 : 0);
Packit f574b8
	}
Packit f574b8
	++i;
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
static void HTGetWord(char *word, char *line, int stop, int stop2)
Packit f574b8
{
Packit f574b8
    int x = 0, y;
Packit f574b8
Packit f574b8
    for (x = 0; (line[x]
Packit f574b8
		 && UCH(line[x]) != UCH(stop)
Packit f574b8
		 && UCH(line[x]) != UCH(stop2)); x++) {
Packit f574b8
	word[x] = line[x];
Packit f574b8
    }
Packit f574b8
Packit f574b8
    word[x] = '\0';
Packit f574b8
    if (line[x])
Packit f574b8
	++x;
Packit f574b8
    y = 0;
Packit f574b8
Packit f574b8
    while ((line[y++] = line[x++])) {
Packit f574b8
	;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return;
Packit f574b8
}
Packit f574b8
Packit f574b8
static int HTLoadExtensionsConfigFile(char *fn)
Packit f574b8
{
Packit f574b8
    char line[MAX_STRING_LEN];
Packit f574b8
    char word[MAX_STRING_LEN];
Packit f574b8
    char *ct;
Packit f574b8
    FILE *f;
Packit f574b8
    int count = 0;
Packit f574b8
Packit f574b8
    CTrace((tfp, "HTLoadExtensionsConfigFile: Loading file '%s'.\n", fn));
Packit f574b8
Packit f574b8
    if ((f = fopen(fn, TXT_R)) == NULL) {
Packit f574b8
	CTrace((tfp, "HTLoadExtensionsConfigFile: Could not open '%s'.\n", fn));
Packit f574b8
	return count;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    while (!(HTGetLine(line, (int) sizeof(line), f))) {
Packit f574b8
	HTGetWord(word, line, ' ', '\t');
Packit f574b8
	if (line[0] == '\0' || word[0] == '#')
Packit f574b8
	    continue;
Packit f574b8
	ct = NULL;
Packit f574b8
	StrAllocCopy(ct, word);
Packit f574b8
	LYLowerCase(ct);
Packit f574b8
Packit f574b8
	while (line[0]) {
Packit f574b8
	    HTGetWord(word, line, ' ', '\t');
Packit f574b8
	    if (word[0] && (word[0] != ' ')) {
Packit f574b8
		char *ext = NULL;
Packit f574b8
Packit f574b8
		HTSprintf0(&ext, ".%s", word);
Packit f574b8
		LYLowerCase(ext);
Packit f574b8
Packit f574b8
		CTrace((tfp, "setting suffix '%s' to '%s'.\n", ext, ct));
Packit f574b8
Packit f574b8
		if (strstr(ct, "tex") != NULL ||
Packit f574b8
		    strstr(ct, "postscript") != NULL ||
Packit f574b8
		    strstr(ct, "sh") != NULL ||
Packit f574b8
		    strstr(ct, "troff") != NULL ||
Packit f574b8
		    strstr(ct, "rtf") != NULL)
Packit f574b8
		    SET_SUFFIX1(ext, ct, "8bit");
Packit f574b8
		else
Packit f574b8
		    SET_SUFFIX1(ext, ct, "binary");
Packit f574b8
		count++;
Packit f574b8
Packit f574b8
		FREE(ext);
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
	FREE(ct);
Packit f574b8
    }
Packit f574b8
    LYCloseInput(f);
Packit f574b8
Packit f574b8
    return count;
Packit f574b8
}