/*
* The Shark CGI Function/0.3: a one line function for C CGI programming.
* Copyright (C) 2002,2003 Michel Blomgren - shark@zebra.ath.cx
*
* http://sharkcgi.sourceforge.net/
* http://sourceforge.net/projects/sharkcgi/
*
* This function is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This function is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this function ["LICENSE" file]; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
*
* NOTE! This function uses putenv(3) to put the variables in the environment.
* It takes for granted that putenv() aliases (don't copy) the environment
* string passed to it. I've provided a small program (src/putenvcheck.c) to
* check if your box aliases or copies the putenv()-string. If it copies, then
* beware, Shark will malloc(3) memory for each environment variable set up,
* and if putenv() copies then you'll end-up with twice the amount of allocated
* memory, all for nothing.
*
*
* The "Shark CGI Function" is referred to as simply "Shark" or "the function"
* from here on. It's only referred to such because it's more simple, it does
* not mean that simply "Shark" is the name of this function.
*
* Shark was inspired by the Un-CGI
* (http://www.midwinter.com/~koreth/uncgi.html) by Steven Grimm,
* koreth@midwinter.com. Steve wrote "Unescape all the fields in a form and
* stick them in the environment so they can be used without awful
* machinations". That pretty much sums up what this routine does.
*
*
* Features:
*
* o Shark handles GET and POST forms by setting up the variable
* name and the variable's content, e.g. for a POST form you'll
* have the environment variable "sharkp_varname=varcontent" and
* for a GET form you'll have the environment variable
* "sharkg_varname=varcontent".
*
* o Shark handles multipart/form-data by extracting all variables
* and putting them in the environment (e.g.
* "sharkmulti_varname=varcontent"). It extracts files that have
* been uploaded and puts them in temporary files, which could
* easily be accessed by the "sharkfile_" environment variable
* (e.g. "sharkfile_varname=/tmp/shark.temp/upload.4531").
*
* o It also handles cookies by extracting any type of URL or ";"-
* terminated cookie format strings. E.g. cookie strings could be
* either "varname=varcontens; varname=varcontens;" or URL-encoded
* strings;
* "cookievar1=hello&cookievar2=hello+world;" (or both), e.g.
*
* o It's not necessary for you, the CGI coder, to remove any
* temporary files that have been created during a file upload,
* Shark will automatically remove any tempfiles that are over 30
* seconds old. This check is done every time Shark is executed.
*
* o In case of error, Shark will report an "Apache-like" error
* message to the requester (the end-user).
*
* o Variables that already exist in the environ will be numbered,
* e.g. if variable "sharkp_fruit" is already defined and another
* "sharkp_fruit" is about to be defined it will be named
* "sharkp_fruit2". This is good for "<select multiple>"
* input-fields.
*
*
* Bad features (or "so many good features and no bad ones?"):
*
* o I have to admit that the multipart/form-data function is
* currently too slow, ideas on making it faster is highly
* appreciated! Here are some stats...
*
* While imitating a CGI environment and emulating a 970KB upload
* of two files, I time(1)'d it and I got these "real" times on
* different systems (this is _excluding_ any potential upload
* time, which was not emulated):
*
* On an AMD Athlon XP 1800+ running Linux: 0.163s.
* On a COMPAQ AlphaServer DS20E 666 MHz (2 processors) running Linux: 0.183s.
* On a 375MHz PPC (604ev5 - MachV) running Linux: 0.49s.
* On a TI UltraSparc II (BlackBird) running Linux: 0.34s.
* On a R220 (SPARC) running SunOS 5.8: 0.5s.
* On a dual Intel P3 Xeon 500Mhz running FreeBSD: 0.98s.
*
* o One idea to make it faster would be to mmap(2) stdin instead of
* first allocating enough space with malloc(3) and then reading
* stdin into that buffer, which is probably somewhat slower.
* Though the major time-consumer is probably shark__locateit()
* used by shark__get_filename().
*
*
* Not supported:
*
* o The "multipart/mixed" format is not supported yet, sorry!
*
*
* Comments could be emailed to shark@zebra.ath.cx
*
* / Michel Blomgren, Dec 28 2002
*
*
* Usage: Add an extern definition in your main C file, either globally
* or under main() or where ever (e.g. "extern int shark();").
*
* Example C code:
*
*-----------------------------------------------------------------------------
* #include <stdio.h>
* #include <stdlib.h>
* #include <unistd.h>
* #include <sys/wait.h>
*
* extern int shark();
*
* int main()
* {
* char *program = "env";
* int pid;
*
* // a simple way to call shark
* // shark() always return 0 if OK, 1 if error occured...
*
* if (shark())
* return(1);
*
* printf("Content-type: text/plain\n\n");
* fflush(stdout);
*
* pid = fork();
*
* if (pid == 0)
* {
* execlp(program, program, NULL);
* printf("error executing %s!\n", program);
* return(-1);
* }
*
* wait(NULL);
*
* return 0;
* }
* ----------------------------------------------------------------------------
*
*
* How to compile:
*
* Shark compiles successfully with GCC, the following are known
* to work without any problem:
*
* gcc version 2.95.3 20010315 (release)
* gcc version 2.95.4 20020320 [FreeBSD]
* gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-112)
*
* You can not use Sun's "ucbcc"! Why? Because the d_name in the
* dirent structure starts 2 bytes off, so dp->d_name return a
* pointer where the first two characters of each file name is
* missing. If ucbcc didn't have this "bloat", Shark compiles and
* work correctly (proven and tested) with "ucbcc: Sun WorkShop 6
* update 1 C 5.2 2000/09/11".
*
* Compilation example ("$" is your prompt):
*
* $ gcc -Wall -s -O3 shark.c yourcgi.c -o yourcgi.cgi
*
* A big THANK YOU goes to SourceForge.net for their Compile Farm
* feature. Without access to the Compile Farm servers this
* function wouldn't have been as portable as it currently is.
*
*
* A few tips:
*
* o Don't do a 'printf("Content-type: text/html\n\n");'
* before calling shark(); first. shark(); will, in case
* of error, print a html error message.
*
* o Avoid using "international" characters in variable names
* (e.g. '<input name=s�kf�lt ....'). It's not "considered"
* standard in the environment to have those chars in the vars,
* but "technically" there are no problems what so ever.
*
*
*/
/*
* Here I list all functions in Shark that I've included (so far), some of
* which you might find useful in your C cgi. Just copy this part and put it
* into your C source. You'll find a thorough documentation of these functions
* in the README-file.
*
extern int shark(void);
extern int makelowercase(char *);
extern int makeuppercase(char *);
extern void unescape(char *);
extern char *findstringci(char *, char *);
extern void removechar(char *, unsigned int);
extern char *findzero(char *);
extern void removelastlf(char *);
extern char *percentencode(char *);
extern int cat(char *, FILE *);
extern void namealize(char *);
extern void truncatebuf(char *, unsigned int);
extern char *mallocfile(char *, unsigned int *);
extern char *getarg(char *, unsigned int delim,