/********************************************************************
* wilkinson
* 3.19VMS
* 1995/09/25 14:30
* gopher_root1:[gopher.g2.vms2_13.gopherd]ext.c,v
* Exp
*
* Paul Lindner, University of Minnesota CIS.
*
* Copyright 1991, 1992 by the Regents of the University of Minnesota
* see the file "Copyright" in the distribution for conditions of use.
*********************************************************************
* MODULE: ext.c
* These fns define mapping of file extensions to gopher objects.
*********************************************************************
* Revision History:
* ext.c,v
* Revision 3.19VMS 1995/09/25 14:30 wilkinson
* Consolodate VMS/Unix source code for server as well as client
*
* Revision 3.19 1994/09/29 19:57:45 lindner
* Less picky language and view comparisions
*
* Revision 3.18 1994/07/21 15:46:22 lindner
* Brian Coen Patch
*
* Revision 3.17 1994/07/19 20:27:35 lindner
* Use local Locale.h
*
* Revision 3.16 1994/05/02 07:41:11 lindner
* Mods to use setlocale()
*
* Revision 3.15 1994/04/26 22:43:57 lindner
* Fix for Debugmsg
*
* Revision 3.14 1994/04/25 20:49:04 lindner
* Fix for debug code
*
* Revision 3.13 1994/01/20 06:39:18 lindner
* When trying to match an extension to a file type, the server prefers
* exact matches of type & language, but will now fall back to matching
* the type in any language (acf).
*
* Revision 3.12 1993/10/27 20:35:24 lindner
* Plug memory leak
*
* Revision 3.11 1993/10/20 03:17:25 lindner
* Fixed erratic problems with extension adding. Note that the problems
* with directories not working with Gopher0 clients is due to a missing
* parameter in a strncasecmp() call.. Makes one wish ANSI C was more
* widespread...
*
* Also added regular expression code for ignore_patt:
*
* Revision 3.10 1993/10/04 06:39:31 lindner
* Fix for forward declarations
*
* Revision 3.9 1993/09/21 02:35:04 lindner
* Server now adds extensions in a case insensitive manner
*
* Revision 3.8 1993/09/18 03:30:11 lindner
* Remove memory leak
*
* Revision 3.7 1993/09/18 02:22:35 lindner
* More debugging...
*
* Revision 3.6 1993/08/19 20:25:46 lindner
* Mitra's Debug patch
*
* Revision 3.5 1993/08/03 06:03:08 lindner
* Ignored files are now ignored again
*
* Revision 3.4 1993/07/31 00:15:37 lindner
* Fixed weird extension problem
*
* Revision 3.3 1993/07/27 20:15:29 lindner
* Fixed bug where filename was less than extension
*
* Revision 3.2 1993/07/23 03:18:46 lindner
* Mods for using decoder:'s
*
* Revision 3.1.1.1 1993/02/11 18:02:51 lindner
* Gopher+1.2beta release
*
* Revision 1.3 1993/02/09 22:13:19 lindner
* many additions for multilingual gopher
*
* Revision 1.2 1993/01/30 23:56:55 lindner
* Lots of new code for gopher+ stuff.. Change everything to start with EX
*
* Revision 1.1 1992/12/10 23:13:27 lindner
* gopher 1.1 release
*
*
*********************************************************************/
#include <stdio.h>
#include "ext.h"
#include "Malloc.h"
#include "Locale.h"
#include <ctype.h>
#include "util.h"
#ifdef VMS_SERVER
#include "command.h"
#endif
#include "serverutil.h"
#include "openers.h"
#undef stat
#include "Debug.h"
#include "Dirent.h"
#include "Regex.h"
/*
* Some functions to initialize and destroy sites and extensions..
* (Needed for use with DynArrays...)
*/
Extobj *
EXnew()
{
Extobj *temp;
temp = (Extobj *) malloc(sizeof(Extobj));
if (temp == NULL)
return(NULL);
temp->Objtype = '\0';
temp->View = STRnew();
temp->ViewLang = STRnew();
temp->Prefix = STRnew();
temp->ext = STRnew();
temp->exttype = EXT_ERROR;
temp->GenericData = STRnew();
STRinit(temp->View);
STRinit(temp->ViewLang);
STRinit(temp->Prefix);
STRinit(temp->ext);
STRinit(temp->GenericData);
return(temp);
}
/** Destroy an extension structure **/
void
EXdestroy(ext)
Extobj *ext;
{
STRdestroy(ext->View);
STRdestroy(ext->ViewLang);
STRdestroy(ext->Prefix);
STRdestroy(ext->ext);
STRdestroy(ext->GenericData);
free(ext);
}
/** Copy an extension structure **/
void
EXcpy(ext1, ext2)
Extobj *ext1, *ext2;
{
ext1->Objtype = ext2->Objtype;
STRcpy(ext1->View, ext2->View);
STRcpy(ext1->ViewLang, ext2->ViewLang);
STRcpy(ext1->Prefix, ext2->Prefix);
STRcpy(ext1->ext, ext2->ext);
STRcpy(ext1->GenericData, ext2->GenericData);
EXsetExttype(ext1, EXgetExttype(ext2));
}
/*
* Do the grungy work of adding an extension
*/
char *
EXAfindFile(extarr, file, view)
ExtArray *extarr;
char *file;
char *view;
{
boolean status = TRUE;
Extobj *ext, *temp;
DIR *ZeDir;
#ifndef VMS_SERVER
struct dirent *dp;
#else
char *dp;
#endif
struct stat statbuf;
static char tmpfile[512];
char directory[512], *cp;
int tmpfilelen = 0, i;
if (file == NULL || *file == '\0')
return(file);
strcpy(tmpfile, file);
ext = EXnew();
/** Find a viewext if available..
Should be able to cycle through all of them... **/
status = EXAviewSearch(extarr, ext, view);
if (status == TRUE)
strcat(tmpfile, EXgetExt(ext));
EXdestroy(ext);
strcpy(directory, tmpfile);
cp = mtm_basename(directory);
*cp = '.';
*(cp+1) = '\0';
if ((ZeDir = ropendir(directory)) == NULL) {
/** Error **/
return(file);
}
cp = mtm_basename(tmpfile);
for (dp = readdir(ZeDir); dp != NULL; dp = readdir(ZeDir)) {
int x;
#ifndef VMS_SERVER
x = strcasecmp(cp, dp->d_name);
#else
x = strcasecmp(cp, dp/*->d_name*/);
#endif
if (x == 0) {
/** Found an exact match **/
#ifndef VMS_SERVER
strcpy(cp, dp->d_name);
closedir(ZeDir);
#else
strcpy(cp, dp/*->d_name*/);
#endif
return(tmpfile);
}
}
/** Now check for a not so exact match.. **/
#ifndef VMS_SERVER
rewinddir(ZeDir);
#endif
for (dp = readdir(ZeDir); dp != NULL; dp = readdir(ZeDir)) {
int x;
#ifndef VMS_SERVER
x = strncasecmp(cp, dp->d_name, strlen(dp->d_name));
#else
x = strncasecmp(cp, dp/*->d_name*/, strlen(dp/*->d_name*/));
#endif
if (x==0)
/** Found a match for a possible decoder **/
#ifndef VMS_SERVER
strcpy(cp, dp->d_name);
#else
strcpy(cp, dp/*->d_name*/);
#endif
}
#ifndef VMS_SERVER
closedir(ZeDir);
#endif
/** Hmm can't seem to find it.. Let's try the decoders... **/
tmpfilelen = strlen(tmpfile);
/** Check for decoders.. **/
for (i=0; i< EXAgetNumEntries(extarr); i++) {
temp = EXAgetEntry(extarr,i);
if (EXgetExttype(temp) == EXT_DECODER) {
char decodertmp[256];
strcpy(decodertmp, tmpfile);
strcat(decodertmp, EXgetExt(temp));
if (!rstat(decodertmp, &statbuf)) {
/** Found it! **/
strcpy(tmpfile, decodertmp);
return(tmpfile);
}
}
}
/*** Couldn't find anything... **/
return(file);
}
/*
* Get the parameters associated with a particular extension
*
* Fills in ext with the values..
*/
boolean
EXAsearch(extarr, ext, fileext, exttype)
ExtArray *extarr;
Extobj *ext;
char *fileext;
int exttype;
{
int i, extlen;
Extobj *temp;
Debugmsg("EXAsearch:\r\n");
extlen = strlen(fileext);
/*** Linear search. Ick. ***/
for (i=0; i< EXAgetNumEntries(extarr); i++) {
temp = EXAgetEntry(extarr,i);
if (exttype == EXgetExttype(temp)) {
int exlen = strlen(EXgetExt(temp));
if (exlen <= extlen && strcasecmp(fileext+extlen-exlen,
EXgetExt(temp)) == 0) {
EXcpy(ext,temp);
return(TRUE);
}
}
else if (exttype == EXT_IGNORE &&
EXgetExttype(temp) == EXT_IGNOREPAT) {
if (re_comp(EXgetExt(temp)) != NULL)
return(FALSE);
if (re_exec(fileext) == 1) {
EXcpy(ext,temp);
return(TRUE);
}
}
}
return(FALSE);
}
/*
* Do an exact search...
*/
boolean
EXAcasedSearch(extarr, ext, fileext, exttype)
ExtArray *extarr;
Extobj *ext;
char *fileext;
int exttype;
{
int i, extlen;
Extobj *temp;
Debugmsg("EXAsearch:\r\n");
extlen = strlen(fileext);
/*** Linear search. Ick. ***/
for (i=0; i< EXAgetNumEntries(extarr); i++) {
temp = EXAgetEntry(extarr,i);
if (exttype == EXgetExttype(temp)) {
if (strcmp(fileext+extlen-strlen(EXgetExt(temp)),
EXgetExt(temp)) == 0) {
EXcpy(ext,temp);
return(TRUE);
}
}
}
return(FALSE);
}
/*
* Search for a specific view extension...
* Prefers exact match of type & lang, but if it can't find one it will
* fall back to matching type in any language.
*/
boolean
EXAviewSearch(extarr, ext, view)
ExtArray *extarr;
Extobj *ext;
char *view;
{
int i;
Extobj *temp;
char viewnlang[256];
boolean found = FALSE;
/*** Linear search. Ick. ***/
for (i=0; i< EXAgetNumEntries(extarr); i++) {
temp = EXAgetEntry(extarr,i);
if (EXgetExttype(temp) == EXT_VIEW) {
strcpy(viewnlang, EXgetView(temp));
if (!found && strcasecmp(view, viewnlang)==0) {
EXcpy(ext,temp);
found = TRUE;
}
#ifndef __VAXC
if (EXgetVLang(temp) != NULL && *EXgetVLang(temp) != '\0')
#else
if (EXgetVLang(temp) != NULL && strlen(EXgetVLang(temp)))
#endif
{
strcat(viewnlang, " ");
strcat(viewnlang, EXgetVLang(temp));
}
if (strncasecmp(view, viewnlang, strlen(viewnlang))==0) {
EXcpy(ext,temp);
return(TRUE);
}
}
}
return(found);
;
}
/*
* Process gopherd.conf lines "viewext", "ignore", "blockext" and others.
*/
boolean
EXAprocessLine(extarr, exttype, inputline, deflang)
ExtArray *extarr;
int exttype;
char *inputline;
char *deflang;
{
int i;
char ext[64];
char secondparm[64];
char prefix[64];
char Gplustype[64];
char Gpluslang[16];
Extobj *temp;
temp = EXnew();
/*** Set the type of extension we've been given ***/
EXsetExttype(temp, exttype);
if (deflang != NULL)
EXsetVLang(temp, deflang);
inputline = skip_whitespace(inputline);
if (*inputline == '\0') return(FALSE);
/*** The first parameter, the extension ***/
i=0;
while (!isspace(*inputline) && (*inputline != '\0'))
ext[i++] = *inputline++;
ext[i] = '\0';
EXsetExt(temp,ext);
inputline = skip_whitespace(inputline);
if (exttype == EXT_IGNORE || exttype == EXT_IGNOREPAT) {
EXAadd(extarr, temp);
EXdestroy(temp);
return(TRUE);
}
if (*inputline == '\0') return(FALSE);
/*** Second parameter, depends on which token we're using.. ***/
i=0;
while (!isspace(*inputline) && (*inputline != '\0'))
secondparm[i++] = *inputline++;
secondparm[i] = '\0';
if (exttype == EXT_BLOCK || exttype == EXT_BLOCKREF) {
EXsetBlockname(temp, secondparm);
EXAadd(extarr, temp);
EXdestroy(temp);
return(TRUE);
}
else if (exttype == EXT_DECODER) {
EXsetDecoder(temp, secondparm);
EXAadd(extarr, temp);
EXdestroy(temp);
return(TRUE);
}
#ifndef VMS_SERVER
else if (exttype == EXT_VIEW)
#else
else if ((exttype == EXT_VIEW) || (exttype == EXT_MISC))
#endif
EXsetObjtype(temp, *secondparm);
if (*inputline == '\0') return(FALSE);
inputline = skip_whitespace(inputline);
if (*inputline == '\0') return(FALSE);
/*** Prefix ***/
i=0;
while (!isspace(*inputline) && (*inputline != '\0'))
prefix[i++] = *inputline++;
if (*inputline == '\0') return(FALSE);
prefix[i]='\0';
EXsetPrefix(temp, prefix);
inputline = skip_whitespace(inputline);
if (*inputline == '\0') return(FALSE);
/*** Gopher + view type ***/
i=0;
while (!isspace(*inputline) && (*inputline != '\0'))
Gplustype[i++]= *inputline++;
Gplustype[i] = '\0';
EXsetView(temp, Gplustype);
inputline = skip_whitespace(inputline);
/** Gopher+ view language **/
i=0;
while (!isspace(*inputline) && (*inputline != '\0'))
Gpluslang[i++]= *inputline++;
Gpluslang[i] = '\0';
EXsetVLang(temp, Gpluslang);
EXsetExttype(temp, EXT_VIEW);
EXAadd(extarr, temp);
EXdestroy(temp);
return(TRUE);
}
.
Response:
text/plain