From 2810ad72aeb973a898034d6875922284062c5ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Fri, 17 Sep 2021 17:02:29 +0200 Subject: Rework query functions Now, the value/parameter retrieval function handles both GET and POST parameters. --- cforum.c | 10 +++---- example | 12 +++++++++ front.c | 1 + query.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------- query.h | 12 ++++++--- site.h | 2 +- t/front.t | 16 ++++++++++- t/front.tc | 14 +++++++++- 8 files changed, 134 insertions(+), 24 deletions(-) create mode 100755 example diff --git a/cforum.c b/cforum.c index 7fc738e..319e9e1 100644 --- a/cforum.c +++ b/cforum.c @@ -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 diff --git a/example b/example new file mode 100755 index 0000000..55307b9 --- /dev/null +++ b/example @@ -0,0 +1,12 @@ +#!/usr/bin/env perl + +print while ; + +__END__ +Content-Type: text/html + +
+

+

+

+
\ No newline at end of file diff --git a/front.c b/front.c index ff6973e..7bba90a 100644 --- a/front.c +++ b/front.c @@ -1,4 +1,5 @@ #include +#include "query.h" #include "site.h" void diff --git a/query.c b/query.c index 09e7578..bc96778 100644 --- a/query.c +++ b/query.c @@ -1,29 +1,94 @@ +#include #include #include #include #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 diff --git a/query.h b/query.h index 81662a8..98fedb0 100644 --- a/query.h +++ b/query.h @@ -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 diff --git a/site.h b/site.h index e5dba32..f590bad 100644 --- a/site.h +++ b/site.h @@ -1,3 +1,3 @@ -struct site { +struct site{ char *name; } site; \ No newline at end of file diff --git a/t/front.t b/t/front.t index ed6fbf8..0a372a6 100644 --- a/t/front.t +++ b/t/front.t @@ -1,2 +1,16 @@

<%= site.name %>

-<% printf("Hello world!"); %> \ No newline at end of file +<% printf("Hello world!"); %> +
+Request method: <%= getenv("REQUEST_METHOD") %> +
+<% + char *a, *b, *bv; + a = nextparam(512); + printf("%s (%d)
", a, TRUNCATED(a)); + b = nextparam(512); + printf("%s (%d)
", b, TRUNCATED(b)); + bv = split(b); + printf("'%s' contains '%s'
", b, bv); + printf("Next: %s\n", nextparam(512)); + printf("Next: %s\n", nextparam(512)); +%> \ No newline at end of file diff --git a/t/front.tc b/t/front.tc index 0d7aec3..89e665a 100644 --- a/t/front.tc +++ b/t/front.tc @@ -1,4 +1,16 @@ printf("

"); printf("%s", site.name ); printf("

\n"); - printf("Hello world!"); printf("\n"); + printf("Hello world!"); printf("\n
\nRequest method: "); +printf("%s", getenv("REQUEST_METHOD") ); +printf("
\n"); + char *a, *b, *bv; + a = nextparam(512); + printf("%s (%d)
", a, TRUNCATED(a)); + b = nextparam(512); + printf("%s (%d)
", b, TRUNCATED(b)); + bv = split(b); + printf("'%s' contains '%s'
", b, bv); + printf("Next: %s\n", nextparam(512)); + printf("Next: %s\n", nextparam(512)); +printf("\n"); -- cgit v1.2.3