/* * ratMailcap.c -- * * This file contains support for reading & parsing mailcap files * Mailcap files are defined in rfc1343 * * TkRat software and its included text is Copyright 1996-2002 by * Martin Forssén * * The full text of the legal notices is contained in the file called * COPYRIGHT, included with this distribution. */ #include "ratFolder.h" /* * Each entry is represented by one of the following structures */ typedef struct { char *type; char *subtype; char *test; char *view; char *compose; char *composetyped; char *edit; char *print; unsigned int needsterminal : 1; unsigned int copiousoutput : 1; char *description; char *bitmap; } MailcapEntry; /* * Id of the current load of the table */ static int tableId = 0; /* * Pointer to the current table as well as current size, allocated size * and increment. */ static MailcapEntry *tablePtr = NULL; static int tableSize = 0; static int tableAllocated = 0; /* * Local functions */ static void MailcapReload(Tcl_Interp *interp); static char *ExpandString(Tcl_Interp *interp, BodyInfo *bodyInfoPtr, char *s, char **filePtr); /* *---------------------------------------------------------------------- * * MailcapReload -- * * Reloads the mailcaps into memory. * * Results: * None. * * Side effects: * The mailcap files will be loaded. * * *---------------------------------------------------------------------- */ static void MailcapReload(Tcl_Interp *interp) { static char **textBlock = NULL; static int numTextBlocks = 0; static int allocTextBlocks = 0; Tcl_DString ds, bufDs; struct stat sbuf; char buf[1024], *s, *cPtr, **cPtrPtr, *dstPtr, *data, *tPtr, *pPtr; int i, fd, line; /* * Free old data */ for (i=0; ibodyPtr->type]; *cPtr; cPtr++){ if (strchr("|<>%*?\"`'", *cPtr)) { Tcl_DStringAppend(&ds, " ", 1); } else { Tcl_DStringAppend(&ds, cPtr, 1); } } Tcl_DStringAppend(&ds, "/", 1); for (cPtr = bodyInfoPtr->bodyPtr->subtype; *cPtr; cPtr++) { if (strchr("|<>%*?\"`'", *cPtr)) { Tcl_DStringAppend(&ds, " ", 1); } else { Tcl_DStringAppend(&ds, cPtr, 1); } } srcPtr++; continue; } if ('{' != *srcPtr++) { if (filePtr) { *filePtr = NULL; } return NULL; } for (cPtr = srcPtr, l = 0; *srcPtr && '}' != *srcPtr; srcPtr++, l++); if (*srcPtr) { srcPtr++; } for (parmPtr = bodyInfoPtr->bodyPtr->parameter; parmPtr; parmPtr = parmPtr->next) { if (!strncasecmp(cPtr, parmPtr->attribute, l)) { break; } } if (!parmPtr) { if (filePtr) { *filePtr = NULL; } return NULL; } /* * Copy the parameter value and in the process we remove any * chanacters that might be used to slip a trojan horse in * through our gates. */ for (cPtr = parmPtr->value; *cPtr; cPtr++) { if (strchr("|<>%*?\"`'", *cPtr)) { Tcl_DStringAppend(&ds, " ", 1); } else { Tcl_DStringAppend(&ds, cPtr, 1); } } } return Tcl_DStringValue(&ds); } /* *---------------------------------------------------------------------- * * RatMcapFindCmd -- * * Find a matching mailcap entry for a bodypart * * Results: * See ../doc/interface * * Side effects: * The mailcap files may be loaded. * * *---------------------------------------------------------------------- */ int RatMcapFindCmd(Tcl_Interp *interp, BodyInfo *bodyInfoPtr) { char *cmd, *file, *s; Tcl_Channel channel; int i, perm; Tcl_Obj *rPtr, *oPtr; /* * We start by making sure that the mailcap files have been loaded */ if (0 == tableId) { MailcapReload(interp); } /* * Loop through all entries and check them. * - First we check the type/subtype for match. * - If they matched we check eventual test commands */ for (i=0; ibodyPtr->type]) || ('*' != *tablePtr[i].subtype && strcasecmp(tablePtr[i].subtype, bodyInfoPtr->bodyPtr->subtype))) { continue; } if (tablePtr[i].test) { if (!(cmd = ExpandString(interp, bodyInfoPtr, tablePtr[i].test, &file))) { continue; } if (file) { oPtr = Tcl_GetVar2Ex(interp, "option", "permissions", TCL_GLOBAL_ONLY); Tcl_GetIntFromObj(interp, oPtr, &perm); channel = Tcl_OpenFileChannel(interp, file, "w", perm); RatBodySave(interp, channel, bodyInfoPtr, 0, 1); Tcl_Close(interp, channel); } if (system(cmd)) { if (file) { unlink(file); } continue; } if (file) { unlink(file); } } rPtr = Tcl_NewObj(); s = ExpandString(interp, bodyInfoPtr, tablePtr[i].view, NULL); Tcl_ListObjAppendElement(interp, rPtr, Tcl_NewStringObj(s, -1)); Tcl_ListObjAppendElement(interp, rPtr, Tcl_NewBooleanObj(tablePtr[i].needsterminal)); Tcl_ListObjAppendElement(interp, rPtr, Tcl_NewBooleanObj(tablePtr[i].copiousoutput)); Tcl_ListObjAppendElement(interp, rPtr, Tcl_NewStringObj(tablePtr[i].description,-1)); Tcl_ListObjAppendElement(interp, rPtr, Tcl_NewStringObj(tablePtr[i].bitmap, -1)); Tcl_SetObjResult(interp, rPtr); return TCL_OK; } Tcl_SetResult(interp, "{} 0 0 {} {}", TCL_STATIC); return TCL_OK; } /* *---------------------------------------------------------------------- * * RatMailcapReload -- * * This is just a wrapper which calls MailcapReload * * Results: * A standard tcl result. * * Side effects: * The mailcap files will be loaded. * * *---------------------------------------------------------------------- */ int RatMailcapReload(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { MailcapReload(interp); return TCL_OK; }