This is gform.c in view mode; [Download] [Up]
/*** * gform - A generic HTML form decoder * * It takes a HTML form file and scans * this file for comments beginning with <!--gform ....> * These are taken to be formatting info and delivery commands * for gform. * * See gform.txt for description and samples * * Swinburne University of Technology and the author will not be * responsible for any damages or loss suffered or incurred by * any user or any other person arising in any way from the use * of this software. No warranty of any kind, either express or * implied is given. You may copy, modify and redistribute it. * * Ver 1.1e harry@swin.edu.au 8-Nov-95 Swinburne University * * Contibutions: * jem@sunsite.unc.edu University of North Caroline * * See CHANGES for change history. ***/ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <ctype.h> #include <time.h> #include <string.h> #include "config.h" #define bzero(s,n) memset(s,0,n) #include <stdlib.h> #define LEN 4096 /* keywords for gform */ #define DELIVER "DELIVER" /* indicates delivery method */ #define MAIL "MAIL" /* a delivery method */ #define FFILE "FILE" /* a delivery method */ #define PRINT "PRINT" /* Send to printer */ #define SUBJECT "SUBJECT" /* Subject of mail mesg */ #define REPLY "REPLY" /* reply to form submission */ #define GFORM_TAG "<!GFORM " /* gform command line keyword */ #define GFORM_TAG2 "<!--GFORM " /* gform command line keyword */ /* commandline parsing states */ #define NSTATE 0 /* NULL state */ #define TSTATE 1 /* text string with variables */ #define SKIP_WHITE(a) while (isspace(*a)) a++ struct entry { char *name; char *val; struct entry *next; }; /* from cgi-bin/util.c */ char *fmakeword(); char *makeword(); void unescape_url(); void plustospace(); char *tildeexpand(); /* func prototypes */ char *decode_commands(); char *command(); void print_header(); char *strnupr(); void error(); char *insert_value(); char *do_escapes(); int send_to_file(); int isendtag(); char *get_html_filename(); char *get_cmd_val(); struct entry *entries, *head; int state, linecount, printit=0; char *outfile, *address, *subject, DEFSUBJECT[256], *queue, *replyfile, *webhome, date[12], ttime[12]; main(argc, argv) int argc; char *argv[]; { int len,i, line[LEN]; char s[256], *word, *buf, *tmp, *tmp2, *fname; FILE *f1; setdate(date, ttime); if (strcmp(getenv("REQUEST_METHOD"),"POST")!=0) error("This program should be referenced with the method=POST\n",0); if (strcmp(getenv("CONTENT_TYPE"), "application/x-www-form-urlencoded")!=0) error("This program can only be used to decode forms\n",0); len = atoi(getenv("CONTENT_LENGTH")); entries = NULL; replyfile=NULL; outfile = NULL; subject=NULL; address=NULL; /* Get document root directory */ if ((webhome = getenv("DOCUMENT_ROOT"))==NULL) #if defined(WEBHOME) webhome=WEBHOME; #endif if (webhome==NULL) error("Failed to get DOCUMENT_ROOT directory. Define WEBHOME in the config.h file",0); /* Grab all the variable names and data from the form */ for(i=0;len && (!feof(stdin));i++) { if (entries) { entries->next = (struct entry *) malloc(sizeof(struct entry)); entries=entries->next; } else { entries = (struct entry *) malloc(sizeof(struct entry)); head = entries; } /* stick all the fields of the HTML Form into the entries struct */ entries->val = fmakeword(stdin,'&',&len); plustospace(entries->val); unescape_url(entries->val); word = (char *) makeword(entries->val, '='); entries->name = strnupr(word, strlen(word)); entries->next=NULL; } /* We now have all the data from the form, now decode the 'GFORM' commands from the HTML form file */ fname = get_html_filename(); buf = decode_commands(fname); sprintf(DEFSUBJECT,"Form [%s] submission" ,fname); /* Now deliver the results */ if (outfile) /* Results to a file */ send_to_file(outfile,buf); if (address) /* or results thru the mail */ send_email(address,subject,buf); if (printit) /* straight to a printer */ send_to_printer(queue, buf); if (replyfile) { /* The HTML file to reply with */ #ifdef USERDIR for (tmp2=replyfile; *replyfile=='/'; replyfile++); if (*replyfile == '~') tmp2=tildeexpand(replyfile); else { #endif tmp2 = (char *) malloc(strlen(webhome)+strlen(replyfile)+1); if (*replyfile=='/') replyfile++; sprintf(tmp2,"%s/%s",webhome,replyfile); #ifdef USERDIR } #endif if ((f1 = fopen(tmp2,"r"))==NULL) { sprintf(s,"Opening Replyfile: %s not found",replyfile); error(s,0); } else { print_header(); while (fread(line,1,LEN,f1)!=0) fprintf(stdout,"%s",line); } fclose(f1); } else { /* A default thank you reply */ print_header(); printf("<BODY>"); printf("<TITLE>Thank you</TITLE>"); printf("<H3>Thank you</H3>"); printf("</BODY>"); } return(0); } /*** * decode_commands * Read the HTML form file and look for commands * Replace variables, translate escaped chars * and return the results * ***/ char *decode_commands(fname) char *fname; { FILE *f1; int BRACKET=0,j,escape, vl, variable, endvar=0; char line[LEN], *commandline,*start, *end, *trace, *word, msg[64], tmp[256], *buf, /* The buf of formatted output */ *vp, *p, ch; if ((f1 = fopen(fname,"r")) == NULL) { #ifdef USERDIR sprintf(tmp,"File not found: %s",fname); #else sprintf(tmp,"File not found: %s<BR>('~' expansion not enabled)",fname); #endif error(tmp,0); } linecount=0; buf = (char *) malloc(1); *buf=0; bzero(line, LEN); while (fgets(line,LEN, f1) !=NULL) { linecount++; state=NSTATE; if (!(commandline = command(line))) continue; /* fixup any escaped chars */ commandline = do_escapes(commandline); SKIP_WHITE(commandline); /* A formatting command line */ if ((state==NSTATE) && (*commandline == '"')) { state = TSTATE; start = commandline+1; trace=start; end=NULL; variable=0; escape=0; for (;*trace && !end;trace++) { if (*trace=='"') { end = trace; *trace=0; if (variable) { variable=0; start=trace; buf = insert_value(buf,vp,vl); } else { buf = (char *) realloc(buf, strlen(buf)+ (trace-start)+1); strncat(buf, start , (trace-start)); } state=NSTATE; if (BRACKET) error("Missing bracket",linecount); } else if (variable && *trace == ')') { BRACKET--; endvar=1; vl--; } else if (variable) { if ((isspace(*trace) || end || endvar) && !BRACKET) { variable=0; start=trace; buf = insert_value(buf,vp,vl); endvar=0; } else vl++; } else if (*trace=='$') { variable=1; vl=0; vp = trace+1; if (*vp == '(') { vp++; BRACKET++; } buf = (char *) realloc(buf, strlen(buf) + (trace-start)+1); strncat(buf, start , (trace-start)); start = vp; } } } /* end of formatting command lines */ else /* now check command keywords */ if (state==NSTATE) { if (strcmp(strnupr(commandline,strlen(DELIVER)), DELIVER)==0) { commandline=commandline+strlen(DELIVER); SKIP_WHITE(commandline); if (*commandline != '=') error("Missing '='",linecount); commandline++; SKIP_WHITE(commandline); /* Handle the FILE delivery command */ if (strcmp(strnupr(commandline,strlen(FFILE)),FFILE)==0) { commandline=commandline+strlen(FFILE); SKIP_WHITE(commandline); if (*commandline !='"') error("\" Expected ",linecount); else outfile=get_cmd_val(commandline); state=NSTATE; /* Handle the PRINT delivery command */ } else if (strcmp(strnupr(commandline,strlen(PRINT)),PRINT)==0) { commandline=commandline+strlen(PRINT); SKIP_WHITE(commandline); if (isendtag(commandline)) queue=0; else if (*commandline !='"') error("\" Expected ",linecount); else queue = get_cmd_val(commandline); printit=1; state=NSTATE; /* Handle the MAIL delivery command */ } else if (strcmp(strnupr(commandline, strlen(MAIL)),MAIL)==0) { commandline=commandline+strlen(MAIL); SKIP_WHITE(commandline); if (*commandline!='"') error("\" Expected ",linecount); else { address=get_cmd_val(commandline); commandline+=strlen(commandline)+1; } SKIP_WHITE(commandline); if (strcmp(strnupr(commandline,strlen(SUBJECT)),SUBJECT)==0) { commandline=commandline+strlen(SUBJECT); SKIP_WHITE(commandline); if (*commandline!='=') error("= Expected",linecount); commandline++; SKIP_WHITE(commandline); if (*commandline!='"') error("\" Expected ",linecount); else subject=get_cmd_val(commandline); } else subject=DEFSUBJECT; state=NSTATE; } else { sprintf(msg,"Expected %s, %s or %s\n", FFILE, PRINT, MAIL); error(msg, linecount); } /* Handle REPLY command */ } else if (strcmp(strnupr(commandline,strlen(REPLY)), REPLY)==0) { commandline=commandline+strlen(REPLY); SKIP_WHITE(commandline); if (*commandline != '=') error("Missing '='",linecount); commandline++; SKIP_WHITE(commandline); if (*commandline != '"') error("\" Expected ",linecount); else replyfile=get_cmd_val(commandline); state=NSTATE; } else error("Commandline syntax, check \"",linecount); } if (state==TSTATE) error("Missing \"",linecount); bzero(line, LEN); } /* end of lines */ fclose(f1); /* Handle Escaped '$' and '"' that have been turned into char 1 and 2 with do_escapes(). Handled last as not to interfere with the parsing of commandline */ for (j=0;j<strlen(buf);j++) if (*(buf+j)==1) *(buf+j) = '$'; else if (*(buf+j)==2) *(buf+j) = '"'; return(buf); } /** * insert_value * replace a variable with its value * **/ char *insert_value(buf, vp, vl) char *buf, *vp; int vl; { char *word, msg[64], *envvar; int hit=0; word = strnupr(vp,vl); entries=head; while (entries) { if (strcmp(word,entries->name)==0) { buf = (char *) realloc(buf,strlen(buf) + strlen(entries->val)+4); /* 3 is to allow for ", " when multiple results */ if (hit) strcat(buf,", "); strcat(buf,entries->val); hit++; } entries=entries->next; } /* if variable is not found in the list of variables, try environement variables */ if (!hit) if (strcmp(word, "DATE")==0) { buf = (char *) realloc(buf,strlen(buf) + strlen(date)+1); strcat(buf, date); } else if (strcmp(word,"TIME")==0) { buf = (char *) realloc(buf,strlen(buf) + strlen(ttime)+1); strcat(buf, ttime); } else if ((envvar = getenv(word))!=NULL) { buf = (char *) realloc(buf,strlen(buf) + strlen(envvar)+1); strcat(buf, envvar); } else { /* Nothing found */ buf = (char *) realloc(buf, strlen(buf) + 5); strcat(buf,"null"); } return(buf); } /*** * do_escapes * Replaces all escaped chars with actual char its escaped. * ***/ char* strdup(s) { unsigned long len; char* copy = NULL; if (s == NULL) /* saftey check to postpone stupid errors */ return(NULL); len = strlen(s); /* length of string - terminator */ copy = (char*)malloc((size_t)(sizeof(char)*(len + 1))); strncpy(copy,s,len + 1); return(copy); } char *do_escapes(line) char *line; { char *p, *tmp, *top; p = strdup(line); if ((tmp = (char *) malloc(2 * strlen(line)))==NULL) return(NULL); top = tmp; while (*p) { if (*p=='\\') { p++; switch (*p) { case 'n' : *p = 10; break; case 't' : *p = 8; break; case 'r' : *p = 13; break; case 'f' : *p = 12; break; case '$' : *p = 1; break; /* special case */ case '"' : *p = 2; break; /* special case */ } } *(tmp++) = *(p++); } return(top); } /*** * command * Looks for a 'gform' commandline. * Returns the uppercase commandline (less the leading command tag * or NULL if it is not a commandline. * For backword compatibility, the old GFORM_TAG is still supported * but not really correct. * ***/ char *command(line) char *line; { char *commandline, *word, *word2; word = strnupr(line,strlen(GFORM_TAG)); word2 = strnupr(line,strlen(GFORM_TAG2)); if (strncmp(GFORM_TAG, word,strlen(GFORM_TAG))==0) { commandline=line+strlen(GFORM_TAG); return(commandline); } else if (strncmp(GFORM_TAG2, word2,strlen(GFORM_TAG2))==0) { commandline=line+strlen(GFORM_TAG2); return(commandline); } else return(NULL); } /*** * send_to_file * Send buffer to a file * ***/ int send_to_file(fname, buf) char *fname, *buf; { FILE *f; if ((f = fopen(fname,"a")) == NULL) return(0); fprintf(f,"%s",buf); fclose(f); return(1); } /*** * print_header * Prints the required header for http stuff * ***/ void print_header() { printf("Content-type: text/html\n\n"); return; } /*** * strnupr * takes a character string and converts 'len' into * uppercase. It then returns a pointer to the uppercase * chars. ***/ char *strnupr(line, len) char *line; int len; { int i; char *newline; newline = (char *) malloc(len + 1); for (i=0;i<len;i++) *(newline+i) = toupper(line[i]); *(newline+len) = '\0'; return(newline); } /*** * isendtag(cgar *p) * Returns 1 if p is pointing to an end-of-comment tag * ***/ int isendtag(p) char *p; { char *q = p; if (q) { if (*q=='-' && q+1 && *(q+1)=='-' && q+2) { q+=2; SKIP_WHITE(q); } if (*q=='>') return(1); } return(0); } /*** * get_html_filename() * Returns the filename of the FORM that called us. * ***/ char *get_html_filename() { static char http[]="HTTP://"; char *tmp, *path, *p, *uref, *referer = getenv("HTTP_REFERER"); char s[256]; struct stat fstat; if (referer==NULL) { referer=getenv("QUERY_STRING"); if (referer==NULL) error("Could not get environment", 0); } p = referer; if (strlen(referer)>6) { uref = strnupr(referer,7); if (strncmp(http,uref,7)==0) { p = referer+7; while (p && *p!='/') p++; /* skip host */ p++; } } for (tmp=p; *p=='/'; p++); #ifdef USERDIR if (*p=='~') { tmp=tildeexpand(p); if (!tmp) { sprintf(s,"Unable to expand: %s",p); error(s,0); } else if (stat(tmp,&fstat)) { sprintf(s,"File not Found: %s",tmp); error(s,0); } return(tmp); } else { #endif path = (char *) malloc(strlen(webhome)+ (tmp==NULL ? 0: strlen(tmp)) + 2); sprintf(path, "%s/%s",webhome, tmp); return(path); #ifdef USERDIR } #endif } /*** * get_cmd_val(string) * Returns a string between quotes , less the quotes * ***/ char *get_cmd_val(s) char *s; { char *p; p = s+1; while (*p && *p!='"') p++; if (!*p) error("\" Expected ",linecount); *p=0; return(s+1); } /*** * setdate() * * Sets 2 variables to the current date and time * ***/ setdate(date, ttime) char *date, *ttime; { time_t t; struct tm *ttm; static char *months[]={"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug","Sep","Oct","Nov","Dec" }; t=time(0); ttm = localtime(&t); sprintf(ttime, "%.2d:%.2d:%.2d",ttm->tm_hour, ttm->tm_min,ttm->tm_sec); sprintf(date,"%2d-%s-%2d",ttm->tm_mday, months[ttm->tm_mon],ttm->tm_year); } /*** * error * Prints a simple error message back to the user * ***/ void error(msg, linecount) char *msg; int linecount; { print_header(); if (linecount) printf("<P>gform: Error (line %d) %s<P>\n",linecount,msg); else printf("<P>gform: Error %s<P>\n",msg); exit(1); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.