#include #include #include #include #include "query.h" /* * Return an allocated string containing the next query string parameter * ("key=value"). The string is truncated to max characters. If truncation * occurred, the -1th character of the string is set to 1. */ char * nextparam(enum method method, int max) { char *buf; int i, sz; static int j = 0; /* Return NULL if at end of parameter string. */ if(method == GET && !query.string[j-1]) return NULL; #define STEP 256 sz = STEP; if(!(buf = malloc(1+sz))) /* Leave space for -1th character. */ err(1, "malloc"); /* * buf's -1th character is set to 1 if the string * has been truncated (i.e. if input exceeded max). */ buf++; TRUNCATED(buf) = 0; #define READ(b) (method == GET? \ (*(b) = query.string[j++]): \ fread(b, 1, 1, stdin)) /* * The parameter is read in a rather lopsided loop, treating * the first character specially. */ first: /* Return NULL if at end of parameter string. */ if(!READ(buf)) return NULL; /* Skip empty parameters. */ if(*buf == '&') goto first; i = 0; goto rest; for(; READ(buf+i); i++){ rest: if(buf[i] == '&'){ buf[i] = 0; break; } if(i+1 > max){ TRUNCATED(buf) = 1; /* Skip ahead to next parameter. */ while(READ(buf+i+1) && buf[i+1] != '&') ; break; } if(i+1 >= sz){ sz += STEP; /* Remember to adjust for -1th character. */ if(buf--, buf = realloc(buf, 1+sz), !buf++) err(1, "realloc"); } } buf[i] = 0; return buf; } /* Fill global query structure from CGI environment variables. */ void setquery() { query.string = getenv("QUERY_STRING"); if(!query.string){ fprintf(stderr, "no QUERY_STRING\n"); exit(1); } query.method = strcmp(getenv("REQUEST_METHOD"), "POST")? GET: POST; } /* * Split parameter string on equals sign and return value portion; * return NULL if none found. For example, v = split(p) results in * p pointing to the parameter key and v pointing to the value. */ char * split(char *param) { int n; n = strcspn(param, "="); if(!param[n]) return NULL; param[n] = 0; return param+n+1; }