diff options
-rw-r--r-- | cforum.c | 10 | ||||
-rwxr-xr-x | example | 12 | ||||
-rw-r--r-- | front.c | 1 | ||||
-rw-r--r-- | query.c | 91 | ||||
-rw-r--r-- | query.h | 12 | ||||
-rw-r--r-- | site.h | 2 | ||||
-rw-r--r-- | t/front.t | 16 | ||||
-rw-r--r-- | t/front.tc | 14 |
8 files changed, 134 insertions, 24 deletions
@@ -6,7 +6,7 @@ #include "ctl.h" /* Controllers. */ #include "err.h" /* HTTP errors. */ #include "site.h" /* Site settings. Defines global struct site. */ -#include "query.h" /* Query functions. Defines global string qs. */ +#include "query.h" /* Query functions. Defines global struct query. */ #define MAXERR 300 @@ -57,13 +57,13 @@ main(int argc, char *argv[]) sqlite3_finalize(res); /* - * The global variable qs is set to the query string, or the - * program dies. From now on, qs is assumed to be set. + * The global struct query is set, or the program dies. + * From now on, query is assumed to be set. */ - setqs(); + setquery(); /* Handle request. */ - if(!qs || !*qs) + if(!*query.string) front(); /* INSERT CONDITIONS HERE */ else @@ -0,0 +1,12 @@ +#!/usr/bin/env perl + +print while <DATA>; + +__END__ +Content-Type: text/html + +<form action="cforum" method="post"> + <p><label for="name">Name</label><input type="text" name="name" value="" id="name"> + <p><textarea name="text" rows="8" cols="40"></textarea> + <p><input type="submit" value="Continue →"></p> +</form>
\ No newline at end of file @@ -1,4 +1,5 @@ #include <stdio.h> +#include "query.h" #include "site.h" void @@ -1,29 +1,94 @@ +#include <err.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "query.h" +/* + * Return allocated string containing 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(int max) +{ + char *buf; + int i, sz; + static int j = 0; + + if(!query.post && !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) (query.post? fread(b, 1, 1, stdin): (*(b) = query.string[j++])) + + /* Return NULL if first character cannot be read. */ + if(!READ(buf)) + return NULL; + + i = 0; + goto loop; + + for(; READ(buf+i); i++){ +loop: + 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 -setqs() +setquery() { - qs = getenv("QUERY_STRING"); - if(!qs){ + query.string = getenv("QUERY_STRING"); + if(!query.string){ fprintf(stderr, "no QUERY_STRING\n"); exit(1); } + query.post = strcmp(getenv("REQUEST_METHOD"), "POST") == 0; } +/* + * Split parameter string on equals sign and return value portion; + * return NULL if none found. + */ char * -query(char *key) +split(char *param) { - char *w; int n; - - for(w = strtok(qs, "&"); w; w = strtok(NULL, "&")){ - n = strcspn(w, "="); - if(strncmp(w, key, n) == 0) - return w + n + (w[n] == '='); - } - - return NULL; + + n = strcspn(param, "="); + if(!param[n]) + return NULL; + param[n] = 0; + return param+n+1; }
\ No newline at end of file @@ -1,4 +1,10 @@ -char *qs; +#define TRUNCATED(s) s[-1] -void setqs(void); -char *query(char *);
\ No newline at end of file +struct query{ + int post; + char *string; +} query; + +char *nextparam(int); +void setquery(void); +char *split(char *);
\ No newline at end of file @@ -1,3 +1,3 @@ -struct site { +struct site{ char *name; } site;
\ No newline at end of file @@ -1,2 +1,16 @@ <h1><%= site.name %></h1> -<% printf("Hello world!"); %>
\ No newline at end of file +<% printf("Hello world!"); %> +<br> +Request method: <%= getenv("REQUEST_METHOD") %> +<br> +<% + char *a, *b, *bv; + a = nextparam(512); + printf("%s (%d)<br>", a, TRUNCATED(a)); + b = nextparam(512); + printf("%s (%d)<br>", b, TRUNCATED(b)); + bv = split(b); + printf("'%s' contains '%s'<br>", b, bv); + printf("Next: %s\n", nextparam(512)); + printf("Next: %s\n", nextparam(512)); +%>
\ No newline at end of file @@ -1,4 +1,16 @@ printf("<h1>"); printf("%s", site.name ); printf("</h1>\n"); - printf("Hello world!"); printf("\n"); + printf("Hello world!"); printf("\n<br>\nRequest method: "); +printf("%s", getenv("REQUEST_METHOD") ); +printf("<br>\n"); + char *a, *b, *bv; + a = nextparam(512); + printf("%s (%d)<br>", a, TRUNCATED(a)); + b = nextparam(512); + printf("%s (%d)<br>", b, TRUNCATED(b)); + bv = split(b); + printf("'%s' contains '%s'<br>", b, bv); + printf("Next: %s\n", nextparam(512)); + printf("Next: %s\n", nextparam(512)); +printf("\n"); |