tvote.c: implement voting functionality - vote - simple cgi voting system for w… | |
git clone git://src.adamsgaard.dk/vote | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 0b3501599120c01cca8c2e8532fcd31e781f48ec | |
parent d5823861bfb88b89fc65a8844cd7e9a623bb0690 | |
Author: Anders Damsgaard <[email protected]> | |
Date: Mon, 28 Sep 2020 14:09:43 +0200 | |
vote.c: implement voting functionality | |
Diffstat: | |
M vote.c | 91 +++++++++++++++++++++--------… | |
1 file changed, 62 insertions(+), 29 deletions(-) | |
--- | |
diff --git a/vote.c b/vote.c | |
t@@ -12,7 +12,6 @@ | |
#include "util.h" | |
#define LEN(s) (sizeof(s) / sizeof(s[0])) | |
-#define OUT(s) (fputs((s), stdout)) | |
#define POLLS_DIR "polls" | |
static char fname[PATH_MAX]; | |
t@@ -20,23 +19,24 @@ static char poll[1024]; | |
static char create[2]; | |
static char question[4096]; | |
static char options[4096]; | |
+static char choice[16]; | |
void | |
http_status(int statuscode) | |
{ | |
switch(statuscode) { | |
case 401: | |
- OUT("Status: 401 Bad Request\r\n\r\n"); | |
+ printf("Status: 401 Bad Request\r\n\r\n"); | |
break; | |
case 404: | |
- OUT("Status: 404 Not Found\r\n\r\n"); | |
+ printf("Status: 404 Not Found\r\n\r\n"); | |
break; | |
case 500: | |
- OUT("Status: 500 Internal Server Error\r\n\r\n"); | |
+ printf("Status: 500 Internal Server Error\r\n\r\n"); | |
break; | |
default: | |
err(1, "unknown status code %d\n", statuscode); | |
- OUT("Status: 500 Internal Server Error\r\n\r\n"); | |
+ printf("Status: 500 Internal Server Error\r\n\r\n"); | |
} | |
} | |
t@@ -60,8 +60,8 @@ pollfile(const char *poll_name, const char *postfix) | |
void | |
print_html_head() | |
{ | |
- OUT("Content-type: text/html; charset=utf-8\r\n\r\n"); | |
- OUT("<!DOCTYPE html>\n" | |
+ printf("Content-type: text/html; charset=utf-8\r\n\r\n"); | |
+ printf("<!DOCTYPE html>\n" | |
"<html>\n" | |
"<body>\n"); | |
} | |
t@@ -69,33 +69,45 @@ print_html_head() | |
void | |
print_html_foot() | |
{ | |
- OUT("</body>\n" | |
+ printf("</body>\n" | |
"</html>\n"); | |
} | |
int | |
-print_poll_line(char *line, int intable) | |
+print_poll_line(char *line, size_t *i, int intable, int vote) | |
{ | |
size_t c; | |
if (sscanf(line, "%ld\t%s", &c, options) == 2) { | |
- if (!intable) | |
- puts("<br><table>"); | |
- printf("<tr><td>%ld</td><td>%s</td></tr>\n", c, options); | |
+ if (!intable) { | |
+ puts("</p>\n<table>"); | |
+ if (vote) { | |
+ puts("<form method=\"get\" action=\"\">"); | |
+ printf("<input type=\"hidden\" name=\"poll\" " | |
+ "value=\"%s\" />\n", poll); | |
+ } | |
+ } | |
+ if (vote) { | |
+ printf("\t<tr><td>"); | |
+ printf("<input type=\"radio\" " | |
+ "id=\"%ld\" name=\"choice\" value=\"%ld\" />", | |
+ ++*i, *i); | |
+ printf("</td><td>%s</td></tr>\n", options); | |
+ } else | |
+ printf("\t<tr><td>%ld</td><td>%s</td></tr>\n", c, opti… | |
return 1; | |
} else { | |
- if (intable) | |
- puts("</table>"); | |
+ | |
printf("%s<br>\n", line); | |
return 0; | |
} | |
} | |
void | |
-print_poll_file(FILE *fp) | |
+print_poll_file(FILE *fp, int vote) | |
{ | |
char *line = NULL; | |
- size_t linesize = 0, lineno = 0; | |
+ size_t linesize = 0, lineno = 0, i = 0; | |
ssize_t linelen; | |
int intable = 0; | |
t@@ -107,9 +119,9 @@ print_poll_file(FILE *fp) | |
if (lineno == 1) { | |
printf("<h2>"); | |
fwrite(line, linelen, 1, stdout); | |
- printf("</h2>\n"); | |
+ printf("</h2>\n<p>"); | |
} else { | |
- intable = print_poll_line(line, intable); | |
+ intable = print_poll_line(line, &i, intable, vote); | |
} | |
} | |
free(line); | |
t@@ -117,7 +129,13 @@ print_poll_file(FILE *fp) | |
http_status(500); | |
err(1, "print_poll_file: getline"); | |
} | |
+ | |
puts("</table>"); | |
+ if (vote) { | |
+ puts("<input type=\"submit\" value=\"Submit\" " | |
+ "class=\"button\"/>"); | |
+ puts("</form>"); | |
+ } | |
} | |
int | |
t@@ -183,7 +201,7 @@ create_poll_file(const char *name, const char *question, c… | |
} | |
void | |
-show_poll(const char *poll) | |
+show_poll(const char *poll, int vote) | |
{ | |
FILE *fp; | |
t@@ -191,7 +209,7 @@ show_poll(const char *poll) | |
http_status(404); | |
exit(1); | |
} else { | |
- print_poll_file(fp); | |
+ print_poll_file(fp, vote); | |
fclose(fp); | |
} | |
} | |
t@@ -280,28 +298,28 @@ increment_option(char *poll, size_t n) | |
void | |
print_poll_create_form() | |
{ | |
- OUT("<h2>Create new poll</h2>"); | |
- OUT("<form method=\"get\" action=\"\">\n" | |
+ puts("<h2>Create new poll</h2>"); | |
+ puts("<form method=\"get\" action=\"\">\n" | |
"<input type=\"hidden\" name=\"create\" value=\"1\" />\n" | |
"<table class=\"create\" width=\"100%\" border=\"0\" " | |
"cellpadding=\"0\" cellspacing=\"0\">\n" | |
"<tr>\n" | |
" <td width=\"100%\" class=\"input\">\n" | |
" <input type=\"text\" name=\"poll\" " | |
- " placeholder=\"Name\" size=\"60\" " | |
- " autofocus=\"autofocus\" class=\"name\" />\n" | |
+ "placeholder=\"Name\" size=\"60\" " | |
+ "autofocus=\"autofocus\" class=\"name\" />\n" | |
" </td>\n" | |
"</tr>\n" | |
"<tr>\n" | |
" <td width=\"100%\" class=\"input\">\n" | |
" <input type=\"text\" name=\"question\" " | |
- " placeholder=\"Question\" size=\"60\" class=\… | |
+ "placeholder=\"Question\" size=\"60\" class=\"question\" />\n" | |
" </td>\n" | |
"</tr>\n" | |
"<tr>\n" | |
" <td width=\"100%\" class=\"input\">\n" | |
" <textarea rows=\"5\" cols=\"60\" name=\"options\" " | |
- " placeholder=\"Options (1 per line)\"></texta… | |
+ "placeholder=\"Options (1 per line)\"></textarea>\n" | |
" </td>\n" | |
"</tr>\n" | |
"<tr>\n" | |
t@@ -351,11 +369,20 @@ parse_query() | |
} | |
} | |
+ if ((p = getparam(query, "choice"))) { | |
+ if (decodeparam(choice, sizeof(create), p) == -1) { | |
+ http_status(401); | |
+ exit(1); | |
+ } | |
+ } | |
+ | |
} | |
int | |
main() | |
{ | |
+ size_t c; | |
+ const char *errstr; | |
struct stat sb; | |
if (unveil(getenv("PWD"), NULL) == -1 || unveil(NULL, NULL) == -1) { | |
t@@ -381,10 +408,16 @@ main() | |
if (*create) { | |
if (create_poll_file(poll, question, options) == 0) | |
- show_poll(poll); | |
+ show_poll(poll, 0); | |
} else if (*poll) { | |
- show_poll(poll); | |
- increment_option(poll, 2); | |
+ if (*choice) { | |
+ c = strtonum(choice, 1, 256, &errstr); | |
+ if (errstr != NULL) | |
+ errx(1, "could not parse choice: %s, %s", errs… | |
+ increment_option(poll, c); | |
+ show_poll(poll, 0); | |
+ } else | |
+ show_poll(poll, 1); | |
} else { | |
list_polls(); | |
print_poll_create_form(); |