From 9ff1b81d65c370a938cd9d9c033e04e395f00704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Sat, 18 Sep 2021 22:51:30 +0200 Subject: New user --- Makefile | 2 +- README | 19 +++++++------- ctl.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- db.c | 44 ++++++++++++++++++++++++++++++--- db.h | 4 +-- query.c | 11 +++++++-- site.h | 19 ++++++++++++++ t/front.t | 3 +++ t/head.t | 8 ++++++ t/newuser.t | 35 ++++++++++++++++++++++++++ t/post.t | 2 +- 11 files changed, 210 insertions(+), 19 deletions(-) create mode 100644 t/newuser.t diff --git a/Makefile b/Makefile index 93275cb..0c9ab3a 100644 --- a/Makefile +++ b/Makefile @@ -33,5 +33,5 @@ db: sqlite3 db "CREATE TABLE posts(parent INT, user INT NOT NULL, created INT NOT NULL, edited INT, subject NOT NULL, text NOT NULL, FOREIGN KEY (user) REFERENCES users(oid));" sqlite3 db "INSERT INTO posts values(NULL, 1, 1462137896, NULL, 'Hello World!', 'This is the first post.');" sqlite3 db "INSERT INTO posts values(1, 1, 1462138896, NULL, 'Re: Hello World!', 'This is the second post!');" - sqlite3 db "CREATE TABLE atts(post INT NOT NULL, name NOT NULL, description, mime NOT NULL, data BLOB, FOREIGN KEY (post) REFERENCES posts(oid));" + sqlite3 db "CREATE TABLE atts(post INT NOT NULL, name NOT NULL, desc, mime NOT NULL, data BLOB, FOREIGN KEY (post) REFERENCES posts(oid));" sqlite3 db "$$(printf "INSERT INTO atts values(1, 'example', 'Some example shell code.', 'text/plain', '#!/bin/sh\necho Hello World!');")" \ No newline at end of file diff --git a/README b/README index 63ca7e0..8030d7f 100644 --- a/README +++ b/README @@ -8,21 +8,22 @@ C89, it can be run on practically any UNIX system. It is also rather small: wc -l *.c *.h */*.t */*.lex - 100 cforum.c - 143 ctl.c - 230 db.c + 101 cforum.c + 223 ctl.c + 268 db.c 10 err.c - 106 query.c + 113 query.c 6 ctl.h 40 db.h 0 err.h 14 query.h - 2 site.h + 21 site.h 3 t/err.t 1 t/foot.t - 26 t/front.t - 6 t/head.t + 29 t/front.t + 14 t/head.t + 34 t/newuser.t 28 t/post.t 12 t/user.t - 87 mktpl/mktpl.lex - 814 total + 95 mktpl/mktpl.lex + 1012 total diff --git a/ctl.c b/ctl.c index 64934cc..e4b25a7 100644 --- a/ctl.c +++ b/ctl.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -35,7 +36,86 @@ newpost() void newuser() -{} +{ + char *confirm, *hlite, *msg, *name, *full, *p, *pass, *v; + char title[] = "New User"; + + if(!(msg = malloc(128))) + err(1, "malloc"); + + *msg = 0; + confirm = hlite = name = full = pass = NULL; + + if(query.method == GET){ + printf("Content-Type: text/html\n\n"); + #include "t/newuser.tc" + return; + } + + while(p = nextparam(POST, MAXUSERPARAM)){ + if(!(v = split(p))) continue; + + if(!confirm && strcmp(p, "confirm") == 0) + confirm = strdup(v); + else if(!name && strcmp(p, "name") == 0) + name = strdup(v); + else if(!full && strcmp(p, "full") == 0) + full = strdup(v); + else if(!pass && strcmp(p, "pass") == 0) + pass = strdup(v); + else + continue; + + if(TRUNCATED(p)){ + hlite = strdup(p); + snprintf(msg, 128, + "Input length exceeds server limitations"); + 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"); + goto err; + } + + /* Decode URL-encoded fields. */ + + /* Restrain lengths of decoded fields. */ + if(name && *name && strlen(name)-1 > MAXUSERNAME){ + hlite = strdup("name"); + snprintf(msg, 128, "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", + MAXUSERFULL-1); + goto err; + } + if(pass && *pass && strlen(pass)-1 > MAXUSERPASS){ + hlite = strdup("pass"); + snprintf(msg, 128, "Password longer than %d characters", + MAXUSERPASS-1); + goto err; + } + + if(pass && confirm && strcmp(pass, confirm) != 0){ + snprintf(msg, 128, "Passwords do not match"); + goto err; + } + + printf("Content-Type: text/html\n\n"); + printf("You are valid\n"); + return; +err: + printf("Content-Type: text/html\n\n"); + #include "t/newuser.tc" + return; +} /* * The `show' functions show an existing attachment/post/user diff --git a/db.c b/db.c index cf75ec6..a6391a6 100644 --- a/db.c +++ b/db.c @@ -17,7 +17,7 @@ addatt(struct att *att) sqlite3_stmt *stmt; if(sqlite3_prepare(db, "INSERT INTO atts" - " (post, name, description, mime, data)" + " (post, name, desc, mime, data)" " VALUES (?, ?, ?, ?, ?)", -1, &stmt, 0) != SQLITE_OK) goto err; @@ -30,7 +30,7 @@ addatt(struct att *att) != SQLITE_OK) goto err; - if(sqlite3_bind_text(stmt, 3, att->description, -1, SQLITE_STATIC) + if(sqlite3_bind_text(stmt, 3, att->desc, -1, SQLITE_STATIC) != SQLITE_OK) goto err; @@ -52,6 +52,44 @@ err: return 0; } +int +addpost(struct post *post) +{ + sqlite3_stmt *stmt; + + if(sqlite3_prepare(db, "INSERT INTO posts" + " (parent, user, created, subject, text)" + " VALUES (?, ?, ?, ?, ?)", + -1, &stmt, 0) != SQLITE_OK) + goto err; + + if(sqlite3_bind_int(stmt, 1, post->parent) != SQLITE_OK) + goto err; + + if(sqlite3_bind_int(stmt, 2, post->user) != SQLITE_OK) + goto err; + + if(sqlite3_bind_int(stmt, 3, post->created) != SQLITE_OK) + goto err; + + if(sqlite3_bind_text(stmt, 4, post->subject, -1, SQLITE_STATIC) + != SQLITE_OK) + goto err; + + if(sqlite3_bind_text(stmt, 5, post->text, -1, SQLITE_STATIC) + != SQLITE_OK) + goto err; + + if(sqlite3_step(stmt) != SQLITE_DONE) + goto err; + + sqlite3_finalize(stmt); + return 1; +err: + sqlite3_finalize(stmt); + return 0; +} + int adduser(struct user *user) { @@ -141,7 +179,7 @@ nextatt(sqlite3_stmt *stmt) att->id = sqlite3_column_int(stmt, 0); att->post = sqlite3_column_int(stmt, 1); att->name = strdupn(sqlite3_column_text(stmt, 2)); - att->description = strdupn(sqlite3_column_text(stmt, 3)); + att->desc = strdupn(sqlite3_column_text(stmt, 3)); att->mime = strdupn(sqlite3_column_text(stmt, 4)); att->bytes = sqlite3_column_bytes(stmt, 5); diff --git a/db.h b/db.h index d6f229d..1385b98 100644 --- a/db.h +++ b/db.h @@ -5,9 +5,9 @@ sqlite3 *db; struct att{ int id; int post; - int bytes; + int bytes; /* Size of data. */ char *name; - char *description; + char *desc; char *mime; char *data; }; diff --git a/query.c b/query.c index 7947d59..370fa54 100644 --- a/query.c +++ b/query.c @@ -6,8 +6,9 @@ /* * 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. + * ("key=value"). The string is truncated to max characters (but is always + * NUL-terminated). If truncation occurred, the -1th character of the string + * is set to 1. */ char * nextparam(enum method method, int max) @@ -104,4 +105,10 @@ split(char *param) return NULL; param[n] = 0; return param+n+1; +} + +void +urldecode(char *s) +{ + } \ No newline at end of file diff --git a/site.h b/site.h index f590bad..4e13319 100644 --- a/site.h +++ b/site.h @@ -1,3 +1,22 @@ +/* + * TODO: It is probably better to use the CONTENT_LENGTH + * environment variable to decide the length of the entire + * posted query string and then compare it to a max value, + * such as: + */ + +#define MAXATTDATA 4096 +#define MAXUSERDATA 512 +#define MAXPOSTDATA 4096 + +/* Maximum size of newuser parameter, incl. NUL. */ +#define MAXUSERPARAM 512 + +/* Maximum size of user information, incl. NUL. */ +#define MAXUSERNAME 80 +#define MAXUSERFULL 128 +#define MAXUSERPASS 128 + struct site{ char *name; } site; \ No newline at end of file diff --git a/t/front.t b/t/front.t index 9d39469..2662be2 100644 --- a/t/front.t +++ b/t/front.t @@ -1,5 +1,8 @@ <% #include "head.tc" %>

<%= site.name %>

+

Latest posts

<% while(post = nextpost(pstmt)){ diff --git a/t/head.t b/t/head.t index d9da813..7962c5b 100644 --- a/t/head.t +++ b/t/head.t @@ -3,5 +3,13 @@ <%= title %> + \ No newline at end of file diff --git a/t/newuser.t b/t/newuser.t new file mode 100644 index 0000000..a0a0dd9 --- /dev/null +++ b/t/newuser.t @@ -0,0 +1,35 @@ +<% #include "head.tc" %> +

New User

+<% if(*msg){ %> +

<%= msg %>

+<% } %> +" action="?new=user" method="POST"> +
+ + + + + + + + + + + + + + + + + +
">
">(optional)
+

By clicking Create, you confirm

+
    +
  1. that this user is a real human,
  2. +
  3. that you will not abuse the service,
  4. +
  5. that the information you provide will be saved on the server, and
  6. +
  7. that your user may be terminated by an administrator at any point and for any reason.
  8. +
+

+ +<% #include "foot.tc" %> \ No newline at end of file diff --git a/t/post.t b/t/post.t index 1e3d360..e30ddbe 100644 --- a/t/post.t +++ b/t/post.t @@ -20,7 +20,7 @@ id); %>"><%= att->name %> <%= att->mime %> - <%= att->description %> + <%= att->desc %> <% free(att); }while(att = nextatt(stmt)); %> -- cgit v1.2.3