htp-1.16/ 0000755 0000510 0000310 00000000000 10665777573 012124 5 ustar hoenicke fb10-sem htp-1.16/Makefile 0000600 0000510 0000310 00000001655 10665777571 013561 0 ustar hoenicke fb10-sem #
# makefile - htp
#
# HTML pre-processor
# Copyright (c) 2002 Jochen Hoenicke
#
TOP=.
SUBDIRS = src tests homepage examples
DISTFILES = Makefile Makefile.config CLARIFIED_ARTISTIC
include $(TOP)/Makefile.config
do-scrub:
rm -f $(MAIN)-*.zip $(MAIN)-*.tar.gz
do-clean:
rm -rf $(RELDIR)
rm -f *~
release: all release-src release-doc release-bin
ls -l $(MAIN)-$(VERSION)*
@test "$(RELEASE)" == 1 || \
echo "****** ADD RELEASE=1 TO Makefile.config *******"
release-src: dist
tar -czf $(MAIN)-$(VERSION).tar.gz $(RELDIR)
rm -rf $(RELDIR)
@test "$(RELEASE)" == 1 || \
echo "****** ADD RELEASE=1 TO Makefile.config *******"
release-doc:
rm -rf $(RELDIR)
$(MAKE) -C src $(MAINEXE)
$(MAKE) install-doc pkgdocdir=`pwd`/$(RELDIR)
zip -r $(MAIN)-$(VERSION)-doc.zip $(RELDIR)
rm -rf $(RELDIR)
release-bin:
$(MAKE) -C src $(MAINEXE)
zip -j $(MAIN)-$(VERSION)-$(shell uname -s).zip src/$(MAINEXE) CLARIFIED_ARTISTIC
htp-1.16/Makefile.config 0000600 0000510 0000310 00000004361 10665777571 015022 0 ustar hoenicke fb10-sem #
# makefile - htp
#
# HTML pre-processor
# Copyright (c) 2002-2003 Jochen Hoenicke
#
RELEASE = 1
#
# development tools
#
CC = gcc
LINK = gcc
INSTALL = install
RSYNC = rsync --rsh=ssh -v
DIFF = diff -q
OBJEXT = o
EXEEXT =
DESTDIR =
prefix = $(DESTDIR)/usr/local
bindir = $(prefix)/bin
docdir = $(prefix)/share/doc
pkgdocdir = $(prefix)/share/doc/htp
#
# tool command-line options ... notice that these are geared towards GNU
#
ifdef RELEASE
CCOPT = -c -Wall -O2
else
CCOPT = -c -Wall -O2 -g -DDEBUG=1
endif
# Adapt the following defines to the features of your OS.
DEFINES = -DHAVE_SNPRINTF -DHAVE_PIPE -DHAVE_STPCPY -D_GNU_SOURCE=1
LOPT =
# -lefence
# -lmpatrol -lbfd -liberty
#Memory debug:
#LOPT = -lmpatrol -L$(HOME)/zola/lib -lbfd -liberty
# for cygwin/win32 ?
#LOPT = -lc -Wl,-u,_WinMain@16
#
# project name and version
#
MAIN = htp
VERSION = 1.16
ifdef RELEASE
FULLVERSION=$(VERSION)
else
FULLVERSION=$(VERSION) cvs $(shell date +%Y-%m-%d)
endif
RELDIR = $(MAIN)-$(VERSION)
#
# Layout of web server
#
ifdef RELEASE
TESTDIR =
else
TESTDIR = /$(USER)
endif
CGIBIN = http://htp.sourceforge.net/cgi-bin
RSYNCBASE = $(USER)@htp.sourceforge.net:/home/groups/h/ht/htp
RSYNCCGI = $(RSYNCBASE)/cgi-bin
HTP_DIR = /home/groups/h/ht/htp/htdocs$(TESTDIR)
RSYNCDIR = $(RSYNCBASE)/htdocs$(TESTDIR)
REF_URL = $(TESTDIR)/ref
#
# No user servicable parts below :)
#
MAINEXE = $(MAIN)$(EXEEXT)
HTP = $(TOP)/src/$(MAINEXE)
ifndef SUBDIR
SUBDIR = .
endif
ifndef SUBDIRS
SUBDIRS =
endif
.PHONY: all install dist scrub clean do-dist do-scrub do-clean
.PHONY: install-bin install-doc
all: subdir-all
dist: do-dist subdir-dist
scrub: do-scrub subdir-scrub
clean: do-clean subdir-clean
rsync: do-rsync subdir-rsync
do-scrub: do-clean
do-clean:
do-rsync:
install: install-bin install-doc
install-bin: subdir-install-bin
install-doc: subdir-install-doc
run-htp: $(HTML)
%.html: %.htp $(HTP) $(HTP_DEF)
$(HTP) -NODEPEND $< $@
htp.rsp: Makefile
@> $@
for i in $(HTP_SRC:%.htp=%); do echo $$i.htp $$i.html >>$@; done
#Rule to traverse sub-directories
subdir-%:
@test -z "$(SUBDIRS)" || sh -c 'for i in $(SUBDIRS); do \
$(MAKE) -C $$i SUBDIR=$(SUBDIR)/$$i $* || exit 1; done'
do-dist:
mkdir -p $(TOP)/$(RELDIR)/$(SUBDIR)
cp $(DISTFILES) $(TOP)/$(RELDIR)/$(SUBDIR)
htp-1.16/CLARIFIED_ARTISTIC 0000644 0000510 0000310 00000014557 10665777571 014645 0 ustar hoenicke fb10-sem The Clarified Artistic License
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Distribution fee" is a fee you charge for providing a copy
of this Package to another party.
"Freely Available" means that no fee is charged for the right to
use the item, though there may be fees involved in handling the
item. It also means that recipients of the item may redistribute
it under the same conditions they received it.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain, or those made Freely Available, or from
the Copyright Holder. A Package modified in such a way shall still be
considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or an
equivalent medium, or placing the modifications on a major network
archive site allowing unrestricted access to them, or by allowing the
Copyright Holder to include your modifications in the Standard Version
of the Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
e) permit and encourge anyone who receives a copy of the modified Package
permission to make your modifications Freely Available
in some specific way.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
e) offer the machine-readable source of the Package, with your
modifications, by mail order.
5. You may charge a distribution fee for any distribution of this Package.
If you offer support for this Package, you may charge any fee you choose
for that support. You may not charge a license fee for the right to use
this Package itself. You may distribute this Package in aggregate with
other (possibly commercial and possibly nonfree) programs as part of a
larger (possibly commercial and possibly nonfree) software distribution,
and charge license fees for other parts of that software distribution,
provided that you do not advertise this Package as a product of your own.
If the Package includes an interpreter, You may embed this Package's
interpreter within an executable of yours (by linking); this shall be
construed as a mere form of aggregation, provided that the complete
Standard Version of the interpreter is so embedded.
6. The scripts and library files supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package. If such scripts or library files are aggregated with this
Package via the so-called "undump" or "unexec" methods of producing a
binary executable image, then distribution of such an image shall
neither be construed as a distribution of this Package nor shall it
fall under the restrictions of Paragraphs 3 and 4, provided that you do
not represent such an executable image as a Standard Version of this
Package.
7. C subroutines (or comparably compiled subroutines in other
languages) supplied by you and linked into this Package in order to
emulate subroutines and variables of the language defined by this
Package shall not be considered part of this Package, but are the
equivalent of input as in Paragraph 6, provided these subroutines do
not change the language in any way that would cause it to fail the
regression tests for the language.
8. Aggregation of the Standard Version of the Package with a commercial
distribution is always permitted provided that the use of this Package
is embedded; that is, when no overt attempt is made to make this Package's
interfaces visible to the end user of the commercial distribution.
Such use shall not be construed as a distribution of this Package.
9. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End
htp-1.16/src/ 0000755 0000510 0000310 00000000000 10665777571 012711 5 ustar hoenicke fb10-sem htp-1.16/src/Makefile 0000644 0000510 0000310 00000002367 10665777571 014361 0 ustar hoenicke fb10-sem #
# makefile - htp
#
# HTML pre-processor
# Copyright (c) 2002 Jochen Hoenicke
#
TOP=..
#
# object files used
#
SRC = htp.c bool-proc.c def-proc.c defs.c file-proc.c gif.c html.c \
htp-files.c image-proc.c image.c jpeg.c macro.c misc-proc.c msg.c \
option.c png.c set-proc.c snprintf.c streams.c suballoc.c textfile.c \
use-proc.c util.c varstore.c ver.c while-proc.c
HEADERS = bool-proc.h def-proc.h defs.h file-proc.h gif.h html.h \
htp-files.h htp.h image-proc.h image.h jpeg.h macro.h misc-proc.h \
msg.h option.h os.h png.h set-proc.h snprintf.h streams.h suballoc.h \
textfile.h use-proc.h varstore.h ver.h while-proc.h
OBJ = $(SRC:%.c=%.$(OBJEXT))
DISTFILES = Makefile $(SRC) $(HEADERS) LICENSE.txt
include $(TOP)/Makefile.config
all: $(MAINEXE)
version.inc: $(wildcard *.[ch])
echo '#define VER_STRING "$(FULLVERSION)"' > version.inc
echo '#define PROGRAM_NAME "$(MAIN)"' >> version.inc
install-bin: $(MAINEXE)
mkdir -p $(bindir)
$(INSTALL) -s $(MAINEXE) $(bindir)
#
# explicit dependency: final executable
#
$(MAINEXE) : $(OBJ)
$(LINK) -o $@ $(OBJ) $(LOPT)
#
# implicit dependencies for source code
#
%.$(OBJEXT) : %.c
$(CC) $(CCOPT) $(DEFINES) -o $*.$(OBJEXT) $<
do-clean:
rm -f *~ $(MAINEXE) *.$(OBJEXT)
htp.o ver.o: version.inc
htp-1.16/src/htp.c 0000600 0000510 0000310 00000043553 10665777571 013652 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// 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.
//
*/
#include "defs.h"
#include "htp-files.h"
#include "macro.h"
#include "option.h"
/* The global and project specific htp.def files. These are used for
* dependency checking.
*/
static char globalFilename[MAX_PATHNAME_LEN];
static char projectFilename[MAX_PATHNAME_LEN];
/*
// HTML file stream functions
*/
BOOL ProcessTask(TASK *task)
{
char *newPlaintext;
uint markupResult;
HTML_MARKUP htmlMarkup;
BOOL result;
uint markupType;
assert(task != NULL);
assert(task->infile != NULL);
assert(task->outfile != NULL);
assert(task->varstore != NULL);
task->conditionalLevel = 0;
for(;;)
{
result = ReadHtmlMarkup(task->infile, task->outfile,
&markupType, &htmlMarkup);
if(result == ERROR)
{
/* problem reading in the file */
return FALSE;
}
else if(result == FALSE)
{
/* end-of-file */
break;
}
newPlaintext = NULL;
markupResult = ExpandAll(task, &htmlMarkup, &newPlaintext, markupType);
/* destroy the structure, now only interested in the markup string */
DestroyMarkupStruct(&htmlMarkup);
switch(markupResult)
{
case MARKUP_OKAY:
{
/* add the markup to the output file as it should appear */
StreamPrintF(task->outfile, "%c%s%c",
MARKUP_OPEN_DELIM(markupType),
newPlaintext, MARKUP_CLOSE_DELIM(markupType));
}
break;
case NEW_MARKUP:
case MARKUP_REPLACED:
{
/* the markup has been replaced by a normal string */
PutStreamString(task->outfile, newPlaintext);
}
break;
case DISCARD_MARKUP:
{
/* markup will not be included in final output */
}
break;
case MARKUP_ERROR:
{
/* (need to destroy plaintext buffer before exiting) */
FreeMemory(newPlaintext);
return FALSE;
}
default:
{
FreeMemory(newPlaintext);
printf("%s: serious internal error\n", PROGRAM_NAME);
exit(1);
}
}
/* free the plain text buffer and continue with processing */
if (newPlaintext)
{
FreeMemory(newPlaintext);
newPlaintext = NULL;
}
}
if (task->conditionalLevel > 0)
{
HtpMsg(MSG_ERROR, task->infile, "Missing for in line %d",
task->conditionalLine[task->conditionalLevel-1]);
}
return TRUE;
}
BOOL ProcessFileByName(VARSTORE *parentVarStore,
const char *in, const char *out)
{
STREAM infile;
STREAM outfile;
TASK task;
BOOL result;
const char *templateFile;
/*
// the "file" 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)
*/
static VARSTORE fileVarStore;
assert(in != NULL);
assert(out != NULL);
/* assume no processing required */
result = TRUE;
/* check the global and project default files first */
if(*globalFilename != NUL)
{
result = FullyCheckDependencies(globalFilename, out);
}
if((result == TRUE) && (*projectFilename != NUL))
{
result = FullyCheckDependencies(projectFilename, out);
}
/* check the dependencies of the target file to see whether or not */
/* to proceed ... the global and project default files are checked as well */
if(result == TRUE)
{
result = FullyCheckDependencies(in, out);
}
/* if TRUE, no need to go any further */
if(result == TRUE)
{
/* explain why no processing required, and return as if processing */
/* was completed */
printf("%s: File \"%s\" is completely up to date.\n", PROGRAM_NAME,
out);
return TRUE;
}
/* continue, at least one file was found that requires out to be updated */
/* initialize the project variable store and push it onto context */
InitializeVariableStore(&fileVarStore);
PushVariableStoreContext(parentVarStore, &fileVarStore);
fileVarStore.isGlobal = TRUE;
/* open the output file */
if(CreateFileWriter(&outfile, out, FALSE) == FALSE)
{
printf("%s: unable to open file \"%s\" for writing\n", PROGRAM_NAME, out);
DestroyVariableStore(&fileVarStore);
return FALSE;
}
if(CreateFileReader(&infile, in) == FALSE)
{
printf("%s: unable to open file \"%s\" for reading\n",
PROGRAM_NAME, in);
CloseStream(&outfile);
DestroyVariableStore(&fileVarStore);
return FALSE;
}
if(InitializeLocalOption() == FALSE)
{
printf("%s: unable to initialize local option store\n",
PROGRAM_NAME);
CloseStream(&infile);
CloseStream(&outfile);
DestroyVariableStore(&fileVarStore);
return FALSE;
}
/* build a task structure */
task.infile = &infile;
task.outfile = &outfile;
task.varstore = &fileVarStore;
task.sourceFilename = in;
StoreVariable(&fileVarStore, "_htpfile_in", (void *) in,
VAR_TYPE_SET_MACRO, VAR_FLAG_NONE, NULL, NULL);
StoreVariable(&fileVarStore, "_htpfile_out", (void *) out,
VAR_TYPE_SET_MACRO, VAR_FLAG_NONE, NULL, NULL);
printf("%s: Processing file \"%s\" to output file \"%s\" ...\n",
PROGRAM_NAME, in, out);
result = ProcessTask(&task);
/* done with this file, want to reuse struct */
CloseStream(&infile);
/* need to check for a template file */
if((result == TRUE) && (VariableExists(&fileVarStore, VAR_TEMPLATE_NAME)))
{
templateFile = GetVariableValue(&fileVarStore, VAR_TEMPLATE_NAME);
if(CreateFileReader(&infile, templateFile) == FALSE)
{
printf("%s: unable to open template file \"%s\"\n",
PROGRAM_NAME, templateFile);
CloseStream(&outfile);
DestroyLocalOption();
DestroyVariableStore(&fileVarStore);
return FALSE;
}
task.infile = &infile;
task.outfile = &outfile;
task.varstore = &fileVarStore;
task.sourceFilename = in;
printf("%s: Processing template file \"%s\" ...\n", PROGRAM_NAME,
templateFile);
result = ProcessTask(&task);
CloseStream(&infile);
}
if(result == TRUE)
{
printf("%s: final output file \"%s\" successfully created\n\n",
PROGRAM_NAME, outfile.name);
}
else
{
printf("\n%s: error encountered, file \"%s\" not completed\n\n",
PROGRAM_NAME, outfile.name);
}
CloseStream(&outfile);
/* destroy incomplete file if not configured elsewise */
if(result != TRUE)
{
if(PRECIOUS == FALSE)
{
assert(out != NULL);
remove(out);
}
}
/* destroy the local options for these files */
DestroyLocalOption();
/* destroy the project store as well */
DestroyVariableStore(&fileVarStore);
return result;
}
BOOL ProcessDefaultFile(VARSTORE *varstore, const char *file)
{
TASK defTask;
STREAM infile;
STREAM outfile;
BOOL result;
if(CreateFileReader(&infile, file) == FALSE)
{
printf("%s: unable to open default project file \"%s\"\n",
PROGRAM_NAME, file);
return FALSE;
}
/* use a null outfile because there is no file to write to */
CreateNullWriter(&outfile);
/* build a task (just like any other) and process the file */
/* use the global variable store to hold all the macros found */
defTask.infile = &infile;
defTask.outfile = &outfile;
defTask.varstore = varstore;
defTask.sourceFilename = file;
printf("%s: Processing default file \"%s\" ... \n",
PROGRAM_NAME, file);
result = ProcessTask(&defTask);
CloseStream(&infile);
CloseStream(&outfile);
return result;
}
BOOL ProcessResponseFile(VARSTORE *parentVarStore, const char *resp)
{
char textline[128];
char defResp[MAX_PATHNAME_LEN];
char newDirectory[MAX_PATHNAME_LEN];
char oldDirectory[MAX_PATHNAME_LEN];
STREAM respfile;
int result;
char *in;
char *out;
char *ptr;
BOOL useNewDir;
BOOL respFileOpen;
FIND_TOKEN findToken;
uint numread;
char nl_bitmap[3];
VARSTORE projectVarStore;
assert(resp != NULL);
nl_bitmap[0] = '\n';
nl_bitmap[1] = '\n';
nl_bitmap[2] = '\n';
useNewDir = FALSE;
if(strchr(ALL_FILESYSTEM_DELIMITERS, resp[strlen(resp) - 1]) != NULL)
{
/* some tests as done to ensure that (a) newDirectory does not trail */
/* with a directory separator and that (b) the separator is present */
/* before appending the filename ... requirement (a) is a DOS issue */
/* the response file is actually a directory the response file is */
/* possibly kept in ... copy it to the newDirectory variable for */
/* later use, but remove the trailing delimiter (MS-DOS issue) */
strcpy(newDirectory, resp);
newDirectory[strlen(newDirectory) - 1] = NUL;
/* now, see if default response file is present */
strcpy(defResp, newDirectory);
strcat(defResp, DIR_DELIMITER_STRING);
strcat(defResp, DEFAULT_RESPONSE_FILE);
useNewDir = TRUE;
respFileOpen = CreateFileReader(&respfile, defResp);
}
else
{
respFileOpen = CreateFileReader(&respfile, resp);
}
if(respFileOpen == FALSE)
{
printf("%s: unable to open \"%s\" as a response file\n", PROGRAM_NAME,
resp);
return FALSE;
}
printf("%s: Processing response file \"%s\" ...\n", PROGRAM_NAME,
respfile.name);
/* processing a response file in another directory, change to that */
/* directory before processing the files */
if(useNewDir)
{
getcwd(oldDirectory, sizeof oldDirectory);
chdir(newDirectory);
}
/* initialize the variable store for response file and push it */
InitializeVariableStore(&projectVarStore);
PushVariableStoreContext(parentVarStore, &projectVarStore);
projectVarStore.isGlobal = TRUE;
/* find the local project default file */
if(FileExists("htp.def"))
{
StringCopy(projectFilename, "htp.def", MAX_PATHNAME_LEN);
ProcessDefaultFile(&projectVarStore, projectFilename);
}
else
{
projectFilename[0] = NUL;
}
result = TRUE;
do
{
numread = GetStreamBlock(&respfile, textline, sizeof(textline),
nl_bitmap);
if(numread == 0)
{
/* EOF */
break;
}
/* Kill the newline at the end of the line */
if (textline[numread-1] == '\n')
textline[numread-1] = NUL;
in = NULL;
out = NULL;
/* walk tokens ... allow for tab character as token and ignore */
/* multiple token characters between filenames */
ptr = StringFirstToken(&findToken, textline, " \t");
while(ptr != NULL)
{
/* is this just a repeated token? */
if((*ptr == ' ') || (*ptr == '\t') || !(*ptr))
{
ptr = StringNextToken(&findToken);
continue;
}
/* found something ... like parsing the command-line, look for */
/* options, then response files, then regular in and out filenames */
if((*ptr == '-') || (*ptr == '/'))
{
ParseToken(NULL, ptr+1);
}
else if(*ptr == ';')
{
/* comment, ignore the rest of the line */
break;
}
else if(in == NULL)
{
in = ptr;
}
else if(out == NULL)
{
out = ptr;
}
else
{
/* hmm ... extra information on line */
HtpMsg(MSG_WARNING, &respfile,
"extra option \"%s\" specified in response file, ignoring",
ptr);
}
ptr = StringNextToken(&findToken);
}
if (in == NULL)
continue;
if (out == NULL)
{
char tempFilename[MAX_PATHNAME_LEN];
StringCopy(tempFilename, projectFilename, MAX_PATHNAME_LEN);
/* in is the response file.
* recurse but with the parentVarStore.
*/
PopVariableStoreContext(&projectVarStore);
result = ProcessResponseFile(parentVarStore, in);
PushVariableStoreContext(parentVarStore, &projectVarStore);
/* restore the projectFilename for dependency checking */
StringCopy(projectFilename, tempFilename, MAX_PATHNAME_LEN);
}
else if((in != NULL) && (out != NULL))
{
/* both in and out were specified, process a file */
result = ProcessFileByName(&projectVarStore, in, out);
}
} while(result == TRUE);
/* destroy the response files store */
DestroyVariableStore(&projectVarStore);
CloseStream(&respfile);
/* restore the directory this all started in */
if(useNewDir)
{
chdir(oldDirectory);
}
return result;
}
int main(int argc, char *argv[])
{
int result;
uint ctr;
char *in;
char *out;
char *resp;
/*
// 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;
DisplayHeader();
if(argc == 1)
{
usage();
return 1;
}
/* initialize debugging */
#if DEBUG
DebugInit("htpdeb.out");
atexit(DebugTerminate);
#endif
#ifdef USE_SUBALLOC
/* initialize the suballoc memory module */
InitializeMemory();
atexit(TerminateMemory);
#endif
/* initialize global variable options */
if(InitializeGlobalOption() == FALSE)
{
printf("%s: fatal error, unable to initialize internal options\n",
PROGRAM_NAME);
return 1;
}
in = NULL;
out = NULL;
resp = NULL;
/* search command-line for options */
for(ctr = 1; ctr < (uint) argc; ctr++)
{
if((*argv[ctr] == '-') || (*argv[ctr] == '/'))
{
/* command-line option specified */
ParseToken(NULL, argv[ctr]+1);
}
else if(*argv[ctr] == '@')
{
/* response file specified */
resp = argv[ctr] + 1;
if(*resp == NUL)
{
resp = (char *) DEFAULT_RESPONSE_FILE;
}
}
else if(in == NULL)
{
/* input file was specified */
in = argv[ctr];
}
else if(out == NULL)
{
/* output file was specified */
out = argv[ctr];
}
else
{
printf("%s: unknown argument \"%s\" specified\n",
PROGRAM_NAME, argv[ctr]);
return 1;
}
}
if(USAGE == TRUE)
{
usage();
return 1;
}
if((in == NULL || out == NULL) && (resp == NULL))
{
usage();
return 1;
}
/* initialize the global variable store before proceeding */
if(InitializeVariableStore(&globalVarStore) != TRUE)
{
printf("%s: unable to initialize global variable store (out of memory?)\n",
PROGRAM_NAME);
return 1;
}
globalVarStore.isGlobal = TRUE;
/* store htp version number in global store */
StoreVariable(&globalVarStore, "_htp_version", VER_STRING,
VAR_TYPE_SET_MACRO, VAR_FLAG_NONE, NULL, NULL);
/* before reading in the response file or processing any files, handle */
/* the default file, if there is one ... all of its macros are held in */
/* the global variable store */
if(HtpDefaultFilename(globalFilename, MAX_PATHNAME_LEN))
{
ProcessDefaultFile(&globalVarStore, globalFilename);
}
else
{
globalFilename[0] = NUL;
}
/* now, process the response file (if there is one) or the files */
/* specified on the command-line */
if(resp != NULL)
{
result = ProcessResponseFile(&globalVarStore, resp);
}
else
{
/* find the local project default file */
if(FileExists("htp.def"))
{
StringCopy(projectFilename, "htp.def", MAX_PATHNAME_LEN);
ProcessDefaultFile(&globalVarStore, projectFilename);
}
else
{
projectFilename[0] = NUL;
}
result = ProcessFileByName(&globalVarStore, in, out);
}
/* display varstore stats */
DEBUG_PRINT(("Variable lookups=%u string cmps=%u rotations=%u\n",
variableLookups, variableStringCompares, variableRotations));
/* destroy the global variable store */
DestroyVariableStore(&globalVarStore);
/* destroy global option */
DestroyGlobalOption();
#ifdef USE_SUBALLOC
/* display suballoc stats */
DEBUG_PRINT(("suballoc total allocations=%u free pool hits=%u system heap allocs=%u\n",
totalAllocations, freePoolHits, totalAllocations - freePoolHits));
#endif
return (result == TRUE) ? 0 : 1;
}
htp-1.16/src/bool-proc.c 0000600 0000510 0000310 00000013566 10665777571 014754 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// bool-proc.c
//
// specialized markup processors
//
// Copyright (c) 2002-2003 Jochen Hoenicke.
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "bool-proc.h"
#include "defs.h"
#include "htp-files.h"
static BOOL EvaluateIfTag(TASK *task, HTML_MARKUP *htmlMarkup)
{
BOOL condTrue, notTagFound;
HTML_ATTRIBUTE *attrib;
const char *value;
uint type;
/* this is an ugly way to handle the IF-IF NOT test, but will need */
/* be cleaned up in the future */
notTagFound = UnlinkBoolAttributeInMarkup(htmlMarkup, "NOT");
/* should either be one or two attributes in markup */
if(htmlMarkup->attrib == NULL)
{
HtpMsg(MSG_ERROR, task->infile, "no conditional to test");
return MARKUP_ERROR;
}
if(htmlMarkup->attrib->next != NULL)
{
HtpMsg(MSG_ERROR, task->infile,
"too many items in conditional expression");
return MARKUP_ERROR;
}
attrib = htmlMarkup->attrib;
/* get the macros associated type (UNKNOWN if macro is not defined) */
type = GetVariableType(task->varstore, attrib->name);
/* if only a name is specified, only care if macro is defined */
if(attrib->value == NULL)
{
condTrue = (type != VAR_TYPE_UNKNOWN) ? TRUE : FALSE;
}
else
{
/* macro value comparison */
if(type == VAR_TYPE_SET_MACRO)
{
/* macro comparison (case-sensitive) */
value = GetVariableValue(task->varstore, attrib->name);
condTrue = (value && strcmp(value, attrib->value) == 0)
? TRUE : FALSE;
}
else
{
/* block macro, comparisons not allowed */
condTrue = FALSE;
}
}
/* reverse conditional if NOT attribute found */
return condTrue != notTagFound;
}
static BOOL DiscardConditionalBlock(TASK *task, BOOL takeElseBlock)
{
HTML_MARKUP htmlMarkup;
BOOL result;
uint embeddedConditionals;
uint markupType;
char ch;
/* discard the block, looking for the matching ELSE or /IF statement */
embeddedConditionals = 0;
for(;;)
{
result = ReadHtmlMarkup(task->infile, NULL, &markupType, &htmlMarkup);
if(result == ERROR)
{
return FALSE;
}
else if(result == FALSE)
{
/* end-of-file before end-of-conditional ... error */
HtpMsg(MSG_ERROR, task->infile,
"Missing for in line %d",
task->conditionalLine[task->conditionalLevel-1]);
return FALSE;
}
/* another conditional started? */
if(IsMarkupTag(&htmlMarkup, "IF"))
{
embeddedConditionals++;
}
else if(IsMarkupTag(&htmlMarkup, "/IF"))
{
/* end of the conditional? */
if(embeddedConditionals == 0)
{
DestroyMarkupStruct(&htmlMarkup);
task->conditionalLevel--;
break;
}
embeddedConditionals--;
}
else if(embeddedConditionals == 0 && takeElseBlock)
{
/* Check whether this is an ELSE or a taken ELSEIF tag. */
if (IsMarkupTag(&htmlMarkup, "ELSE")
|| (IsMarkupTag(&htmlMarkup, "ELSEIF")
&& EvaluateIfTag(task, &htmlMarkup) == TRUE))
{
DestroyMarkupStruct(&htmlMarkup);
/* Skip EOL, but put it back if it's another character */
if (GetStreamChar(task->infile, &ch) && ch != '\n')
{
UnreadStreamChar(task->infile, ch);
}
break;
}
}
/* destroy and continue */
DestroyMarkupStruct(&htmlMarkup);
}
return TRUE;
}
uint BooleanProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
char ch;
UNREF_PARAM(newPlaintext);
/* conditionalLevel keeps track of boolean depth */
if(task->conditionalLevel == 0
&& !IsMarkupTag(htmlMarkup, "IF"))
{
HtpMsg(MSG_ERROR, task->infile,
"<%s> without matching IF tag", htmlMarkup->tag);
return MARKUP_ERROR;
}
if(IsMarkupTag(htmlMarkup, "IF"))
{
if (task->conditionalLevel >= MAX_CONDITIONAL_LEVEL)
{
HtpMsg(MSG_ERROR, task->infile, "Too many nested tags");
return MARKUP_ERROR;
}
task->conditionalLine[task->conditionalLevel++]
= task->infile->lineNumber;
if (EvaluateIfTag(task, htmlMarkup) == FALSE)
{
/* discard the rest of the conditional block since this
* portion has evaluated false. We still can take the
* ELSE, though
*/
if(DiscardConditionalBlock(task, TRUE) == FALSE)
{
return MARKUP_ERROR;
}
}
else
{
/* Skip EOL, but put it back if it's another character */
if (GetStreamChar(task->infile, &ch) && ch != '\n')
{
UnreadStreamChar(task->infile, ch);
}
}
}
else if (IsMarkupTag(htmlMarkup, "ELSE")
|| IsMarkupTag(htmlMarkup, "ELSEIF"))
{
/* this can only occur if the associated conditional statement */
/* evaluated TRUE, so the remaining block must be discarded */
/* We must not even take the ELSE part */
if(DiscardConditionalBlock(task, FALSE) == FALSE)
{
return MARKUP_ERROR;
}
}
else
{
/* end of conditional */
assert(task->conditionalLevel > 0);
task->conditionalLevel--;
}
return DISCARD_MARKUP;
}
htp-1.16/src/def-proc.c 0000644 0000510 0000310 00000026072 10665777571 014563 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// def-proc.c
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "def-proc.h"
#include "defs.h"
#include "htp-files.h"
#include "macro.h"
#include "option.h"
/*
// Block macro destructor callback ... used whenever a block macro is
// destroyed with a RemoveVariable() or ClearVariableList()
*/
void BlockDestructor(const char *name, void *value, uint type, uint flags,
void *param)
{
STREAM *stream = (STREAM*) value;
UNREF_PARAM(name);
UNREF_PARAM(type);
UNREF_PARAM(flags);
CloseStream(stream);
FreeMemory(stream);
/* DEF macros use param */
if(param != NULL)
{
FreeMemory(param);
}
}
BOOL ReadBlockToFile(TASK *task, BOOL expand, const char *tag,
STREAM *blockFile) {
char *plaintext;
char ch;
HTML_MARKUP newHtml;
BOOL result;
static uint blockDepth = 0;
uint markupType;
STREAM *oldOutFile;
uint markupResult;
HtpMsg(MSG_INFO, task->infile, "reading %s block to memory",
expand ? "expanded" : "raw");
oldOutFile = task->outfile;
task->outfile = blockFile;
/* Skip EOL, but put it back if it's another character */
if (GetStreamChar(task->infile, &ch) && ch != '\n')
{
UnreadStreamChar(task->infile, ch);
}
task->outfile->name = DuplicateString(task->infile->name);
task->outfile->lineNumber = task->infile->lineNumber;
/* start copying the file into the temporary file, looking for the */
/* BLOCK or /BLOCK tag if block macro, DEF or /DEF otherwise ... */
/* just squirrel away all other tags and text */
for(;;)
{
result = ReadHtmlMarkup(task->infile, blockFile,
&markupType, &newHtml);
if(result == ERROR)
{
task->outfile = oldOutFile;
return FALSE;
}
else if(result == FALSE)
{
/* end-of-file encountered before end-of-block */
HtpMsg(MSG_ERROR, task->infile,
"EOF encountered before %s in line %d was closed",
tag, task->outfile->lineNumber);
task->outfile = oldOutFile;
return FALSE;
}
if ((markupType & MARKUP_TYPE_HTP) && blockDepth == 0
&& newHtml.tag[0] == '/'
&& stricmp(tag, newHtml.tag+1) == 0)
{
/* found the end of the macro block */
DestroyMarkupStruct(&newHtml);
break;
}
plaintext = NULL;
if (expand) {
/* give the default processor a chance to expand macros, etc. */
markupResult = ExpandAll(task, &newHtml,
&plaintext, markupType);
} else {
if(markupType & MARKUP_TYPE_HTP)
{
/* check for embedded block declarations */
if (stricmp(tag, newHtml.tag) == 0)
{
/* add to the block macro depth and continue */
blockDepth++;
}
else if (newHtml.tag[0] == '/'
&& stricmp(tag, newHtml.tag+1) == 0)
{
/* depth has decreased one */
blockDepth--;
}
}
/* if continuing, then the plaintext is put into the
* output stream as-is ... there is no case where the
* processor continues scanning but discards a markup
*/
if(MarkupToPlaintext(&newHtml, &plaintext) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile,
"unable to build plain text from markup (out of memory?)");
task->outfile = oldOutFile;
return MARKUP_ERROR;
}
markupResult = MARKUP_OKAY;
}
switch(markupResult)
{
case MARKUP_OKAY:
{
/* add the markup to the output file as it should appear */
StreamPrintF(blockFile, "%c%s%c",
MARKUP_OPEN_DELIM(markupType),
plaintext, MARKUP_CLOSE_DELIM(markupType));
}
break;
case NEW_MARKUP:
case MARKUP_REPLACED:
{
/* the markup has been replaced by a normal string */
StreamPrintF(blockFile, "%s", plaintext);
}
break;
case DISCARD_MARKUP:
{
/* markup will not be included in final output */
}
break;
case MARKUP_ERROR:
{
/* (need to destroy plaintext buffer before exiting) */
FreeMemory(plaintext);
task->outfile = oldOutFile;
return FALSE;
}
default:
{
FreeMemory(plaintext);
printf("%s: serious internal error\n", PROGRAM_NAME);
exit(1);
}
}
/* destroy the HTML markup, not needed any longer */
DestroyMarkupStruct(&newHtml);
/* destroy the plaintext buffer */
if (plaintext)
FreeMemory(plaintext);
}
task->outfile = oldOutFile;
return TRUE;
}
BOOL ReadinBlock(TASK *task, HTML_MARKUP *htmlMarkup, STREAM *blockStream) {
BOOL expand = UnlinkBoolAttributeInMarkup(htmlMarkup, "EXPAND");
if (htmlMarkup->attrib != NULL) {
HtpMsg(MSG_WARNING, task->infile,
"Unhandled %s attribute in %s markup",
htmlMarkup->attrib->name, htmlMarkup->tag);
}
/* try and create the temporary file */
if(CreateBufferWriter(blockStream, htmlMarkup->tag) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile,
"unable to create stream for %s macro", htmlMarkup->tag);
return FALSE;
}
if (ReadBlockToFile(task, expand, htmlMarkup->tag, blockStream) == FALSE) {
CloseStream(blockStream);
FreeMemory(blockStream);
return FALSE;
}
FlushBufferWriter(blockStream);
return TRUE;
}
uint BlockProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
char *defName, *param;
STREAM *stream;
BOOL blockMacro;
uint macroType;
VARSTORE *varstore;
HTML_ATTRIBUTE *attrib;
UNREF_PARAM(newPlaintext);
/* first: is this a BLOCK macro or a DEF macro? This function is */
/* overloaded to handle both types, and must internally change its */
/* functionality for each type */
/* if this is false, this is a DEF macro */
if(stricmp(htmlMarkup->tag, "BLOCK") == 0)
{
blockMacro = TRUE;
macroType = VAR_TYPE_BLOCK_MACRO;
/* no extra varstore parameter for a block macro */
param = NULL;
}
else
{
blockMacro = FALSE;
if (stricmp(htmlMarkup->tag, "BLOCKDEF") == 0)
{
macroType = VAR_TYPE_BLOCKDEF_MACRO;
}
else
{
assert(stricmp(htmlMarkup->tag, "DEF") == 0);
macroType = VAR_TYPE_DEF_MACRO;
}
/* get the OPTION parameter */
attrib = UnlinkAttributeInMarkup(htmlMarkup, "OPTION");
if (attrib != NULL) {
FreeMemory(attrib->name);
param = attrib->value;
if (attrib->whitespace)
FreeMemory(attrib->whitespace);
FreeMemory(attrib);
}
else
{
param = NULL;
}
}
/* check if name is present */
attrib = UnlinkAttributeInMarkup(htmlMarkup, "NAME");
if (attrib != NULL && attrib->value != NULL) {
/* new syntax */
FreeMemory(attrib->name);
defName = attrib->value;
if (attrib->whitespace)
FreeMemory(attrib->whitespace);
FreeMemory(attrib);
} else {
/* The only attribute is the macro name without value
* (which can be "name" though).
*/
if (attrib == NULL) {
attrib = htmlMarkup->attrib;
if(attrib == NULL)
{
HtpMsg(MSG_ERROR, task->infile,
"%s markup without name", htmlMarkup->tag);
return MARKUP_ERROR;
}
htmlMarkup->attrib = attrib->next;
}
defName = attrib->name;
if (attrib->whitespace)
FreeMemory(attrib->whitespace);
if (attrib->value != NULL || htmlMarkup->attrib != NULL)
{
HtpMsg(MSG_ERROR, task->infile,
"bad %s markup", htmlMarkup->tag);
if (attrib->value != NULL)
FreeMemory(attrib->value);
FreeMemory(attrib);
return MARKUP_ERROR;
}
FreeMemory(attrib);
/* old style only allowed for block macros */
if(!blockMacro)
{
HtpMsg(MSG_ERROR, task->infile,
"%s requires NAME attribute", htmlMarkup->tag);
return MARKUP_ERROR;
}
}
/* store the block file name and the block macro name as a variable */
varstore = task->varstore;
if (UnlinkBoolAttributeInMarkup(htmlMarkup, "GLOBAL")) {
while (!varstore->isGlobal)
varstore = varstore->parent;
}
stream = (STREAM*) AllocMemory(sizeof(STREAM));
if (!ReadinBlock(task, htmlMarkup, stream))
{
FreeMemory(defName);
if (param != NULL)
FreeMemory(param);
return MARKUP_ERROR;
}
if(StoreVariable(varstore, defName, stream, macroType,
VAR_FLAG_DEALLOC_NAME, param, BlockDestructor) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile,
"unable to store macro information (out of memory?)");
FreeMemory(defName);
if (param != NULL)
FreeMemory(param);
return MARKUP_ERROR;
}
return DISCARD_MARKUP;
}
uint UndefProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
HTML_ATTRIBUTE *attrib;
uint type;
UNREF_PARAM(newPlaintext);
attrib = htmlMarkup->attrib;
/* need at least one attribute to undef */
if(htmlMarkup->attrib == NULL)
{
HtpMsg(MSG_ERROR, task->infile, "UNDEF requires at least one name");
return MARKUP_ERROR;
}
/* walk the list of attributes, deleting them as found */
while (attrib != NULL)
{
/* only remove it if it is a [BLOCK]DEF macro */
type = GetVariableType(task->varstore, attrib->name);
if(type == VAR_TYPE_DEF_MACRO || type == VAR_TYPE_BLOCKDEF_MACRO)
{
RemoveVariable(task->varstore, attrib->name);
HtpMsg(MSG_INFO, task->infile, "metatag \"%s\" removed",
attrib->name);
}
else
{
HtpMsg(MSG_ERROR, task->infile,
"metatag \"%s\" never defined", attrib->name);
return MARKUP_ERROR;
}
attrib = attrib->next;
}
return DISCARD_MARKUP;
}
htp-1.16/src/defs.c 0000600 0000510 0000310 00000002731 10665777571 013771 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// defs.c
//
// major definitions
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "defs.h"
/*
// default response filename
*/
const char *DEFAULT_RESPONSE_FILE = "htp.rsp";
/*
// 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~";
/*
// 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
*/
char htpOpenMarkup = HTML_OPEN_MARKUP;
char htpCloseMarkup = HTML_CLOSE_MARKUP;
/*
// include file search path
*/
char searchPath[SEARCH_PATH_SIZE] = { 0, };
htp-1.16/src/file-proc.c 0000600 0000510 0000310 00000046315 10665777571 014736 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// -proc.c
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "defs.h"
#include "macro.h"
#include "htp-files.h"
#include "def-proc.h"
#include "file-proc.h"
#include "snprintf.h"
#ifdef HAVE_PIPE
#include
#include
#include
#endif
uint ExternalFileProcessor(TASK *task, HTML_MARKUP *htmlMarkup,
const char *externalName, char **newPlaintext)
{
struct stat fileStat;
struct tm *fileTime;
HTML_ATTRIBUTE *attrib;
assert(externalName != NULL);
assert(htmlMarkup != NULL);
/* get information on the file itself */
if(stat(externalName, &fileStat) != 0)
{
HtpMsg(MSG_ERROR, task->infile, "unable to retrieve file information on \"%s\"",
externalName);
return MARKUP_ERROR;
}
/* allocate room for the replacment plaintext */
if((*newPlaintext = AllocMemory(MAX_TIME_DATE_SIZE)) == NULL)
{
HtpMsg(MSG_ERROR, task->infile, "unable to allocate memory for expansion");
return MARKUP_ERROR;
}
/* create new plaintext depending on what extra information is specified */
if((attrib = UnlinkAttributeInMarkup(htmlMarkup, "SIZE")) != NULL)
{
uint precision;
HTML_ATTRIBUTE *pattrib;
/* get the precision attribute value, if present */
precision = DEFAULT_PRECISION;
if ((pattrib = UnlinkAttributeInMarkup(htmlMarkup, "PRECISION")) != NULL)
{
if(pattrib->value != NULL)
{
precision = atoi(pattrib->value);
}
else
{
HtpMsg(MSG_WARNING, task->infile,
"precision attribute needs a value");
}
DestroyAttribute(pattrib);
FreeMemory(pattrib);
}
/* expand markup depending on how SIZE should be represented */
if((attrib->value == NULL) || (stricmp(attrib->value, "BYTE") == 0))
{
/* byte representation is default */
snprintf(*newPlaintext, MAX_TIME_DATE_SIZE,
"%lu", fileStat.st_size);
}
else if(stricmp(attrib->value, "KBYTE") == 0)
{
snprintf(*newPlaintext, MAX_TIME_DATE_SIZE,
"%.*f", (int) precision,
(double) ((double) fileStat.st_size / (double) KBYTE));
}
else if(stricmp(attrib->value, "MBYTE") == 0)
{
snprintf(*newPlaintext, MAX_TIME_DATE_SIZE,
"%.*f", (int) precision,
(double) ((double) fileStat.st_size / (double) MBYTE));
}
else if(stricmp(attrib->value, "GBYTE") == 0)
{
snprintf(*newPlaintext, MAX_TIME_DATE_SIZE,
"%.*f", (int) precision,
(double) ((double) fileStat.st_size / (double) GBYTE));
}
else
{
/* free the plaintext memory before returning */
HtpMsg(MSG_ERROR, task->infile, "unknown SIZE specifier");
DestroyAttribute(attrib);
FreeMemory(attrib);
FreeMemory(*newPlaintext);
*newPlaintext = NULL;
return MARKUP_ERROR;
}
DestroyAttribute(attrib);
FreeMemory(attrib);
}
else if((attrib = UnlinkAttributeInMarkup(htmlMarkup, "TIME")) != NULL)
{
const char *value;
/* convert into an ANSI time structure */
fileTime = localtime(&fileStat.st_mtime);
/* see if the attribute has a value ... if so, let it be the */
/* strftime() formatter */
if((value = MarkupAttributeValue(htmlMarkup, "TIME")) != NULL)
{
strftime(*newPlaintext, MAX_TIME_DATE_SIZE, value, fileTime);
}
else
{
strftime(*newPlaintext, MAX_TIME_DATE_SIZE, "%I:%M:%S %p", fileTime);
}
DestroyAttribute(attrib);
FreeMemory(attrib);
}
else if((attrib = UnlinkAttributeInMarkup(htmlMarkup, "DATE")) != NULL)
{
/* convert into an ANSI time structure */
fileTime = localtime(&fileStat.st_mtime);
/* see if the attribute has a value ... if so, let it be the */
/* strftime() formatter */
if (attrib->value != NULL)
{
strftime(*newPlaintext, MAX_TIME_DATE_SIZE,
attrib->value, fileTime);
}
else
{
strftime(*newPlaintext, MAX_TIME_DATE_SIZE,
"%a %b %d, %Y", fileTime);
}
DestroyAttribute(attrib);
FreeMemory(attrib);
}
else
{
/* free the plaintext, unused */
FreeMemory(*newPlaintext);
*newPlaintext = NULL;
HtpMsg(MSG_ERROR, task->infile, "invalid FILE tag");
return MARKUP_ERROR;
}
/* the new plaintext was created successfully */
return NEW_MARKUP;
}
uint FileExecuteProcessor(TASK *task,
HTML_ATTRIBUTE *attrib, HTML_MARKUP *htmlMarkup)
{
const char *cmdline;
const char *output;
HTML_ATTRIBUTE *outputAttrib;
#ifndef HAVE_PIPE
char newCmdline[MAX_CMDLINE_LEN];
char tempFilename[MAX_PATHNAME_LEN];
#endif
BOOL redirect, ignoreError;
STREAM infile;
TASK newTask;
BOOL result = TRUE;
int exitCode;
assert(task != NULL);
assert(htmlMarkup != NULL);
cmdline = attrib->value;
redirect = UnlinkBoolAttributeInMarkup(htmlMarkup, "REDIRECT");
ignoreError = UnlinkBoolAttributeInMarkup(htmlMarkup, "NOERROR");
outputAttrib = UnlinkAttributeInMarkup(htmlMarkup, "OUTPUT");
if (outputAttrib != NULL)
output = outputAttrib->value;
else
output = NULL;
/* either output or redirect, but not both, must be specified */
if((output == NULL) && (redirect == FALSE))
{
HtpMsg(MSG_ERROR, task->infile, "Either REDIRECT or OUTPUT must be specified for FILE EXECUTE");
return MARKUP_ERROR;
}
if((output != NULL) && (redirect == TRUE))
{
HtpMsg(MSG_ERROR, task->infile, "REDIRECT and OUTPUT cannot both be specified for FILE EXECUTE");
DestroyAttribute(outputAttrib);
FreeMemory(outputAttrib);
return MARKUP_ERROR;
}
HtpMsg(MSG_INFO, task->infile, "Executing command \"%s\" ...", cmdline);
#ifndef HAVE_PIPE
/* if redirection required, append to the command-line a redirector to */
/* a temporary file */
if(redirect)
{
if(CreateTempFilename(tempFilename, MAX_PATHNAME_LEN) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile, "unable to create a temporary file for redirection");
return MARKUP_ERROR;
}
strncpy(newCmdline, cmdline, MAX_PATHNAME_LEN);
strncat(newCmdline, " > ", MAX_PATHNAME_LEN);
strncat(newCmdline, tempFilename, MAX_PATHNAME_LEN);
cmdline = newCmdline;
output = tempFilename;
}
/* execute the command */
exitCode = system(cmdline);
#else
/* if redirection required, create a pipe for our child process */
if(redirect) {
pid_t pid;
int pipefds[2];
extern char **environ;
pipe(pipefds);
pid = fork();
if (pid == 0) {
char *argv[4];
if (redirect) {
dup2(pipefds[1], 1);
close(pipefds[0]);
close(pipefds[1]);
}
argv[0] = "sh";
argv[1] = "-c";
argv[2] = (char*)cmdline;
argv[3] = NULL;
execve("/bin/sh", argv, environ);
exit(127);
} else
close(pipefds[1]);
if (pid == -1)
exitCode = -1;
else {
if (CreateFDReader(&infile, "stdout", pipefds[0]) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile, "unable to open execute result file");
return MARKUP_ERROR;
}
/* build a new task */
newTask.infile = &infile;
newTask.outfile = task->outfile;
newTask.varstore = task->varstore;
newTask.sourceFilename = task->sourceFilename;
/* process the file */
result = ProcessTask(&newTask);
if (!result) {
/* Error message was already spitted out. However, we
* should give a hint where the meta-tag was called.
*/
HtpMsg(MSG_ERROR, task->infile,
"... in output from '%s'", cmdline);
}
CloseStream(&infile);
/* wait for termination of the command */
while (waitpid(pid, &exitCode, 0) == -1) {
if (errno != EINTR) {
exitCode = -1;
break;
}
}
}
} else {
/* execute the command */
exitCode = system(cmdline);
}
#endif
if(exitCode != 0 && ignoreError == FALSE)
{
/* the program has exited with an error condition */
HtpMsg(MSG_ERROR, task->infile, "Command \"%s\" exited with an error code of %u",
cmdline, exitCode);
/* remove the temporary file, in case it was partially created */
if (output != NULL)
remove(output);
if (outputAttrib != NULL) {
DestroyAttribute(outputAttrib);
FreeMemory(outputAttrib);
}
return MARKUP_ERROR;
}
if (output != NULL)
{
/* include the output file like it was anything else */
/* first, open it */
if(CreateFileReader(&infile, output) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile, "unable to open execute result file");
return MARKUP_ERROR;
}
/* build a new task */
newTask.infile = &infile;
newTask.outfile = task->outfile;
newTask.varstore = task->varstore;
newTask.sourceFilename = task->sourceFilename;
/* process the file */
result = ProcessTask(&newTask);
if (!result) {
/* Error message was already spitted out. However, we
* should give a hint where the meta-tag was called.
*/
HtpMsg(MSG_ERROR, task->infile,
"... in output from '%s'", cmdline);
}
/* close and destroy the output file */
CloseStream(&infile);
remove(output);
if (outputAttrib != NULL) {
DestroyAttribute(outputAttrib);
FreeMemory(outputAttrib);
}
}
return (result == TRUE) ? DISCARD_MARKUP : MARKUP_ERROR;
}
uint FileTemplateProcessor(TASK *task, HTML_ATTRIBUTE *attrib)
{
assert(task != NULL);
assert(attrib != NULL);
/* the template file is not actually processed now, but rather
* when the rest of the file is completed ... to postpone
* processing, the template name is kept in the variable store
* under a special name and retrieved later
*/
if(StoreVariable(task->varstore, VAR_TEMPLATE_NAME, attrib->value,
VAR_TYPE_INTERNAL, VAR_FLAG_DEALLOC_VALUE,
NULL, NULL) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile,
"unable to store template filename for post-processing (out of memory?)");
return MARKUP_ERROR;
}
/* attrib->value was moved into VARSTORE */
attrib->value = NULL;
return DISCARD_MARKUP;
}
uint FileIncludeProcessor(TASK *task,
const char *filename, HTML_MARKUP *htmlMarkup)
{
STREAM incfile;
BOOL result;
TASK newTask;
char fullPathname[MAX_PATHNAME_LEN];
VARSTORE varstore;
VARSTORE *topVarstore;
uint flag;
/* open the include file as input */
if(CreateFileReader(&incfile, filename) == FALSE)
{
/* use the search path to find the file */
if(SearchForFile(filename, fullPathname, MAX_PATHNAME_LEN) == FALSE)
{
/* could not find the file in the search path either */
HtpMsg(MSG_ERROR, task->infile, "unable to open include file \"%s\"",
filename);
return MARKUP_ERROR;
}
if(CreateFileReader(&incfile, fullPathname) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile, "unable to open include file \"%s\"",
fullPathname);
return MARKUP_ERROR;
}
}
else
{
StringCopy(fullPathname, filename, MAX_PATHNAME_LEN);
}
/* if additional parameters exist in the tag, build a local varstore */
/* and push it onto the context */
if (htmlMarkup->attrib != NULL)
{
HTML_ATTRIBUTE *attrib;
if(InitializeVariableStore(&varstore) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile, "unable to initialize context for include file");
CloseStream(&incfile);
return MARKUP_ERROR;
}
/* start including the parameters as local macros */
while (htmlMarkup->attrib != NULL)
{
attrib = htmlMarkup->attrib;
/* varstore inherits the name and value from attribute. */
flag = VAR_FLAG_DEALLOC_NAME | VAR_FLAG_DEALLOC_VALUE;
if (!attrib->value) {
attrib->value = "";
flag &= ~VAR_FLAG_DEALLOC_VALUE;
}
if (StoreVariable(&varstore, attrib->name, attrib->value,
VAR_TYPE_SET_MACRO,
flag | VAR_FLAG_DEALLOC_NAME | VAR_FLAG_DEALLOC_VALUE,
NULL, NULL) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile,
"unable to add variable to context for include file");
CloseStream(&incfile);
DestroyVariableStore(&varstore);
return MARKUP_ERROR;
}
if (attrib->whitespace)
FreeMemory(attrib->whitespace);
/* unlink attrib */
htmlMarkup->attrib = attrib->next;
FreeMemory(attrib);
}
/* push this onto the context and use it for the include file */
PushVariableStoreContext(task->varstore, &varstore);
topVarstore = &varstore;
}
else
{
topVarstore = task->varstore;
}
/* build a new task structure */
newTask.infile = &incfile;
newTask.outfile = task->outfile;
newTask.varstore = topVarstore;
newTask.sourceFilename = task->sourceFilename;
/* informational message for the user */
HtpMsg(MSG_INFO, task->infile, "including file \"%s\"", fullPathname);
/* process the new input file */
result = ProcessTask(&newTask);
if (!result) {
/* Error message was already spitted out. However, we
* should give a hint where the meta-tag was called.
*/
HtpMsg(MSG_ERROR, task->infile, "... in file included here");
}
/* pop the local context */
if(topVarstore == &varstore)
{
assert(topVarstore->child == NULL);
PopVariableStoreContext(topVarstore);
DestroyVariableStore(&varstore);
}
CloseStream(&incfile);
/* if the new file did not process, return an error, otherwise discard */
/* the markup */
return (result == TRUE) ? DISCARD_MARKUP : MARKUP_ERROR;
}
uint FileProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
HTML_ATTRIBUTE *attrib;
BOOL result;
if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, "EXECUTE")) != NULL)
{
result = FileExecuteProcessor(task, attrib, htmlMarkup);
DestroyAttribute(attrib);
FreeMemory(attrib);
}
else if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, "TEMPLATE")) != NULL)
{
result = FileTemplateProcessor(task, attrib);
DestroyAttribute(attrib);
FreeMemory(attrib);
}
else if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, "INCLUDE")) != NULL)
{
result = FileIncludeProcessor(task, attrib->value, htmlMarkup);
DestroyAttribute(attrib);
FreeMemory(attrib);
}
else if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, "SEARCH")) != NULL)
{
/* set the include search path to what was specified */
if(attrib->value != NULL)
{
StringCopy(searchPath, attrib->value, SEARCH_PATH_SIZE);
}
else
{
/* search path is cleared */
searchPath[0] = NUL;
}
result = DISCARD_MARKUP;
DestroyAttribute(attrib);
FreeMemory(attrib);
}
else if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, "NAME")) != NULL)
{
/* if a NAME attribute is found, and it contains a value, use
* the ExternalFileProcessor to create the plaintext (this
* function only reports output file's time, date, name)
*/
if (attrib->value != NULL)
{
result = ExternalFileProcessor(task, htmlMarkup, attrib->value,
newPlaintext);
}
else
{
/* should be repleaced by output file name */
*newPlaintext = DuplicateString(task->outfile->name);
HtpMsg(MSG_INFO, task->outfile, "adding output filename");
result = NEW_MARKUP;
}
DestroyAttribute(attrib);
FreeMemory(attrib);
}
else
{
/* Invoke ExternalFileProcessor on current input file, to
* handle TIME, DATE attributes
*/
result = ExternalFileProcessor(task, htmlMarkup,
task->sourceFilename, newPlaintext);
}
if (result != MARKUP_ERROR && htmlMarkup->attrib != NULL)
{
HtpMsg(MSG_WARNING, task->infile,
"Unhandled %s attribute in %s markup",
htmlMarkup->attrib->name, htmlMarkup->tag);
}
/* the new plaintext has been created */
return result;
}
uint OutputProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
STREAM outputfile;
HTML_ATTRIBUTE *attrib;
BOOL append, expand, result;
UNREF_PARAM(newPlaintext);
/* get the filename to include */
if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, "FILE")) == NULL)
{
HtpMsg(MSG_ERROR, task->infile, "output filename not specified");
return MARKUP_ERROR;
}
append = UnlinkBoolAttributeInMarkup(htmlMarkup, "APPEND");
expand = UnlinkBoolAttributeInMarkup(htmlMarkup, "EXPAND");
if (htmlMarkup->attrib != NULL) {
HtpMsg(MSG_WARNING, task->infile,
"Unhandled %s attribute in %s markup",
htmlMarkup->attrib->name, htmlMarkup->tag);
}
/* open the output file */
if(CreateFileWriter(&outputfile, attrib->value, append) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile,
"unable to open output file \"%s\"", attrib->value);
return MARKUP_ERROR;
}
DestroyAttribute(attrib);
FreeMemory(attrib);
result = ReadBlockToFile(task, expand, htmlMarkup->tag, &outputfile);
FreeMemory((char *) outputfile.name);
CloseStream(&outputfile);
return result == FALSE ? MARKUP_ERROR : DISCARD_MARKUP;
}
htp-1.16/src/gif.c 0000644 0000510 0000310 00000003023 10665777571 013620 0 ustar hoenicke fb10-sem /*
//
// gif.c
//
// GIF (Graphic Interchange Format) support functions
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "htp.h"
BOOL GifFormatFound(FILE *file)
{
BYTE header[8];
/* move to BOF */
if(fseek(file, 0, SEEK_SET) != 0)
{
DEBUG_PRINT(("unable to seek to start of GIF file"));
return FALSE;
}
/* read first six bytes, looking for GIF header + version info */
if(fread(header, 1, 6, file) != 6)
{
DEBUG_PRINT(("could not read GIF image file header"));
return FALSE;
}
/* is this a GIF file? */
if((memcmp(header, "GIF87a", 6) == 0) || (memcmp(header, "GIF89a", 6) == 0))
{
return TRUE;
}
/* not a GIF file */
return FALSE;
}
BOOL GifReadDimensions(FILE *file, DWORD *height, DWORD *width)
{
BYTE buff[4];
/* move to the image size position in the file header */
if(fseek(file, 6, SEEK_SET) != 0)
{
DEBUG_PRINT(("unable to seek to start of GIF file"));
return FALSE;
}
/* read width and height into a byte array */
if(fread(buff, 1, 4, file) != 4)
{
DEBUG_PRINT(("unable to read word from JFIF file"));
return FALSE;
}
/* this gets around machine endian problems while retaining the */
/* fact that GIF uses little-endian notation */
*width = MAKE_WORD(buff[1], buff[0]);
*height = MAKE_WORD(buff[3], buff[2]);
return TRUE;
}
htp-1.16/src/html.c 0000600 0000510 0000310 00000037236 10665777571 014024 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// html.c
//
// HTML markup tag functions
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "htp.h"
const char *FindWhitespace(const char *str)
{
assert(str != NULL);
while(*str != NUL)
{
if(isspace(*str))
{
break;
}
str++;
}
return str;
}
const char *FindNonWhitespace(const char *str)
{
assert(str != NULL);
while(*str != NUL)
{
if(!isspace(*str))
{
break;
}
str++;
}
return str;
}
/*
// HTML_ATTRIBUTE functions
*/
static BOOL MakeAttribute(HTML_ATTRIBUTE *htmlAttribute, const char *name,
const char *value, int quotes)
{
assert(htmlAttribute != NULL);
assert(name != NULL);
/* create a duplicate of the string for the attribute structure */
if((htmlAttribute->name = DuplicateString(name)) == NULL)
{
return FALSE;
}
/* do the same for the value, if it exists */
if(value != NULL)
{
if((htmlAttribute->value = DuplicateString(value)) == NULL)
{
FreeMemory(htmlAttribute->name);
htmlAttribute->name = NULL;
return FALSE;
}
}
else
{
htmlAttribute->value = NULL;
}
/* keep track if this was a quoted value */
htmlAttribute->quotes = quotes;
htmlAttribute->whitespace = NULL;
return TRUE;
}
BOOL ChangeAttributeName(HTML_ATTRIBUTE *htmlAttribute, char *name)
{
assert(htmlAttribute != NULL);
/* although name should never be null, let it slide */
if(htmlAttribute->name != NULL)
{
FreeMemory(htmlAttribute->name);
htmlAttribute->name = NULL;
}
htmlAttribute->name = name;
return TRUE;
}
BOOL ChangeAttributeValue(HTML_ATTRIBUTE *htmlAttribute, char *value,
int quotes)
{
assert(htmlAttribute != NULL);
/* free the value's memory, if previously defined */
if(htmlAttribute->value != NULL)
{
FreeMemory(htmlAttribute->value);
htmlAttribute->value = NULL;
}
htmlAttribute->value = value;
htmlAttribute->quotes = quotes;
return TRUE;
}
void DestroyAttribute(HTML_ATTRIBUTE *htmlAttribute)
{
assert(htmlAttribute != NULL);
/* the attribute should always have a name */
assert(htmlAttribute->name != NULL);
FreeMemory(htmlAttribute->name);
htmlAttribute->name = NULL;
if(htmlAttribute->value != NULL)
{
FreeMemory(htmlAttribute->value);
htmlAttribute->value = NULL;
}
if (htmlAttribute->whitespace != NULL)
{
FreeMemory(htmlAttribute->whitespace);
htmlAttribute->whitespace = NULL;
}
}
/*
// HTML_MARKUP functions
*/
/*
this is perhaps the ugliest piece of code in the entire program ... it
is also one of the most critical. (Surprise.)
Allan Todd provided a very important fix: htp 1.0 and before would
crash and burn if it hit a large comment. This was problematic for
JavaScript and VBScript, which embed the interpreted code in comments
to prevent other browsers from gagging. Allans solution is simply
to pack the entire comment into one attribute.
*/
BOOL PlaintextToMarkup(const char *plaintext, HTML_MARKUP *htmlMarkup)
{
const char *plainPtr, *start;
HTML_ATTRIBUTE **attribLink, *attrib;
assert(plaintext != NULL);
assert(htmlMarkup != NULL);
/* although this isnt a good thing, its not something to halt execution over */
if(plaintext[0] == NUL)
{
DEBUG_PRINT(("no plaintext to convert"));
return FALSE;
}
plainPtr = plaintext;
/* initialize the markup structure */
htmlMarkup->tag = NULL;
htmlMarkup->single = FALSE;
htmlMarkup->attrib = NULL;
attribLink = &htmlMarkup->attrib;
/* walk the markup and build tag and attribute list (re-using the markup */
/* argument to walk the copied string) */
/* walk past any initial whitespace */
plainPtr = FindNonWhitespace(plainPtr);
if(*plainPtr == NUL)
{
return TRUE;
}
/* mark first token as the tag */
start = plainPtr;
/* walk to the first whitespace, mark it as NUL, and this is the tag */
plainPtr = FindWhitespace(plainPtr);
/* copy the markup tag into the structure */
if((htmlMarkup->tag = DuplicateSubString(start, plainPtr - start)) == NULL)
{
DEBUG_PRINT(("unable to duplicate markup token"));
return FALSE;
}
/* save and skip whitespace */
start = plainPtr;
plainPtr = FindNonWhitespace(plainPtr);
htmlMarkup->whitespace = DuplicateSubString(start, plainPtr - start);
/* if a comment or php code, throw the whole she-bang into the attribute */
if (!strncmp(htmlMarkup->tag, "!--", 3)
|| htmlMarkup->tag[0] == '?')
{
if (*plainPtr == 0)
return TRUE;
*attribLink = attrib = AllocMemory(sizeof(HTML_ATTRIBUTE));
if(attrib == NULL)
{
DEBUG_PRINT(("unable to add attribute to markup"));
DestroyMarkupStruct(htmlMarkup);
return FALSE;
}
attrib->name = DuplicateString(plainPtr);
attrib->value = NULL;
attrib->whitespace = NULL;
attrib->quotes = QUOTES_NONE;
attrib->next = NULL;
return TRUE;
}
/* start walking the rest of markup, looking for attributes and their */
/* values */
while(*plainPtr != NUL)
{
/* real attribute ore xml-closing? */
if (strcmp(plainPtr, "/") == 0) {
htmlMarkup->single = TRUE;
break;
}
*attribLink = attrib = AllocMemory(sizeof(HTML_ATTRIBUTE));
if(attrib == NULL)
{
DEBUG_PRINT(("unable to add attribute to markup"));
DestroyMarkupStruct(htmlMarkup);
return FALSE;
}
/* walk through the attribute, looking for whitespace or an */
/* equal sign */
start = plainPtr;
while(*plainPtr != NUL
&& *plainPtr != '='
&& !isspace(*plainPtr))
{
plainPtr++;
}
attrib->name = DuplicateSubString(start, plainPtr - start);
attrib->value = NULL;
attrib->quotes = QUOTES_NONE;
attrib->next = NULL;
attrib->whitespace = NULL;
attribLink = &attrib->next;
if(*plainPtr == '=')
{
plainPtr++;
if(*plainPtr == '\"' || *plainPtr == '\'')
{
/* quoted value, search for end quote */
char quote = *plainPtr;
attrib->quotes = quote == '\"' ? QUOTES_DOUBLE: QUOTES_SINGLE;
plainPtr++;
start = plainPtr;
while(*plainPtr != quote)
{
/* ReadHtml already checked that there is
* a matching quote, but the quotes may
* have appeared at a unchecked place before.
*/
if (*plainPtr == NUL) {
DEBUG_PRINT(("can't find matching quote in markup"));
DestroyMarkupStruct(htmlMarkup);
return FALSE;
}
plainPtr++;
}
attrib->value = DuplicateSubString(start, plainPtr - start);
plainPtr++;
}
else
{
start = plainPtr;
plainPtr = FindWhitespace(plainPtr);
attrib->value = DuplicateSubString(start, plainPtr - start);
}
}
/* skip past whitespace (looking for next value)
*/
start = plainPtr;
plainPtr = FindNonWhitespace(plainPtr);
attrib->whitespace = DuplicateSubString(start, plainPtr - start);
}
return TRUE;
}
BOOL AddAttributeToMarkup(HTML_MARKUP *htmlMarkup, const char *name,
const char *value, int quotedValue)
{
HTML_ATTRIBUTE **attribPtr, *attrib;
assert(htmlMarkup != NULL);
assert(name != NULL);
attrib = AllocMemory(sizeof(HTML_ATTRIBUTE));
if(attrib == NULL)
{
DEBUG_PRINT(("unable to create attribute structure"));
return FALSE;
}
if (!MakeAttribute(attrib, name, value, quotedValue))
{
FreeMemory(attrib);
DEBUG_PRINT(("unable to make attribute"));
return FALSE;
}
attribPtr = &htmlMarkup->attrib;
while (*attribPtr != NULL) {
attribPtr = &(*attribPtr)->next;
}
*attribPtr = attrib;
attrib->next = NULL;
return TRUE;
}
void DestroyMarkupStruct(HTML_MARKUP *htmlMarkup)
{
HTML_ATTRIBUTE *attrib, *next;
assert(htmlMarkup != NULL);
/* destroy the tag */
/* do not assert against this, as this function might be used to */
/* destroy a partially-built structure */
if(htmlMarkup->tag != NULL)
{
FreeMemory(htmlMarkup->tag);
htmlMarkup->tag = NULL;
}
attrib = htmlMarkup->attrib;
htmlMarkup->attrib = NULL;
if (htmlMarkup->whitespace != NULL)
{
FreeMemory(htmlMarkup->whitespace);
htmlMarkup->whitespace = NULL;
}
/* destroy all markup attributes */
while (attrib != NULL) {
next = attrib->next;
DestroyAttribute(attrib);
FreeMemory(attrib);
attrib = next;
}
}
BOOL IsMarkupTag(HTML_MARKUP *htmlMarkup, const char *tag)
{
assert(htmlMarkup != NULL);
assert(tag != NULL);
return (stricmp(htmlMarkup->tag, tag) == 0) ? TRUE : FALSE;
}
BOOL MarkupToPlaintext(HTML_MARKUP *htmlMarkup, char **plaintext)
{
HTML_ATTRIBUTE *htmlAttribute;
uint size;
uint attrSize;
uint maxAttrSize;
uint wslen;
char *buffer, *bufferPtr;
assert(htmlMarkup != NULL);
assert(htmlMarkup->tag != NULL);
assert(plaintext != NULL);
/* estimate the required size of the plaintext buffer */
maxAttrSize = 0;
/* compute length of separating space char */
wslen = htmlMarkup->whitespace != NULL ?
strlen(htmlMarkup->whitespace) : 0;
/* force whitespace if more attributes follow */
if (wslen == 0 && (htmlMarkup->attrib || htmlMarkup->single))
wslen = 1;
/* additional byte is to account for NUL */
size = strlen(htmlMarkup->tag) + wslen + 1;
htmlAttribute = htmlMarkup->attrib;
while (htmlAttribute != NULL) {
char *quotes = "";
assert(htmlAttribute != NULL);
assert(htmlAttribute->name != NULL);
/* compute length of separating space char */
wslen = htmlAttribute->whitespace != NULL ?
strlen(htmlAttribute->whitespace) : 0;
/* Force whitespace if more attributes follow */
if (wslen == 0
&& (htmlAttribute->next || htmlMarkup->single))
wslen = 1;
attrSize = strlen(htmlAttribute->name) + wslen;
switch (htmlAttribute->quotes)
{
case QUOTES_DOUBLE:
quotes= "\"";
break;
case QUOTES_SINGLE:
quotes= "\'";
break;
}
if(htmlAttribute->value != NULL)
{
/* additional byte added to account for equal sign */
attrSize += strlen(htmlAttribute->value) + 1;
/* account for the quote characters */
attrSize += 2 * strlen(quotes);
}
/* additional byte added for NULL character */
attrSize++;
size += attrSize;
if(maxAttrSize < attrSize)
{
maxAttrSize = attrSize;
}
htmlAttribute = htmlAttribute->next;
}
if (htmlMarkup->single) {
size ++;
}
if((buffer = AllocMemory(size)) == NULL)
{
DEBUG_PRINT(("unable to allocate plaintext buffer (%u bytes)", size));
return FALSE;
}
/* start copying in the markup as plaintext */
bufferPtr = stpcpy(buffer, htmlMarkup->tag);
if (htmlMarkup->whitespace == NULL
|| htmlMarkup->whitespace[0] == 0) {
/* Force whitespace if more attributes follow */
if (htmlMarkup->attrib || htmlMarkup->single)
bufferPtr = stpcpy(bufferPtr, " ");
} else {
bufferPtr = stpcpy(bufferPtr, htmlMarkup->whitespace);
}
htmlAttribute = htmlMarkup->attrib;
while (htmlAttribute != NULL)
{
char *quotes = "";
/* checked previously, but check again */
assert(htmlAttribute != NULL);
assert(htmlAttribute->name != NULL);
switch (htmlAttribute->quotes)
{
case QUOTES_DOUBLE:
quotes= "\"";
break;
case QUOTES_SINGLE:
quotes= "\'";
break;
}
bufferPtr = stpcpy(bufferPtr, htmlAttribute->name);
if (htmlAttribute->value != NULL)
{
bufferPtr = stpcpy(bufferPtr, "=");
bufferPtr = stpcpy(bufferPtr, quotes);
bufferPtr = stpcpy(bufferPtr, htmlAttribute->value);
bufferPtr = stpcpy(bufferPtr, quotes);
}
if (htmlAttribute->whitespace == NULL
|| htmlAttribute->whitespace[0] == 0) {
/* Force whitespace if more attributes follow */
if (htmlAttribute->next || htmlMarkup->single)
bufferPtr = stpcpy(bufferPtr, " ");
} else {
bufferPtr = stpcpy(bufferPtr, htmlAttribute->whitespace);
}
htmlAttribute = htmlAttribute->next;
}
if ((htmlMarkup->single) == TRUE) {
bufferPtr = stpcpy(bufferPtr,"/");
}
/* give the buffer to caller */
*plaintext = buffer;
return TRUE;
}
HTML_ATTRIBUTE **FindMarkupAttribute(HTML_MARKUP *htmlMarkup, const char *name)
{
HTML_ATTRIBUTE **attribPtr;
assert(htmlMarkup != NULL);
assert(name != NULL);
attribPtr = &htmlMarkup->attrib;
while (*attribPtr != NULL) {
if (stricmp((*attribPtr)->name, name) == 0)
return attribPtr;
attribPtr = &(*attribPtr)->next;
}
return NULL;
}
const char *MarkupAttributeValue(HTML_MARKUP *htmlMarkup, const char *name)
{
HTML_ATTRIBUTE **attribPtr;
assert(htmlMarkup != NULL);
if((attribPtr = FindMarkupAttribute(htmlMarkup, name)) == NULL)
{
return NULL;
}
/* check validity of attribute */
assert ((*attribPtr)->name != NULL);
return (*attribPtr)->value;
}
BOOL ChangeMarkupTag(HTML_MARKUP *htmlMarkup, char *tag)
{
assert(htmlMarkup != NULL);
assert(tag != NULL);
if(htmlMarkup->tag != NULL)
{
FreeMemory(htmlMarkup->tag);
}
htmlMarkup->tag = tag;
return TRUE;
}
HTML_ATTRIBUTE *UnlinkAttributeInMarkup(HTML_MARKUP *htmlMarkup,
const char *name)
{
HTML_ATTRIBUTE **attribPtr, *attrib;
assert(htmlMarkup != NULL);
if((attribPtr = FindMarkupAttribute(htmlMarkup, name)) == NULL)
{
return NULL;
}
attrib = *attribPtr;
*attribPtr = attrib->next;
attrib->next = NULL;
return attrib;
}
BOOL UnlinkBoolAttributeInMarkup(HTML_MARKUP *htmlMarkup, const char *name)
{
HTML_ATTRIBUTE **attribPtr, *attrib;
assert(htmlMarkup != NULL);
if((attribPtr = FindMarkupAttribute(htmlMarkup, name)) == NULL)
{
return FALSE;
}
attrib = *attribPtr;
/* If it has a value it is not a bool attribute */
if (attrib->value != NULL)
return FALSE;
*attribPtr = attrib->next;
attrib->next = NULL;
FreeMemory(attrib->name);
if (attrib->whitespace)
FreeMemory(attrib->whitespace);
FreeMemory(attrib);
return TRUE;
}
htp-1.16/src/htp-files.c 0000600 0000510 0000310 00000034701 10665777571 014745 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// htp-files.c
//
// htp specific file access
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "defs.h"
#include "option.h"
#include "streams.h"
#include "bool-proc.h"
#include "snprintf.h"
/*
// 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;
}
/* convert the dependency and target filenames for this filesystem */
if((dependName = ConvertDirDelimiter(dependency)) == NULL)
{
return ERROR;
}
if((targetName = ConvertDirDelimiter(target)) == NULL)
{
FreeMemory(dependName);
return ERROR;
}
/* get information on the dependency file */
if(stat(dependName, &dependStat) != 0)
{
/* dependency file needs to exist */
FreeMemory(dependName);
FreeMemory(targetName);
return ERROR;
}
/* get information on the target file */
if(stat(targetName, &targetStat) != 0)
{
/* target file does not exist, dependency needs to be updated */
FreeMemory(dependName);
FreeMemory(targetName);
return FALSE;
}
FreeMemory(dependName);
FreeMemory(targetName);
/* compare modification times to determine if up-to-date */
return (dependStat.st_mtime <= targetStat.st_mtime) ? TRUE : FALSE;
}
/*
// searches for the specified file in the search path ... this function is
// very stupid, it simply gets the first directory in the search string,
// appends the file directly to the end, and tests for existance. Repeat.
*/
BOOL SearchForFile(const char *filename, char *fullPathname, uint size)
{
char *searchPathCopy;
char *ptr;
char *convertedName;
FIND_TOKEN findToken;
/* quick check for search path even being defined */
if(searchPath[0] == NUL)
{
return FALSE;
}
/* need to make a copy of the search path for String...Token() to butcher up */
if((searchPathCopy = DuplicateString(searchPath)) == NULL)
{
printf("%s: unable to allocate temporary buffer for include path (out of memory?)\n",
PROGRAM_NAME);
return FALSE;
}
/* look for ';' delimiter */
ptr = StringFirstToken(&findToken, searchPathCopy, ";");
while(ptr != NULL)
{
StringCopy(fullPathname, ptr, size);
/* if the last character is not a directory delimiter, add it */
if(strchr(ALL_FILESYSTEM_DELIMITERS, fullPathname[strlen(fullPathname) - 1]) == NULL)
{
strncat(fullPathname, DIR_DELIMITER_STRING, size);
}
/* append the file name */
strncat(fullPathname, filename, size);
/* need to do a complete conversion of delimiters in the filename, but */
/* ConvertDirDelimiter() returns a AllocMemory()'d copy of the string ... */
convertedName = ConvertDirDelimiter(fullPathname);
/* check for existance */
if(FileExists(convertedName) == TRUE)
{
/* clean up and get outta here */
StringCopy(fullPathname, convertedName, size);
FreeMemory(searchPathCopy);
FreeMemory(convertedName);
return TRUE;
}
FreeMemory(convertedName);
convertedName = NULL;
ptr = StringNextToken(&findToken);
}
/* clean up */
FreeMemory(searchPathCopy);
return FALSE;
}
static char *markupBuffer = NULL;
static uint markupSize = 0;
static void FreeMarkupBuffer(void) {
FreeMemory(markupBuffer);
markupBuffer = NULL;
}
/*
// TRUE = plaintext is filled with new plain text markup, FALSE if end of file,
// ERROR if a problem
// !! Don't like using ERROR in any BOOL return values
*/
BOOL ReadHtmlMarkup(STREAM *infile, STREAM *outfile,
uint *markupType, HTML_MARKUP *htmlMarkup)
{
char ch;
uint ctr;
char inQuotes;
uint startLine;
uint numread;
char open_markup[3];
char tag_specials[3];
open_markup[0] = HTML_OPEN_MARKUP;
open_markup[1] = htpOpenMarkup;
open_markup[2] = htpOpenMarkup;
tag_specials[1] = '\"';
tag_specials[2] = '\'';
#if 0
memset(open_markup, 0, sizeof(open_markup));
BITMAP_SET(open_markup, HTML_OPEN_MARKUP);
BITMAP_SET(open_markup, htpOpenMarkup);
memset(tag_specials, 0, sizeof(tag_specials));
BITMAP_SET(tag_specials, HTML_CLOSE_MARKUP);
BITMAP_SET(tag_specials, htpCloseMarkup);
BITMAP_SET(tag_specials, '\"');
BITMAP_SET(tag_specials, '\'');
#endif
assert(infile != NULL);
/* if outfile is NULL, then the input stream is just being walked and */
/* not parsed for output ... i.e., don't assert outfile != NULL */
/* allocate some space for markup plaintext ... this will dynamically */
/* expand if necessary, and has to be freed by the caller */
if(markupBuffer == NULL)
{
if ((markupBuffer = AllocMemory(MIN_PLAINTEXT_SIZE)) == NULL)
{
HtpMsg(MSG_ERROR, NULL,
"unable to allocate memory to read HTML file");
return ERROR;
}
/* track the markupBuffer size */
markupSize = MIN_PLAINTEXT_SIZE;
atexit(FreeMarkupBuffer);
}
for (;;)
{
numread = GetStreamBlock(infile, markupBuffer,
markupSize, open_markup);
if (numread == 0)
{
/*EOF*/
/* no markup found, end of file */
return FALSE;
}
if (IS_OPEN_MARKUP(markupBuffer[numread-1]))
{
/* get the type of markup for caller */
*markupType = MarkupType(markupBuffer[numread-1]);
if (numread > 1 && outfile != NULL) {
/* there is normal text, just copy it to the output file */
markupBuffer[numread-1] = NUL;
StreamPrintF(outfile, "%s", markupBuffer);
}
break;
}
/* no open markup found in 2KB. Print the full block and
* continue.
*/
if (outfile != NULL)
StreamPrintF(outfile, "%s", markupBuffer);
}
/* copy the markup into the markupBuffer */
ctr = 0;
inQuotes = NUL;
startLine = infile->lineNumber;
tag_specials[0] = MARKUP_CLOSE_DELIM(*markupType);
for(;;)
{
numread = GetStreamBlock(infile, markupBuffer + ctr,
markupSize - ctr, tag_specials);
if (numread == 0)
{
/* EOF ... this is not acceptable before the markup is */
/* terminated */
infile->lineNumber = startLine;
HtpMsg(MSG_ERROR, infile,
"markup tag is never closed", startLine);
return ERROR;
}
ctr += numread;
ch = markupBuffer[ctr - 1];
if ((IS_CLOSE_MARKUP(ch))
&& (MarkupType(ch) == *markupType))
{
/* Check whether this end tag closes the tag. We need
* special checks for PHP-tags and comment tags
*/
if (strncmp(markupBuffer, "!--", 3) == 0
/* comment tag: check for -- */
? strncmp(markupBuffer+ctr-3, "--", 2) == 0
/* PHP tag: check for ? */
: markupBuffer[0] == '?' ? markupBuffer[ctr-2] == '?'
/* normal tag: check for matching quotes */
: inQuotes == NUL)
{
/* end of markup, terminate string and exit */
markupBuffer[ctr - 1] = NUL;
break;
}
}
/* track quotation marks ... can only close markup when */
/* all quotes have been closed */
if(inQuotes)
{
if (ch == inQuotes)
inQuotes = NUL;
}
else if (ch == '\'' || ch == '\"')
{
inQuotes = ch;
}
/* check for overflow ... resize markupBuffer if necessary */
if(ctr >= markupSize - 1)
{
char *newmarkupBuffer =
ResizeMemory(markupBuffer, markupSize + PLAINTEXT_GROW_SIZE);
if(newmarkupBuffer == NULL)
{
/* unable to enlarge markupBuffer area */
HtpMsg(MSG_ERROR, NULL,
"unable to reallocate memory for reading HTML file");
return ERROR;
}
markupBuffer = newmarkupBuffer;
markupSize += PLAINTEXT_GROW_SIZE;
}
}
if(PlaintextToMarkup(markupBuffer, htmlMarkup) == FALSE)
{
HtpMsg(MSG_ERROR, infile,
"could not parse markup tag (out of memory?)");
return ERROR;
}
return TRUE;
}
BOOL FullyCheckDependencies(const char *in, const char *out)
{
BOOL result;
STREAM infile;
char title[128];
HTML_MARKUP markup;
const char *includeFile;
const char *imageFile;
BOOL readResult;
BOOL checkResult;
uint markupType;
assert(in != NULL);
assert(out != NULL);
if(DEPEND == FALSE)
{
/* outta here */
return FALSE;
}
/* check if target file is completely up to date compared to input file */
result = IsTargetUpdated(in, out);
if(result == ERROR)
{
printf("%s: unable to get file information for file \"%s\"\n",
PROGRAM_NAME, in);
return ERROR;
}
else if(result == FALSE)
{
/* target is not updated */
return FALSE;
}
/* because target is up to date, need to search dependency file for */
/* FILE INCLUDE tags and check those files likewise */
/* open file */
snprintf(title, 128, "Dependency check for %s", in);
if (CreateFileReader(&infile, in) == FALSE)
{
printf("%s: unable to open file \"%s\" for reading while checking dependencies\n",
PROGRAM_NAME, in);
return ERROR;
}
infile.name = title;
/* assume everything is hunky-dory unless otherwise discovered */
checkResult = TRUE;
/* get the next markup tag from the input file */
while((readResult = ReadHtmlMarkup(&infile, NULL,
&markupType, &markup)) != FALSE)
{
if(readResult == ERROR)
{
/* error occurred processing the HTML file */
checkResult = ERROR;
break;
}
/* check markup type ... only interested in htp markups currently */
if((markupType & MARKUP_TYPE_HTP) == 0)
{
DestroyMarkupStruct(&markup);
continue;
}
/* if FILE INCLUDE markup, get the filename specified */
includeFile = NULL;
imageFile = NULL;
if(IsMarkupTag(&markup, "FILE"))
{
if(MarkupAttributeValue(&markup, "EXECUTE") != NULL)
{
/* If we find an execute tag, we can't be sure that it
* is up to date */
result = FALSE;
DestroyMarkupStruct(&markup);
break;
}
includeFile = MarkupAttributeValue(&markup, "INCLUDE");
if (includeFile == NULL)
{
includeFile = MarkupAttributeValue(&markup, "TEMPLATE");
}
}
else if(IsMarkupTag(&markup, "IMG"))
{
imageFile = MarkupAttributeValue(&markup, "SRC");
}
else if(IsMarkupTag(&markup, "OPT"))
{
if(UnlinkBoolAttributeInMarkup(&markup, "NODEPEND"))
{
/* !! dependency checking disabled in source file ... since this */
/* can swing back and forth throughout the files, and its just */
/* a pain to track what is technically the last one set, */
/* if one is found, dependency checking is disabled and the */
/* targets are not considered updated */
/* this could be fixed with some work */
checkResult = FALSE;
DestroyMarkupStruct(&markup);
break;
}
}
/* by default assume everything is up to date unless more information */
/* is available through other files */
result = TRUE;
/* check include or image file timestamps */
if(includeFile != NULL)
{
/* !! the accursed recursion strikes again */
/* check the dependencies based on this new file */
result = FullyCheckDependencies(includeFile, out);
}
else if(imageFile != NULL)
{
/* check the image files timestamp as part of dependency checking */
if(FileExists(imageFile))
{
result = IsTargetUpdated(imageFile, out);
}
}
/* unneeded now */
DestroyMarkupStruct(&markup);
if(result != TRUE)
{
/* if FALSE, not up to date, no need to go further */
/* if ERROR, need to stop and report to caller */
checkResult = result;
break;
}
/* otherwise, TRUE indicates that everything is okay, */
/* so keep searching */
}
/* EOF encountered in the HTML input file ... target is updated */
CloseStream(&infile);
return checkResult;
}
htp-1.16/src/image-proc.c 0000600 0000510 0000310 00000014634 10665777571 015100 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// image-proc.c
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "defs.h"
#include "option.h"
#include "snprintf.h"
/*
// specialized markup processors
*/
uint ImageProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
char str[32];
IMAGEFILE imageFile;
DWORD width, height;
const char *imgSource;
const char *imgFilename;
const char *imgText;
char altFilename[MAX_FILENAME_LEN+8];
UNREF_PARAM(newPlaintext);
/* parse down the image source to just the filename */
imgSource = MarkupAttributeValue(htmlMarkup, "SRC");
if(imgSource == NULL)
{
HtpMsg(MSG_WARNING, task->infile, "image SRC not specified, skipping");
return MARKUP_OKAY;
}
/* try to find ALT text in store */
/* first: is there already ALT attribute? if so, skip this step */
if(MarkupAttributeValue(htmlMarkup, "ALT") == NULL)
{
/* parse the image name, just find the filename */
imgFilename = FindFilename(imgSource);
strcpy(altFilename, "_htpalt_");
StringCopy(altFilename + 8, imgFilename, MAX_FILENAME_LEN);
/* add the specified text to the image */
imgText = GetVariableValue(task->varstore, altFilename);
if (imgText != NULL) {
AddAttributeToMarkup (htmlMarkup, "alt", imgText, QUOTES_DOUBLE);
HtpMsg(MSG_INFO, task->infile, "ALT text \"%s\" added to IMG \"%s\"",
imgText, imgSource);
}
}
/* if option is turned off, then just include the markup as-is */
if(IMGXY == FALSE)
{
return MARKUP_OKAY;
}
/* if width and/or height are already specified, then include the */
/* markup as-is with no modifications */
if (MarkupAttributeValue(htmlMarkup, "HEIGHT") != NULL
|| MarkupAttributeValue(htmlMarkup, "WIDTH") != NULL)
{
return MARKUP_OKAY;
}
/* open the image file, get its dimensions, and close the file */
if(OpenImageFile(imgSource, &imageFile) == FALSE)
{
HtpMsg(MSG_WARNING, task->infile, "unable to open image file \"%s\"",
imgSource);
return MARKUP_OKAY;
}
if(GetImageDimensions(&imageFile, &width, &height) == FALSE)
{
HtpMsg(MSG_WARNING, task->infile, "unable to determine image file \"%s\" dimensions",
imgSource);
}
else
{
/* add the width and height specifier for the image */
snprintf(str, 32, "%lu", width);
AddAttributeToMarkup(htmlMarkup, "width", str, QUOTES_DOUBLE);
snprintf(str, 32, "%lu", height);
AddAttributeToMarkup(htmlMarkup, "height", str, QUOTES_DOUBLE);
/* print out an informational message to the user */
HtpMsg(MSG_INFO, task->outfile, "image file \"%s\" dimensions (%u x %u) added",
imgSource, width, height);
}
CloseImageFile(&imageFile);
/* include the markup in the final output */
return MARKUP_OKAY;
}
uint AltTextProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
const char *imgName, *imgText;
char *altNameCopy, *imgTextCopy;
char altName[MAX_FILENAME_LEN+8];
UNREF_PARAM(newPlaintext);
/* get the relevant information */
imgName = MarkupAttributeValue(htmlMarkup, "NAME");
/* requires at least a NAME parameter */
if (imgName == NULL)
{
HtpMsg(MSG_ERROR, task->infile,
"ALTTEXT requires a nonempty NAME attribute");
return MARKUP_ERROR;
}
imgText = MarkupAttributeValue(htmlMarkup, "TEXT");
strcpy(altName, "_htpalt_");
StringCopy(altName + 8, imgName, MAX_FILENAME_LEN);
/* if no name specified, delete it from the store */
if(imgText == NULL)
{
/* try to find the graphic name in the ALTTEXT store */
if (RemoveVariable(task->varstore, altName) == TRUE)
{
HtpMsg(MSG_INFO, task->infile, "ALT text for image \"%s\" removed",
imgName);
} else {
/* tried to delete an image not already in the store */
/* just post a warning */
HtpMsg(MSG_WARNING, task->infile,
"attempted to delete image text not already defined");
}
return DISCARD_MARKUP;
}
if ((altNameCopy = DuplicateString(altName)) == NULL
|| (imgTextCopy = DuplicateString(imgText)) == NULL) {
HtpMsg(MSG_ERROR, task->infile,
"Can't duplicate text, out of Memory.");
if (altNameCopy != NULL)
FreeMemory(altNameCopy);
return MARKUP_ERROR;
}
StoreVariable(task->varstore, altNameCopy, imgTextCopy,
VAR_TYPE_ALTTEXT,
VAR_FLAG_DEALLOC_NAME | VAR_FLAG_DEALLOC_VALUE,
NULL, NULL);
HtpMsg(MSG_INFO, task->infile, "ALT text for image \"%s\" set to \"%s\"",
imgName, imgText);
return DISCARD_MARKUP;
}
uint ImageUrlProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
const char *url, *path;
char *pathCopy;
UNREF_PARAM(newPlaintext);
/* get the relevant information */
url = MarkupAttributeValue(htmlMarkup, "URL");
/* requires at least a NAME parameter */
if (url == NULL)
{
HtpMsg(MSG_ERROR, task->infile,
"IMAGEURL requires a nonempty URL attribute");
return MARKUP_ERROR;
}
path = MarkupAttributeValue(htmlMarkup, "PATH");
/* if no name specified, delete it from the store */
if (path == NULL)
{
if (RemoveImageUrl(url)) {
HtpMsg(MSG_INFO, task->infile, "path for image URL \"%s\" removed",
url);
} else {
/* tried to delete an image not already in the store */
/* just post a warning */
HtpMsg(MSG_WARNING, task->infile,
"attempted to delete URL path not already defined");
}
return DISCARD_MARKUP;
}
if ((pathCopy = ConvertDirDelimiter(path)) == NULL) {
HtpMsg(MSG_ERROR, task->infile,
"Can't duplicate path, out of Memory.");
return MARKUP_ERROR;
}
StoreImageUrl(url, pathCopy);
HtpMsg(MSG_INFO, task->infile, "path for URL \"%s\" set to \"%s\"",
url, path);
return DISCARD_MARKUP;
}
htp-1.16/src/image.c 0000644 0000510 0000310 00000012527 10665777571 014146 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// image.c
//
// Image file functions
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "htp.h"
#include "gif.h"
#include "jpeg.h"
#include "png.h"
typedef struct tagIMAGEURL
{
char *url;
char *path;
struct tagIMAGEURL *next;
} IMAGEURL;
static IMAGEURL* imageurl_store = NULL;
IMAGEURL *FindImageUrl (const char *url) {
IMAGEURL* urls;
urls = imageurl_store;
while (urls != NULL) {
if (stricmp(url, urls->url) == 0) {
return urls;
}
urls = urls->next;
}
return NULL;
}
BOOL ExistsImageUrl (const char *url)
{
return (FindImageUrl != NULL);
}
BOOL StoreImageUrl (const char *url, char* path) {
IMAGEURL* urls;
DEBUG_PRINT(("Storing image URL (%s,%s)...",url, path));
urls = FindImageUrl(url);
if (urls == NULL) {
if((urls = AllocMemory(sizeof(IMAGEURL))) == NULL)
{
DEBUG_PRINT(("unable to allocate memory for new image URL"));
return FALSE;
}
if((urls->url = DuplicateString(url)) == NULL)
{
FreeMemory(urls);
DEBUG_PRINT(("unable to allocate memory for new URL"));
return FALSE;
}
urls->next = imageurl_store;
imageurl_store = urls;
} else {
FreeMemory(urls->path);
}
urls->path = path;
return TRUE;
}
BOOL RemoveImageUrl (const char *url) {
IMAGEURL *urls, **prev;
prev = &imageurl_store;
urls = imageurl_store;
while (urls != NULL) {
if (stricmp(url, urls->url) == 0) {
break;
}
prev = &urls->next;
urls = urls->next;
}
if (urls == NULL) {
DEBUG_PRINT(("unable to find image URL for remove"));
return FALSE;
}
*prev = urls->next;
FreeMemory(urls->url);
FreeMemory(urls->path);
FreeMemory(urls);
return TRUE;
}
char *GetPathFor (IMAGEURL *imageurl, const char *src) {
uint urlsize, srcsize, pathsize, suffixsize, length;
char *filename, *suffix;
DEBUG_PRINT(("GetPathFor (%s,%s) %s",imageurl->url,imageurl->path,src));
urlsize = strlen(imageurl->url);
srcsize = strlen(src);
if (srcsize < urlsize) {
return NULL;
}
if (strnicmp(imageurl->url,src,urlsize) != 0) {
return NULL;
}
pathsize = strlen(imageurl->path);
suffix = ConvertDirDelimiter(src + urlsize);
suffixsize = strlen(suffix);
length = pathsize + suffixsize ;
if ((filename = AllocMemory(length+1)) == NULL) {
DEBUG_PRINT(("unable to allocate memory for filename in GetPathFor"));
return NULL;
}
StringCopy(filename, imageurl->path, pathsize + 1);
StringCopy(filename + pathsize, suffix, suffixsize +1);
filename[length] = NUL;
FreeMemory(suffix);
return filename;
}
typedef struct {
BOOL (*checkFormat) (FILE * file);
BOOL (*readDimensions) (FILE * file, DWORD *height, DWORD *width);
} ImageOps;
ImageOps ops[] = {
{ GifFormatFound , GifReadDimensions },
{ JpegFormatFound, JpegReadDimensions },
{ PngFormatFound , PngReadDimensions }
};
#define IMAGE_TYPE_COUNT (sizeof(ops) / sizeof(ImageOps))
#define IMAGE_TYPE_UNKNOWN IMAGE_TYPE_COUNT
BOOL OpenImageFile(const char *filename, IMAGEFILE *imageFile)
{
uint type;
IMAGEURL* imageurl;
assert(filename != NULL);
assert(imageFile != NULL);
imageFile->name = NULL;
DEBUG_PRINT(("trying imageurls..."));
imageurl = imageurl_store;
while (imageurl) {
DEBUG_PRINT(("trying imageurl %s for %s",imageurl->url,filename));
if ((imageFile->name = GetPathFor(imageurl, filename))) {
break;
}
imageurl = imageurl->next;
}
if (imageFile->name == NULL) {
if ((imageFile->name = ConvertDirDelimiter(filename)) == NULL)
{
DEBUG_PRINT(("could not duplicate filename string"));
return FALSE;
}
}
imageFile->file = fopen(imageFile->name, "rb");
if (imageFile->file == NULL) {
DEBUG_PRINT(("could not open image file %s", imageFile->name));
FreeMemory(imageFile->name);
return FALSE;
}
/* build the rest of the image file structure */
/* by default, unknown image type */
for (type = 0; type < IMAGE_TYPE_COUNT; type++) {
if (ops[type].checkFormat(imageFile->file))
break;
}
/* If type is unknown, the variable type is already
* IMAGE_TYPE_COUNT == IMAGE_TYPE_UNKNOWN.
*/
imageFile->imageType = type;
return TRUE;
}
void CloseImageFile(IMAGEFILE *imageFile)
{
assert(imageFile != NULL);
assert(imageFile->name != NULL);
assert(imageFile->file != NULL);
FreeMemory(imageFile->name);
fclose(imageFile->file);
imageFile->name = NULL;
imageFile->file = NULL;
}
BOOL GetImageDimensions(IMAGEFILE *imageFile, DWORD *width, DWORD *height)
{
assert(imageFile != NULL);
assert(width != NULL);
assert(height != NULL);
/* unknown file type */
if(imageFile->imageType == IMAGE_TYPE_UNKNOWN)
return FALSE;
return ops[imageFile->imageType].readDimensions(imageFile->file,
height, width);
}
htp-1.16/src/jpeg.c 0000644 0000510 0000310 00000012744 10665777571 014012 0 ustar hoenicke fb10-sem /*
//
// jpeg.c
//
// JPEG FIF (File Interchange Format) support functions
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "htp.h"
/*
// a great deal of this code was ripped off wholesale from the Independent
// JPEG Group's sample source code, obtainable from any SimTel mirror under
// msdos/graphics/jpegsrc6.zip
*/
/*
// JPEG markers
*/
#define M_SOF0 0xC0 /* Start Of Frame N */
#define M_SOF1 0xC1 /* N indicates which compression process */
#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
#define M_SOF3 0xC3
#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
#define M_SOF6 0xC6
#define M_SOF7 0xC7
#define M_SOF9 0xC9
#define M_SOF10 0xCA
#define M_SOF11 0xCB
#define M_SOF13 0xCD
#define M_SOF14 0xCE
#define M_SOF15 0xCF
#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */
#define M_EOI 0xD9 /* End Of Image (end of datastream) */
#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
#define M_APP0 0xE0
#define M_COM 0xFE /* COMment */
BOOL JpegReadByte(FILE *file, BYTE *b)
{
int i;
if((i = fgetc(file)) == EOF)
return FALSE;
*b = (BYTE) i;
return TRUE;
}
BOOL JpegFirstMarker(FILE *file)
{
BYTE flag;
BYTE marker;
/* move to the beginning of the file */
if(fseek(file, 0, SEEK_SET) != 0)
{
HtpMsg(MSG_WARNING, NULL, "unable to seek to start of JFIF file");
return FALSE;
}
/* look for the start of image marker */
if(JpegReadByte(file, &flag) == FALSE)
{
return FALSE;
}
if(JpegReadByte(file, &marker) == FALSE)
{
return FALSE;
}
/* start of image? */
if((flag != 0xFF) || (marker != M_SOI))
{
return FALSE;
}
return TRUE;
}
BOOL JpegNextMarker(FILE *file, BYTE *marker, WORD *size)
{
BYTE flag;
BYTE buff[2];
int bytesread = 0;
/* move file pointer to next 0xFF flag */
do {
if (JpegReadByte(file, &flag) == FALSE)
return FALSE;
bytesread++;
} while (flag != 0xFF);
/* extra 0xFF flags are legal as padding, so move past them */
while (flag == 0xFF) {
if (JpegReadByte(file, &flag) == FALSE)
return FALSE;
bytesread++;
}
*marker = flag;
if (bytesread > 2) {
HtpMsg(MSG_WARNING, NULL,
"Skipped %d bytes of garbage in JFIF file", bytesread - 2);
}
if(fread(buff, 1, 2, file) != 2)
{
return FALSE;
}
*size = MAKE_WORD(buff[0], buff[1]);
/* exit condition really depends if a good marker was found */
return TRUE;
}
BOOL JpegFormatFound(FILE *file)
{
BYTE marker;
WORD size;
char signature[8];
if(JpegFirstMarker(file) == FALSE)
{
return FALSE;
}
if(JpegNextMarker(file, &marker, &size) == FALSE)
{
return FALSE;
}
/* should see an APP0 marker */
if(marker != M_APP0)
{
return FALSE;
}
/* file format is now pointing to JFIF header */
/* look for the signature */
if(fread(signature, 1, 5, file) != 5)
{
HtpMsg(MSG_WARNING, NULL, "unable to read JFIF signature from file");
return FALSE;
}
/* it all comes down to the signature being present */
return (strcmp(signature, "JFIF") == 0) ? TRUE : FALSE;
}
BOOL JpegReadDimensions(FILE *file, DWORD *height, DWORD *width)
{
BYTE marker, buff[5];
WORD size;
/* make sure we can find the first marker */
if(JpegFirstMarker(file) == FALSE)
{
return FALSE;
}
/* read file looking for SOF (start of frame) ... when it or */
/* or SOS (start of scan, the compressed data) is reached, stop */
while(JpegNextMarker(file, &marker, &size) == TRUE)
{
/* if SOS, stop */
if(marker == M_SOS)
{
HtpMsg(MSG_WARNING, NULL, "JFIF SOS marker found before SOF marker");
break;
}
/* if not SOF, continue */
switch (marker) {
case M_SOF0: /* Baseline */
case M_SOF1: /* Extended sequential, Huffman */
case M_SOF2: /* Progressive, Huffman */
case M_SOF3: /* Lossless, Huffman */
case M_SOF5: /* Differential sequential, Huffman */
case M_SOF6: /* Differential progressive, Huffman */
case M_SOF7: /* Differential lossless, Huffman */
case M_SOF9: /* Extended sequential, arithmetic */
case M_SOF10: /* Progressive, arithmetic */
case M_SOF11: /* Lossless, arithmetic */
case M_SOF13: /* Differential sequential, arithmetic */
case M_SOF14: /* Differential progressive, arithmetic */
case M_SOF15: /* Differential lossless, arithmetic */
/* start of frame found ... process the dimension information */
/* read the height and width and get outta here */
if(fread(buff, 1, 5, file) != 5)
{
HtpMsg(MSG_WARNING, NULL,
"unable to read dimensions from JFIF file");
return FALSE;
}
/* words are kept in MSB format */
*height = MAKE_WORD(buff[1], buff[2]);
*width = MAKE_WORD(buff[3], buff[4]);
return TRUE;
default:
if (fseek (file, size-2, SEEK_CUR) != 0)
{
HtpMsg(MSG_WARNING, NULL, "unable to seek past JFIF block");
return FALSE;
}
}
}
HtpMsg(MSG_WARNING, NULL, ("JFIF SOF marker not found"));
/* didn't find the SOF or found the SOS */
return FALSE;
}
htp-1.16/src/macro.c 0000600 0000510 0000310 00000054305 10665777571 014155 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// macro.c
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "macro.h"
#include "defs.h"
#include "def-proc.h"
/*
// specialized markup processors
*/
#include "option.h"
#include "image-proc.h"
#include "file-proc.h"
#include "def-proc.h"
#include "use-proc.h"
#include "set-proc.h"
#include "bool-proc.h"
#include "misc-proc.h"
#include "while-proc.h"
static MARKUP_PROCESSORS markupProcessor[] =
{
{ "IMG", MARKUP_TYPE_HTML, ImageProcessor },
{ "OPT", MARKUP_TYPE_HTP, OptionProcessor },
{ "FILE", MARKUP_TYPE_HTP, FileProcessor },
{ "INC", MARKUP_TYPE_HTP, IncProcessor },
{ "SET", MARKUP_TYPE_HTP, SetProcessor },
{ "BLOCK", MARKUP_TYPE_HTP, BlockProcessor },
{ "BLOCKDEF", MARKUP_TYPE_HTP, BlockProcessor },
{ "USE", MARKUP_TYPE_HTP, UseProcessor },
{ "IF", MARKUP_TYPE_HTP, BooleanProcessor },
{ "/IF", MARKUP_TYPE_HTP, BooleanProcessor },
{ "IFNOT", MARKUP_TYPE_HTP, ConditionalWarning },
{ "ELSE", MARKUP_TYPE_HTP, BooleanProcessor },
{ "ELSEIF", MARKUP_TYPE_HTP, BooleanProcessor },
{ "/HEAD", MARKUP_TYPE_HTML, HeadProcessor },
{ "UNSET", MARKUP_TYPE_HTP, UnsetProcessor },
{ "PRE", MARKUP_TYPE_HTML, PreProcessor },
{ "/PRE", MARKUP_TYPE_HTML, PreProcessor },
{ "ALTTEXT", MARKUP_TYPE_HTP, AltTextProcessor },
{ "DEF", MARKUP_TYPE_HTP, BlockProcessor },
{ "OUTPUT", MARKUP_TYPE_HTP, OutputProcessor },
{ "UNDEF", MARKUP_TYPE_HTP, UndefProcessor },
{ "WHILE", MARKUP_TYPE_HTP, WhileProcessor },
{ "/WHILE", MARKUP_TYPE_HTP, WhileProcessor },
{ "!---", MARKUP_TYPE_HTP, HtpCommentProcessor },
{ "QUOTE", MARKUP_TYPE_HTP, QuoteProcessor },
{ "IMAGEURL", MARKUP_TYPE_HTP, ImageUrlProcessor }
};
#define MARKUP_PROCESSOR_COUNT (sizeof(markupProcessor)/sizeof(markupProcessor[0]))
/*
// HTML processing
*/
static BOOL FindMatchingBrace(TASK *task, const char **text)
{
const char *textPtr;
int braceLevel;
textPtr = *text;
DEBUG_PRINT(("FindMatchingBrace on %s", textPtr));
assert (*textPtr == '{');
textPtr++;
braceLevel = 0;
while (TRUE) {
switch(*textPtr) {
case NUL:
HtpMsg(MSG_ERROR, task->infile, "ending brace not found in macro name");
return FALSE;
case '}':
if (!braceLevel) {
*text = textPtr + 1;
return TRUE;
}
braceLevel--;
break;
case '{':
braceLevel++;
break;
}
textPtr++;
}
}
BOOL ExpandMacrosInString(TASK *task, const char *text, char **newText,
int *quotes, BOOL *changed)
{
const char *expansion;
char *macro, *newMacro;
const char *textPtr;
uint expansionLength;
uint skipped;
uint textLength;
int singletonMacro, dummy;
BOOL macroChanged, destAlloced;
char *destText;
uint destTextSize;
uint copiedSoFar;
assert(task != NULL);
assert(text != NULL);
assert(newText != NULL);
assert(quotes != NULL);
assert(changed != NULL);
textLength = strlen(text);
destText = (char *) text;
destTextSize = textLength + 1;
destAlloced = FALSE;
*changed = FALSE;
*newText = destText;
/* assume singletonMacro until we find some other text */
singletonMacro = 1;
/* loop repeatedly to evaluate the string until no more macros are found */
while ((textPtr = strchr(text, '$')) != NULL)
{
/* Copy skipped text to destText */
if (textPtr > text) {
int len = textPtr - text;
if (destAlloced) {
memcpy(destText, text, len);
}
singletonMacro = 0;
text += len;
textLength -= len;
destText += len;
}
/* skip the '$' */
text++;
textLength--;
/* process the macro */
/* find the end of the macro name and let textPtr point to it. */
/* macro specified with braces? */
if(*text == '{')
{
textPtr = text;
if (! FindMatchingBrace(task, &textPtr)) {
if (destAlloced) {
FreeMemory(*newText);
}
*newText = NULL;
return FALSE;
}
macro = DuplicateSubString(text + 1, textPtr - text - 2);
}
else if (isalnum(*text) || *text == '_' || *text == '-')
{
/* start of macro, no braces, copy until first non
* alphanumeric (including '_' and '-') character.
*/
textPtr = text+1;
while (isalnum(*textPtr) || *textPtr == '_' || *textPtr == '-')
textPtr++;
macro = DuplicateSubString(text, textPtr - text);
}
else
{
/* macro-name consisting of a single control character.
*/
int len = ((*text == NUL) ? 0 : 1);
textPtr = text + len;
macro = DuplicateSubString(text, len);
}
/* skip macro name */
skipped = textPtr - text;
text = textPtr;
textLength -= skipped;
if (strcmp(macro, "$") == 0)
{
/* special case, expand $$ to $. */
expansion = "$";
expansionLength = 1;
}
else
{
uint type;
/* Recursivly expand macro */
if (!ExpandMacrosInString(task, macro, &newMacro,
&dummy, ¯oChanged)) {
FreeMemory(macro);
if (destAlloced) {
FreeMemory(*newText);
}
*newText = NULL;
return FALSE;
}
if (macroChanged) {
FreeMemory(macro);
macro = newMacro;
}
/* make sure variable exists in store */
if(VariableExists(task->varstore, macro) != TRUE)
{
HtpMsg(MSG_ERROR, task->infile,
"unrecognized macro name \"%s\"", macro);
FreeMemory(macro);
if (destAlloced) {
FreeMemory(*newText);
}
*newText = NULL;
return FALSE;
}
type = GetVariableType(task->varstore, macro);
/* block macros need a special expand routine */
if (type == VAR_TYPE_BLOCK_MACRO)
{
STREAM *blockFile =
(STREAM*) GetVariableValue(task->varstore, macro);
assert(blockFile->sflags == STREAM_FLAG_BUFFER);
expansion = blockFile->u.buffer.buffer;
expansionLength = blockFile->u.buffer.offset;
}
else if (type == VAR_TYPE_SET_MACRO)
{
/* get the macros value and replace the attribute value */
expansion = GetVariableValue(task->varstore, macro);
if (expansion == NULL)
expansion = "";
expansionLength = strlen(expansion);
}
else
{
if (destAlloced) {
FreeMemory(*newText);
}
*newText = NULL;
HtpMsg(MSG_ERROR, task->infile,
"macro \"%s\" is a meta-tag", macro);
FreeMemory(macro);
return FALSE;
}
HtpMsg(MSG_INFO, task->infile, "expanding macro \"%s\" to \"%s\"",
macro, expansion);
}
FreeMemory(macro);
destTextSize += expansionLength - skipped - 1;
if (expansionLength > skipped || !destAlloced) {
copiedSoFar = destText - *newText;
destText = AllocMemory(destTextSize);
if (destText == NULL) {
if (destAlloced) {
FreeMemory(*newText);
}
*newText = NULL;
HtpMsg(MSG_ERROR, task->infile, "Out of memory");
return FALSE;
}
memcpy(destText, *newText, copiedSoFar);
if (destAlloced) {
FreeMemory(*newText);
}
*newText = destText;
destText += copiedSoFar;
destAlloced = TRUE;
}
/* Macro did not change, copy it directly */
memcpy(destText, expansion, expansionLength);
destText += expansionLength;
/* increment the change count */
*changed = TRUE;
if (singletonMacro && !textLength) {
/* since the macro is the entire value, no harm (and */
/* more robust) to surround it by quotes */
*quotes = QUOTES_DOUBLE;
*destText = 0;
return TRUE;
}
/* need to go back and re-evaluate the value for more macros */
}
if (destAlloced) {
memcpy(destText, text, textLength);
destText += textLength;
*destText = 0;
}
return TRUE;
}
BOOL ExpandMacros(TASK *task, HTML_MARKUP *htmlMarkup)
{
HTML_ATTRIBUTE *attrib;
char *newName, *newValue, *newTag;
int quotes;
BOOL changed;
assert(task != NULL);
assert(htmlMarkup != NULL);
/* expand any macros in the tags */
if(htmlMarkup->tag != NULL)
{
if(ExpandMacrosInString(task, htmlMarkup->tag, &newTag,
"es, &changed) != TRUE)
{
return FALSE;
}
if(changed)
{
ChangeMarkupTag(htmlMarkup, newTag);
}
}
if (stricmp(htmlMarkup->tag, "WHILE") == 0
|| stricmp(htmlMarkup->tag, "!---") == 0) {
return TRUE;
}
/* do the same for all attributes, both name and value */
attrib = htmlMarkup->attrib;
while (attrib != NULL)
{
if(attrib->name != NULL)
{
if (!ExpandMacrosInString(task, attrib->name, &newName,
"es, &changed))
{
return FALSE;
}
if(changed)
{
ChangeAttributeName(attrib, newName);
}
}
if(attrib->value != NULL)
{
quotes = attrib->quotes;
if (!ExpandMacrosInString(task, attrib->value, &newValue,
"es, &changed))
{
return FALSE;
}
if(changed)
{
ChangeAttributeValue(attrib, newValue, quotes);
}
}
attrib = attrib->next;
}
return TRUE;
}
uint ExpandMetatag(TASK *task, HTML_MARKUP *htmlMarkup)
{
const char *options;
char *optionCopy;
FIND_TOKEN findToken;
char *optionPtr;
HTML_ATTRIBUTE *attrib;
VARSTORE defVarstore;
uint flag;
char *value;
const char *defName;
STREAM *blockStream;
STREAM *defStream;
STREAM defFile;
TASK newTask;
BOOL result;
BOOL hasWildcard;
uint macroType;
/* first things first: find the tag in the metatag store */
if(VariableExists(task->varstore, htmlMarkup->tag) == FALSE)
{
/* don't change a thing */
return MARKUP_OKAY;
}
/* verify the macro in the store is a metatag definition */
macroType = GetVariableType(task->varstore, htmlMarkup->tag);
if(macroType != VAR_TYPE_DEF_MACRO
&& macroType != VAR_TYPE_BLOCKDEF_MACRO)
{
return MARKUP_OKAY;
}
/* get a pointer to the name */
defName = htmlMarkup->tag;
/* get the filename the DEF macro is held in */
if ((defStream = (STREAM *) GetVariableValue(task->varstore, defName))
== NULL)
{
/* this shouldnt be */
HtpMsg(MSG_ERROR, task->infile,
"DEF macro \"%s\" was not store properly", defName);
return MARKUP_ERROR;
}
/* get options to compare against markups paramater list */
options = GetVariableParam(task->varstore, defName);
/* initialize a local variable store, even if its not used */
InitializeVariableStore(&defVarstore);
/* if NULL, then no options allowed */
if (options != NULL) {
/* options should be space-delimited, use StringToken() */
if((optionCopy = DuplicateString(options)) == NULL)
{
HtpMsg(MSG_ERROR, task->infile, "Unable to duplicate option macro (out of memory?)");
DestroyVariableStore(&defVarstore);
return MARKUP_ERROR;
}
hasWildcard = FALSE;
/* build array of pointers to null-terminated option */
optionPtr = StringFirstToken(&findToken, optionCopy, " ");
while (optionPtr != NULL)
{
/* ignore multiple spaces */
if (*optionPtr == NUL)
continue;
if (strcmp(optionPtr, "*") == 0)
{
hasWildcard = TRUE;
}
else if ((attrib = UnlinkAttributeInMarkup(htmlMarkup,
optionPtr)) != NULL)
{
/* since this is a good attribute, add it to the
* local store
*/
flag = VAR_FLAG_DEALLOC_NAME | VAR_FLAG_DEALLOC_VALUE;
value = attrib->value;
if (value == NULL) {
value = "";
flag &= ~VAR_FLAG_DEALLOC_VALUE;
}
if(StoreVariable(&defVarstore, attrib->name, attrib->value,
VAR_TYPE_SET_MACRO,
flag, NULL, NULL) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile,
"Unable to store local macro for metatag");
DestroyVariableStore(&defVarstore);
DestroyAttribute(attrib);
FreeMemory(attrib);
FreeMemory(optionCopy);
return MARKUP_ERROR;
}
if (attrib->whitespace)
FreeMemory(attrib->whitespace);
FreeMemory(attrib);
}
else
{
char *name = DuplicateString(optionPtr);
/* This option is undefined. Add an explicit
* undefined value to hide variables with same
* name in outer scope.
*/
if (StoreVariable(&defVarstore, name, NULL,
VAR_TYPE_UNKNOWN,
VAR_FLAG_DEALLOC_NAME
| VAR_FLAG_UNDEFINED,
NULL, NULL) == FALSE) {
HtpMsg(MSG_ERROR, task->infile,
"Unable to store local macro for metatag");
DestroyVariableStore(&defVarstore);
FreeMemory(name);
FreeMemory(optionCopy);
return MARKUP_ERROR;
}
}
optionPtr = StringNextToken(&findToken);
}
FreeMemory(optionCopy);
if (hasWildcard)
{
uint wildcardLength = 0;
char *wildcards;
/* get length of wildcard parameter */
attrib = htmlMarkup->attrib;
while (attrib != NULL)
{
wildcardLength +=
strlen(attrib->name) + strlen(attrib->value) + 2;
if (attrib->quotes)
wildcardLength += 2;
attrib = attrib->next;
}
if (wildcardLength > 0) {
/* Build the wildcard string. */
char *ptr;
wildcards = AllocMemory(wildcardLength);
ptr = wildcards;
while ((attrib = htmlMarkup->attrib) != NULL) {
ptr = stpcpy(ptr, attrib->name);
*ptr++ = '=';
if (attrib->quotes == QUOTES_DOUBLE)
*ptr++ = '"';
else if (attrib->quotes == QUOTES_SINGLE)
*ptr++ = '\'';
ptr = stpcpy(ptr, attrib->value);
if (attrib->quotes == QUOTES_DOUBLE)
*ptr++ = '"';
else if (attrib->quotes == QUOTES_SINGLE)
*ptr++ = '\'';
*ptr++ = ' ';
htmlMarkup->attrib = attrib->next;
DestroyAttribute(attrib);
FreeMemory(attrib);
}
/* Replace last space with NUL to terminate wildcards */
*(ptr-1) = 0;
flag = VAR_FLAG_DEALLOC_VALUE;
} else {
wildcards = "";
flag = VAR_FLAG_NONE;
}
if(StoreVariable(&defVarstore, "*", wildcards,
VAR_TYPE_SET_MACRO, flag,
NULL, NULL) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile,
"Unable to store local macro for metatag");
DestroyVariableStore(&defVarstore);
if ((flag & VAR_FLAG_DEALLOC_VALUE))
FreeMemory(wildcards);
return MARKUP_ERROR;
}
}
}
/* If this is a BLOCKDEF macro expand the trailing block into */
/* the macro named block */
if (macroType == VAR_TYPE_BLOCKDEF_MACRO)
{
blockStream = (STREAM*) AllocMemory(sizeof(STREAM));
if (!ReadinBlock(task, htmlMarkup, blockStream))
{
DestroyVariableStore(&defVarstore);
return MARKUP_ERROR;
}
/* store the block file name and the block macro name as a variable */
if(StoreVariable(&defVarstore, "BLOCK", blockStream,
VAR_TYPE_BLOCK_MACRO, VAR_FLAG_NONE,
NULL, BlockDestructor) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile,
"unable to store macro information (out of memory?)");
DestroyVariableStore(&defVarstore);
return MARKUP_ERROR;
}
}
if (htmlMarkup->attrib != NULL) {
HtpMsg(MSG_ERROR, task->infile,
"%s metatag \"%s\" does not accept a parameter named \"%s\"",
macroType == VAR_TYPE_BLOCKDEF_MACRO ? "blockdef" : "def",
defName, htmlMarkup->attrib->name);
DestroyVariableStore(&defVarstore);
return MARKUP_ERROR;
}
/* expand the DEF macro like a block macro ... */
/* open the file the macro is held in */
if(CreateBufferReader(&defFile, defStream) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile,
"unable to open block for %s metatag \"%s\"",
macroType == VAR_TYPE_BLOCKDEF_MACRO ? "blockdef" : "def",
defName);
DestroyVariableStore(&defVarstore);
return MARKUP_ERROR;
}
HtpMsg(MSG_INFO, task->infile, "dereferencing %s metatag \"%s\"",
macroType == VAR_TYPE_BLOCKDEF_MACRO ? "blockdef" : "def",
defName);
/* build a new task structure */
newTask.infile = &defFile;
newTask.outfile = task->outfile;
newTask.sourceFilename = task->sourceFilename;
if (options != NULL || macroType == VAR_TYPE_BLOCKDEF_MACRO) {
/* Put in the defVarstore */
PushVariableStoreContext(task->varstore, &defVarstore);
newTask.varstore = &defVarstore;
} else {
newTask.varstore = task->varstore;
}
/* process the new input file */
result = ProcessTask(&newTask);
/* remove the new context if necessary */
if(newTask.varstore == &defVarstore)
{
assert(defVarstore.child == NULL);
PopVariableStoreContext(&defVarstore);
}
/* no matter what, destroy the local store */
DestroyVariableStore(&defVarstore);
CloseStream(&defFile);
if (!result) {
/* Error message was already spitted out. However, we should
* give a hint where the meta-tag was called.
*/
HtpMsg(MSG_ERROR, task->infile,
"... in metatag \"%s\"", defName);
return MARKUP_ERROR;
}
return DISCARD_MARKUP;
}
uint ExpandAll(TASK *task, HTML_MARKUP *htmlMarkup,
char** newPlaintextPtr, uint markupType)
{
uint ctr;
uint markupResult;
if(ExpandMacros(task, htmlMarkup) == FALSE)
{
/* problem encountered trying to expand macros */
return MARKUP_ERROR;
}
/* give the metatag processor a chance to expand metatags */
/* this is a little strange, but if MARKUP_OKAY it means the the */
/* metatag processor didnt recognize the tag, and therefore should */
/* be handled by the other processors */
if((markupResult = ExpandMetatag(task, htmlMarkup)) == MARKUP_OKAY)
{
/* find the first processor that wants to do something with the */
/* markup tag */
for(ctr = 0; ctr < MARKUP_PROCESSOR_COUNT; ctr++)
{
if(markupProcessor[ctr].markupType & markupType)
{
if(IsMarkupTag(htmlMarkup, markupProcessor[ctr].tag))
{
assert(markupProcessor[ctr].markupFunc != NULL);
markupResult = markupProcessor[ctr]
.markupFunc(task, htmlMarkup, newPlaintextPtr);
break;
}
}
}
}
/* unless the function requested to use its new markup string, */
/* take the HTML_MARKUP structure and build a new markup */
if((markupResult != NEW_MARKUP) && (markupResult != DISCARD_MARKUP))
{
if(MarkupToPlaintext(htmlMarkup, newPlaintextPtr) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile, "unable to build plain text from markup (out of memory?)");
return MARKUP_ERROR;
}
}
return markupResult;
}
htp-1.16/src/misc-proc.c 0000644 0000510 0000310 00000004616 10665777571 014760 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// misc-proc.c
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "misc-proc.h"
#include "defs.h"
#include "option.h"
uint HeadProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
UNREF_PARAM(htmlMarkup);
UNREF_PARAM(newPlaintext);
/* authors ego-gratifying easter egg */
/* put a generator meta-tag at the end of the HTML header */
StreamPrintF(task->outfile,
"outfile, " />\n");
} else {
StreamPrintF(task->outfile, ">\n");
}
return MARKUP_OKAY;
}
uint HtpCommentProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
UNREF_PARAM(task);
UNREF_PARAM(htmlMarkup);
UNREF_PARAM(newPlaintext);
return DISCARD_MARKUP;
}
uint QuoteProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
HTML_ATTRIBUTE *attrib;
UNREF_PARAM(task);
UNREF_PARAM(newPlaintext);
attrib = htmlMarkup->attrib;
if (attrib == NULL || attrib->value != NULL) {
HtpMsg(MSG_ERROR, task->infile, "improper QUOTE syntax");
return MARKUP_ERROR;
}
FreeMemory(htmlMarkup->tag);
if (htmlMarkup->whitespace)
FreeMemory(htmlMarkup->whitespace);
htmlMarkup->tag = attrib->name;
htmlMarkup->whitespace = attrib->whitespace;
htmlMarkup->attrib = attrib->next;
FreeMemory(attrib);
return MARKUP_OKAY;
}
uint ConditionalWarning(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
UNREF_PARAM(htmlMarkup);
UNREF_PARAM(newPlaintext);
HtpMsg(MSG_ERROR, task->infile, "IFNOT tag no longer recognized; use IF NOT instead");
return MARKUP_ERROR;
}
uint PreProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
UNREF_PARAM(htmlMarkup);
UNREF_PARAM(newPlaintext);
/* inside a
...
the CR's are important */
if(IsMarkupTag(htmlMarkup, "PRE"))
{
ForceLinefeeds(task->outfile, TRUE);
}
else if(IsMarkupTag(htmlMarkup, "/PRE"))
{
ForceLinefeeds(task->outfile, FALSE);
}
return MARKUP_OKAY;
}
htp-1.16/src/msg.c 0000600 0000510 0000310 00000005664 10665777571 013646 0 ustar hoenicke fb10-sem /*
//
// msg.c
//
// Processing messages (informational, warning, and error)
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "htp.h"
#include "option.h"
#include "snprintf.h"
/* symbols used to express severity of message */
const char *severitySymbol[3] =
{
"[-]",
"[*]",
"[!]",
};
void HtpMsg(uint level, STREAM *textFile, const char *format, ...)
{
va_list argptr;
char *str;
/* check severity level */
if(level < GetOptionValue(OPT_I_MESSAGE))
{
return;
}
/* allocate room for string ... 1K should be large enough, but a more */
/* deterministic method would be better */
if((str = AllocMemory(1024)) == NULL)
{
return;
}
/* convert variable arguments into single string */
va_start(argptr, format);
vsnprintf(str, 1024, format, argptr);
va_end(argptr);
/* print the standard message header followed by formatted message */
printf("%s ", severitySymbol[level]);
if(textFile != NULL)
{
printf("%s line %d: ", textFile->name, textFile->lineNumber);
}
printf("%s\n", str);
/* free the string and exit */
FreeMemory(str);
}
#if DEBUG
FILE *debugMsgFile = NULL;
void DebugInit(const char *debugMsgFilename)
{
remove(debugMsgFilename);
debugMsgFile = fopen(debugMsgFilename, "at");
if(debugMsgFile == NULL)
{
printf("htp: unable to open debug file \"%s\", aborting\n",
debugMsgFilename);
exit(1);
}
}
void DebugTerminate(void)
{
if(debugMsgFile != NULL)
{
fclose(debugMsgFile);
debugMsgFile = NULL;
}
}
/*
// DebugMsg
//
// DebugMsg is a helper function to (a) log a formatted string to disk and
// (b) display the same string to the screen. This function is called by
// DEBUG_PRINT, which is normally removed from the code in a final release
// build.
//
// Because this debug information is really most useful when the program
// is coughing up blood, this function will flush contents every time,
// doing whatever it can to get the debug string to disk. Slow, but that's
// what a debug build is for.
//
// Important: this file can't use the abstraction present in textfile.c
// because *that* module uses DEBUG_PRINT as well ... (same for suballoc.c
// functions)
//
*/
void DebugMsg(const char *format, ...)
{
va_list argptr;
char *str;
/* 1K should be enough, but no guarantees */
if((str = malloc(1024)) == NULL)
{
/* !! gaaak */
return;
}
/* convert variable arguments into single string */
va_start(argptr, format);
vsnprintf(str, 1024, format, argptr);
va_end(argptr);
/* write the string to disk */
fprintf(debugMsgFile, "%s", str);
/* flush it out to disk */
fflush(debugMsgFile);
#if 0
/* write it to screen */
printf(str);
#endif
free(str);
}
#endif
htp-1.16/src/option.c 0000644 0000510 0000310 00000010403 10665777571 014363 0 ustar hoenicke fb10-sem /*
//
// option.c
//
// Program options and setting
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "option.h"
#include "msg.h"
static uint globalOptions[OPT_I_COUNT];
static uint localOptions[OPT_I_COUNT];
uint *currentOptions;
/*
//
*/
const char *option_msg_index[] = {
"image pre-processing",
NULL,
"dependency checking",
"precious output",
"condensed output",
NULL,
"markup delimiter",
"use XML-style generator tag",
};
const char *option_msg_value[] = {
"turned OFF",
"turned ON",
"turned to SEMI",
"set to \"<\"",
"set to \"[\"",
"set to \"{\""
};
BOOL SetOption(TASK *task, uint index, uint value)
{
if(task != NULL && option_msg_index[index] != NULL) {
HtpMsg(MSG_INFO, task->infile,
"%s %s", option_msg_index[index], option_msg_value[value]);
}
currentOptions[index] = value;
if (index == OPT_I_DELIM)
{
switch (value)
{
case OPT_V_DELIM_HTML:
htpOpenMarkup = '<';
htpCloseMarkup = '>';
break;
case OPT_V_DELIM_CURLY:
htpOpenMarkup = '{';
htpCloseMarkup = '}';
break;
case OPT_V_DELIM_SQUARE:
htpOpenMarkup = '[';
htpCloseMarkup = ']';
break;
}
}
return TRUE;
}
BOOL InitializeGlobalOption()
{
/* set defaults for all options */
globalOptions[OPT_I_IMGXY] = OPT_V_TRUE;
globalOptions[OPT_I_MESSAGE] = MSG_INFO;
globalOptions[OPT_I_DEPEND] = OPT_V_TRUE;
globalOptions[OPT_I_PRECIOUS] = OPT_V_FALSE;
globalOptions[OPT_I_CONDENSE] = OPT_V_SEMI;
globalOptions[OPT_I_USAGE] = OPT_V_FALSE;
globalOptions[OPT_I_DELIM] = OPT_V_DELIM_HTML;
globalOptions[OPT_I_XML] = OPT_V_FALSE;
currentOptions = globalOptions;
return TRUE;
}
void DestroyGlobalOption(void)
{
}
BOOL InitializeLocalOption(void)
{
memcpy(localOptions, globalOptions, sizeof(globalOptions));
currentOptions = localOptions;
return TRUE;
}
void DestroyLocalOption(void)
{
}
BOOL ParseToken(TASK *task, const char *string)
{
static const struct {
char *name;
uint index, value;
} opt[] = {
{"IMGXY", OPT_I_IMGXY, OPT_V_TRUE},
{"NOIMGXY", OPT_I_IMGXY, OPT_V_FALSE},
{"VERBOSE", OPT_I_MESSAGE, MSG_INFO},
{"QUIET", OPT_I_MESSAGE, MSG_WARNING},
{"DEPEND", OPT_I_DEPEND, OPT_V_TRUE},
{"NODEPEND", OPT_I_DEPEND, OPT_V_FALSE},
{"PRECIOUS", OPT_I_PRECIOUS, OPT_V_TRUE},
{"NOPRECIOUS", OPT_I_PRECIOUS, OPT_V_FALSE},
{"CONDENSE", OPT_I_CONDENSE, OPT_V_TRUE},
{"SEMICONDENSE", OPT_I_CONDENSE, OPT_V_SEMI},
{"NOCONDENSE", OPT_I_CONDENSE, OPT_V_FALSE},
{"DELIM=HTML", OPT_I_DELIM, OPT_V_DELIM_HTML},
{"DELIM=SQUARE", OPT_I_DELIM, OPT_V_DELIM_SQUARE},
{"DELIM=CURLY", OPT_I_DELIM, OPT_V_DELIM_CURLY},
{"XML", OPT_I_XML, OPT_V_TRUE},
{"XML=FALSE", OPT_I_XML, OPT_V_FALSE},
{"?", OPT_I_USAGE, OPT_V_TRUE},
{"H", OPT_I_USAGE, OPT_V_TRUE},
{"-HELP", OPT_I_USAGE, OPT_V_TRUE}
};
int i;
for (i = 0; i < sizeof(opt) / sizeof(opt[0]); i++) {
if (stricmp(opt[i].name, string) == 0)
return SetOption(task, opt[i].index, opt[i].value);
}
/* dont like it, but dont stop processing either */
HtpMsg(MSG_WARNING, task != NULL ? task->infile : NULL,
"unknown option \"%s\" specified", string);
return TRUE;
}
uint OptionProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
char buff[MAX_OPTION_LENGTH];
char *token;
HTML_ATTRIBUTE *attrib;
UNREF_PARAM(newPlaintext);
/* technically, would like to avoid iterating through the HTML_MARKUP */
/* structure for certain (future design) reasons, but really have to */
/* for this to work */
attrib = htmlMarkup->attrib;
while (attrib != NULL)
{
token = attrib->name;
if(attrib->value != NULL)
{
StringCopy(buff, token, sizeof(buff));
strncat(buff, "=", sizeof(buff) - 1);
strncat(buff, attrib->value, sizeof(buff) - 1);
token = buff;
}
if(ParseToken(task, token) == FALSE)
{
return MARKUP_ERROR;
}
attrib = attrib->next;
}
return DISCARD_MARKUP;
}
htp-1.16/src/png.c 0000644 0000510 0000310 00000004200 10665777571 013635 0 ustar hoenicke fb10-sem /*
//
// png.c
//
// PNG (Portable Network Graphics) support functions
//
// By Rev. Bob, 1999 - derived from gif.c by Jim Nelson
//
// gif.c Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "htp.h"
BOOL PngFormatFound(FILE *file)
{
BYTE header[8];
/* move to BOF */
if(fseek(file, 0, SEEK_SET) != 0)
{
DEBUG_PRINT(("unable to seek to start of PNG file"));
return FALSE;
}
/* read first eight bytes, looking for PNG header + version info */
if(fread(header, 1, 8, file) != 8)
{
DEBUG_PRINT(("could not read PNG image file header"));
return FALSE;
}
/* is this a PNG file? */
if(memcmp(header, "\211PNG\r\n\032\n", 8) == 0)
{
if(fseek(file, 12, SEEK_SET) != 0)
{
DEBUG_PRINT(("unable to seek to IHDR block of PNG file"));
return FALSE;
}
if(fread(header, 1, 4, file) != 4)
{
DEBUG_PRINT(("could not read PNG image IHDR signature"));
return FALSE;
}
if(memcmp(header, "IHDR", 4) == 0)
{
/* PNG signature and IHDR block found, must be good */
return TRUE;
}
}
/* not a PNG file */
return FALSE;
}
/* Modify parms here and in png.h - must use 4-byte integers! */
BOOL PngReadDimensions(FILE *file, DWORD *height, DWORD *width)
{
/* PNG uses MSB LSB (B3 B2 B1 B0) notation - most significant first */
BYTE buff[8];
/* move to the image size position (+16) in the file header */
if(fseek(file, 16, SEEK_SET) != 0)
{
DEBUG_PRINT(("unable to seek to start of PNG file"));
return FALSE;
}
/* read the width and height, byte by byte */
/* this gets around machine endian problems while retaining the */
/* fact that PNG uses MSB LSB (big-endian) notation */
if(fread(buff, 1, 8, file) != 8)
{
return FALSE;
}
*width = MAKE_DWORD(buff[0], buff[1], buff[2], buff[3]);
*height = MAKE_DWORD(buff[4], buff[5], buff[6], buff[7]);
return TRUE;
}
htp-1.16/src/set-proc.c 0000600 0000510 0000310 00000012130 10665777571 014576 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// set-proc.c
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "set-proc.h"
#include "defs.h"
#include "snprintf.h"
uint SetProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
char *name;
char *value;
uint flag;
HTML_ATTRIBUTE *attrib;
VARSTORE *varstore;
UNREF_PARAM(newPlaintext);
varstore = task->varstore;
if (UnlinkBoolAttributeInMarkup(htmlMarkup, "GLOBAL")) {
while (!varstore->isGlobal)
varstore = varstore->parent;
}
/* have to declare at least one macro, but more are acceptable */
if(htmlMarkup->attrib == NULL)
{
HtpMsg(MSG_ERROR, task->infile, "incomplete macro declaration");
return MARKUP_ERROR;
}
/* walk the list and add each macro to the variable store */
while ((attrib = htmlMarkup->attrib) != NULL)
{
name = attrib->name;
value = attrib->value;
flag = VAR_FLAG_DEALLOC_NAME | VAR_FLAG_DEALLOC_VALUE;
if (!value) {
value = "";
flag &= ~VAR_FLAG_DEALLOC_VALUE;
}
/* put the new variable into the store */
if(StoreVariable(varstore, name, value,
VAR_TYPE_SET_MACRO,
flag, NULL, NULL) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile,
"unable to store macro \"%s\" (out of memory?)",
name);
return MARKUP_ERROR;
}
HtpMsg(MSG_INFO, task->infile, "macro \"%s\" assigned value \"%s\"",
name, value);
if (attrib->whitespace)
FreeMemory(attrib->whitespace);
/* unlink attrib */
htmlMarkup->attrib = attrib->next;
FreeMemory(attrib);
}
return DISCARD_MARKUP;
}
uint UnsetProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
HTML_ATTRIBUTE *attrib;
uint type;
UNREF_PARAM(newPlaintext);
attrib = htmlMarkup->attrib;
/* need at least one attribute to undef */
if(attrib == NULL)
{
HtpMsg(MSG_ERROR, task->infile, "UNDEF requires at least one name");
return MARKUP_ERROR;
}
/* walk the list of attributes, deleting them as found */
while (attrib != NULL)
{
/* is it in the store? */
type = GetVariableType(task->varstore, attrib->name);
if((type == VAR_TYPE_SET_MACRO) || (type == VAR_TYPE_BLOCK_MACRO))
{
RemoveVariable(task->varstore, attrib->name);
}
else
{
HtpMsg(MSG_ERROR, task->infile, "No macro \"%s\" to unset",
attrib->name);
return MARKUP_ERROR;
}
HtpMsg(MSG_INFO, task->infile, "macro \"%s\" unset", attrib->name);
attrib = attrib->next;
}
return DISCARD_MARKUP;
}
uint IncProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
const char *expansion;
char valueStr[MAX_INC_VALUE_LENGTH];
int value;
HTML_ATTRIBUTE *attrib;
VARSTORE *varstore;
varstore = task->varstore;
if (UnlinkBoolAttributeInMarkup(htmlMarkup, "GLOBAL")) {
while (!varstore->isGlobal)
varstore = varstore->parent;
}
attrib = htmlMarkup->attrib;
while (attrib != NULL)
{
/* make sure variable exists in store */
if(VariableExists(task->varstore, attrib->name) != TRUE)
{
/* only a warning */
HtpMsg(MSG_ERROR, task->infile, "unrecognized macro name \"%s\"",
attrib->name);
return MARKUP_ERROR;
}
/* block macros cannot be increased */
if(GetVariableType(task->varstore, attrib->name) != VAR_TYPE_SET_MACRO)
{
HtpMsg(MSG_ERROR, task->infile,
"\"%s\" is not a set macro.",
attrib->name);
return MARKUP_ERROR;
}
/* get the macro value and replace the attribute value */
expansion = GetVariableValue(varstore, attrib->name);
if(expansion == NULL)
{
HtpMsg(MSG_WARNING, task->infile, "no value for macro \"%s\"",
attrib->name);
return MARKUP_ERROR;
}
value = atoi(expansion);
if (attrib->value != NULL) {
value += atoi(attrib->value);
} else {
value++;
}
snprintf(valueStr, MAX_INC_VALUE_LENGTH, "%i", value);
if(UpdateVariableValue(task->varstore, attrib->name,
DuplicateString(valueStr)) == FALSE) {
HtpMsg(MSG_WARNING, task->infile,
"new value %s for macro \"%s\" could not be stored.",
valueStr, attrib->name);
return MARKUP_ERROR;
}
HtpMsg(MSG_INFO, task->infile, "incrementing macro \"%s\" to %s",
attrib->name, valueStr);
attrib = attrib->next;
}
return DISCARD_MARKUP;
}
htp-1.16/src/snprintf.c 0000644 0000510 0000310 00000057641 10665777571 014735 0 ustar hoenicke fb10-sem /*
* NOTE: If you change this file, please merge it into rsync, samba, etc.
*/
/*
* Copyright Patrick Powell 1995
* This code is based on code written by Patrick Powell (papowell@astart.com)
* It may be used for any purpose as long as this notice remains intact
* on all source code distributions
*/
/**************************************************************
* Original:
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
* A bombproof version of doprnt (dopr) included.
* Sigh. This sort of thing is always nasty do deal with. Note that
* the version here does not include floating point...
*
* snprintf() is used instead of sprintf() as it does limit checks
* for string length. This covers a nasty loophole.
*
* The other functions are there to prevent NULL pointers from
* causing nast effects.
*
* More Recently:
* Brandon Long 9/15/96 for mutt 0.43
* This was ugly. It is still ugly. I opted out of floating point
* numbers, but the formatter understands just about everything
* from the normal C string format, at least as far as I can tell from
* the Solaris 2.5 printf(3S) man page.
*
* Brandon Long 10/22/97 for mutt 0.87.1
* Ok, added some minimal floating point support, which means this
* probably requires libm on most operating systems. Don't yet
* support the exponent (e,E) and sigfig (g,G). Also, fmtint()
* was pretty badly broken, it just wasn't being exercised in ways
* which showed it, so that's been fixed. Also, formated the code
* to mutt conventions, and removed dead code left over from the
* original. Also, there is now a builtin-test, just compile with:
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
* and run snprintf for results.
*
* Thomas Roessler 01/27/98 for mutt 0.89i
* The PGP code was using unsigned hexadecimal formats.
* Unfortunately, unsigned formats simply didn't work.
*
* Michael Elkins 03/05/98 for mutt 0.90.8
* The original code assumed that both snprintf() and vsnprintf() were
* missing. Some systems only have snprintf() but not vsnprintf(), so
* the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
*
* Andrew Tridgell (tridge@samba.org) Oct 1998
* fixed handling of %.0f
* added test for HAVE_LONG_DOUBLE
*
* tridge@samba.org, idra@samba.org, April 2001
* got rid of fcvt code (twas buggy and made testing harder)
* added C99 semantics
*
* date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0
* actually print args for %g and %e
*
* date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0
* Since includes.h isn't included here, VA_COPY has to be defined here. I don't
* see any include file that is guaranteed to be here, so I'm defining it
* locally. Fixes AIX and Solaris builds.
*
* date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13
* put the ifdef for HAVE_VA_COPY in one place rather than in lots of
* functions
*
* date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4
* Fix usage of va_list passed as an arg. Use __va_copy before using it
* when it exists.
*
* date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14
* Fix incorrect zpadlen handling in fmtfp.
* Thanks to Ollie Oldham for spotting it.
* few mods to make it easier to compile the tests.
* addedd the "Ollie" test to the floating point ones.
*
* Martin Pool (mbp@samba.org) April 2003
* Remove NO_CONFIG_H so that the test case can be built within a source
* tree with less trouble.
* Remove unnecessary SAFE_FREE() definition.
*
* Martin Pool (mbp@samba.org) May 2003
* Put in a prototype for dummy_snprintf() to quiet compiler warnings.
*
* Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
* if the C library has some snprintf functions already.
**************************************************************/
/* Change by Jochen Hoenicke, Oct 2003: deautoconfigured :) */
#define HAVE_STRING_H
#define HAVE_CTYPE_H
#define HAVE_STDLIB_H
#ifdef HAVE_SNPRINTF
#define HAVE_VSNPRINTF
#define HAVE_C99_VSNPRINTF
#endif
#ifdef TEST_SNPRINTF /* need math library headers for testing */
/* In test mode, we pretend that this system doesn't have any snprintf
* functions, regardless of what config.h says. */
# undef HAVE_SNPRINTF
# undef HAVE_VSNPRINTF
# undef HAVE_C99_VSNPRINTF
# undef HAVE_ASPRINTF
# undef HAVE_VASPRINTF
# include
#endif /* TEST_SNPRINTF */
#ifdef HAVE_STRING_H
#include
#endif
#ifdef HAVE_STRINGS_H
#include
#endif
#ifdef HAVE_CTYPE_H
#include
#endif
#include
#include
#ifdef HAVE_STDLIB_H
#include
#endif
#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF)
/* only include stdio.h if we are not re-defining snprintf or vsnprintf */
#include
/* make the compiler happy with an empty file */
void dummy_snprintf(void);
void dummy_snprintf(void) {}
#endif /* HAVE_SNPRINTF, etc */
#ifdef HAVE_LONG_DOUBLE
#define LDOUBLE long double
#else
#define LDOUBLE double
#endif
#ifdef HAVE_LONG_LONG
#define LLONG long long
#else
#define LLONG long
#endif
#ifndef VA_COPY
#ifdef HAVE_VA_COPY
#define VA_COPY(dest, src) va_copy(dest, src)
#else
#ifdef HAVE___VA_COPY
#define VA_COPY(dest, src) __va_copy(dest, src)
#else
#define VA_COPY(dest, src) (dest) = (src)
#endif
#endif
/*
* dopr(): poor man's version of doprintf
*/
/* format read states */
#define DP_S_DEFAULT 0
#define DP_S_FLAGS 1
#define DP_S_MIN 2
#define DP_S_DOT 3
#define DP_S_MAX 4
#define DP_S_MOD 5
#define DP_S_CONV 6
#define DP_S_DONE 7
/* format flags - Bits */
#define DP_F_MINUS (1 << 0)
#define DP_F_PLUS (1 << 1)
#define DP_F_SPACE (1 << 2)
#define DP_F_NUM (1 << 3)
#define DP_F_ZERO (1 << 4)
#define DP_F_UP (1 << 5)
#define DP_F_UNSIGNED (1 << 6)
/* Conversion Flags */
#define DP_C_SHORT 1
#define DP_C_LONG 2
#define DP_C_LDOUBLE 3
#define DP_C_LLONG 4
#define char_to_int(p) ((p)- '0')
#ifndef MAX
#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
#endif
/* yes this really must be a ||. Don't muck with this (tridge) */
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
static size_t dopr(char *buffer, size_t maxlen, const char *format,
va_list args_in);
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max);
static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags);
static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags);
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
{
char ch;
LLONG value;
LDOUBLE fvalue;
char *strvalue;
int min;
int max;
int state;
int flags;
int cflags;
size_t currlen;
va_list args;
VA_COPY(args, args_in);
state = DP_S_DEFAULT;
currlen = flags = cflags = min = 0;
max = -1;
ch = *format++;
while (state != DP_S_DONE) {
if (ch == '\0')
state = DP_S_DONE;
switch(state) {
case DP_S_DEFAULT:
if (ch == '%')
state = DP_S_FLAGS;
else
dopr_outch (buffer, &currlen, maxlen, ch);
ch = *format++;
break;
case DP_S_FLAGS:
switch (ch) {
case '-':
flags |= DP_F_MINUS;
ch = *format++;
break;
case '+':
flags |= DP_F_PLUS;
ch = *format++;
break;
case ' ':
flags |= DP_F_SPACE;
ch = *format++;
break;
case '#':
flags |= DP_F_NUM;
ch = *format++;
break;
case '0':
flags |= DP_F_ZERO;
ch = *format++;
break;
default:
state = DP_S_MIN;
break;
}
break;
case DP_S_MIN:
if (isdigit((unsigned char)ch)) {
min = 10*min + char_to_int (ch);
ch = *format++;
} else if (ch == '*') {
min = va_arg (args, int);
ch = *format++;
state = DP_S_DOT;
} else {
state = DP_S_DOT;
}
break;
case DP_S_DOT:
if (ch == '.') {
state = DP_S_MAX;
ch = *format++;
} else {
state = DP_S_MOD;
}
break;
case DP_S_MAX:
if (isdigit((unsigned char)ch)) {
if (max < 0)
max = 0;
max = 10*max + char_to_int (ch);
ch = *format++;
} else if (ch == '*') {
max = va_arg (args, int);
ch = *format++;
state = DP_S_MOD;
} else {
state = DP_S_MOD;
}
break;
case DP_S_MOD:
switch (ch) {
case 'h':
cflags = DP_C_SHORT;
ch = *format++;
break;
case 'l':
cflags = DP_C_LONG;
ch = *format++;
if (ch == 'l') { /* It's a long long */
cflags = DP_C_LLONG;
ch = *format++;
}
break;
case 'L':
cflags = DP_C_LDOUBLE;
ch = *format++;
break;
default:
break;
}
state = DP_S_CONV;
break;
case DP_S_CONV:
switch (ch) {
case 'd':
case 'i':
if (cflags == DP_C_SHORT)
value = va_arg (args, int);
else if (cflags == DP_C_LONG)
value = va_arg (args, long int);
else if (cflags == DP_C_LLONG)
value = va_arg (args, LLONG);
else
value = va_arg (args, int);
fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
break;
case 'o':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (long)va_arg (args, unsigned LLONG);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
break;
case 'u':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (LLONG)va_arg (args, unsigned LLONG);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
break;
case 'X':
flags |= DP_F_UP;
case 'x':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (LLONG)va_arg (args, unsigned LLONG);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
break;
case 'f':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
/* um, floating point? */
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
break;
case 'E':
flags |= DP_F_UP;
case 'e':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
break;
case 'G':
flags |= DP_F_UP;
case 'g':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
break;
case 'c':
dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
break;
case 's':
strvalue = va_arg (args, char *);
if (!strvalue) strvalue = "(NULL)";
if (max == -1) {
max = strlen(strvalue);
}
if (min > 0 && max >= 0 && min > max) max = min;
fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
break;
case 'p':
strvalue = va_arg (args, void *);
fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
break;
case 'n':
if (cflags == DP_C_SHORT) {
short int *num;
num = va_arg (args, short int *);
*num = currlen;
} else if (cflags == DP_C_LONG) {
long int *num;
num = va_arg (args, long int *);
*num = (long int)currlen;
} else if (cflags == DP_C_LLONG) {
LLONG *num;
num = va_arg (args, LLONG *);
*num = (LLONG)currlen;
} else {
int *num;
num = va_arg (args, int *);
*num = currlen;
}
break;
case '%':
dopr_outch (buffer, &currlen, maxlen, ch);
break;
case 'w':
/* not supported yet, treat as next char */
ch = *format++;
break;
default:
/* Unknown, skip */
break;
}
ch = *format++;
state = DP_S_DEFAULT;
flags = cflags = min = 0;
max = -1;
break;
case DP_S_DONE:
break;
default:
/* hmm? */
break; /* some picky compilers need this */
}
}
if (maxlen != 0) {
if (currlen < maxlen - 1)
buffer[currlen] = '\0';
else if (maxlen > 0)
buffer[maxlen - 1] = '\0';
}
return currlen;
}
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max)
{
int padlen, strln; /* amount to pad */
int cnt = 0;
#ifdef DEBUG_SNPRINTF
printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
#endif
if (value == 0) {
value = "";
}
for (strln = 0; value[strln]; ++strln); /* strlen */
padlen = min - strln;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justify */
while ((padlen > 0) && (cnt < max)) {
dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
++cnt;
}
while (*value && (cnt < max)) {
dopr_outch (buffer, currlen, maxlen, *value++);
++cnt;
}
while ((padlen < 0) && (cnt < max)) {
dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
++cnt;
}
}
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags)
{
int signvalue = 0;
unsigned long uvalue;
char convert[20];
int place = 0;
int spadlen = 0; /* amount to space pad */
int zpadlen = 0; /* amount to zero pad */
int caps = 0;
if (max < 0)
max = 0;
uvalue = value;
if(!(flags & DP_F_UNSIGNED)) {
if( value < 0 ) {
signvalue = '-';
uvalue = -value;
} else {
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
signvalue = '+';
else if (flags & DP_F_SPACE)
signvalue = ' ';
}
}
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
do {
convert[place++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")
[uvalue % (unsigned)base ];
uvalue = (uvalue / (unsigned)base );
} while(uvalue && (place < 20));
if (place == 20) place--;
convert[place] = 0;
zpadlen = max - place;
spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
if (zpadlen < 0) zpadlen = 0;
if (spadlen < 0) spadlen = 0;
if (flags & DP_F_ZERO) {
zpadlen = MAX(zpadlen, spadlen);
spadlen = 0;
}
if (flags & DP_F_MINUS)
spadlen = -spadlen; /* Left Justifty */
#ifdef DEBUG_SNPRINTF
printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
zpadlen, spadlen, min, max, place);
#endif
/* Spaces */
while (spadlen > 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
--spadlen;
}
/* Sign */
if (signvalue)
dopr_outch (buffer, currlen, maxlen, signvalue);
/* Zeros */
if (zpadlen > 0) {
while (zpadlen > 0) {
dopr_outch (buffer, currlen, maxlen, '0');
--zpadlen;
}
}
/* Digits */
while (place > 0)
dopr_outch (buffer, currlen, maxlen, convert[--place]);
/* Left Justified spaces */
while (spadlen < 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
++spadlen;
}
}
static LDOUBLE abs_val(LDOUBLE value)
{
LDOUBLE result = value;
if (value < 0)
result = -value;
return result;
}
static LDOUBLE POW10(int exp)
{
LDOUBLE result = 1;
while (exp) {
result *= 10;
exp--;
}
return result;
}
static LLONG ROUND(LDOUBLE value)
{
LLONG intpart;
intpart = (LLONG)value;
value = value - intpart;
if (value >= 0.5) intpart++;
return intpart;
}
/* a replacement for modf that doesn't need the math library. Should
be portable, but slow */
static double my_modf(double x0, double *iptr)
{
int i;
long l;
double x = x0;
double f = 1.0;
for (i=0;i<100;i++) {
l = (long)x;
if (l <= (x+1) && l >= (x-1)) break;
x *= 0.1;
f *= 10.0;
}
if (i == 100) {
/* yikes! the number is beyond what we can handle. What do we do? */
(*iptr) = 0;
return 0;
}
if (i != 0) {
double i2;
double ret;
ret = my_modf(x0-l*f, &i2);
(*iptr) = l*f + i2;
return ret;
}
(*iptr) = l;
return x - (*iptr);
}
static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags)
{
int signvalue = 0;
double ufvalue;
char iconvert[311];
char fconvert[311];
int iplace = 0;
int fplace = 0;
int padlen = 0; /* amount to pad */
int zpadlen = 0;
int caps = 0;
int idx;
double intpart;
double fracpart;
double temp;
/*
* AIX manpage says the default is 0, but Solaris says the default
* is 6, and sprintf on AIX defaults to 6
*/
if (max < 0)
max = 6;
ufvalue = abs_val (fvalue);
if (fvalue < 0) {
signvalue = '-';
} else {
if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
signvalue = '+';
} else {
if (flags & DP_F_SPACE)
signvalue = ' ';
}
}
#if 0
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
#endif
#if 0
if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */
#endif
/*
* Sorry, we only support 16 digits past the decimal because of our
* conversion method
*/
if (max > 16)
max = 16;
/* We "cheat" by converting the fractional part to integer by
* multiplying by a factor of 10
*/
temp = ufvalue;
my_modf(temp, &intpart);
fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
if (fracpart >= POW10(max)) {
intpart++;
fracpart -= POW10(max);
}
/* Convert integer part */
do {
temp = intpart*0.1;
my_modf(temp, &intpart);
idx = (int) ((temp -intpart +0.05)* 10.0);
/* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
/* printf ("%llf, %f, %x\n", temp, intpart, idx); */
iconvert[iplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
} while (intpart && (iplace < 311));
if (iplace == 311) iplace--;
iconvert[iplace] = 0;
/* Convert fractional part */
if (fracpart)
{
do {
temp = fracpart*0.1;
my_modf(temp, &fracpart);
idx = (int) ((temp -fracpart +0.05)* 10.0);
/* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
/* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
fconvert[fplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
} while(fracpart && (fplace < 311));
if (fplace == 311) fplace--;
}
fconvert[fplace] = 0;
/* -1 for decimal point, another -1 if we are printing a sign */
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
zpadlen = max - fplace;
if (zpadlen < 0) zpadlen = 0;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justifty */
if ((flags & DP_F_ZERO) && (padlen > 0)) {
if (signvalue) {
dopr_outch (buffer, currlen, maxlen, signvalue);
--padlen;
signvalue = 0;
}
while (padlen > 0) {
dopr_outch (buffer, currlen, maxlen, '0');
--padlen;
}
}
while (padlen > 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
}
if (signvalue)
dopr_outch (buffer, currlen, maxlen, signvalue);
while (iplace > 0)
dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
#ifdef DEBUG_SNPRINTF
printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
#endif
/*
* Decimal point. This should probably use locale to find the correct
* char to print out.
*/
if (max > 0) {
dopr_outch (buffer, currlen, maxlen, '.');
while (zpadlen > 0) {
dopr_outch (buffer, currlen, maxlen, '0');
--zpadlen;
}
while (fplace > 0)
dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
}
while (padlen < 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
}
}
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
{
if (*currlen < maxlen) {
buffer[(*currlen)] = c;
}
(*currlen)++;
}
int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
return dopr(str, count, fmt, args);
}
#endif
/* yes this really must be a ||. Don't muck with this (tridge)
*
* The logic for these two is that we need our own definition if the
* OS *either* has no definition of *sprintf, or if it does have one
* that doesn't work properly according to the autoconf test.
*/
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
int snprintf(char *str,size_t count,const char *fmt,...)
{
size_t ret;
va_list ap;
va_start(ap, fmt);
ret = vsnprintf(str, count, fmt, ap);
va_end(ap);
return ret;
}
#endif
#endif
#ifndef HAVE_VASPRINTF
int vasprintf(char **ptr, const char *format, va_list ap)
{
int ret;
va_list ap2;
VA_COPY(ap2, ap);
ret = vsnprintf(NULL, 0, format, ap2);
if (ret <= 0) return ret;
(*ptr) = (char *)malloc(ret+1);
if (!*ptr) return -1;
VA_COPY(ap2, ap);
ret = vsnprintf(*ptr, ret+1, format, ap2);
return ret;
}
#endif
#ifndef HAVE_ASPRINTF
int asprintf(char **ptr, const char *format, ...)
{
va_list ap;
int ret;
*ptr = NULL;
va_start(ap, format);
ret = vasprintf(ptr, format, ap);
va_end(ap);
return ret;
}
#endif
#ifdef TEST_SNPRINTF
int sprintf(char *str,const char *fmt,...);
int main (void)
{
char buf1[1024];
char buf2[1024];
char *fp_fmt[] = {
"%1.1f",
"%-1.5f",
"%1.5f",
"%123.9f",
"%10.5f",
"% 10.5f",
"%+22.9f",
"%+4.9f",
"%01.3f",
"%4f",
"%3.1f",
"%3.2f",
"%.0f",
"%f",
"-16.16f",
NULL
};
double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996,
0.9996, 1.996, 4.136, 5.030201, 0.00205,
/* END LIST */ 0};
char *int_fmt[] = {
"%-1.5d",
"%1.5d",
"%123.9d",
"%5.5d",
"%10.5d",
"% 10.5d",
"%+22.33d",
"%01.3d",
"%4d",
"%d",
NULL
};
long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
char *str_fmt[] = {
"10.5s",
"5.10s",
"10.1s",
"0.10s",
"10.0s",
"1.10s",
"%s",
"%.1s",
"%.10s",
"%10s",
NULL
};
char *str_vals[] = {"hello", "a", "", "a longer string", NULL};
int x, y;
int fail = 0;
int num = 0;
printf ("Testing snprintf format codes against system sprintf...\n");
for (x = 0; fp_fmt[x] ; x++) {
for (y = 0; fp_nums[y] != 0 ; y++) {
int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]);
int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
sprintf (buf2, fp_fmt[x], fp_nums[y]);
if (strcmp (buf1, buf2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
fp_fmt[x], buf1, buf2);
fail++;
}
if (l1 != l2) {
printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]);
fail++;
}
num++;
}
}
for (x = 0; int_fmt[x] ; x++) {
for (y = 0; int_nums[y] != 0 ; y++) {
int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]);
int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
sprintf (buf2, int_fmt[x], int_nums[y]);
if (strcmp (buf1, buf2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
int_fmt[x], buf1, buf2);
fail++;
}
if (l1 != l2) {
printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]);
fail++;
}
num++;
}
}
for (x = 0; str_fmt[x] ; x++) {
for (y = 0; str_vals[y] != 0 ; y++) {
int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]);
int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]);
sprintf (buf2, str_fmt[x], str_vals[y]);
if (strcmp (buf1, buf2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
str_fmt[x], buf1, buf2);
fail++;
}
if (l1 != l2) {
printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]);
fail++;
}
num++;
}
}
printf ("%d tests failed out of %d.\n", fail, num);
printf("seeing how many digits we support\n");
{
double v0 = 0.12345678901234567890123456789012345678901;
for (x=0; x<100; x++) {
double p = pow(10, x);
double r = v0*p;
snprintf(buf1, sizeof(buf1), "%1.1f", r);
sprintf(buf2, "%1.1f", r);
if (strcmp(buf1, buf2)) {
printf("we seem to support %d digits\n", x-1);
break;
}
}
}
return 0;
}
#endif /* TEST_SNPRINTF */
htp-1.16/src/streams.c 0000644 0000510 0000310 00000020171 10665777571 014534 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// $Id: streams.c,v 1.14 2006/06/12 13:41:33 hoenicke Exp $
//
// file/buffer stream functions
//
// Copyright (c) 2001 Jochen Hoenicke under Artistic License.
//
*/
#include "htp.h"
#include "snprintf.h"
BOOL CreateNullWriter (STREAM* stream) {
stream->sflags = STREAM_FLAG_NULL_FILE;
stream->name = "NULL";
stream->lineNumber = 1;
return TRUE;
}
BOOL CreateBufferWriter (STREAM* stream, const char *name) {
stream->sflags = STREAM_FLAG_BUFFER;
stream->u.buffer.length = 128;
stream->u.buffer.buffer = AllocMemory(stream->u.buffer.length);
stream->u.buffer.offset = 0;
if (stream->u.buffer.buffer == NULL)
{
HtpMsg(MSG_ERROR, NULL, "unable to allocate stream buffer");
return FALSE;
}
return TRUE;
}
BOOL CreateBufferReader (STREAM* stream, STREAM *writeStream)
{
if (writeStream->sflags != STREAM_FLAG_BUFFER)
{
HtpMsg(MSG_ERROR, NULL, "CreateBufferReader: wrong buffer type");
return FALSE;
}
stream->sflags = STREAM_FLAG_BUFFER | STREAM_FLAG_READER;
stream->name = writeStream->name;
stream->lineNumber = writeStream->lineNumber;
stream->u.buffer.length = writeStream->u.buffer.offset;
stream->u.buffer.buffer = writeStream->u.buffer.buffer;
stream->u.buffer.offset = 0;
stream->hasUnread = FALSE;
return TRUE;
}
BOOL FlushBufferWriter (STREAM *stream)
{
char *str;
if (stream->sflags != STREAM_FLAG_BUFFER)
{
HtpMsg(MSG_ERROR, NULL, "CreateBufferReader: wrong buffer type");
return FALSE;
}
str = AllocMemory(stream->u.buffer.offset + 1);
memcpy(str, stream->u.buffer.buffer, stream->u.buffer.offset);
str[stream->u.buffer.offset] = 0;
FreeMemory(stream->u.buffer.buffer);
stream->u.buffer.buffer = str;
return TRUE;
}
BOOL CreateFileReader (STREAM *stream, const char *filename)
{
stream->sflags = STREAM_FLAG_READER;
stream->name = filename;
stream->lineNumber = 1;
stream->hasUnread = FALSE;
return OpenFile(filename, "r", &stream->u.textfile);
}
BOOL CreateFDReader (STREAM *stream, const char *filename, int filedes)
{
stream->sflags = STREAM_FLAG_READER;
stream->name = filename;
stream->lineNumber = 1;
stream->hasUnread = FALSE;
return OpenFD(filedes, "r", &stream->u.textfile);
}
BOOL CreateFileWriter (STREAM *stream, const char *filename, BOOL append)
{
stream->sflags = 0;
stream->name = filename;
stream->lineNumber = 1;
return OpenFile(filename, append ? "a" : "w", &stream->u.textfile);
}
void CloseStream (STREAM *stream)
{
if ((stream->sflags & STREAM_FLAG_BUFFER)) {
if (!(stream->sflags & STREAM_FLAG_READER)) {
FreeMemory(stream->u.buffer.buffer);
FreeMemory((void *)stream->name);
}
} else if ((stream->sflags & STREAM_FLAG_NULL_FILE)) {
/* nothing */
} else {
CloseFile(&stream->u.textfile);
}
}
BOOL GetStreamChar(STREAM *stream, char *c)
{
assert(stream != NULL);
assert((stream->sflags & STREAM_FLAG_READER));
assert(stream->u.buffer.buffer != NULL);
if (stream->hasUnread)
{
*c = stream->unread;
stream->hasUnread = FALSE;
return TRUE;
}
if ((stream->sflags & STREAM_FLAG_BUFFER))
{
/* Check for EOF */
if (stream->u.buffer.length <= stream->u.buffer.offset)
return FALSE;
*c = stream->u.buffer.buffer[stream->u.buffer.offset++];
if (*c == '\n')
stream->lineNumber++;
return TRUE;
} else {
BOOL result = GetFileChar(&stream->u.textfile, c);
if (*c == '\n')
stream->lineNumber++;
return result;
}
}
BOOL UnreadStreamChar(STREAM *stream, char c)
{
assert(stream != NULL);
assert((stream->sflags & STREAM_FLAG_READER));
assert(stream->u.buffer.buffer != NULL);
assert(!stream->hasUnread);
stream->hasUnread = TRUE;
stream->unread = c;
return TRUE;
}
uint GetStreamBlock(STREAM *stream, char *buffer, uint size, char delim[3])
{
char *ptr, ch;
int read = 0;
assert(stream != NULL);
assert((stream->sflags & STREAM_FLAG_READER));
assert(buffer != NULL);
if (stream->hasUnread)
{
*buffer++ = ch = stream->unread;
size--;
stream->hasUnread = FALSE;
if (ch == delim[0]
|| ch == delim[1])
return 1;
read = 1;
}
if ((stream->sflags & STREAM_FLAG_BUFFER))
{
char * end = stream->u.buffer.buffer + stream->u.buffer.length;
char * start = stream->u.buffer.buffer + stream->u.buffer.offset;
/* Check for EOF */
if (start >= end)
return FALSE;
/* leave space for trailing NUL. */
size--;
if (start + size < end)
end = start + size;
/* Search for new line. */
ptr = start;
while (ptr < end)
{
*buffer++ = ch = *ptr++;
if (ch == '\n')
stream->lineNumber++;
if (ch == delim[0]
|| ch == delim[1]
|| ch == delim[2])
break;
}
*buffer = 0;
stream->u.buffer.offset += ptr - start;
return read + ptr - start;
} else {
if(feof(stream->u.textfile.file))
return FALSE;
ptr = buffer;
/* compare size to 1 rather than 0 to leave room for trailing NUL */
while(size-- > 1)
{
if(GetFileChar(&stream->u.textfile, ptr) == FALSE)
{
break;
}
ch = *ptr;
if(ch == '\n')
{
stream->lineNumber++;
}
ptr++;
if (ch == delim[0]
|| ch == delim[1]
|| ch == delim[2])
break;
}
*ptr = 0;
return read + ptr - buffer;
}
}
BOOL PutStreamString(STREAM *stream, const char *str)
{
/* check the arguments */
assert(stream != NULL);
assert(!(stream->sflags & STREAM_FLAG_READER));
if ((stream->sflags & STREAM_FLAG_BUFFER))
{
ulong len = strlen(str);
ulong free = stream->u.buffer.length - stream->u.buffer.offset;
if (len > free) {
char * newbuffer;
while (len > free) {
free += stream->u.buffer.length;
stream->u.buffer.length *= 2;
}
newbuffer = ResizeMemory(stream->u.buffer.buffer,
stream->u.buffer.length);
if (newbuffer == NULL) {
/* unable to enlarge buffer area */
HtpMsg(MSG_ERROR, NULL, "unable to grow stream buffers");
return FALSE;
}
stream->u.buffer.buffer = newbuffer;
}
memcpy (stream->u.buffer.buffer + stream->u.buffer.offset, str, len);
stream->u.buffer.offset += len;
return TRUE;
} else if ((stream->sflags & STREAM_FLAG_NULL_FILE)) {
return TRUE;
} else {
return PutFileString(&stream->u.textfile, str);
}
}
BOOL StreamPrintF(STREAM *stream, const char *format, ...)
{
va_list argptr;
/* reserve room to hold the final string ... allocating 4K works
* most time. If that isn't enough, we reallocate later. */
char buffer[4*KBYTE];
char *str = buffer;
int len;
/* convert formatted arguments into single string */
va_start(argptr, format);
len = vsnprintf(str, sizeof(buffer), format, argptr);
va_end(argptr);
if (len > sizeof(buffer) - 1) {
str = AllocMemory(len + 1);
va_start(argptr, format);
len = vsnprintf(str, len + 1, format, argptr);
va_end(argptr);
}
len = PutStreamString(stream, str);
if (str != buffer)
FreeMemory(str);
return len;
}
void ForceLinefeeds(STREAM *stream, BOOL forced)
{
if (!(stream->sflags & (STREAM_FLAG_BUFFER | STREAM_FLAG_NULL_FILE)))
{
if (forced)
stream->u.textfile.flags |= TEXTFILE_FLAG_FORCE_CR;
else
stream->u.textfile.flags &= ~TEXTFILE_FLAG_FORCE_CR;
}
}
htp-1.16/src/suballoc.c 0000644 0000510 0000310 00000040730 10665777571 014665 0 ustar hoenicke fb10-sem /*
//
// suballoc.c
//
// Memory suballocation
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "htp.h"
#ifdef USE_SUBALLOC
/*
// performance counters
*/
#if DEBUG
uint freePoolHits = 0;
uint totalAllocations = 0;
#endif
/*
// pattern used to clear memory on allocation and free
*/
#define SUBALLOC_ALLOC_BYTE (0xA5)
#define SUBALLOC_FREE_BYTE (0x5A)
/*
// each memory allocation has a small header, which is used by
// this module alone
*/
#define SUBALLOC_MAX_HEADER_FILE_SIZE (16)
typedef struct tagSUBALLOC_HEADER
{
struct tagSUBALLOC_HEADER *next;
struct tagSUBALLOC_HEADER *prev;
char file[SUBALLOC_MAX_HEADER_FILE_SIZE];
uint line;
uint allocSize;
uint userSize;
DWORD signature;
} SUBALLOC_HEADER;
#define SUBALLOC_SIGNATURE (0xFEA55AEF)
#define SUBALLOC_END_SIGNATURE (0xA5EFFE5A)
/*
// the memory pool is kept on a doubly-linked list
*/
typedef struct tagSUBALLOC_POOL
{
SUBALLOC_HEADER *head;
SUBALLOC_HEADER *tail;
uint totalMemorySize;
} SUBALLOC_POOL;
SUBALLOC_POOL freePool;
SUBALLOC_POOL reservedPool;
/*
// memory pool functions
*/
void InitializePool(SUBALLOC_POOL *pool)
{
assert(pool != NULL);
pool->head = NULL;
pool->tail = NULL;
pool->totalMemorySize = 0;
}
SUBALLOC_HEADER *PointerToHeader(void *ptr)
{
assert(ptr != NULL);
return (SUBALLOC_HEADER *) (((BYTE *) ptr) - sizeof(SUBALLOC_HEADER));
}
void *GetUserBuffer(SUBALLOC_HEADER *header)
{
/* cant assert good header, this function might be used during its */
/* construction */
assert(header != NULL);
return ((BYTE *) header) + sizeof(SUBALLOC_HEADER);
}
BOOL IsHeaderOkay(SUBALLOC_HEADER *header)
{
if(header == NULL)
{
DebugMsg("IsHeaderOkay: NULL header\n");
return FALSE;
}
/* check head signature */
if(header->signature != SUBALLOC_SIGNATURE)
{
DebugMsg("IsHeaderOkay: bad start signature, file %s line %u\n",
header->file, header->line);
return FALSE;
}
return TRUE;
}
void SetEndSignature(SUBALLOC_HEADER *header)
{
BYTE *startSignature;
static DWORD endSignature = SUBALLOC_END_SIGNATURE;
assert(header != NULL);
/* find the first byte of the area beyond the user-allocated buffer */
startSignature = (BYTE *) header + sizeof(SUBALLOC_HEADER)
+ header->userSize;
/* since some machines don't like misaligned accesses, copy the signature */
/* in byte by byte */
memcpy(startSignature, &endSignature, sizeof(DWORD));
}
BOOL IsEndSignatureOkay(SUBALLOC_HEADER *header)
{
BYTE *startSignature;
static DWORD endSignature = SUBALLOC_END_SIGNATURE;
assert(header != NULL);
/* find the first byte beyond the user-allocated buffer */
startSignature = (BYTE *) header + sizeof(SUBALLOC_HEADER)
+ header->userSize;
/* since some machines don't like misaligned accessed, compare the */
/* signature byte by byte */
return (memcmp(startSignature, &endSignature, sizeof(DWORD)) == 0)
? TRUE : FALSE;
}
SUBALLOC_HEADER *CreatePoolElement(uint size)
{
SUBALLOC_HEADER *header;
uint allocSize;
#if SUBALLOC_MINALLOCSIZE
allocSize = (size < SUBALLOC_MINALLOCSIZE) ? SUBALLOC_MINALLOCSIZE : size;
#else
allocSize = size;
#endif
/* allocate header, end signature, and user buffer */
if((header = malloc(allocSize + sizeof(SUBALLOC_HEADER) + sizeof(DWORD))) == NULL)
{
return NULL;
}
#if DEBUG
header->next = (void *) 0x12345678;
header->prev = (void *) 0x12345678;
#endif
/* set up as much of the header as possible */
header->allocSize = allocSize;
header->userSize = size;
header->signature = SUBALLOC_SIGNATURE;
#if SUBALLOC_CLEARMEM
memset(GetUserBuffer(header), SUBALLOC_ALLOC_BYTE, allocSize);
#endif
/* set the end signature */
SetEndSignature(header);
assert(IsHeaderOkay(header) == TRUE);
assert(IsEndSignatureOkay(header) == TRUE);
return header;
}
void FreePoolElement(SUBALLOC_HEADER *header)
{
assert(IsHeaderOkay(header) == TRUE);
#if SUBALLOC_CLEARMEM
memset(GetUserBuffer(header), SUBALLOC_FREE_BYTE, header->allocSize);
#endif
free(header);
}
SUBALLOC_HEADER *ResizePoolElement(SUBALLOC_HEADER *header, uint newSize)
{
uint allocSize;
SUBALLOC_HEADER *newHeader;
assert(IsHeaderOkay(header) == TRUE);
assert(newSize != 0);
#if SUBALLOC_MINALLOCSIZE
allocSize = (newSize < SUBALLOC_MINALLOCSIZE) ? SUBALLOC_MINALLOCSIZE
: newSize;
#else
allocSize = newSize;
#endif
/* it COULD already be this size */
if(header->allocSize >= allocSize)
{
header->userSize = newSize;
SetEndSignature(header);
assert(IsHeaderOkay(header) == TRUE);
assert(IsEndSignatureOkay(header) == TRUE);
return header;
}
newHeader = realloc(header, newSize + sizeof(SUBALLOC_HEADER) + sizeof(DWORD));
if(newHeader == NULL)
{
/* couldnt resize block */
return NULL;
}
#if DEBUG
newHeader->prev = (void *) 0x12345678;
newHeader->next = (void *) 0x12345678;
#endif
/* fill in the new header */
newHeader->userSize = newSize;
newHeader->allocSize = allocSize;
newHeader->signature = SUBALLOC_SIGNATURE;
/* set the end signature */
SetEndSignature(newHeader);
assert(IsHeaderOkay(newHeader) == TRUE);
assert(IsEndSignatureOkay(newHeader) == TRUE);
return newHeader;
}
void AddPoolElement(SUBALLOC_POOL *pool, SUBALLOC_HEADER *header)
{
assert(pool != NULL);
assert(IsHeaderOkay(header) == TRUE);
if(pool->head != NULL)
{
header->prev = pool->tail;
pool->tail->next = header;
}
else
{
pool->head = header;
header->prev = NULL;
}
header->next = NULL;
pool->tail = header;
pool->totalMemorySize += header->allocSize;
}
SUBALLOC_HEADER *RemoveFirstElement(SUBALLOC_POOL *pool)
{
SUBALLOC_HEADER *header;
assert(pool != NULL);
if(pool->head == NULL)
{
return NULL;
}
header = pool->head;
if((pool->head = header->next) != NULL)
{
pool->head->prev = NULL;
}
assert(pool->totalMemorySize >= header->allocSize);
pool->totalMemorySize -= header->allocSize;
assert(IsHeaderOkay(header) == TRUE);
return header;
}
void RemoveElement(SUBALLOC_POOL *pool, SUBALLOC_HEADER *header)
{
assert(pool != NULL);
assert(IsHeaderOkay(header) == TRUE);
if(pool->head == header)
{
pool->head = header->next;
if(pool->head != NULL)
{
pool->head->prev = NULL;
}
}
else if(pool->tail == header)
{
pool->tail = header->prev;
if(pool->tail != NULL)
{
pool->tail->next = NULL;
}
}
else
{
header->prev->next = header->next;
header->next->prev = header->prev;
}
assert(pool->totalMemorySize >= header->allocSize);
pool->totalMemorySize -= header->allocSize;
}
SUBALLOC_HEADER *RemovePoolElementBySize(SUBALLOC_POOL *pool, uint size)
{
SUBALLOC_HEADER *curr;
#if !SUBALLOC_FIRSTFIT
SUBALLOC_HEADER *bestfit;
uint bestfitDiff;
uint currDiff;
#endif
assert(pool != NULL);
assert(size != 0);
#if !SUBALLOC_FIRSTFIT
bestfit = NULL;
bestfitDiff = UINT_MAX;
#endif
curr = pool->head;
while(curr != NULL)
{
assert(IsHeaderOkay(curr) == TRUE);
if(curr->allocSize < size)
{
/* too small */
curr = curr->next;
continue;
}
#if SUBALLOC_FIRSTFIT
/* found one, unlink from the list */
RemoveElement(pool, curr);
#if SUBALLOC_DEBLOG
DebugMsg("suballoc: first fit found block of %u bytes for alloc of %u bytes\n",
curr->allocSize, size);
#endif
return curr;
#else
#if SUBALLOC_MINALLOCSIZE
/* if the block is the minimum allocation size, then it is the */
/* best fit, by definition */
if(curr->allocSize == SUBALLOC_MINALLOCSIZE)
{
bestfit = curr;
break;
}
#endif
currDiff = curr->allocSize - size;
if(currDiff == 0)
{
/* this is as good as it gets */
bestfit = curr;
break;
}
if(currDiff < bestfitDiff)
{
bestfitDiff = currDiff;
bestfit = curr;
}
curr = curr->next;
#endif
}
#if !SUBALLOC_FIRSTFIT
if(bestfit != NULL)
{
RemoveElement(pool, bestfit);
#if SUBALLOC_DEBLOG
DebugMsg("suballoc: best fit found block of %u bytes for alloc of %u bytes\n",
bestfit->allocSize, size);
#endif
return bestfit;
}
#endif
/* nothing was found */
return NULL;
}
BOOL RemovePoolElementByAddr(SUBALLOC_POOL *pool, SUBALLOC_HEADER *header)
{
SUBALLOC_HEADER *curr;
assert(pool != NULL);
assert(IsHeaderOkay(header) == TRUE);
curr = pool->head;
while(curr != NULL)
{
assert(IsHeaderOkay(curr) == TRUE);
if(curr == header)
{
RemoveElement(pool, curr);
return TRUE;
}
curr = curr->next;
}
return FALSE;
}
void RemoveLargestPoolElement(SUBALLOC_POOL *pool)
{
SUBALLOC_HEADER *curr;
SUBALLOC_HEADER *largest;
assert(pool != NULL);
largest = NULL;
/* walk the list, looking for the largest allocated block */
for(curr = pool->head; curr != NULL; curr = curr->next)
{
assert(IsHeaderOkay(curr) == TRUE);
if(largest == NULL)
{
largest = curr;
continue;
}
if(curr->allocSize > largest->allocSize)
{
largest = curr;
continue;
}
}
/* if one was found, remove it */
if(largest != NULL)
{
#if SUBALLOC_DEBLOG
DebugMsg("removing largest buffer of %u bytes from pool of %u bytes\n",
largest->allocSize, pool->totalMemorySize);
#endif
if(largest->prev != NULL)
{
largest->prev->next = largest->next;
}
if(largest->next != NULL)
{
largest->next->prev = largest->prev;
}
/* removed, so destroy it and account for it in the pool */
assert(pool->totalMemorySize >= largest->allocSize);
pool->totalMemorySize -= largest->allocSize;
FreePoolElement(largest);
}
}
/*
// public functions
*/
void InitializeMemory(void)
{
InitializePool(&freePool);
InitializePool(&reservedPool);
}
void TerminateMemory(void)
{
SUBALLOC_HEADER *header;
if(reservedPool.head != NULL)
{
#if SUBALLOC_DEBLOG
DebugMsg("UNFREED MEMORY: %u bytes held in reserved pool\n",
reservedPool.totalMemorySize);
#endif
#if SUBALLOC_WARNING
printf("suballoc: %u bytes unfreed\n", reservedPool.totalMemorySize);
#endif
}
#if SUBALLOC_DEBLOG
DebugMsg("suballoc: %u bytes held in free pool\n", freePool.totalMemorySize);
#endif
while((header = RemoveFirstElement(&reservedPool)) != NULL)
{
assert(IsHeaderOkay(header) == TRUE);
assert(IsEndSignatureOkay(header) == TRUE);
#if SUBALLOC_DEBLOG
DebugMsg("Removing reserved alloc for %u bytes from %s line %u\n", header->userSize,
header->file, header->line);
#endif
FreePoolElement(header);
}
while((header = RemoveFirstElement(&freePool)) != NULL)
{
assert(IsHeaderOkay(header) == TRUE);
/* dont check end signature, it is not valid in free pool */
#if SUBALLOC_DEBLOG
DebugMsg("Removing free alloc for %u bytes from %s line %u\n",
header->userSize, header->file, header->line);
#endif
FreePoolElement(header);
}
}
void *_AllocMemory(uint size, const char *file, uint line)
{
SUBALLOC_HEADER *header;
#if SUBALLOC_DEBLOG
DebugMsg("Allocating %u bytes in file %s line %u\n", size, file, line);
#endif
#if DEBUG
totalAllocations++;
#endif
if(size == 0)
{
#if SUBALLOC_DEBLOG
DebugMsg("Allocation for 0 bytes in file %s line %u\n", file, line);
#endif
return NULL;
}
/* if buffer of sufficient size already in pool, use that one */
if((header = RemovePoolElementBySize(&freePool, size)) == NULL)
{
/* need to create a new pool item */
if((header = CreatePoolElement(size)) == NULL)
{
/* out of memory! */
#if SUBALLOC_DEBLOG
DebugMsg("System heap out of memory! file %s line %u\n", file, line);
#endif
return NULL;
}
}
else
{
#if DEBUG
freePoolHits++;
#endif
}
assert(IsHeaderOkay(header) == TRUE);
/* replace the headers file and line with this new information */
if(file != NULL)
{
StringCopy(header->file, file, SUBALLOC_MAX_HEADER_FILE_SIZE);
}
else
{
header->file[0] = NUL;
}
header->line = line;
header->userSize = size;
/* set the end signature */
SetEndSignature(header);
/* add the new suballoc to the reserved pool */
AddPoolElement(&reservedPool, header);
assert(IsHeaderOkay(header) == TRUE);
assert(IsEndSignatureOkay(header) == TRUE);
return GetUserBuffer(header);
}
void _FreeMemory(void *ptr, const char *file, uint line)
{
SUBALLOC_HEADER *header;
#if !SUBALLOC_DEBLOG
UNREF_PARAM(file);
UNREF_PARAM(line);
#endif
if(ptr == NULL)
{
#if SUBALLOC_DEBLOG
DebugMsg("Tried to free NULL pointer in file %s line %u\n", file, line);
#endif
return;
}
header = (SUBALLOC_HEADER *) (((BYTE *) ptr) - sizeof(SUBALLOC_HEADER));
assert(IsHeaderOkay(header) == TRUE);
assert(IsEndSignatureOkay(header) == TRUE);
#if SUBALLOC_DEBLOG
DebugMsg("Freeing %u bytes (%u alloced) in file %s line %u\n",
header->userSize, header->allocSize, file, line);
#endif
if(RemovePoolElementByAddr(&reservedPool, header) == FALSE)
{
/* doh! */
HtpMsg(MSG_ERROR, NULL, "Fatal error: block of memory freed not in reserved pool, exiting ...\n");
exit(1);
}
#if SUBALLOC_CLEARMEM
memset(GetUserBuffer(header), SUBALLOC_FREE_BYTE, header->allocSize);
#endif
/* move it back into the free pool */
AddPoolElement(&freePool, header);
#if SUBALLOC_MAXFREEPOOLSIZE
/* check to see that the free pool size hasnt grown too big */
while(freePool.totalMemorySize > SUBALLOC_MAXFREEPOOLSIZE)
{
RemoveLargestPoolElement(&freePool);
}
#endif
}
void *_ResizeMemory(void *ptr, uint newSize, const char *file, uint line)
{
SUBALLOC_HEADER *header;
SUBALLOC_HEADER *newHeader;
#if SUBALLOC_DEBLOG
DebugMsg("Reallocing to new size of %u bytes in file %s line %u\n",
newSize, file, line);
#endif
if((newSize == 0) && (ptr != NULL))
{
/* treat as a free */
FreeMemory(ptr);
return NULL;
}
if((ptr == NULL) && (newSize != 0))
{
/* treat as an alloc */
return AllocMemory(newSize);
}
if((ptr == NULL) && (newSize == 0))
{
/* treat as a dumbo programmer */
return NULL;
}
header = PointerToHeader(ptr);
assert(IsHeaderOkay(header) == TRUE);
assert(IsEndSignatureOkay(header) == TRUE);
if(RemovePoolElementByAddr(&reservedPool, header) == FALSE)
{
/* oof */
HtpMsg(MSG_ERROR, NULL, "Fatal error: block of memory freed not in reserved pool, exiting ...\n");
exit(1);
}
/* resize memory buffer */
newHeader = ResizePoolElement(header, newSize);
if(newHeader == NULL)
{
/* failed to resize */
AddPoolElement(&reservedPool, header);
return NULL;
}
/* succeeded, fill in rest of header */
if(file != NULL)
{
StringCopy(newHeader->file, file, SUBALLOC_MAX_HEADER_FILE_SIZE);
}
else
{
newHeader->file[0] = NUL;
}
newHeader->line = line;
/* add to reserve pool and return to user */
AddPoolElement(&reservedPool, newHeader);
assert(IsHeaderOkay(newHeader) == TRUE);
assert(IsEndSignatureOkay(newHeader) == TRUE);
return GetUserBuffer(newHeader);
}
uint MemorySize(void *ptr)
{
SUBALLOC_HEADER *header;
if(ptr == NULL)
{
return 0;
}
header = PointerToHeader(ptr);
assert(IsHeaderOkay(header) == TRUE);
if(IsHeaderOkay(header) == FALSE)
{
return 0;
}
return header->userSize;
}
#endif
htp-1.16/src/textfile.c 0000644 0000510 0000310 00000007457 10665777571 014716 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// textfile.c
//
// Text file functions
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "htp.h"
#include "option.h"
BOOL OpenFile(const char *filename, const char *openFlags, TEXTFILE *textFile)
{
char *os_filename;
assert(filename != NULL);
assert(openFlags != NULL);
assert(textFile != NULL);
/* convert the filename to the native machine's format */
/* (MS-DOS to UNIX and vice-versa) */
/* this returns an allocated copy of the string, so it must be freed */
/* when the structure is destroyed */
if((os_filename = ConvertDirDelimiter(filename)) == NULL)
{
DEBUG_PRINT(("unable to convert dir delimiter"));
return FALSE;
}
/* initialize the rest of the structure */
textFile->emptyLine = TRUE;
textFile->pendingSpaces = 0;
textFile->flags = TEXTFILE_FLAG_NONE;
textFile->file = fopen(os_filename, openFlags);
FreeMemory(os_filename);
if(textFile->file == NULL)
{
DEBUG_PRINT(("unable to open file %s", filename));
return FALSE;
}
return TRUE;
}
BOOL OpenFD(int filedes, const char *openFlags, TEXTFILE *textFile)
{
assert(openFlags != NULL);
assert(textFile != NULL);
/* initialize the rest of the structure */
textFile->emptyLine = TRUE;
textFile->pendingSpaces = 0;
textFile->flags = TEXTFILE_FLAG_NONE;
textFile->file = fdopen(filedes, openFlags);
if(textFile->file == NULL)
{
DEBUG_PRINT(("unable to open fd %d", filedes));
return FALSE;
}
return TRUE;
}
void CloseFile(TEXTFILE *textFile)
{
assert(textFile != NULL);
assert(textFile->file != NULL);
fclose(textFile->file);
textFile->file = NULL;
}
BOOL GetFileChar(TEXTFILE *textFile, char *ch)
{
int getCh;
assert(textFile != NULL);
assert(ch != NULL);
assert(textFile->file != NULL);
if((getCh = fgetc(textFile->file)) == EOF)
{
return FALSE;
}
*ch = (char) getCh;
return TRUE;
}
BOOL PutFileString(TEXTFILE *textFile, const char *str)
{
char ch;
uint pendingSpaces;
uint condensing;
BOOL emptyLine;
assert(textFile != NULL);
assert(textFile->file != NULL);
condensing =
(textFile->flags & TEXTFILE_FLAG_FORCE_CR) != 0 ? OPT_V_FALSE
: GetOptionValue(OPT_I_CONDENSE);
emptyLine = textFile->emptyLine;
pendingSpaces = textFile->pendingSpaces;
while ((ch = *str++) != NUL) {
if (ch == '\r')
continue;
if (ch == ' ')
{
pendingSpaces++;
continue;
}
if (ch == '\n')
{
/* suppress linefeeds? */
if (condensing == OPT_V_TRUE)
{
/* Handle newline just as a space.
* C/R being dropped between words
*/
pendingSpaces++;
continue;
}
if (condensing == OPT_V_SEMI)
{
/* Remove spaces at end of line */
pendingSpaces = 0;
/* Remove empty lines */
if (emptyLine)
continue;
}
emptyLine = TRUE;
}
else
{
emptyLine = FALSE;
}
while (pendingSpaces > 0) {
fputc(' ', textFile->file);
pendingSpaces--;
if (condensing == OPT_V_TRUE)
pendingSpaces = 0;
}
fputc(ch, textFile->file);
}
textFile->emptyLine = emptyLine;
textFile->pendingSpaces = pendingSpaces;
return TRUE;
}
htp-1.16/src/use-proc.c 0000600 0000510 0000310 00000014153 10665777571 014606 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// use-proc.c
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "use-proc.h"
#include "defs.h"
uint UseProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
const char *name;
HTML_ATTRIBUTE *nameAttrib;
const char *value;
STREAM incfile;
BOOL noexpand;
int result;
uint type;
VARSTORE varstore;
VARSTORE *topVarstore;
nameAttrib = htmlMarkup->attrib;
if(nameAttrib == NULL)
{
HtpMsg(MSG_ERROR, task->infile, "USE markup without parameter");
return MARKUP_ERROR;
}
if (nameAttrib->value) {
if (stricmp(nameAttrib->name, "NAME") == 0) {
HtpMsg(MSG_WARNING, task->infile,
"deprecated USE syntax, see manual");
name = nameAttrib->value;
} else {
HtpMsg(MSG_ERROR, task->infile, "illegal USE markup");
return MARKUP_ERROR;
}
} else {
name = nameAttrib->name;
}
htmlMarkup->attrib = nameAttrib->next;
/* check if the noexpand flag is present */
noexpand = UnlinkBoolAttributeInMarkup(htmlMarkup, "NOEXPAND");
/* get the type of macro */
type = GetVariableType(task->varstore, name);
/* verify the macro exists and of correct type */
if ((type != VAR_TYPE_SET_MACRO) && (type != VAR_TYPE_BLOCK_MACRO))
{
HtpMsg(MSG_ERROR, task->infile,
"macro %s has not been declared", name);
DestroyAttribute(nameAttrib);
FreeMemory(nameAttrib);
return MARKUP_ERROR;
}
/* if more than one parameter is on the USE tag, then assume they are */
/* local variables for the macro */
if (htmlMarkup->attrib != NULL)
{
if(type == VAR_TYPE_SET_MACRO)
{
/* nope, not yet */
HtpMsg(MSG_ERROR, task->infile, "macro parameters can only be used for BLOCK macros");
DestroyAttribute(nameAttrib);
FreeMemory(nameAttrib);
return MARKUP_ERROR;
}
/* create a local variable store */
if(InitializeVariableStore(&varstore) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile, "unable to initialize local context for macro");
DestroyAttribute(nameAttrib);
FreeMemory(nameAttrib);
return MARKUP_ERROR;
}
/* add each additional parameter to the local varstore */
while (htmlMarkup->attrib != NULL)
{
/* No need to duplicate values, as varstore is
* destroyed before this function returns.
*/
if(StoreVariable(&varstore, htmlMarkup->attrib->name,
htmlMarkup->attrib->value, VAR_TYPE_SET_MACRO, VAR_FLAG_NONE,
NULL, NULL) == FALSE)
{
HtpMsg(MSG_ERROR, task->infile, "unable to add variable to block's local context");
DestroyVariableStore(&varstore);
DestroyAttribute(nameAttrib);
FreeMemory(nameAttrib);
return MARKUP_ERROR;
}
htmlMarkup->attrib = htmlMarkup->attrib->next;
}
/* make this variable store the topmost context */
PushVariableStoreContext(task->varstore, &varstore);
topVarstore = &varstore;
}
else
{
topVarstore = task->varstore;
}
if (type == VAR_TYPE_SET_MACRO)
{
/* get the value of the macro */
value = GetVariableValue(task->varstore, name);
/* if NULL, then the macro was declared with no value, this is okay, */
/* just don't do anything */
if(value == NULL)
{
DestroyAttribute(nameAttrib);
FreeMemory(nameAttrib);
return DISCARD_MARKUP;
}
HtpMsg(MSG_INFO, task->infile, "dereferencing macro \"%s\"", name);
PutStreamString(task->outfile, value);
DestroyAttribute(nameAttrib);
FreeMemory(nameAttrib);
return DISCARD_MARKUP;
}
else /* type == VAR_TYPE_BLOCK_MACRO */
{
/* !! magic number */
TASK newTask;
STREAM *blockFile;
/* get the blockFile of the macro */
blockFile = (STREAM*) GetVariableValue(task->varstore, name);
/* if NULL, big-time error */
assert (blockFile != NULL);
HtpMsg(MSG_INFO, task->infile, "dereferencing block macro \"%s\"%s", name, noexpand ? " with noexpand" : "");
if (noexpand)
{
PutStreamString(task->outfile, blockFile->u.buffer.buffer);
DestroyAttribute(nameAttrib);
FreeMemory(nameAttrib);
return DISCARD_MARKUP;
}
result = CreateBufferReader(&incfile, blockFile);
assert(result);
/* build a new task structure */
newTask.infile = &incfile;
newTask.outfile = task->outfile;
newTask.sourceFilename = task->sourceFilename;
/* re-use current variable store if no local variable store was */
/* allocated, otherwise use the new one */
newTask.varstore = topVarstore;
/* process the new input file */
result = ProcessTask(&newTask);
if (!result) {
/* Error message was already spitted out. However, we
* should give a hint where the meta-tag was called.
*/
HtpMsg(MSG_ERROR, task->infile, "... in block macro \"%s\"", name);
}
/* remove the new context (and make sure it is, in fact, the block's */
/* context) */
if(topVarstore == &varstore)
{
assert(varstore.child == NULL);
PopVariableStoreContext(&varstore);
DestroyVariableStore(&varstore);
}
CloseStream(&incfile);
/* if the new file did not process, return an error, otherwise discard */
/* the markup */
DestroyAttribute(nameAttrib);
FreeMemory(nameAttrib);
return (result == TRUE) ? DISCARD_MARKUP : MARKUP_ERROR;
}
}
htp-1.16/src/util.c 0000644 0000510 0000310 00000015446 10665777571 014044 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// util.c
//
// common functions
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "defs.h"
/*
//
// generic, global utility functions
//
*/
/*
// returns the markup type flag ... either the closing or opening delimiter
// in the markup can be passed in
*/
uint MarkupType(char delim)
{
uint markupType;
markupType = 0;
if((delim == HTML_OPEN_MARKUP) || (delim == HTML_CLOSE_MARKUP))
{
markupType |= MARKUP_TYPE_HTML;
}
if((delim == htpOpenMarkup) || (delim == htpCloseMarkup))
{
markupType |= MARKUP_TYPE_HTP;
}
return markupType;
}
#ifndef HAVE_PIPE
/*
// 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;
}
#endif
#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
*/
const char *FindFilename(const char *pathname)
{
const 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);
}
/*
// Like DuplicateString, but only duplicate a sub string of length len.
// The substring is NUL terminated.
*/
char *DuplicateSubString(const char *src, int len)
{
char *new;
uint size;
assert(src != NULL && len <= strlen(src));
size = len + 1;
/* allocate memory for the duplicate string */
if((new = AllocMemory(size)) == NULL)
{
return NULL;
}
/* copy the string */
memcpy(new, src, len);
new[len] = 0;
return new;
}
/*
// converts directory delimiters for any pathname into one supporting the
// delimiters used by the present filesystem ... it is encumbent on the
// caller to free() the string returned once finished
*/
char *ConvertDirDelimiter(const char *pathname)
{
char *newPathname;
char *strptr;
if(pathname == NULL)
{
return NULL;
}
/* duplicate the pathname for conversion */
if((newPathname = DuplicateString(pathname)) == NULL)
{
return NULL;
}
/* walk the string, looking for delimiters belonging to other filesystems */
/* replace with native filesystems delimiter */
strptr = newPathname;
while(*strptr != NUL)
{
if(strchr(OTHER_FILESYSTEM_DELIMITER, *strptr) != NULL)
{
*strptr = DIR_DELIMITER;
}
strptr++;
}
return newPathname;
}
/*
// uses stat() to check for file existance ... maybe not the best way?
*/
BOOL FileExists(const char *pathname)
{
struct stat dummy;
return (stat(pathname, &dummy) == 0) ? TRUE : FALSE;
}
#ifndef HAVE_STPCPY
char *stpcpy(char *d, const char *s) {
do {
*d++ = *s;
} while (*s++);
return d-1;
}
#endif
htp-1.16/src/varstore.c 0000600 0000510 0000310 00000021704 10665777571 014716 0 ustar hoenicke fb10-sem /*
//
// varstore.c
//
// Variable store functions (implemented with a splay tree)
// The splay tree algorithm are taken from D. Sleator's examples.
//
// Copyright (c) 1995-96 Jim Nelson.
// Copyright (c) 2002 Jochen Hoenicke.
// Released under Artistic License.
//
*/
#include "htp.h"
#include "defs.h"
/* statistics for performance measurement */
#if DEBUG
uint variableLookups = 0;
uint variableStringCompares = 0;
uint variableRotations = 0;
#endif
/*
// top down splay routine.
//
// If name is in the tree with root t, it will be moved to the
// top of the tree and the element is returned.
//
// If name is not in the tree a neighbour of name is moved to the
// top of the tree and NULL is returned.
//
// If tree is empty NULL is returned.
*/
static VARIABLE *VariableSplay (const char *name, VARIABLE ** root) {
VARIABLE N, *t, *l, *r, *result;
int cmp;
t = *root;
if (t == NULL)
return t;
/* Fast path */
cmp = stricmp(name, t->name);
if (cmp == 0)
return t;
/* Slow path: Need to reorder tree */
result = NULL;
N.left = N.right = NULL;
l = r = &N;
for (;;) {
#if DEBUG
variableStringCompares++;
#endif
if (cmp < 0) {
if (t->left == NULL)
break;
cmp = stricmp(name, t->left->name);
if (cmp < 0) {
VARIABLE *y;
y = t->left; /* rotate right */
t->left = y->right;
y->right = t;
t = y;
#if DEBUG
variableStringCompares++;
variableRotations++;
#endif
if (t->left == NULL)
break;
cmp = stricmp(name, t->left->name);
}
r->left = t; /* link right */
r = t;
t = t->left;
} else if (cmp > 0) {
if (t->right == NULL)
break;
cmp = stricmp(name, t->right->name);
if (cmp > 0) {
VARIABLE *y;
y = t->right; /* rotate left */
t->right = y->left;
y->left = t;
t = y;
#if DEBUG
variableStringCompares++;
variableRotations++;
#endif
if (t->right == NULL)
break;
cmp = stricmp(name, t->right->name);
}
l->right = t; /* link left */
l = t;
t = t->right;
} else {
/* we found the name */
result = t;
break;
}
}
l->right = t->left; /* assemble */
r->left = t->right;
t->left = N.right;
t->right = N.left;
*root = t;
return result;
}
BOOL InitializeVariableStore(VARSTORE *varstore)
{
assert(varstore != NULL);
/* initialize the store */
varstore->parent = NULL;
varstore->root = NULL;
varstore->child = NULL;
varstore->isGlobal = FALSE;
return TRUE;
}
/*
// Call destructors for variable and/or free the name/value.
*/
static void DestroyVariable(VARIABLE *variable)
{
/* if the variable has a destructor callback, do it */
if(variable->destructor != NULL)
{
variable->destructor(variable->name, variable->value, variable->type,
variable->flag, variable->param);
}
/* Deallocate name and value if the corresponding flags are set */
if (variable->flag & VAR_FLAG_DEALLOC_NAME) {
FreeMemory(variable->name);
}
if (variable->flag & VAR_FLAG_DEALLOC_VALUE) {
FreeMemory(variable->value);
}
}
static void ClearVariableTree(VARIABLE *t)
{
if (t == NULL)
return;
ClearVariableTree(t->left);
ClearVariableTree(t->right);
DestroyVariable(t);
FreeMemory(t);
}
void DestroyVariableStore(VARSTORE *varstore)
{
/* The children must have been destroyed earlier */
assert(varstore->child == NULL);
/* unlink from parent */
if(varstore->parent != NULL)
{
varstore->parent->child = NULL;
varstore->parent = NULL;
}
/* destroy all variables in this store */
ClearVariableTree(varstore->root);
varstore->root = NULL;
}
static VARIABLE *FindVariable(VARSTORE *varstore, const char *name)
{
VARIABLE *ptr;
assert(varstore != NULL);
assert(name != NULL);
#if DEBUG
variableLookups++;
#endif
do {
ptr = VariableSplay(name, &varstore->root);
if(ptr)
return ptr;
/* check all parent stores as well */
varstore = varstore->parent;
} while (varstore != NULL);
return NULL;
}
void *GetVariableValue(VARSTORE *varstore, const char *name)
{
char *value;
VARIABLE *variable;
if(name != NULL)
{
if((variable = FindVariable(varstore, name)) != NULL)
{
return variable->value;
}
if((value = getenv(name)) != NULL)
{
return value;
}
}
return NULL;
}
BOOL StoreVariable(VARSTORE *varstore, const char *name, void *value,
uint type, uint flag, void *param, VAR_DESTRUCTOR destructor)
{
VARIABLE *variable;
assert(varstore != NULL);
assert(name != NULL);
/* remove any variable with the same name in the store */
variable = VariableSplay(name, &varstore->root);
if (variable) {
/* Replace an existing variable */
DestroyVariable(variable);
} else {
/* allocate space for the variable structure */
if((variable = AllocMemory(sizeof(VARIABLE))) == NULL)
{
DEBUG_PRINT(("unable to allocate memory for new variable"));
return FALSE;
}
if (varstore->root == NULL) {
variable->left = variable->right = NULL;
} else if (stricmp(name, varstore->root->name) < 0) {
variable->left = varstore->root->left;
variable->right = varstore->root;
varstore->root->left = NULL;
} else {
variable->right = varstore->root->right;
variable->left = varstore->root;
varstore->root->right = NULL;
}
varstore->root = variable;
}
/* set the variable's name and value */
variable->name = (char *) name;
variable->value = value;
/* set flags and destructor pointer */
variable->type = type;
variable->flag = flag;
variable->param = param;
variable->destructor = destructor;
return TRUE;
}
/*
// TODO: Get rid of the function. IncProcessor is the only one using this.
*/
BOOL UpdateVariableValue(VARSTORE *varstore, const char *name, void *value)
{
VARIABLE *variable;
assert(name != NULL);
assert(value != NULL);
do {
variable = VariableSplay(name, &varstore->root);
if (variable)
break;
/* check the parent store if this isn't the global store */
if (varstore->isGlobal)
break;
varstore = varstore->parent;
} while (varstore != NULL);
if (variable == NULL)
return FALSE;
/* Replace an existing variable */
if (variable->value != NULL
&& (variable->flag & VAR_FLAG_DEALLOC_VALUE))
FreeMemory(variable->value);
variable->value = value;
variable->flag |= VAR_FLAG_DEALLOC_VALUE;
variable->flag &= ~VAR_FLAG_UNDEFINED;
return TRUE;
}
uint GetVariableType(VARSTORE *varstore, const char *name)
{
VARIABLE *variable;
if(name != NULL)
{
if((variable = FindVariable(varstore, name)) != NULL)
{
return variable->type;
}
if(getenv(name) != NULL)
{
return 1;
}
}
return VAR_TYPE_UNKNOWN;
}
uint GetVariableFlag(VARSTORE *varstore, const char *name)
{
VARIABLE *variable;
if(name != NULL)
{
if((variable = FindVariable(varstore, name)) != NULL)
{
return variable->flag;
}
}
return VAR_FLAG_UNKNOWN;
}
BOOL RemoveVariable(VARSTORE *varstore, const char *name)
{
VARIABLE *ptr;
assert(varstore != NULL);
assert(name != NULL);
ptr = VariableSplay(name, &varstore->root);
if(ptr)
{
/* found the variable */
if (ptr->left == NULL)
{
varstore->root = ptr->right;
}
else
{
VariableSplay(name, &ptr->left);
varstore->root = ptr->left;
varstore->root->right = ptr->right;
}
/* call destructors */
DestroyVariable(ptr);
/* free the structure */
FreeMemory(ptr);
return TRUE;
}
/* check all parent stores as well */
if(varstore->parent != NULL)
{
return RemoveVariable(varstore->parent, name);
}
return FALSE;
}
BOOL VariableExists(VARSTORE *varstore, const char *name)
{
if (FindVariable(varstore, name) != NULL) {
return TRUE;
}
if (getenv(name) != NULL) {
return TRUE;
}
return FALSE;
}
void *GetVariableParam(VARSTORE *varstore, const char *name)
{
VARIABLE *var;
if(name != NULL)
{
if((var = FindVariable(varstore, name)) != NULL)
{
return var->param;
}
}
return NULL;
}
void PushVariableStoreContext(VARSTORE *parent, VARSTORE *varstore)
{
assert(parent != NULL);
assert(parent->child == NULL);
assert(varstore != NULL);
assert(varstore->parent == NULL);
parent->child = varstore;
varstore->parent = parent;
varstore->child = NULL;
}
VARSTORE *PopVariableStoreContext(VARSTORE *varstore)
{
assert(varstore != NULL);
assert(varstore->child == NULL);
/* unlink from parent and return current context */
varstore->parent->child = NULL;
varstore->parent = NULL;
return varstore;
}
htp-1.16/src/ver.c 0000600 0000510 0000310 00000002064 10665777571 013643 0 ustar hoenicke fb10-sem /*
//
// ver.c
//
// version and program information
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "htp.h"
/*
// program usage & syntax
*/
void DisplayHeader(void)
{
printf("\n%s %s - HTML pre-processor\n", PROGRAM_NAME, VER_STRING);
printf("Copyright (c) 1995-96 Jim Nelson\n");
printf("Copyright (c) 2002-03 Jochen Hoenicke under Artistic License\n");
printf("[%s]\n\n", PROGRAM_OS);
}
void usage(void)
{
printf("Original author, Jim Nelson.\n");
printf("email:\thtp-discuss@lists.sourceforge.net\n");
printf("WWW:\thttp://htp.sourceforge.net/\n\n");
printf("usage: %s [options] \n",
PROGRAM_NAME);
printf(" %s [options] @\n", PROGRAM_NAME);
printf(" %s [options] @\n", PROGRAM_NAME);
printf("\nSee on-line reference for full details.\n");
printf("\nThis is software is released unter the Artistic License.\n");
}
htp-1.16/src/while-proc.c 0000644 0000510 0000310 00000012146 10665777571 015132 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// bool-proc.c
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#include "while-proc.h"
#include "defs.h"
#include "def-proc.h"
#include "htp-files.h"
#include "macro.h"
BOOL ConditionValue(TASK *task, HTML_ATTRIBUTE *attrib, BOOL notTagFound)
{
char *name;
int quotes;
BOOL changed;
BOOL condTrue;
const char* value;
char *attribValue;
uint type;
if (!ExpandMacrosInString(task, attrib->name, &name,
"es, &changed)) {
return ERROR;
}
HtpMsg(MSG_INFO, task->infile, "while loop check %s", name);
/* get the macros associated value (NULL if macro not defined) */
if((value = GetVariableValue(task->varstore, name)) != NULL)
{
type = GetVariableType(task->varstore, name);
}
else
{
type = VAR_TYPE_SET_MACRO;
}
if (changed)
FreeMemory(name);
/* if only a name is specified, only care if macro is defined */
if(attrib->value == NULL)
{
condTrue = (value != NULL) ? TRUE : FALSE;
}
else
{
/* macro value comparison */
if(type == VAR_TYPE_SET_MACRO)
{
/* macro comparison (case-sensitive) */
if (!ExpandMacrosInString(task, attrib->value, &attribValue,
"es, &changed))
{
return ERROR;
}
condTrue = (value != NULL && strcmp(value, attribValue) == 0);
if (changed)
FreeMemory(attribValue);
}
else
{
/* block macro, comparisons not allowed */
condTrue = FALSE;
}
}
/* reverse conditional if NOT attribute found */
if(notTagFound == TRUE)
{
condTrue = (condTrue == TRUE) ? FALSE : TRUE;
}
return condTrue;
}
BOOL ProcessWhileBlock(TASK *task, STREAM* blockStream)
{
TASK newTask;
BOOL result;
HtpMsg(MSG_INFO, task->infile, "expanding WHILE loop");
/* build a new task structure */
newTask.infile = blockStream;
newTask.outfile = task->outfile;
newTask.sourceFilename = task->sourceFilename;
newTask.varstore = task->varstore;
/* process the new input file */
result = ProcessTask(&newTask);
CloseStream(blockStream);
return result;
}
uint WhileProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
static uint whileLevel = 0;
BOOL condTrue;
BOOL notTagFound;
STREAM blockFile;
STREAM inFile;
HTML_ATTRIBUTE *attrib;
UNREF_PARAM(newPlaintext);
condTrue = FALSE;
/* conditionalLevel keeps track of boolean depth */
if(whileLevel == 0)
{
if((IsMarkupTag(htmlMarkup, "/WHILE")))
{
HtpMsg(MSG_ERROR, task->infile, "while block must start with WHILE tag");
return MARKUP_ERROR;
}
}
if(IsMarkupTag(htmlMarkup, "WHILE"))
{
whileLevel++;
/* this is an ugly way to handle the IF-IF NOT test, but will need */
/* be cleaned up in the future */
notTagFound = UnlinkBoolAttributeInMarkup(htmlMarkup, "NOT");
/* should be exactly one remaining attribute in markup */
attrib = htmlMarkup->attrib;
if (attrib == NULL)
{
HtpMsg(MSG_ERROR, task->infile, "no conditional to test");
return MARKUP_ERROR;
}
if(attrib->next != NULL)
{
HtpMsg(MSG_ERROR, task->infile, "too many items in conditional expression");
return MARKUP_ERROR;
}
htmlMarkup->attrib = NULL;
condTrue = ConditionValue(task, attrib, notTagFound);
if (condTrue == ERROR) {
DestroyAttribute(attrib);
FreeMemory(attrib);
return MARKUP_ERROR;
}
if(ReadinBlock(task, htmlMarkup, &blockFile) == FALSE)
{
DestroyAttribute(attrib);
FreeMemory(attrib);
return MARKUP_ERROR;
}
while (condTrue) {
/* condition is true, so we have to expand the block */
CreateBufferReader(&inFile, &blockFile);
if(! ProcessWhileBlock(task, &inFile)) {
CloseStream(&blockFile);
DestroyAttribute(attrib);
FreeMemory(attrib);
return MARKUP_ERROR;
}
/* check condition */
condTrue = ConditionValue(task, attrib, notTagFound);
if (condTrue == ERROR) {
CloseStream(&blockFile);
DestroyAttribute(attrib);
FreeMemory(attrib);
return MARKUP_ERROR;
}
}
CloseStream(&blockFile);
DestroyAttribute(attrib);
FreeMemory(attrib);
return DISCARD_MARKUP;
}
else
{
/* end of while */
assert(whileLevel > 0);
whileLevel--;
}
return DISCARD_MARKUP;
}
htp-1.16/src/bool-proc.h 0000644 0000510 0000310 00000000676 10665777571 014767 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// bool-proc.h
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef BOOL_PROC_H
#define BOOL_PROC_H
#include "defs.h"
uint BooleanProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
#endif
htp-1.16/src/def-proc.h 0000644 0000510 0000310 00000001743 10665777571 014566 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// def-proc.h
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef DEF_PROC_H
#define DEF_PROC_H
#include "defs.h"
/* Reads in a block and puts it into a temporary file. The name of
* the temporary file is put into newFilename, which must be able to hold
* MAX_PATHNAME_LEN characters.
*/
void BlockDestructor(const char *name, void *value,
uint type, uint flags, void *param);
BOOL ReadBlockToFile(TASK *task, BOOL expand,
const char *tag, STREAM *blockStream);
BOOL ReadinBlock(TASK *task, HTML_MARKUP *htmlMarkup, STREAM *blockStream);
uint BlockProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
uint UndefProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
#endif
htp-1.16/src/defs.h 0000600 0000510 0000310 00000010401 10665777571 013767 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// defs.h
//
// major definitions
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef DEFS_H
#define DEFS_H
#include "htp.h"
/*
// default response filename
*/
extern const char *DEFAULT_RESPONSE_FILE;
/*
// 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)
#define VAR_TYPE_BLOCKDEF_MACRO (6)
/*
// variable flags
*/
#define VAR_FLAG_NONE (0x0000)
#define VAR_FLAG_DEALLOC_VALUE (0x0002)
#define VAR_FLAG_DEALLOC_NAME (0x0004)
#define VAR_FLAG_UNDEFINED (0x0008)
/*
// 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 (2048)
#define PLAINTEXT_GROW_SIZE (2048)
#endif
/*
// miscellaneous definitions
*/
#define MAX_TIME_DATE_SIZE (128)
#define DEFAULT_PRECISION (0)
#define SEARCH_PATH_SIZE (1024)
#define MAX_CONDITIONAL_LEVEL (32)
/*
// 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
{
STREAM *infile;
STREAM *outfile;
VARSTORE *varstore;
const char *sourceFilename;
uint conditionalLevel;
uint conditionalLine[MAX_CONDITIONAL_LEVEL];
} 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
*/
extern const char *VAR_TEMPLATE_NAME;
/*
// 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 ('>')
extern char htpOpenMarkup;
extern char htpCloseMarkup;
#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)
/*
// include file search path
*/
extern char searchPath[SEARCH_PATH_SIZE];
#endif
htp-1.16/src/file-proc.h 0000644 0000510 0000310 00000001535 10665777571 014746 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// -proc.h
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef FILE_PROC_H
#define FILE_PROC_H
#include "defs.h"
/*
uint ExternalFileProcessor(TASK *task, HTML_MARKUP *htmlMarkup,
const char *externalName, char **newPlaintext);
uint FileExecuteProcessor(TASK *task, HTML_MARKUP *htmlMarkup);
uint FileTemplateProcessor(TASK *task, HTML_MARKUP *htmlMarkup);
uint FileIncludeProcessor(TASK *task, HTML_MARKUP *htmlMarkup);
*/
uint FileProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
uint OutputProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
#endif
htp-1.16/src/gif.h 0000644 0000510 0000310 00000000560 10665777571 013630 0 ustar hoenicke fb10-sem /*
//
// gif.h
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef GIF_H
#define GIF_H
/* GIF format detected? */
BOOL GifFormatFound(FILE *file);
/* get image dimensions */
BOOL GifReadDimensions(FILE *file, DWORD *height, DWORD *width);
#endif
htp-1.16/src/html.h 0000644 0000510 0000310 00000003705 10665777571 014033 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// html.h
//
// HTML markup tag functions
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef MARKUP_H
#define MARKUP_H
#define MAX_ATTRIBUTE_COUNT (32)
#define QUOTES_NONE 0
#define QUOTES_DOUBLE 1
#define QUOTES_SINGLE 2
typedef struct tagHTML_ATTRIBUTE
{
char *name;
char *value;
int quotes;
char *whitespace;
struct tagHTML_ATTRIBUTE *next;
} HTML_ATTRIBUTE;
typedef struct tagHTML_MARKUP
{
char *tag;
BOOL single; /* single tag (xml-style) ending with "/>" */
char *whitespace;
HTML_ATTRIBUTE *attrib;
} HTML_MARKUP;
/*
// functions
*/
/* whitespace functions are not specific to markup tags, but commonly used */
const char *FindWhitespace(const char *str);
const char *FindNonWhitespace(const char *str);
/* HTML_ATTRIBUTE functions */
BOOL ChangeAttributeName(HTML_ATTRIBUTE *htmlAttribute, char *name);
BOOL ChangeAttributeValue(HTML_ATTRIBUTE *htmlAttribute, char *value,
int quotes);
void DestroyAttribute(HTML_ATTRIBUTE *htmlAttribute);
/* HTML_MARKUP functions */
BOOL PlaintextToMarkup(const char *plaintext, HTML_MARKUP *htmlMarkup);
BOOL MarkupToPlaintext(HTML_MARKUP *htmlMarkup, char **plaintext);
BOOL AddAttributeToMarkup(HTML_MARKUP *htmlMarkup,
const char *name, const char *value, int quotes);
void DestroyMarkupStruct(HTML_MARKUP *htmlMarkup);
BOOL IsMarkupTag(HTML_MARKUP *htmlMarkup, const char *tag);
BOOL UnlinkBoolAttributeInMarkup(HTML_MARKUP *htmlMarkup, const char *name);
const char *MarkupAttributeValue(HTML_MARKUP *htmlMarkup, const char *name);
BOOL ChangeMarkupTag(HTML_MARKUP *htmlMarkup, char *tag);
HTML_ATTRIBUTE *UnlinkAttributeInMarkup(HTML_MARKUP *htmlMarkup, const char *name);
#endif
htp-1.16/src/htp-files.h 0000644 0000510 0000310 00000003152 10665777571 014756 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// htp-files.h
//
// htp specific file access
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef HTP_FILES_H
#define HTP_FILES_H
#include "defs.h"
/*
// 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);
/*
// 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);
/*
// searches for the specified file in the search path ... this function is
// very stupid, it simply gets the first directory in the search string,
// appends the file directly to the end, and tests for existance. Repeat.
*/
BOOL SearchForFile(const char *filename, char *fullPathname, uint size);
/*
// TRUE = htlmMarkup is filled with new markup, FALSE if end of file,
// ERROR if a problem
// !! Don't like using ERROR in any BOOL return values
*/
BOOL ReadHtmlMarkup(STREAM *infile, STREAM *outfile,
uint *markupType, HTML_MARKUP *htmlMarkup);
BOOL FullyCheckDependencies(const char *in, const char *out);
#endif
htp-1.16/src/htp.h 0000644 0000510 0000310 00000006337 10665777571 013666 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// htp.h
//
// Common include file
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef HTP_H
#define HTP_H
/*
// for assert()
*/
#ifndef DEBUG
#define NDEBUG
#endif
/*
// common definitions
*/
typedef unsigned int BOOL;
#define FALSE (0)
#define TRUE (1)
#define ERROR ((uint) -1)
#define NUL ((char) 0)
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
/*
// common data sizes
*/
#define KBYTE (1024L)
#define MBYTE (KBYTE * KBYTE)
#define GBYTE (MBYTE * KBYTE)
/*
// debug information macro
*/
#if DEBUG
#define DEBUG_PRINT(p) \
DebugMsg("\n(%s) %s line %u: ", PROGRAM_NAME, __FILE__, __LINE__); \
DebugMsg p; \
DebugMsg("\n");
#else
#define DEBUG_PRINT(p)
#endif
/*
// macros to handle unused/unreferenced local variables & parameters in
// functions
//
// DEBUG_* macros are defined as nothing in non-debug version, too catch
// unreferenced stuff in final build version
//
// Macros wholesale ripped off from Windows NT device driver kit ... if
// they originated elsewhere, this is the first I've seen them
*/
#define UNREF_PARAM(p) ((p) = (p))
#define UNREF_LOCAL(l) ((l) = (l))
#if DEBUG
#define DEBUG_UNREF_PARAM(p) ((p) = (p))
#define DEBUG_UNREF_LOCAL(l) ((l) = (l))
#else
#define DEBUG_UNREF_PARAM(p)
#define DEBUG_UNREF_LOCAL(l)
#endif
/*
// common macros
*/
#define MAKE_WORD(h, l) ((((WORD) (h)) << 8) | ((WORD) (l)))
#define MAKE_DWORD(hh,hl,lh,ll) \
((((DWORD) (hh)) << 24) | (((DWORD)(hl)) << 16) \
| (((DWORD) (lh)) << 8) | ((DWORD)(ll)))
/*
// C library
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
// operating-system dependent header file
*/
#include "os.h"
/*
// modules
*/
#include "image.h"
#include "html.h"
#include "ver.h"
#include "textfile.h"
#include "streams.h"
#include "varstore.h"
#include "msg.h"
#include "suballoc.h"
/*
// returns the markup type flag ... either the closing or opening delimiter
// in the markup can be passed in
*/
uint MarkupType(char delim);
/*
// common functions (maintained in util.c)
*/
BOOL CreateTempFilename(char *tempfilename, uint size);
char *StringCopy(char *dest, const char *src, uint size);
char *ConvertDirDelimiter(const char *pathname);
BOOL FileExists(const char *pathname);
const char *FindFilename(const char *pathname);
char *DuplicateString(const char *src);
char *DuplicateSubString(const char *src, int len);
#ifndef HAVE_STPCPY
char *stpcpy(char *dest, const char *src);
#endif
/*
// re-entrant strtok() functions and structures
*/
typedef struct tagFIND_TOKEN
{
const char *tokens;
char *lastChar;
char *nextStart;
} FIND_TOKEN;
char *StringFirstToken(FIND_TOKEN *findToken, char *string, const char *tokens);
char *StringNextToken(FIND_TOKEN *findToken);
#endif
htp-1.16/src/image-proc.h 0000644 0000510 0000310 00000001144 10665777571 015105 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// image-proc.h
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef IMAGE_PROC_H
#define IMAGE_PROC_H
#include "defs.h"
uint ImageProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
uint AltTextProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
uint ImageUrlProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
#endif
htp-1.16/src/image.h 0000644 0000510 0000310 00000001312 10665777571 014141 0 ustar hoenicke fb10-sem /*
//
// image.h
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef IMAGE_H
#define IMAGE_H
/*
// image file structure
*/
typedef struct tagIMAGEFILE
{
char *name;
FILE *file;
uint imageType;
} IMAGEFILE;
BOOL OpenImageFile(const char *filename, IMAGEFILE *imageFile);
void CloseImageFile(IMAGEFILE *imageFile);
BOOL GetImageDimensions(IMAGEFILE *imageFile, DWORD *width, DWORD *height);
/*
// image url substitution
*/
BOOL ExistsImageUrl (const char *url);
BOOL StoreImageUrl (const char *url, char* path);
BOOL RemoveImageUrl (const char *url);
#endif
htp-1.16/src/jpeg.h 0000644 0000510 0000310 00000000635 10665777571 014013 0 ustar hoenicke fb10-sem /*
//
// jpeg.h
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef JPEG_H
#define JPEG_H
/* is this a JPEG File Interchange Format (JFIF) file? */
BOOL JpegFormatFound(FILE *file);
/* one-shot-does-it-all function */
BOOL JpegReadDimensions(FILE *file, DWORD *height, DWORD *width);
#endif
htp-1.16/src/macro.h 0000644 0000510 0000310 00000001377 10665777571 014173 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// macro.h
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef MACRO_H
#define MACRO_H
#include "defs.h"
BOOL ExpandMacrosInString(TASK *task, const char *text, char **newText,
int *quoted, uint *changeCount);
BOOL ExpandMacros(TASK *task, HTML_MARKUP *htmlMarkup);
#define METATAG_MAX_OPTIONS (256)
uint ExpandMetatag(TASK *task, HTML_MARKUP *htmlMarkup);
uint ExpandAll(TASK *task, HTML_MARKUP *htmlMarkup,
char** newPlaintextPtr, uint markupType);
#endif
htp-1.16/src/misc-proc.h 0000644 0000510 0000310 00000001401 10665777571 014752 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// misc-proc.h
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef MISC_PROC_H
#define MISC_PROC_H
#include "defs.h"
uint HeadProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
uint QuoteProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
uint HtpCommentProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
uint ConditionalWarning(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
uint PreProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
#endif
htp-1.16/src/msg.h 0000644 0000510 0000310 00000001616 10665777571 013654 0 ustar hoenicke fb10-sem /*
//
// msg.h
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef MSG_H
#define MSG_H
/*
// message severity levels
*/
#define MSG_ERROR (2)
#define MSG_WARNING (1)
#define MSG_INFO (0)
/*
// set the printable message level ... if the message being written
// does not meet the level, it is not printed
*/
void SetMessageSeverityLevel(uint level);
/*
// error/warning/info message display function
*/
#ifndef DUMB_MSG_PROTOTYPE
void HtpMsg(uint severityLevel, STREAM *textFile, const char *format, ...);
#endif
#if DEBUG
/*
// debug message display, which also will dump to disk
*/
void DebugInit(const char *debugMsgFilename);
void DebugTerminate(void);
#ifndef DUMB_MSG_PROTOTYPE
void DebugMsg(const char *format, ...);
#endif
#endif
#endif
htp-1.16/src/option.h 0000644 0000510 0000310 00000004324 10665777571 014375 0 ustar hoenicke fb10-sem /*
//
// option.h
//
// Program options and setting
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef OPTION_H
#define OPTION_H
#include "defs.h"
/* option names */
#define OPT_I_IMGXY 0
#define OPT_I_MESSAGE 1
#define OPT_I_DEPEND 2
#define OPT_I_PRECIOUS 3
#define OPT_I_CONDENSE 4
#define OPT_I_USAGE 5
#define OPT_I_DELIM 6
#define OPT_I_XML 7
#define OPT_I_COUNT 8
/* option values */
#define OPT_V_FALSE 0
#define OPT_V_TRUE 1
#define OPT_V_SEMI 2
#define OPT_V_DELIM_HTML 3
#define OPT_V_DELIM_SQUARE 4
#define OPT_V_DELIM_CURLY 5
/* maximum length of an option name */
#define MAX_OPTION_LENGTH 32
extern uint *currentOptions;
/* these are used at the beginning and end of program execution, respectively */
BOOL InitializeGlobalOption(void);
void DestroyGlobalOption(void);
/* these are used at the beginning and end of local context, that is, as a new */
/* file is being created and completed */
BOOL InitializeLocalOption(void);
void DestroyLocalOption(void);
/* parse text or markups for options ... global setting dictates whether to */
/* use current context or default to global option settings */
BOOL ParseToken(TASK *task, const char *string);
uint OptionProcessor(TASK *task,
HTML_MARKUP *htmlMarkup,
char **newPlaintext);
/* retrieve option information ... IsOptionEnabled() doesnt mean much for */
/* options that require values rather than boolean states, and for boolean */
/* options, GetOptionValue() returns OPT_V_TRUE or OPT_V_FALSE */
#define IsOptionEnabled(i) (currentOptions[i] == OPT_V_TRUE)
#define IsOptionValue(i,v) (currentOptions[i] == (v))
#define GetOptionValue(i) (currentOptions[i])
/* macros for quick lookups */
#define IMGXY (IsOptionEnabled(OPT_I_IMGXY))
#define DEPEND (IsOptionEnabled(OPT_I_DEPEND))
#define PRECIOUS (IsOptionEnabled(OPT_I_PRECIOUS))
#define CONDENSE (IsOptionValue(OPT_I_CONDENSE,OPT_V_TRUE))
#define SEMICONDENSE (IsOptionValue(OPT_I_CONDENSE,OPT_V_SEMI))
#define USAGE (IsOptionEnabled(OPT_I_USAGE))
#endif
htp-1.16/src/os.h 0000644 0000510 0000310 00000005226 10665777571 013510 0 ustar hoenicke fb10-sem /*
//
// os.h
//
// Operating system definitions and constants
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef OS_H
#define OS_H
#if __MSDOS__
#define PROGRAM_OS ("DOS")
/*
// this section should (but is not guaranteed) to conform to most MS-DOS
// compilers
*/
#include
/* not defined in the standard include files */
typedef unsigned int uint;
typedef unsigned long ulong;
/* directory delimiters */
#define DIR_DELIMITER '\\'
#define DIR_DELIMITER_STRING "\\"
#define DIR_CURRENT_STRING ".\\"
/* the "other" filesystem delimiter table (for conversion) */
#define OTHER_FILESYSTEM_DELIMITER "/"
/* DOS filesystem does not support pathnames beyond 64 characters (!!) */
#define MAX_PATHNAME_LEN (64)
#define MAX_CMDLINE_LEN (128)
#define MAX_FILENAME_LEN (13)
#elif defined(__WIN32__) || defined(_WIN32)
#define PROGRAM_OS ("Win32")
/*
// this section specifically designed for Microsoft Visual C++ 4.0
*/
#include
/* not defined in the standard include files */
typedef unsigned int uint;
typedef unsigned long ulong;
/* directory delimiters */
#define DIR_DELIMITER '\\'
#define DIR_DELIMITER_STRING "\\"
#define DIR_CURRENT_STRING ".\\"
/* the "other" filesystem delimiter table (for conversion) */
#define OTHER_FILESYSTEM_DELIMITER "/"
/* Win32 filesystem supports long filenames! */
#define MAX_PATHNAME_LEN (1024)
#define MAX_CMDLINE_LEN (1024)
#define MAX_FILENAME_LEN (256)
#else
#define PROGRAM_OS ("Linux/Posix")
/*
// Linux/UNIX is the only other OS being actively developed
// other UNIX platforms should pretty much look like this, though
*/
#include
#define stricmp strcasecmp
#define strnicmp strncasecmp
#if __CYGWIN__
typedef unsigned long ulong;
#endif
/* directory delimiters */
#define DIR_DELIMITER '/'
#define DIR_DELIMITER_STRING "/"
#define DIR_CURRENT_STRING "./"
/* the "other" filesystem delimiter table (for conversion) */
#define OTHER_FILESYSTEM_DELIMITER "\\"
/* max pathname for UNIX (may be more, but this is sufficient) */
/* (BTW, these values may be incorrect, but they should be sufficient. */
/* Anyone with more concrete values, please email me.) */
#define MAX_PATHNAME_LEN (256)
#define MAX_CMDLINE_LEN (1024)
#define MAX_FILENAME_LEN (32)
#endif
/*
// all supported filesystem delimiters
*/
#define ALL_FILESYSTEM_DELIMITERS "/\\"
#endif
htp-1.16/src/png.h 0000644 0000510 0000310 00000000561 10665777571 013650 0 ustar hoenicke fb10-sem /*
//
// png.h
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef PNG_H
#define PNG_H
/* PNG format detected? */
BOOL PngFormatFound(FILE *file);
/* get image dimensions */
BOOL PngReadDimensions(FILE *file, DWORD *height, DWORD *width);
#endif
htp-1.16/src/set-proc.h 0000644 0000510 0000310 00000001167 10665777571 014623 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// set-proc.h
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef SET_PROC_H
#define SET_PROC_H
#include "defs.h"
uint SetProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
uint UnsetProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
#define MAX_INC_VALUE_LENGTH (32)
uint IncProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
#endif
htp-1.16/src/snprintf.h 0000644 0000510 0000310 00000001652 10665777571 014731 0 ustar hoenicke fb10-sem #ifndef _PORTABLE_SNPRINTF_H_
#define _PORTABLE_SNPRINTF_H_
#define PORTABLE_SNPRINTF_VERSION_MAJOR 2
#define PORTABLE_SNPRINTF_VERSION_MINOR 2
#ifdef HAVE_SNPRINTF
#include
#else
extern int snprintf(char *, size_t, const char *, /*args*/ ...);
extern int vsnprintf(char *, size_t, const char *, va_list);
#endif
#if defined(HAVE_SNPRINTF) && defined(PREFER_PORTABLE_SNPRINTF)
extern int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...);
extern int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap);
#define snprintf portable_snprintf
#define vsnprintf portable_vsnprintf
#endif
extern int asprintf (char **ptr, const char *fmt, /*args*/ ...);
extern int vasprintf (char **ptr, const char *fmt, va_list ap);
extern int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...);
extern int vasnprintf(char **ptr, size_t str_m, const char *fmt, va_list ap);
#endif
htp-1.16/src/streams.h 0000644 0000510 0000310 00000003542 10665777571 014544 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// $Id: streams.h,v 1.5 2002/10/15 12:30:07 hoenicke Exp $
//
// file/buffer stream functions
//
// Copyright (c) 2001 Jochen Hoenicke under Artistic License.
//
*/
#ifndef STREAM_H
#define STREAM_H
#include "textfile.h"
#define STREAM_FLAG_BUFFER 1
#define STREAM_FLAG_NULL_FILE 2
#define STREAM_FLAG_READER 4
#define BITS_PER_UNIT (8*sizeof(unsigned long))
typedef unsigned long bitmap[256 / BITS_PER_UNIT];
#define BITMAP_COFF(c) (((unsigned char)(c))/BITS_PER_UNIT)
#define BITMAP_CMASK(c) ((unsigned long)1 << ((c) & (BITS_PER_UNIT-1)))
#define BITMAP_SET(b,c) b[BITMAP_COFF(c)] |= BITMAP_CMASK(c)
#define BITMAP_GET(b,c) (b[BITMAP_COFF(c)] & BITMAP_CMASK(c))
typedef struct tagSTREAMBUFFER {
char *buffer;
ulong offset;
ulong length;
} STREAMBUFFER;
typedef struct tagSTREAM {
uint sflags;
uint lineNumber;
const char *name;
BOOL hasUnread;
char unread;
union {
TEXTFILE textfile;
STREAMBUFFER buffer;
} u;
} STREAM;
BOOL CreateNullWriter (STREAM* stream);
BOOL CreateBufferWriter (STREAM* stream, const char *name);
BOOL CreateBufferReader (STREAM* stream, STREAM *writeStream);
BOOL FlushBufferWriter (STREAM *stream);
BOOL CreateFileReader (STREAM *stream, const char *filename);
BOOL CreateFDReader (STREAM *stream, const char *filename, int fd);
BOOL CreateFileWriter (STREAM *stream, const char *filename, BOOL append);
void CloseStream (STREAM *stream);
BOOL GetStreamChar(STREAM *stream, char *c);
BOOL UnreadStreamChar(STREAM *stream, char c);
BOOL GetStreamBlock(STREAM *stream, char *buffer, uint size, char delims[3]);
BOOL PutStreamString(STREAM *stram, const char *buffer);
BOOL StreamPrintF(STREAM *stream, const char *format, ...);
void ForceLinefeeds(STREAM *stream, BOOL forced);
#endif
htp-1.16/src/suballoc.h 0000644 0000510 0000310 00000007113 10665777571 014670 0 ustar hoenicke fb10-sem /*
//
// suballoc.h
//
// Memory suballocation ... rather than go out to heap for all the memory,
// htp maintains a small cache of recently allocated memory for speedier
// requests
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef SUBALLOC_H
#define SUBALLOC_H
/*
//#undef USE_SUBALLOC
*/
#ifndef USE_SUBALLOC
#define AllocMemory(size) malloc(size)
#define FreeMemory(ptr) free(ptr)
#define ResizeMemory(ptr, newSize) realloc(ptr, newSize)
#else
/*
// performance counters
*/
#if DEBUG
extern uint totalAllocations;
extern uint freePoolHits;
#endif
/*
// suballoc has several features that can be controlled via #defines
// most features are turned off for release versions of the software to
// speed up execution
//
// These features are:
//
// SUBALLOC_WARNING prints warning to stdout when problems are
// detected
//
// SUBALLOC_CLEARMEM all memory is cleared with a special bit
// pattern (not all zero or all one) when
// allocated and freed
//
// SUBALLOC_DEBLOG will print all allocs and frees to a debug
// log
//
// SUBALLOC_MINALLOCSIZE size (in bytes) of minimum allocation ...
// helps prevent heap thrashing when lots of
// small allocations occur ... if set to 0
// then allocation sizes match requested size
//
// SUBALLOC_FIRSTFIT if set, suballoc pulls the first properly sized
// block out of its free pool, rather than the
// one with the best fit ... faster, but may lead
// to unnecessary allocs from the system heap
//
// SUBALLOC_MAXFREEPOOLSIZE if set, suballoc will keep the free pool
// size equal to or less than this amount
// ... too small a size will lead to excessive
// heap allocations, too large could cause the
// program to keep vital memory from the operating
// system
//
*/
#define SUBALLOC_MINALLOCSIZE (64)
#define SUBALLOC_FIRSTFIT (1)
#if DEBUG
#define SUBALLOC_WARNING (1)
#define SUBALLOC_CLEARMEM (1)
#define SUBALLOC_DEBLOG (0)
#else
#define SUBALLOC_WARNING (0)
#define SUBALLOC_CLEARMEM (0)
#define SUBALLOC_DEBLOG (0)
#endif
#if __MSDOS__
#define SUBALLOC_MAXFREEPOOLSIZE (60 * KBYTE)
#else
#define SUBALLOC_MAXFREEPOOLSIZE (512 * KBYTE)
#endif
/*
// Initialize and terminate functions ... should be called before and
// after using following functions
*/
void InitializeMemory(void);
void TerminateMemory(void);
/*
// AllocMemory
//
// malloc() look-alike
*/
void *_AllocMemory(uint size, const char *file, uint line);
#define AllocMemory(size) _AllocMemory(size, __FILE__, __LINE__)
/*
// FreeMemory
//
// free() look-alike
*/
void _FreeMemory(void *ptr, const char *file, uint line);
#define FreeMemory(ptr) _FreeMemory(ptr, __FILE__, __LINE__);
/*
// ResizeMemory
//
// realloc() look-alike
*/
void *_ResizeMemory(void *ptr, uint newSize, const char *file, uint line);
#define ResizeMemory(ptr, newSize) \
_ResizeMemory(ptr, newSize, __FILE__, __LINE__)
/*
// MemorySize
//
// Returns available size of buffer
*/
uint MemorySize(void *ptr);
#endif
#endif
htp-1.16/src/textfile.h 0000644 0000510 0000310 00000001766 10665777571 014720 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// textfile.h
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef TEXTFILE_H
#define TEXTFILE_H
/*
// text file function
*/
typedef struct tagFILEINFO
{
FILE *file;
uint pendingSpaces;
BOOL emptyLine;
WORD flags;
} TEXTFILE;
/*
// TEXTFILE flags
*/
#define TEXTFILE_FLAG_NONE (0)
#define TEXTFILE_FLAG_NULL_FILE (0x0001)
#define TEXTFILE_FLAG_FORCE_CR (0x0002)
/*
// text file functions
*/
BOOL OpenFile(const char *filename, const char *openFlags, TEXTFILE *textFile);
BOOL OpenFD(int filedes, const char *openFlags, TEXTFILE *textFile);
void CloseFile(TEXTFILE *textFile);
void CreateNullFile(TEXTFILE *textFile);
BOOL GetFileChar(TEXTFILE *textFile, char *ch);
BOOL PutFileString(TEXTFILE *textFile, const char *ch);
#endif
htp-1.16/src/use-proc.h 0000644 0000510 0000310 00000000671 10665777571 014623 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// use-proc.h
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef USE_PROC_H
#define USE_PROC_H
#include "defs.h"
uint UseProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
#endif
htp-1.16/src/varstore.h 0000600 0000510 0000310 00000007171 10665777571 014725 0 ustar hoenicke fb10-sem /*
//
// varstore.h
//
// Variable store functions (implemented with a splay tree)
//
// Copyright (c) 1995-96 Jim Nelson.
// Copyright (c) 2002 Jochen Hoenicke.
// Released under Artistic License.
//
*/
#ifndef VARSTORE_H
#define VARSTORE_H
/*
// maximum length for the variable name and the variables value
*/
#define MAX_VARNAME_LEN (256)
#define MAX_VARVALUE_LEN (1024)
/*
// variable destructor callback ... set to NULL if no callback required when
// destroyed
*/
typedef void (*VAR_DESTRUCTOR)(const char *name, void *value,
uint type, uint flag, void *param);
/*
// a variable held in the store
*/
typedef struct tagVARIABLE
{
struct tagVARIABLE *left;
struct tagVARIABLE *right;
char *name;
void *value;
uint type;
uint flag;
void *param;
VAR_DESTRUCTOR destructor;
} VARIABLE;
/*
// variable store structure
//
// parent and child refers to scope ... when traversing the chain for a
// particular macro, always look to parent scope if not found in current
*/
typedef struct tagVARSTORE
{
struct tagVARSTORE *parent;
struct tagVARSTORE *child;
VARIABLE *root;
BOOL isGlobal;
} VARSTORE;
/*
// statistics for performance measurement
*/
#if DEBUG
extern uint variableLookups;
extern uint variableStringCompares;
extern uint variableRotations;
#endif
/*
// GetVariableType() will return this value if the variable is not found
*/
#define VAR_TYPE_UNKNOWN ((uint) -1)
/*
// GetVariableFlag() will return this value if the variable is not found
*/
#define VAR_FLAG_UNKNOWN ((uint) -1)
/*
// initialize a VARSTORE
*/
BOOL InitializeVariableStore(VARSTORE *varstore);
/*
// destroys a variable store and ALL child scope stores
*/
void DestroyVariableStore(VARSTORE *varstore);
/*
// Push, pop, and get current varstore context ... note that for pop and
// get, simply passing a variable store somewhere in the context will get
// or pop the topmost one, and for push it will find the topmost context
// before adding the new context
*/
void PushVariableStoreContext(VARSTORE *parent, VARSTORE *varstore);
VARSTORE *PopVariableStoreContext(VARSTORE *varstore);
/*
// add a variable to a store ... the store will keep its
// own copy of the variable kept, no need to maintain name and
// value once added
//
// Set destructor to NULL if no additional processing required before
// destroying the variable. Otherwise, pass a pointer to a function.
//
// Returns FALSE if unable to add variable into the store
*/
BOOL StoreVariable(VARSTORE *varstore, const char *name, void *value,
uint type, uint flag, void *param, VAR_DESTRUCTOR destructor);
/*
// Returns TRUE if variable found in store (case-insensitive)
*/
BOOL VariableExists(VARSTORE *varstore, const char *name);
/*
// A variable's destructor will be called from the context of these
// functions
*/
BOOL RemoveVariable(VARSTORE *varstore, const char *name);
/*
// Get variable information ... returns NULL for GetVariableValue(),
// VAR_TYPE_UNKNOWN for GetVariableType(), and VAR_FLAG_UNKNOWN for
// GetVariableFlag() if variable not in list
//
// GetVariableParam() returns NULL if not found ... since this is a valid
// return value, caller should really use VariableExists() first!
*/
void *GetVariableValue(VARSTORE *varstore, const char *name);
BOOL UpdateVariableValue(VARSTORE *varstore, const char *name, void* value);
uint GetVariableType(VARSTORE *varstore, const char *name);
uint GetVariableFlag(VARSTORE *varstore, const char *name);
void *GetVariableParam(VARSTORE *varstore, const char *name);
#endif
htp-1.16/src/ver.h 0000644 0000510 0000310 00000000541 10665777571 013656 0 ustar hoenicke fb10-sem /*
//
// ver.h
//
// version and program information
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef VER_H
#define VER_H
/*
// program version number
*/
#include "version.inc"
void DisplayHeader(void);
void usage(void);
#endif
htp-1.16/src/while-proc.h 0000644 0000510 0000310 00000000677 10665777571 015145 0 ustar hoenicke fb10-sem /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// while-proc.h
//
// specialized markup processors
//
// Copyright (c) 1995-96 Jim Nelson. Permission to distribute
// granted by the author. No warranties are made on the fitness of this
// source code.
//
*/
#ifndef WHILE_PROC_H
#define WHILE_PROC_H
#include "defs.h"
uint WhileProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext);
#endif
htp-1.16/src/LICENSE.txt 0000644 0000510 0000310 00000012430 10665777571 014534 0 ustar hoenicke fb10-sem This is the license for the sprintf.*
The Frontier Artistic License Version 1.0
Derived from the Artistic License at OpenSource.org.
Submitted to OpenSource.org for Open Source Initiative certification.
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to
make reasonable modifications.
Definitions
"Package" refers to the script, suite, file, or collection of
scripts, suites, and/or files distributed by the Copyright Holder,
and to derivatives of that Package created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes of
the Copyright Holder.
"Copyright Holder" is whoever is named in the copyright statement
or statements for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Reasonable copying fee" is whatever you can justify on the basis
of media cost, duplication charges, time of people involved, and
so on. (You will not be required to justify it to the Copyright
Holder, but only to the computing community at large as a market
that must bear the fee.)
"Freely Available" means that no fee is charged for the item
itself, though there may be fees involved in handling the item.
It also means that recipients of the item may redistribute it under
the same conditions they received it.
Terms
1. You may make and give away verbatim copies of the source form of
the Standard Version of this Package without restriction, provided
that you duplicate all of the original copyright notices and
associated disclaimers.
2. You may apply bug fixes, portability fixes, and other modifications
derived from the Public Domain or from the Copyright Holder. A Package
modified in such a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way,
provided that you insert a prominent notice in each changed script,
suite, or file stating how and when you changed that script, suite,
or file, and provided that you do at least ONE of the following:
a) Use the modified Package only within your corporation or
organization, or retain the modified Package solely for personal use.
b) Place your modifications in the Public Domain or otherwise make
them Freely Available, such as by posting said modifications to Usenet
or an equivalent medium, or placing the modifications on a major archive
site such as ftp.uu.net, or by allowing the Copyright Holder to include
your modifications in the Standard Version of the Package.
c) Rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page (or equivalent) for each non-standard executable
that clearly documents how it differs from the Standard Version.
d) Make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) Distribute a Standard Version of the executables and library
files, together with instructions (in the manual page or
equivalent) on where to get the Standard Version.
b) Accompany the distribution with the machine-readable source of
the Package with your modifications.
c) Accompany any non-standard executables with their corresponding
Standard Version executables, give the non-standard executables
non-standard names, and clearly document the differences in manual
pages (or equivalent), together with instructions on where to get
the Standard Version.
d) Make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of
this Package. You may charge any fee you choose for support of this
Package. You may not charge a fee for this Package itself. However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial)
software distribution provided that you do not advertise this Package
as a product of your own.
6. The scripts and library files supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whomever generated
them, and may be sold commercially, and may be aggregated with this
Package.
7. Scripts, suites, or programs supplied by you that depend on or
otherwise make use of this Package shall not be considered part of
this Package.
8. The name of the Copyright Holder may not be used to endorse or
promote products derived from this software without specific prior
written permission.
9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End
http://www.spinwardstars.com/frontier/fal.html
htp-1.16/tests/ 0000755 0000510 0000310 00000000000 10665777573 013266 5 ustar hoenicke fb10-sem htp-1.16/tests/Makefile 0000644 0000510 0000310 00000001075 10665777571 014727 0 ustar hoenicke fb10-sem #
# makefile - htp
#
# HTML pre-processor
# Copyright (c) 2002 Jochen Hoenicke
#
TOP=..
#
# object files used
#
HTP_DEF = htp.def files.hti
HTP_SRC = macro.htp files.htp wildcard.htp comments.htp options.htp png.htp \
expand.htp tags.htp ifelse.htp phptest.htp
HTML = $(HTP_SRC:%.htp=%.html)
HTP_EXP = $(HTP_SRC:%.htp=%.html.exp)
DISTFILES = Makefile $(HTP_SRC) $(HTP_DEF) $(HTP_EXP)
include $(TOP)/Makefile.config
all: run-htp check
check: $(HTML)
@for i in $(HTML); do \
$(DIFF) $$i $$i.exp || echo "TEST FAILED: $$i"; done
do-clean:
rm -f *~ htp.rsp *.html
htp-1.16/tests/macro.htp 0000644 0000510 0000310 00000001445 10665777571 015106 0 ustar hoenicke fb10-sem val2
macro1 is set
macro1 is empty string
macro5 is empty string
macro1: