aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2021-09-17 17:02:29 +0200
committerJohn Ankarström <john@ankarstrom.se>2021-09-17 17:03:57 +0200
commit2810ad72aeb973a898034d6875922284062c5ce0 (patch)
tree2c7555b79054d57350cc4136e3215094c9b4b685
parent38f8e2242353711d5c87c58f3831306934d2e6b7 (diff)
downloadcforum-2810ad72aeb973a898034d6875922284062c5ce0.tar.gz
Rework query functions
Now, the value/parameter retrieval function handles both GET and POST parameters.
-rw-r--r--cforum.c10
-rwxr-xr-xexample12
-rw-r--r--front.c1
-rw-r--r--query.c91
-rw-r--r--query.h12
-rw-r--r--site.h2
-rw-r--r--t/front.t16
-rw-r--r--t/front.tc14
8 files changed, 134 insertions, 24 deletions
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 <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 &rarr;"></p>
+</form> \ 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 <stdio.h>
+#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 <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
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 @@
<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
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("<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");