aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2021-09-19 01:45:42 +0200
committerJohn Ankarström <john@ankarstrom.se>2021-09-19 01:45:42 +0200
commitc2ba75793e78afb00223003ddfcbc05714bd01bf (patch)
tree1037691fa9cdb7e47258b678cc6a5a70107c85c5
parent4b838fced8cd5fd2c24300e3f9132a1474051a76 (diff)
downloadcforum-c2ba75793e78afb00223003ddfcbc05714bd01bf.tar.gz
Add simple captcha
-rw-r--r--README8
-rw-r--r--ctl.c58
-rw-r--r--t/head.t1
-rw-r--r--t/newuser.t6
4 files changed, 55 insertions, 18 deletions
diff --git a/README b/README
index 01cf301..93d4c80 100644
--- a/README
+++ b/README
@@ -9,7 +9,7 @@ It is also rather small:
wc -l *.c *.h */*.t */*.lex
101 cforum.c
- 267 ctl.c
+ 299 ctl.c
268 db.c
10 err.c
144 query.c
@@ -21,9 +21,9 @@ It is also rather small:
3 t/err.t
1 t/foot.t
29 t/front.t
- 14 t/head.t
- 34 t/newuser.t
+ 15 t/head.t
+ 38 t/newuser.t
28 t/post.t
12 t/user.t
95 mktpl/mktpl.lex
- 1080 total
+ 1117 total
diff --git a/ctl.c b/ctl.c
index a3eb920..91761cc 100644
--- a/ctl.c
+++ b/ctl.c
@@ -54,12 +54,14 @@ newpost()
void
newuser()
{
- char *confirm, *hlite, msg[128], *name, *full, *p, *pass, *v;
+#define MAXMSG 256
+ char *captcha, *confirm, *hlite, msg[MAXMSG], *name, *full, *p, *pass, *v;
char title[] = "New User";
int i;
+ struct user *user;
*msg = 0;
- confirm = hlite = name = full = pass = NULL;
+ captcha = confirm = hlite = name = full = pass = NULL;
if(query.method == GET){
printf("Content-Type: text/html\n\n");
@@ -68,7 +70,7 @@ newuser()
}
if(query.length > MAXUSERDATA){
- snprintf(msg, 128, "Input exceeded server limitations");
+ snprintf(msg, MAXMSG, "Input exceeded server limitations");
printf("Status: 431 Request Header Fields Too Large\n");
printf("Content-Type: text/html\n\n");
#include "t/newuser.tc"
@@ -78,6 +80,8 @@ newuser()
while(p = nextparam(POST, NULL, MAXUSERDATA)){
if(!(v = split(p))) continue;
+ if(!captcha && strcmp(p, "captcha") == 0)
+ captcha = strdup(v);
if(!confirm && strcmp(p, "confirm") == 0)
confirm = strdup(v);
else if(!name && strcmp(p, "name") == 0)
@@ -91,6 +95,10 @@ newuser()
}
/* Decode URL-encoded fields. */
+ if(captcha && *captcha)
+ captcha[urldecode(captcha, -1)] = 0;
+ if(confirm && *confirm)
+ confirm[urldecode(confirm, -1)] = 0;
if(name && *name)
name[urldecode(name, -1)] = 0;
if(full && *full)
@@ -101,19 +109,19 @@ newuser()
/* Constrain lengths of decoded fields. */
if(name && *name && strlen(name)-1 > MAXUSERNAME){
hlite = strdup("name");
- snprintf(msg, 128, "Username longer than %d characters",
+ snprintf(msg, MAXMSG, "Username longer than %d characters",
MAXUSERNAME-1);
goto err;
}
if(full && *full && strlen(full)-1 > MAXUSERFULL){
hlite = strdup("full");
- snprintf(msg, 128, "Full name longer than %d characters",
+ snprintf(msg, MAXMSG, "Full name longer than %d characters",
MAXUSERFULL-1);
goto err;
}
if(pass && *pass && strlen(pass)-1 > MAXUSERPASS){
hlite = strdup("pass");
- snprintf(msg, 128, "Password longer than %d characters",
+ snprintf(msg, MAXMSG, "Password longer than %d characters",
MAXUSERPASS-1);
goto err;
}
@@ -125,7 +133,7 @@ newuser()
for(i = 0; name[i]; i++)
if(!ISVIS(name[i]) || !(name[i] == '_' || ISALNUM(name[i]))){
hlite = strdup("name");
- snprintf(msg, 128,
+ snprintf(msg, MAXMSG,
"Username may only contain ASCII letters, "
"numbers and underscores.");
goto err;
@@ -134,25 +142,49 @@ newuser()
if(!ISVIS(full[i])){
fprintf(stderr, "%d\n", full[i]);
hlite = strdup("full");
- snprintf(msg, 128,
+ snprintf(msg, MAXMSG,
"Full name may only contain visible characters");
goto err;
}
/* Ensure all required fields are there. */
- if(!name || !*name || !pass || !*pass){
- hlite = (!name || !*name)? strdup("name"): strdup("pass");
- snprintf(msg, 128, "Required field missing");
+ if(captcha && strcmp(captcha, "9") != 0){
+ hlite = strdup("captcha");
+ snprintf(msg, MAXMSG, "Incorrectly answered captcha");
+ goto err;
+ }
+ if(!name || !*name){
+ hlite = strdup("name");
+ snprintf(msg, MAXMSG, "Username is required");
+ goto err;
+ }
+ if(!pass || !*pass){
+ hlite = strdup("pass");
+ snprintf(msg, MAXMSG, "Password is required");
goto err;
}
if(pass && confirm && strcmp(pass, confirm) != 0){
- snprintf(msg, 128, "Passwords do not match");
+ snprintf(msg, MAXMSG, "Passwords do not match");
+ goto err;
+ }
+
+ if(!(user = malloc(sizeof(struct user))))
+ err(1, "malloc");
+
+ user->name = name;
+ user->full = *full? full: NULL;
+ user->hash = pass; /* TODO */
+
+ if(!adduser(user)){
+ snprintf(msg, MAXMSG, "Could not add user to database: %s",
+ sqlite3_errmsg(db));
goto err;
}
printf("Content-Type: text/html\n\n");
- printf("You are valid\n");
+ snprintf(msg, MAXMSG, "SUCCESS: User was added to database");
+ #include "t/newuser.tc"
return;
err:
printf("Status: 400 Bad Request\n");
diff --git a/t/head.t b/t/head.t
index 7962c5b..4fbd19a 100644
--- a/t/head.t
+++ b/t/head.t
@@ -4,6 +4,7 @@
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title><%= title %></title>
<style type="text/css">
+ form.hlite-captcha #captcha,
form.hlite-confirm #confirm,
form.hlite-name #name,
form.hlite-full #full,
diff --git a/t/newuser.t b/t/newuser.t
index e62fdc2..7d53f0c 100644
--- a/t/newuser.t
+++ b/t/newuser.t
@@ -10,7 +10,7 @@
<td><input type="text" name="name" value="<% if(name) printhtml(name); %>"></td>
</tr>
<tr id="full">
- <td><label for="full">Full Name</label></td>
+ <td><label for="full">Full name</label></td>
<td><input type="text" name="full" value="<% if(full) printhtml(full); %>"></td>
<td><small>(optional)</small></td>
</tr>
@@ -22,6 +22,10 @@
<td><label for="confirm">Confirm</label></td>
<td><input type="password" name="confirm" value=""></td>
</tr>
+ <tr id="captcha">
+ <td><label for="captcha">What is 2 + 7?</label></td>
+ <td><input type="text" name="captcha" value="<% if(captcha) printhtml(captcha); %>"></td>
+ </tr>
</table>
<p>By clicking <i>Create</i>, you confirm</p>
<ol>