diff options
Diffstat (limited to 'ctl.c')
-rw-r--r-- | ctl.c | 171 |
1 files changed, 97 insertions, 74 deletions
@@ -1,41 +1,16 @@ #include <err.h> +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> +#include <unistd.h> #include "cforum.h" #define MAXMSG 256 -/* Print UNIX timestamp as written date. */ -void -printdate(int timestamp) -{ - char buf[20]; - struct tm *t; - - t = localtime((time_t *)×tamp); - strftime(buf, 20, "%Y-%m-%d %H:%M", t); - - printf(buf); -} - -/* Print HTML-escaped string. */ -void -printhtml(char *s) -{ - char *t; - - for(t = s; *t; t++) - switch(*t){ - case '&': printf("&"); break; - case '\"': printf("""); break; - case '\'': printf("'"); break; - case '<': printf("<"); break; - case '>': printf(">"); break; - default: printf("%c", *t); - } -} +static void printdate(int); +static void printhtml(char *); /* * The `new' functions provide a way to add a new attachment/post/user. @@ -53,21 +28,26 @@ newpost() void newsession() { - char *hlite, msg[MAXMSG], *p, *v; + char *hlite, *home, msg[MAXMSG], *p, rnd[MAXCOOKIE], *v; char *name, *pass, *remember; - char title[] = "Log In"; struct user *user; + struct session session; sqlite3_stmt *stmt; - + + char title[] = "Log In"; + *msg = 0; hlite = name = pass = remember = NULL; - + + home = getenv("REQUEST_URI"); + home[strcspn(home, "?")] = 0; + if(query.method == GET){ printf("Content-Type: text/html\n\n"); #include "t/login.tc" return; } - + if(query.length > MAXSESSIONDATA){ snprintf(msg, MAXMSG, "Input exceeded server limitations"); printf("Status: 431 Request Header Fields Too Large\n"); @@ -75,10 +55,10 @@ newsession() #include "t/login.tc" return; } - + while(p = nextparam(POST, NULL, MAXSESSIONDATA)){ if(!(v = split(p))) continue; - + if(!name && strcmp(p, "name") == 0) name = strdup(v); else if(!pass && strcmp(p, "pass") == 0) @@ -88,7 +68,7 @@ newsession() else continue; } - + if(!name || !*name){ snprintf(msg, MAXMSG, "Username may not be empty"); printf("Status: 400 Bad Request\n"); @@ -96,28 +76,42 @@ newsession() #include "t/login.tc" return; } - - if(sqlite3_prepare(db, "SELECT oid, * from users WHERE name = ?", + + if(sqlite3_prepare(db, "SELECT oid, * FROM users WHERE name = ?", -1, &stmt, 0) != SQLITE_OK) goto fail; - + if(sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC) != SQLITE_OK) goto dberr; - + if(!(user = getuser(stmt))) goto fail; - + if(!haspass(user, pass)) goto fail; + + /* Create session cookie. */ + makerandom(rnd, sizeof(rnd)); + session.user = user->id; + session.string = rnd; + if(!addsession(&session)){ + snprintf(msg, MAXMSG, "Could not create session for user"); + printf("Status: 500 Internal Server Error"); + printf("Content-Type: text/html\n\n"); + #include "t/login.tc" + return; + } - printf("Content-Type: text/plain\n\n"); - printf("Success!\n"); + printf("Status: 303 See Other\n"); + printf("Set-Cookie: user=%d\n", user->id); + printf("Set-Cookie: session=%s\n", rnd); + printf("Location: %s\n\n", home); return; dberr: snprintf(msg, MAXMSG, "Could not retrieve user: %s", sqlite3_errmsg(db)); - printf("Status: 500 Internal Server Errror\n"); + printf("Status: 500 Internal Server Error\n"); printf("Content-Type: text/html\n\n"); #include "t/login.tc" return; @@ -136,16 +130,16 @@ newuser() char title[] = "New User"; int i; struct user *user; - + *msg = 0; captcha = confirm = hlite = name = full = pass = NULL; - + if(query.method == GET){ printf("Content-Type: text/html\n\n"); #include "t/newuser.tc" return; } - + if(query.length > MAXUSERDATA){ snprintf(msg, MAXMSG, "Input exceeded server limitations"); printf("Status: 431 Request Header Fields Too Large\n"); @@ -153,10 +147,10 @@ newuser() #include "t/newuser.tc" return; } - + 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) @@ -170,7 +164,7 @@ newuser() else continue; } - + /* Decode URL-encoded fields. */ if(captcha && *captcha) captcha[urldecode(captcha, -1)] = 0; @@ -182,7 +176,7 @@ newuser() full[urldecode(full, -1)] = 0; if(pass && *pass) pass[urldecode(pass, -1)] = 0; - + /* Constrain lengths of decoded fields. */ if(name && *name && strlen(name)-1 > MAXUSERNAME){ hlite = strdup("name"); @@ -202,10 +196,10 @@ newuser() MAXUSERPASS-1); goto err; } - + #define ISVIS(c) ((unsigned char)c >= 32) #define ISALNUM(c) (c>='A' && c<='Z' || c>='a' && c<='z' || c>='0' && c<='9') - + /* Constrain character sets. */ for(i = 0; name[i]; i++) if(!name[i] == '_' && !ISALNUM(name[i])){ @@ -217,13 +211,12 @@ newuser() } for(i = 0; full[i]; i++) if(!ISVIS(full[i])){ - fprintf(stderr, "%d\n", full[i]); hlite = strdup("full"); snprintf(msg, MAXMSG, "Full name may only contain visible characters"); goto err; } - + /* Validate captcha. */ if(captcha && strcmp(captcha, "9") != 0){ hlite = strdup("captcha"); @@ -247,14 +240,14 @@ newuser() 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; makehash(pass, &user->hash, &user->salt); - + if(!adduser(user)){ if(strcmp(sqlite3_errmsg(db), "column name is not unique")==0) snprintf(msg, MAXMSG, "Username already exists."); @@ -263,7 +256,7 @@ newuser() sqlite3_errmsg(db)); goto err; } - + printf("Content-Type: text/html\n\n"); snprintf(msg, MAXMSG, "SUCCESS: User was added to database"); #include "t/newuser.tc" @@ -275,6 +268,36 @@ err: return; } +/* Print UNIX timestamp as written date. */ +void +printdate(int timestamp) +{ + char buf[20]; + struct tm *t; + + t = localtime((time_t *)×tamp); + strftime(buf, 20, "%Y-%m-%d %H:%M", t); + + printf(buf); +} + +/* Print HTML-escaped string. */ +void +printhtml(char *s) +{ + char *t; + + for(t = s; *t; t++) + switch(*t){ + case '&': printf("&"); break; + case '\"': printf("""); break; + case '\'': printf("'"); break; + case '<': printf("<"); break; + case '>': printf(">"); break; + default: printf("%c", *t); + } +} + /* * The `show' functions show an existing attachment/post/user * or some other type of page. @@ -283,12 +306,12 @@ void showatt(id) { struct att *att; - + if(!(att = getatt(selectbyint("atts", "oid", id)))){ srverr("Could not retrieve attachment"); return; } - + printf("Content-Type: %s\n\n", att->mime); printf("%.*s", att->bytes, att->data); free(att); @@ -301,21 +324,21 @@ showfront() struct post *post; struct user *user; sqlite3_stmt *pstmt, *ustmt; - + if(sqlite3_prepare(db, "SELECT oid, * from posts ORDER BY created DESC", -1, &pstmt, 0) != SQLITE_OK){ srverr("Could not retrieve posts"); return; } - + if(sqlite3_prepare(db, "SELECT oid, * from users ORDER BY created DESC", -1, &ustmt, 0) != SQLITE_OK){ srverr("Could not retrieve users"); return; } - + title = site.name; printf("Content-Type: text/html\n\n"); #include "t/front.tc" @@ -329,19 +352,19 @@ showpost(int id) struct post *post; struct user *user; sqlite3_stmt *stmt; - + if(!(post = getpost(selectbyint("posts", "oid", id)))){ srverr("Could not retrieve post"); return; } - + if(!(user = getuser(selectbyint("users", "oid", post->user)))){ srverr("Could not retrieve post author"); return; } - + stmt = selectbyint("atts", "post", id); - + title = post->subject; printf("Content-Type: text/html\n\n"); #include "t/post.tc" @@ -356,26 +379,26 @@ showuser(int id) sqlite3_stmt *stmt; struct post *post; struct user *user; - + if(!(user = getuser(selectbyint("users", "oid", id)))){ srverr("Could not retrieve user"); return; } - + if(sqlite3_prepare(db, "SELECT oid, * from posts WHERE user = ? ORDER BY created DESC", -1, &stmt, 0) != SQLITE_OK) goto err; - + if(sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) goto err; - + snprintf(title, 120, "User: %s", user->full? user->full: user->name); printf("Content-Type: text/html\n\n"); #include "t/user.tc" free(user); return; - + err: srverr("Could not retrieve posts"); return; |