diff options
-rw-r--r-- | README | 10 | ||||
-rw-r--r-- | ctl.c | 49 | ||||
-rw-r--r-- | query.c | 27 | ||||
-rw-r--r-- | query.h | 3 | ||||
-rw-r--r-- | site.h | 11 | ||||
-rw-r--r-- | t/newuser.t | 4 |
6 files changed, 82 insertions, 22 deletions
@@ -9,15 +9,15 @@ It is also rather small: wc -l *.c *.h */*.t */*.lex 101 cforum.c - 222 ctl.c + 267 ctl.c 268 db.c 10 err.c - 121 query.c + 144 query.c 6 ctl.h 40 db.h 0 err.h - 15 query.h - 21 site.h + 16 query.h + 12 site.h 3 t/err.t 1 t/foot.t 29 t/front.t @@ -26,4 +26,4 @@ It is also rather small: 28 t/post.t 12 t/user.t 95 mktpl/mktpl.lex - 1020 total + 1080 total @@ -21,6 +21,23 @@ printdate(int timestamp) 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 `new' functions provide a way to add a new attachment/post/user. * On GET, they show a form. On POST, they insert the posted information @@ -39,6 +56,7 @@ newuser() { char *confirm, *hlite, msg[128], *name, *full, *p, *pass, *v; char title[] = "New User"; + int i; *msg = 0; confirm = hlite = name = full = pass = NULL; @@ -73,8 +91,14 @@ newuser() } /* Decode URL-encoded fields. */ + if(name && *name) + name[urldecode(name, -1)] = 0; + if(full && *full) + full[urldecode(full, -1)] = 0; + if(pass && *pass) + pass[urldecode(pass, -1)] = 0; - /* Restrain lengths of decoded fields. */ + /* Constrain lengths of decoded fields. */ if(name && *name && strlen(name)-1 > MAXUSERNAME){ hlite = strdup("name"); snprintf(msg, 128, "Username longer than %d characters", @@ -94,13 +118,34 @@ newuser() goto err; } +#define ISVIS(c) ((unsigned int)c >= 20) +#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(!ISVIS(name[i]) || !(name[i] == '_' || ISALNUM(name[i]))){ + hlite = strdup("name"); + snprintf(msg, 128, + "Username may only contain ASCII letters, " + "numbers and underscores."); + goto err; + } + for(i = 0; full[i]; i++) + if(!ISVIS(full[i])){ + fprintf(stderr, "%d\n", full[i]); + hlite = strdup("full"); + snprintf(msg, 128, + "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"); goto err; } - + if(pass && confirm && strcmp(pass, confirm) != 0){ snprintf(msg, 128, "Passwords do not match"); goto err; @@ -115,8 +115,31 @@ split(char *param) return param+n+1; } -void -urldecode(char *s) +/* + * Decode a URL-encoded string in place. If len is negative, the string + * is assumed to be NUL-terminated. The length of the new string is + * returned. Note that the new string is NOT NUL-terminated! To produce + * a NUL-terminated string, use s[urldecode(s, -1)] = 0. + */ +int +urldecode(char *s, int len) { + unsigned int code, i, j; + + if(len < 0) + len = strlen(s); + + for(i = j = 0; i < len; i++, j++){ + if(s[i] == '+') + s[j] = ' '; + else if(s[i] == '%'){ + if(!sscanf(s+i+1, "%2x", &code)) + code = '?'; + s[j] = code; + i += 2; + }else + s[j] = s[i]; + } + return j; }
\ No newline at end of file @@ -13,4 +13,5 @@ enum method{ char *nextparam(enum method, int *, int); void setquery(void); -char *split(char *);
\ No newline at end of file +char *split(char *); +int urldecode(char *, int);
\ No newline at end of file @@ -1,17 +1,8 @@ -/* - * 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: - */ - +/* Maximum allowed Content-Length for various forms. */ #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 40 #define MAXUSERFULL 128 diff --git a/t/newuser.t b/t/newuser.t index a0a0dd9..e62fdc2 100644 --- a/t/newuser.t +++ b/t/newuser.t @@ -7,11 +7,11 @@ <table border="0"> <tr id="name"> <td><label for="name">Username</label></td> - <td><input type="text" name="name" value="<% if(name) printf("%s", name); %>"></td> + <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><input type="text" name="full" value="<% if(full) printf("%s", full); %>"></td> + <td><input type="text" name="full" value="<% if(full) printhtml(full); %>"></td> <td><small>(optional)</small></td> </tr> <tr id="pass"> |