📄 htp.c
字号:
/*//// htp.c//// main(), major functionality modules//// Copyright (c) 1995-96 Jim Nelson. Permission to distribute// granted by the author. No warranties are made on the fitness of this// source code.// Parts of htp are copyright by different authors, but all are released on// the same basis.*/#include "htp.h"/*// default response filename*/const char *DEFAULT_RESPONSE_FILE = "htp.rsp";/*// variable types*/#define VAR_TYPE_SET_MACRO (1)#define VAR_TYPE_BLOCK_MACRO (2)#define VAR_TYPE_INTERNAL (3)#define VAR_TYPE_ALTTEXT (4)#define VAR_TYPE_DEF_MACRO (5)/*// variable flags*/#define VAR_FLAG_NONE (0x0000)#define VAR_FLAG_QUOTED (0x0001)/*// specialized markup processors type definitions*//* MARKUP_FUNC return codes */#define MARKUP_OKAY (0)#define MARKUP_REPLACED (1)#define DISCARD_MARKUP (2)#define MARKUP_ERROR ((uint) -1)#define NEW_MARKUP (3)/*// when reading source files, need to dynamically allocate memory to avoid// overruns ... use a stronger strategy for "real" operating systems, more// conservative for wimpy DOS*/#if __MSDOS__#define MIN_PLAINTEXT_SIZE (128)#define PLAINTEXT_GROW_SIZE (32)#else#define MIN_PLAINTEXT_SIZE (16 * KBYTE)#define PLAINTEXT_GROW_SIZE (4 * KBYTE)#endif/*// miscellaneous definitions*/#define MAX_TIME_DATE_SIZE (128)#define DEFAULT_PRECISION (0)#define SEARCH_PATH_SIZE (1024)/*// htp task structure//// (the word "task" is not to be confused with the traditional operating system// term ... it is used here to represent all the information associated with// the particular job at hand, which is reading in a file, writing out to// a file, and maintaining information during the entire operation)*/typedef struct tagTASK{ TEXTFILE *infile; TEXTFILE *outfile; VARSTORE *varstore; const char *sourceFilename;} TASK;/*// markup processor function and array association structure*/typedef uint (*MARKUP_FUNC)(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);typedef struct tagMARKUP_PROCESSORS{ const char *tag; uint markupType; MARKUP_FUNC markupFunc;} MARKUP_PROCESSORS;/*// template file name (used internally to store name for post-processing)// use squirrelly characters and a space to avoid conflicting with// user names*/const char *VAR_TEMPLATE_NAME = "__!TEMPLATE FILE~";/*// forward references*/BOOL ProcessTask(TASK *task);BOOL OptionCallback(const char *name, const char *value, ulong userParam);/*// the user can configure what kind of characters to use to surround htp// markups, to avoid conflicts with HTML markups ... default is the standard// greater-than/less-than bracketing, but also acceptable are square// brackets and curly brackets (parentheses are just too common in normal// text to be useful)//// Because htp also processes standard HTML markups, a IS_OPEN_MARKUP and// IS_CLOSE_MARKUP macros are used instead of standard comparisons ... watch// out for side-effects//// MARKUP_TYPE_ANY is used for markup processors to define they are// interested in either kind of markup (currently unused)//// MARKUP_OPEN_DELIM and MARKUP_CLOSE_DELIM are used to return the proper// delimiter given the markup type*/#define HTML_OPEN_MARKUP ('<')#define HTML_CLOSE_MARKUP ('>')char htpOpenMarkup = HTML_OPEN_MARKUP;char htpCloseMarkup = HTML_CLOSE_MARKUP;#define IS_OPEN_MARKUP(c) (((c) == '<') || ((c) == htpOpenMarkup))#define IS_CLOSE_MARKUP(c) (((c) == '>') || ((c) == htpCloseMarkup))#define MARKUP_TYPE_HTML (0x0001)#define MARKUP_TYPE_HTP (0x0002)#define MARKUP_TYPE_ANY (0xFFFF)#define MARKUP_OPEN_DELIM(t) \ (((t) & MARKUP_TYPE_HTP) ? htpOpenMarkup : HTML_OPEN_MARKUP)#define MARKUP_CLOSE_DELIM(t) \ (((t) & MARKUP_TYPE_HTP) ? htpCloseMarkup : HTML_CLOSE_MARKUP)/*// the global variable store ... holds permanent, file-to-file macros// (these are set in the global default file) ... filename kept for// dependency checking*/VARSTORE globalVarStore;char globalFilename[MAX_PATHNAME_LEN];/*// the "project" variable store ... holds macros only for files in current// directory, or project (this is loaded from the project default file,// which is called htp.def)*/VARSTORE projectVarStore;char projectFilename[MAX_PATHNAME_LEN];/*// include file search path*/char searchPath[SEARCH_PATH_SIZE] = { 0, };/*// ALT text macro store*/VARSTORE altTextVarStore;/*// for tracking ExpandMacros performance, debug version only*/#if DEBUGuint expandSkipped = 0;uint expandPerformed = 0;#endif/*//// generic, global utility functions//*//*// temporary file name generator*/BOOL CreateTempFilename(char *tempfilename, uint size){ static char *tempDir; char *tmpName; assert(tempfilename != NULL); /* find a preferred temporary directory if not found already */ if(tempDir == NULL) { if((tempDir = getenv("TEMP")) == NULL) { if((tempDir = getenv("TMP")) == NULL) { tempDir = DIR_CURRENT_STRING; } } } /* get a temporary filename */ if((tmpName = tempnam(tempDir, (char *) PROGRAM_NAME)) != NULL) { /* copy the filename to the callers buffer */ StringCopy(tempfilename, tmpName, size); /* free the tempnam buffer and return success */ free(tmpName); return TRUE; } return FALSE;}#if 0/*// extract directory from a filename, if present*/char *GetFileDirectory(const char *filename, char *directory, uint size){ const char *filePtr; uint len; *directory = NUL; len = strlen(filename); if(len == 0) { return directory; } filePtr = filename + len - 1; while(filePtr != filename) { if(*filePtr == DIR_DELIMITER) { return StringCopy(directory, filename, (len <= size) ? len : size); } filePtr--; len--; } return directory;} #endif/*// ParseFilename//// Returns a pointer to the filename in a full pathname*/char *FindFilename(char *pathname){ char *filePtr; uint len; assert(pathname != NULL); if(pathname == NULL) { return NULL; } len = strlen(pathname); if(len == 0) { return pathname; } filePtr = pathname + len - 1; while(filePtr != pathname) { if(strchr(ALL_FILESYSTEM_DELIMITERS, *filePtr) != NULL) { /* found the first delimiter, return pointer to character just */ /* past this one */ /* if pathname ended in a delimiter, then this will return a */ /* pointer to NUL, which is acceptable */ return filePtr + 1; } filePtr--; } return pathname;}/*// safe strncpy() wrapper (suggested by joseph.dandrea@att.com) ... strncpy()// by itself has some ugly problems, and strcpy() is simply dangerous.// Joseph recommended a macro, but I'm sticking to the bulkier solution of// using a function*/char *StringCopy(char *dest, const char *src, uint size){ assert(dest != NULL); assert(src != NULL); strncpy(dest, src, size); dest[size - 1] = NUL; return dest;}/*// re-entrant string tokenizer ... used because option.c requires simultaneous// uses of strtok(), and the standard version just dont cut it*/char *StringFirstToken(FIND_TOKEN *findToken, char *string, const char *tokens){ char *ptr; assert(string != NULL); assert(findToken != NULL); findToken->tokens = tokens; findToken->lastChar = string + strlen(string); findToken->nextStart = findToken->lastChar; if(tokens == NULL) { return string; } if((ptr = strpbrk(string, tokens)) != NULL) { *ptr = NUL; findToken->nextStart = ptr; } return string;}char *StringNextToken(FIND_TOKEN *findToken){ char *ptr; char *start; assert(findToken != NULL); assert(findToken->lastChar != NULL); ptr = findToken->nextStart; /* check if this is the end of the original string */ if(ptr == findToken->lastChar) { return NULL; } /* nextStart points to NUL left by last search, skip past it */ ptr++; start = ptr; /* keep going */ if((ptr = strpbrk(ptr, findToken->tokens)) != NULL) { *ptr = NUL; findToken->nextStart = ptr; } else { findToken->nextStart = findToken->lastChar; } return start;}/*// Wrapper function to (a) allocate memory for the duplicated string and// (b) copy the source string into the new memory location. Caller is// responsible to free the string eventually.*/char *DuplicateString(const char *src){ char *new; uint size; assert(src != NULL); size = strlen(src) + 1; /* allocate memory for the duplicate string */ if((new = AllocMemory(size)) == NULL) { return NULL; } /* copy the string */ return memcpy(new, src, size);}/*// returns the full, qualified pathname of the default htp include file//// Returns FALSE if unable to find the file.*/BOOL HtpDefaultFilename(char *filename, uint size){ char *defFile; /* get the name of the default file from the HTPDEF environement */ /* variable */ if((defFile = getenv("HTPDEF")) == NULL) { return FALSE; } /* verify that the file exists */ if(FileExists(defFile) == FALSE) { return FALSE; } /* copy the filename into the buffer and skeedaddle */ StringCopy(filename, defFile, size); return TRUE;}/*// compare files modified time/date stamp, as a dependency check ... returns// TRUE if the dependency does not require an update, FALSE otherwise (which// could either be a timestamp discrepency, or simply that the resulting file// does not exist) ... if dependency checking is turned off, this function// will always return FALSE.//// Returns ERROR if dependency file does not exist.*/BOOL IsTargetUpdated(const char *dependency, const char *target){ struct stat dependStat; struct stat targetStat; char *dependName; char *targetName; assert(dependency != NULL); assert(target != NULL); /* always update targets? */ if(DEPEND == FALSE) { return FALSE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -