/******************************************************************** * $Author: jgoerzen $ * $Revision: 1.4 $ * $Date: 2002/04/26 13:33:33 $ * $Source: /var/cvs/gopher/gopherd/ext.c,v $ * $State: 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: * $Log: ext.c,v $ * Revision 1.4 2002/04/26 13:33:33 jgoerzen * Removed glib MIME stuff. We'll move to Pygopherd first. * * Revision 1.2 2000/12/20 01:19:20 jgoerzen * Added patches from David Allen * * Revision 1.1.1.1 2000/08/19 00:28:56 jgoerzen * Import from UMN Gopher 2.3.1 after GPLization * * Revision 3.20 1995/09/25 05:02:32 lindner * Convert to ANSI C * * 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 #include "ext.h" #include "Malloc.h" #include "Locale.h" #include #include "util.h" #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(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(Extobj *ext1, Extobj*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(ExtArray *extarr, char *file, char *view) { boolean status = TRUE; Extobj *ext, *temp; DIR *ZeDir; struct dirent *dp; 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; x = strcasecmp(cp, dp->d_name); if (x == 0) { /** Found an exact match **/ strcpy(cp, dp->d_name); closedir(ZeDir); return(tmpfile); } } /** Now check for a not so exact match.. **/ rewinddir(ZeDir); for (dp = readdir(ZeDir); dp != NULL; dp = readdir(ZeDir)) { int x; x = strncasecmp(cp, dp->d_name, strlen(dp->d_name)); if (x==0) /** Found a match for a possible decoder **/ strcpy(cp, dp->d_name); } closedir(ZeDir); /** 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(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(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(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; } if (EXgetVLang(temp) != NULL && *EXgetVLang(temp) != '\0') { 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(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); } else if (exttype == EXT_VIEW) 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); }