gecko-dev/network/main/mkinit.c
1998-05-29 23:28:49 +00:00

782 lines
20 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
* register all neccessary
* stream converters
*/
/* Please leave outside of ifdef for window's precompiled headers. */
#include "mkutils.h"
#ifdef MOZILLA_CLIENT
#ifdef XP_UNIX /* this whole module is ifdef'd UNIX */
#include "netutils.h"
#include "mkgeturl.h"
#include "mkstream.h"
#include "mkformat.h"
#include "net.h"
#include "cvview.h"
#include "cvdisk.h"
#include "cvproxy.h"
#include "cvextcon.h"
#include "txview.h"
#include "xlate.h"
#include "libi18n.h" /* For character code set conversion stream */
#include "cvactive.h"
#include "pa_parse.h"
#include "np.h"
#include "il_strm.h" /* Image Library stream converters. */
/* The master database of mail cap info (link list) */
PRIVATE XP_List *NET_mcMasterList = 0; /* May want to save out this info */
PUBLIC void
NET_mdataFree(NET_mdataStruct *md)
{
FREEIF(md->contenttype);
FREEIF(md->command);
FREEIF(md->testcommand);
FREEIF(md->label);
FREEIF(md->printcommand);
FREEIF(md->src_string);
FREEIF(md->xmode);
FREE(md);
md = NULL;
}
/* File is a directory ?*/
PRIVATE Bool
net_isDir(char *name)
{
XP_StatStruct st;
if (!name || !*name) return (FALSE);
if (!stat (name, &st) && S_ISDIR(st.st_mode))
return (TRUE);
else
return (FALSE);
}
PUBLIC void
NET_CleanupMailCapList(char* filename)
{
NET_mdataStruct *mdata;
FILE *fp = NULL;
XP_List *modifiedList = NULL;
if ( !NET_mcMasterList ) return;
if ( filename && *filename )
{
/* Invalid filename, then don't write */
if ( net_isDir(filename) )
return;
fp = fopen(filename, "w");
if ( !fp ) return;
modifiedList = XP_ListNew();
while ((mdata=(NET_mdataStruct *)XP_ListRemoveEndObject(NET_mcMasterList)))
{
if (mdata->is_local )
{
if ( mdata->src_string && *mdata->src_string)
{
fputs(mdata->src_string, fp);
if ( mdata->src_string[strlen(mdata->src_string)-1] != '\n' )
fputs("\n", fp);
}
else mdata->src_string = 0;
NET_mdataFree(mdata);
}
else if (mdata->is_modified)
XP_ListAddObject(modifiedList, mdata);
else
{
NET_mdataFree(mdata);
}
}
while ((mdata=(NET_mdataStruct *)XP_ListRemoveEndObject(modifiedList)))
{
if ( mdata->src_string && *mdata->src_string)
{
fputs(mdata->src_string, fp);
if ( mdata->src_string[strlen(mdata->src_string)-1] != '\n' )
fputs("\n", fp);
}
else mdata->src_string = 0;
NET_mdataFree(mdata);
}
fclose(fp);
}
else
{
while ((mdata = (NET_mdataStruct *)XP_ListRemoveEndObject(NET_mcMasterList)))
{
NET_mdataFree(mdata);
}
}
XP_ListDestroy(NET_mcMasterList);
NET_mcMasterList = 0;
}
/* register all your converters
*
* YOU MUST register a "*" converter for
* EVERY format out type, this acts as a default
* and prevents a "Could not convert error"
*/
PUBLIC void
NET_RegisterConverters (char * personal_file, char * global_file)
{
NET_CleanupMailCapList(NULL);
NET_mcMasterList = XP_ListNew();
NET_RegisterMIMEDecoders ();
NET_RegisterExternalViewerCommand (IMAGE_WILDCARD, "xv %s", 0);
NET_RegisterExternalViewerCommand ("audio/ulaw", "playulaw", 2000);
#ifdef NOT /* NO default audio */
#ifdef __sun
NET_RegisterExternalViewerCommand (AUDIO_BASIC, "cat > /dev/audio", 2000);
#else
NET_RegisterExternalViewerCommand (AUDIO_BASIC, "playulaw", 2000);
#endif /* __sgi */
#endif /* NOT */
NET_RegisterExternalViewerCommand (VIDEO_MPEG,
/* throw away stderr and stdout, since
mpeg_play is so darn noisy. */
"mpeg_play %s >/dev/null 2>&1", 0);
NET_RegisterExternalViewerCommand ("image/x-xwd", "xwud", 2000);
/* global file must come first!!!!!!!!!!!!!!
*/
if (global_file)
NET_ProcessMailcapFile (global_file, FALSE);
if (personal_file)
NET_ProcessMailcapFile (personal_file, TRUE);
}
/*
* before you modify this,
* make darn sure you want to deviuate from the standard bellcore mailcap
* handling!! *this means you Garrett!!*"
*
* Code borrowed from:
*
* Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
*
* Permission to use, copy, modify, and distribute this material
* for any purpose and without fee is hereby granted, provided
* that the above copyright notice and this permission notice
* appear in all copies, and that the name of Bellcore not be
* used in advertising or publicity pertaining to this
* material without the specific, prior written permission
* of an authorized representative of Bellcore. BELLCORE
* MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
* OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS",
* WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
*/
/*
* Metamail -- A tool to help diverse mail readers
* cope with diverse multimedia mail formats.
*
* Author: Nathaniel S. Borenstein, Bellcore
*
*/
struct MailcapEntry {
char *contenttype;
char *command;
char *testcommand;
int needsterminal;
int copiousoutput;
int needtofree;
char *label;
char *printcommand;
int32 stream_buffer_size;
char *xmode;
};
#define LINE_BUF_SIZE 2048
#define TMPFILE_NAME_SIZE 127
PRIVATE char *GetCommand (char *s, char **t)
{
char *s2;
int quoted = 0;
s2 = (char *) PR_Malloc(PL_strlen(s)*2 + 3); /* absolute max, if all % signs */
if(!s2)
return(NULL);
*s2 = 0;
*t = s2;
while (s && *s)
{
if (quoted)
{
if (*s == '%')
*s2++ = '%';
*s2++ = *s++;
quoted = 0;
}
else
{
if (*s == ';')
{
break; /* finish the string below */
}
if (*s == '\\')
{
quoted = 1;
++s;
}
else
{
*s2++ = *s++;
}
}
}
/* look at the last character of the command and make sure it doesn't have
* a '&'
*/
if( s2 > *t && *(s2-1) == '&')
s2--; /* kill the ampersand */
*s2 = 0; /* terminate string */
if(*s)
return(s+1);
else
return(s);
}
/* Trims leading and trailing space in the input string while converting
* it to all lower case.
*
* WARNING: Modified input string.
*/
PRIVATE char *Cleanse (char *s)
{
char *tmp, *news, *tmpnews;
news = s;
/* strip leading white space */
while (*s && NET_IS_SPACE(*s)) ++s;
/* put in lower case */
for (tmpnews=news, tmp=s; *tmp; tmpnews++, ++tmp) {
*tmpnews = tolower ((unsigned char)*tmp);
}
*tmpnews = '\0';
/* strip trailing white space */
while (*--tmpnews && NET_IS_SPACE(*tmpnews)) *tmpnews = 0;
return(news);
}
PRIVATE void BuildCommand (char *Buf, char *controlstring, char *TmpFileName)
{
char *from, *to;
int prefixed = 0;
for (from=controlstring, to=Buf; *from != '\0'; from++)
{
if (prefixed)
{
prefixed = 0;
switch(*from)
{
case '%':
*to++ = '%';
break;
case 'n':
case 'F':
fprintf(stderr, "metamail: Bad mailcap \"test\" clause: %s\n", controlstring);
case 's':
if (TmpFileName)
{
PL_strcpy(to, TmpFileName);
to += PL_strlen(TmpFileName);
}
break;
default:
fprintf(stderr,
"%s: Ignoring unsupported format code in mailcap file: %%%c\n",
XP_AppName, *from);
break;
}
}
else if (*from == '%')
{
prefixed = 1;
}
else
{
*to++ = *from;
}
}
*to = 0;
}
static void
net_register_new_converter(char *contenttype, char *command, char *xmode,
int buffer_size)
{
/* xmode takes priority over command */
if (xmode && !PL_strcasecmp(xmode, NET_COMMAND_NETSCAPE))
{
if ( !PL_strcasecmp(contenttype, TEXT_HTML) )
NET_RegisterContentTypeConverter (TEXT_HTML, FO_PRESENT,
NULL, INTL_ConvCharCode);
else if (!PL_strcasecmp(contenttype, TEXT_MDL))
NET_RegisterContentTypeConverter (TEXT_MDL, FO_PRESENT,
NULL, INTL_ConvCharCode);
else if (!PL_strcasecmp(contenttype, TEXT_PLAIN))
NET_RegisterContentTypeConverter (TEXT_PLAIN, FO_PRESENT,
NULL, NET_PlainTextConverter);
else if (!PL_strcasecmp(contenttype, IMAGE_GIF))
NET_RegisterContentTypeConverter (IMAGE_GIF,
FO_PRESENT,NULL, IL_ViewStream);
else if (!PL_strcasecmp(contenttype, IMAGE_XBM) ||
!PL_strcasecmp(contenttype, IMAGE_XBM2) ||
!PL_strcasecmp(contenttype, IMAGE_XBM3))
NET_RegisterContentTypeConverter (IMAGE_XBM,
FO_PRESENT,NULL, IL_ViewStream);
else if (!PL_strcasecmp(contenttype, IMAGE_JPG) ||
!PL_strcasecmp(contenttype, IMAGE_PJPG))
NET_RegisterContentTypeConverter (IMAGE_JPG,
FO_PRESENT,NULL, IL_ViewStream);
else if (!PL_strcasecmp(contenttype, IMAGE_PNG))
NET_RegisterContentTypeConverter (IMAGE_PNG,
FO_PRESENT,NULL, IL_ViewStream);
else if (!PL_strcasecmp(contenttype,
APPLICATION_NS_PROXY_AUTOCONFIG))
NET_RegisterContentTypeConverter(
APPLICATION_NS_PROXY_AUTOCONFIG,
FO_PRESENT,
(void *)0, NET_ProxyAutoConfig);
else if (!PL_strcasecmp(contenttype,
APPLICATION_NS_JAVASCRIPT_AUTOCONFIG))
NET_RegisterContentTypeConverter(
APPLICATION_NS_JAVASCRIPT_AUTOCONFIG,
FO_PRESENT,
(void *)0, NET_ProxyAutoConfig);
else
{
fprintf(stderr,
"%s: Ignoring unsupported netscape contenttype in user mailcap file.\n", XP_AppName);
}
}
else if (xmode && !strncasecmp(xmode, NET_COMMAND_PLUGIN,
strlen(NET_COMMAND_PLUGIN)))
{
char *pluginName = xmode + strlen(NET_COMMAND_PLUGIN);
/* For plugins enable the plugin for this mimetype */
NPL_EnablePlugin(contenttype, pluginName, TRUE);
}
else if (xmode &&
(!PL_strcasecmp(xmode, NET_COMMAND_SAVE_TO_DISK) ||
!PL_strcasecmp(xmode, NET_COMMAND_SAVE_BY_NETSCAPE)))
NET_RegisterContentTypeConverter(contenttype,
FO_PRESENT,
NULL, fe_MakeSaveAsStream );
else if (xmode && !PL_strcasecmp(xmode, NET_COMMAND_UNKNOWN))
NET_RegisterContentTypeConverter(contenttype,
FO_PRESENT,
NULL, fe_MakeSaveAsStream );
else if (xmode && !PL_strcasecmp(xmode,NET_COMMAND_DELETED))
{
/* Do nothing */
}
else if (command && *command )/* It's an external application then */
{
/* register the command
*
* but only if it isn't text/html
*/
if(PL_strcasecmp(contenttype, TEXT_HTML) &&
PL_strcasecmp(contenttype, MESSAGE_RFC822) &&
PL_strcasecmp(contenttype, MESSAGE_NEWS))
NET_RegisterExternalViewerCommand(contenttype, command, buffer_size);
}
}
PRIVATE int PassesTest (struct MailcapEntry *mc)
{
int result;
char *cmd, TmpFileName[TMPFILE_NAME_SIZE];
if (!mc->testcommand) return(1);
tmpnam(TmpFileName);
cmd = (char *)PR_Malloc(1024);
if (!cmd)
return(0);
BuildCommand(cmd, mc->testcommand, TmpFileName);
TRACEMSG(("Executing test command: %s\n", cmd));
result = system(cmd);
free(cmd);
remove(TmpFileName);
if(result)
TRACEMSG(("[HTInit] Test failed!\n"));
else
TRACEMSG(("[HTInit] Test passed!\n"));
return(result==0);
}
PRIVATE int ProcessMailcapEntry (FILE *fp, struct MailcapEntry *mc,
char** src_string, Bool is_local)
{
NET_cdataStruct *tmp_cd = NULL;
NET_cdataStruct *cd = NULL;
NET_mdataStruct *md = NULL;
int unprocessed_entryalloc = 1023, len;
char *unprocessed_entry, *s, *t, *buffer;
char *arg, *eq;
char *command=0;
buffer = (char *) PR_Malloc(LINE_BUF_SIZE);
if (!buffer)
return 0;
unprocessed_entry = (char *) PR_Malloc(1 + unprocessed_entryalloc);
if (!unprocessed_entry)
{
free(buffer);
return 0;
}
*unprocessed_entry = '\0';
while (fgets(buffer, LINE_BUF_SIZE, fp))
{
if ( !*src_string )
StrAllocCopy(*src_string, buffer );
else
*src_string = XP_AppendStr(*src_string, buffer);
if (buffer[0] == '#')
continue;
len = PL_strlen(buffer);
if (len == 0)
continue;
if (buffer[len-1] == '\n')
buffer[--len] = 0;
if ((len + PL_strlen(unprocessed_entry)) > unprocessed_entryalloc)
{
unprocessed_entryalloc += 1024;
unprocessed_entry = (char *) PR_Realloc(unprocessed_entry, unprocessed_entryalloc+1);
TRACEMSG(("Growing input line in mkinit"));
if (!unprocessed_entry)
{
TRACEMSG(("ERROR! Growing input line in mkinit"));
return 0;
}
}
if (len > 0 && buffer[len-1] == '\\')
{
buffer[len-1] = 0;
PL_strcat(unprocessed_entry, buffer);
}
else
{
PL_strcat(unprocessed_entry, buffer);
break;
}
}
for (s=unprocessed_entry; *s && NET_IS_SPACE(*s); ++s)
; /* NULL BODY */
if (!*s)
{
/* totally blank entry -- quietly ignore */
free(unprocessed_entry);
free(buffer);
return(0);
}
s = PL_strchr(unprocessed_entry, ';');
if (s == NULL)
{
fprintf(stderr, "%s: Ignoring invalid mailcap entry: %s\n",
XP_AppName, unprocessed_entry);
free(unprocessed_entry);
free(buffer);
PR_Free(*src_string);
*src_string = 0;
return(0);
}
*s++ = 0;
mc->needsterminal = 0;
mc->copiousoutput = 0;
mc->needtofree = 1;
mc->testcommand = 0;
mc->label = NULL;
mc->printcommand = NULL;
mc->contenttype = 0; /* init */
mc->xmode = 0;
mc->stream_buffer_size = 0;
StrAllocCopy(mc->contenttype, unprocessed_entry); /* copy */
if (!mc->contenttype)
{
free(buffer);
TRACEMSG(("mailcap: no content-type"));
return 0;
}
s = GetCommand(s, &mc->command);
while (s && *s != '\0')
{
arg = s;
eq = PL_strchr(arg, '=');
if (eq)
*eq++ = 0;
else
eq = arg;
t = GetCommand(eq, &command);
if (arg && *arg)
{
arg = Cleanse(arg);
if ( eq && !PL_strcmp(arg, NET_MOZILLA_FLAGS))
{
/* xmode is case sensitive. That is why we dont Cleanse it. */
mc->xmode = command;
command = 0;
}
else {
command = Cleanse(command);
if (eq && !PL_strcmp(arg, "test"))
{
mc->testcommand = command;
command = 0;
TRACEMSG(("mailcap: found testcommand:%s\n",mc->testcommand));
}
else if (eq && !PL_strcmp(arg, "description"))
{
mc->label = command;
command = 0;
}
else if (eq && !PL_strcmp(arg, "label"))
{
mc->label = command; /* bogus old name for description */
command = 0;
}
else if (eq && !PL_strcmp(arg, "stream-buffer-size"))
{
mc->stream_buffer_size = atol(command);
TRACEMSG(("mailcap: found stream-buffer-size:%d\n",mc->stream_buffer_size));
FREEIF(command);
command = 0;
}
else
FREEIF(command);
}
}
else if (command && *command) FREEIF(command);
s = t;
}
free(unprocessed_entry);
/* Copy over the mail cap entry so that it can saved into data base */
if (mc)
{
md = NET_mdataCreate();
if ( !md ) return (-1);
StrAllocCopy(md->contenttype, mc->contenttype);
StrAllocCopy(md->command, mc->command);
StrAllocCopy(md->testcommand, mc->testcommand);
StrAllocCopy(md->label, mc->label);
StrAllocCopy(md->printcommand, mc->printcommand);
md->stream_buffer_size = mc->stream_buffer_size;
if (is_local && *src_string && **src_string)
StrAllocCopy(md->src_string, *src_string); /* copy buffer */
StrAllocCopy(md->xmode, mc->xmode);
md->is_local = is_local;
PR_Free(*src_string);
*src_string = 0;
}
if (PassesTest(mc))
{
TRACEMSG(("mailcap: Setting up conversion %s : %s\n", mc->contenttype,
mc->command));
net_register_new_converter(XP_StripLine(mc->contenttype),
mc->command, mc->xmode,
mc->stream_buffer_size);
if (md)
md->test_succeed = TRUE;
}
/* Add to the database */
if (md)
{
NET_mdataStruct *old_md = NULL;
if ( !(old_md = NET_mdataExist(md)))
NET_mdataAdd(md);
else
{
NET_mdataRemove(old_md);
NET_mdataAdd(md);
}
cd = NET_cdataCreate();
cd->ci.type = 0;
cd->is_external = 1;
cd->is_local = 0; /* This is internal; only for user to view */
StrAllocCopy(cd->ci.type, md->contenttype );
/* Does not exist add this contenttype to mime content list */
if ( !(tmp_cd = NET_cdataExist(cd) ) )
NET_cdataAdd(cd);
else /* Already Exist, so we don't need to add it again. Then, free it now */
NET_cdataRemove(cd);
}
free(buffer);
FREEIF(mc->contenttype);
FREEIF(mc->command);
FREEIF(mc->testcommand);
FREEIF(mc->label);
FREEIF(mc->xmode);
return(1);
}
/* reads a mailcap file and adds entries to the
* external viewers converter list
*/
PUBLIC int
NET_ProcessMailcapFile (char *file, Bool is_local)
{
struct MailcapEntry mc;
FILE *fp;
char *src_string = 0;
TRACEMSG(("Loading types config file '%s'\n", file));
if ( !net_isDir(file) )
{
fp = fopen(file, "r");
while (fp && !feof(fp))
{
ProcessMailcapEntry(fp, &mc, &src_string, is_local);
}
if (fp) fclose(fp);
}
return(-1);
}
PUBLIC XP_List *
mailcap_MasterListPointer(void)
{
return (NET_mcMasterList);
}
PUBLIC NET_mdataStruct *
NET_mdataCreate(void)
{
NET_mdataStruct *md = PR_NEW(NET_mdataStruct);
if(!md)
return(NULL);
memset(md, 0, sizeof(NET_mdataStruct));
return md;
}
PUBLIC void
NET_mdataAdd(NET_mdataStruct *md)
{
XP_ListAddObject(NET_mcMasterList, md);
}
PUBLIC void
NET_mdataRemove(NET_mdataStruct *md)
{
XP_ListRemoveObject(NET_mcMasterList, md);
NET_mdataFree(md);
}
PUBLIC NET_mdataStruct*
NET_mdataExist(NET_mdataStruct *old_md )
{
NET_mdataStruct *found_md = NULL;
NET_mdataStruct *md = NULL;
XP_List *infoList;
infoList = mailcap_MasterListPointer();
if ( !infoList )
return found_md;
while ((md= (NET_mdataStruct *)XP_ListNextObject(infoList)))
{
if ( old_md->contenttype &&
md->contenttype &&
!PL_strcasecmp(old_md->contenttype, md->contenttype))
{
/* found matching type */
found_md = md;
break;
}
}
return found_md;
}
#endif /* XP_UNIX */
#endif /* MOZILLA_CLIENT */