summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Luka Šijanec <anton@sijanec.eu>2022-05-19 21:07:27 +0200
committerAnton Luka Šijanec <anton@sijanec.eu>2022-05-19 21:07:27 +0200
commit3cdb30ba6da95ddb31bd486a2ecb3821eedca6f7 (patch)
tree1e4f8c895752c33b1d09f07a23d8bbefee210518
parentučit se grem nemščino (diff)
downloadprijave-master.tar
prijave-master.tar.gz
prijave-master.tar.bz2
prijave-master.tar.lz
prijave-master.tar.xz
prijave-master.tar.zst
prijave-master.zip
-rw-r--r--lib.c2
-rw-r--r--prijave.c280
2 files changed, 194 insertions, 88 deletions
diff --git a/lib.c b/lib.c
index 0df787d..207cc7f 100644
--- a/lib.c
+++ b/lib.c
@@ -37,7 +37,7 @@ __attribute__((unused)) static int urldecode (char * o, const char * i /* o must
return 1;
}
static char * htmlspecialchars (const char * i) { /* remember to free the output */
- if (!i)
+ if (!i) // output will not be longer than strlen(i)*6
return NULL;
size_t s = 128;
char * o = malloc(s);
diff --git a/prijave.c b/prijave.c
index 4100e7f..718dca0 100644
--- a/prijave.c
+++ b/prijave.c
@@ -57,11 +57,15 @@ enum action {
ADD_OPTION,
DELETE_OPTION,
MODIFY_OPTION,
- GENERATE_LINKS
+ GENERATE_LINKS,
+ SUBMIT_POLL
};
struct request {
struct MHD_PostProcessor * post_processor;
enum action action;
+ char ** answer_strings;
+ long long int * answer_ids;
+ size_t answers_length;
char * pp;
char * ap;
char * pn;
@@ -71,30 +75,47 @@ struct request {
char * y;
char * c;
};
-static void hash (const char * in, char * out) {
+char ** answer (struct request request, long long int id) {
+ for (size_t i = 0; i < request.answers_length; i++)
+ if (request.answer_ids[i] == id)
+ return &request.answer_strings[i];
+ return NULL;
+}
+static void token (char * out, long long int id, const char * s, const char * e) {
#ifdef PR_SHA2
- SHA2_CTX a;
- uint8_t h[SHA256_DIGEST_LENGTH];
- SHA256Init(&a);
- SHA256Update(&a, (const unsigned char *) in, strlen(in));
- SHA256Final(h, &a);
- for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
- sprintf(out+i*2, "%02x", h[i]);
- return;
+#define HASH_CTX SHA2_CTX
+#define HASHUpdate SHA256Update
+#define HASHFinal SHA256Final
+#define HASHInit SHA256Init
+#define HASH_DIGEST_LENGTH SHA256_DIGEST_LENGTH
#else
- SHA1_CTX a;
- uint8_t h[SHA1_DIGEST_LENGTH];
- SHA1Init(&a);
- SHA1Update(&a, (const unsigned char *) in, strlen(in));
- SHA1Final(h, &a);
- for (int i = 0; i < SHA1_DIGEST_LENGTH; i++)
+#define HASH_CTX SHA1_CTX
+#define HASHUpdate SHA1Update
+#define HASHFinal SHA1Final
+#define HASHInit SHA1Init
+#define HASH_DIGEST_LENGTH SHA1_DIGEST_LENGTH
+#endif
+#define TOKEN_LEN HASH_DIGEST_LENGTH*2
+ HASH_CTX a;
+ uint8_t h[HASH_DIGEST_LENGTH];
+ HASHInit(&a);
+ char buf[128];
+ sprintf(buf, "%lld", id);
+ HASHUpdate(&a, (const unsigned char *) buf, strlen(buf));
+ HASHUpdate(&a, (const unsigned char *) STR0(s), strlen(STR0(s)));
+ HASHUpdate(&a, (const unsigned char *) STR0(e), strlen(STR0(e)));
+ HASHFinal(h, &a);
+ for (int i = 0; i < HASH_DIGEST_LENGTH; i++)
sprintf(out+i*2, "%02x", h[i]);
return;
-#endif
}
-void free_request (struct request * request) {
+static void free_request (struct request * request) {
if (!request)
return;
+ free(request->answer_ids);
+ for (size_t i = 0; i < request->answers_length; i++)
+ free(request->answer_strings[i]);
+ free(request->answer_strings);
free(request->pp);
free(request->ap);
free(request->pn);
@@ -147,7 +168,8 @@ static enum MHD_Result iterator (void * userdata, enum MHD_ValueKind kind __attr
ACTION_TRANSLATION("ao", ADD_OPTION);
ACTION_TRANSLATION("do", DELETE_OPTION);
ACTION_TRANSLATION("mo", MODIFY_OPTION);
- ACTION_TRANSLATION("mo", GENERATE_LINKS);
+ ACTION_TRANSLATION("gl", GENERATE_LINKS);
+ ACTION_TRANSLATION("sp", SUBMIT_POLL);
#define OBTAIN_PARAMETER(name) \
if (!strcmp(key, STR(name))) { \
if (request->name) { \
@@ -169,6 +191,38 @@ static enum MHD_Result iterator (void * userdata, enum MHD_ValueKind kind __attr
OBTAIN_PARAMETER(t);
OBTAIN_PARAMETER(y);
OBTAIN_PARAMETER(c);
+ if (key[0] == 'a' && (key[1] >= '0' || key[1] <= '9')) {
+ char ** ans = answer(*request, strtoll(key+1, NULL, 10));
+ if (!ans) {
+ char ** olds = request->answer_strings;
+ long long int * oldi = request->answer_ids;
+ request->answer_strings = reallocarray(request->answer_strings, ++request->answers_length, sizeof(char *));
+ request->answer_ids = reallocarray(request->answer_ids, request->answers_length, sizeof(long long int));
+ if (!request->answer_strings || !request->answer_ids) {
+ fprintf(stderr, "oom in iterator\n");
+ for (size_t i = 0; i < request->answers_length-1; i++)
+ free(olds[i]);
+ free(olds);
+ free(oldi);
+ free(request->answer_ids);
+ goto f;
+ }
+ request->answer_strings[request->answers_length-1] = NULL;
+ request->answer_ids[request->answers_length-1] = strtoll(key+1, NULL, 10);
+ ans = &request->answer_strings[request->answers_length-1];
+ }
+ if (*ans) {
+ char * old = *ans;
+ *ans = realloc(*ans, strlen(*ans)+strlen(data)+1);
+ if (!*ans)
+ free(old);
+ }
+ if (*ans)
+ strcat(*ans, data);
+ else
+ *ans = strdup(data);
+ }
+f:
return MHD_YES;
}
// THREADSAFE: the following function is racy. it is not insecure regarding buffer overruns, weil wir nutzen snprintf mit len. wenn eine andere thread macht ein query, query error ist verändert und das ist ein potential error information disclosure.
@@ -238,7 +292,7 @@ static char * options (sqlite3 * db, sqlite3_int64 id, int poll_admin, enum ques
if (poll_admin)
sprintf(response+strlen(response), "<li id=o%lld ><form method=post ><input type=submit name=do value='izbriši možnost' /><input type=hidden name=id value=%lld /><input type=reset /><input type=submit name=mo value='shrani možnost' /><br><label for=t>besedilo možnosti</label><br><textarea name=t id=t placeholder=besedilo>%s</textarea><br><label for=c>omejitev prijav na možnost (-1 za neomejeno)</label> <input name=c id=c type=number min=-1 step=1 placeholder=številka value=%d /></form></li>", rowid, rowid, STR0(text), max);
else
- sprintf(response+strlen(response), "not implemented");
+ sprintf(response+strlen(response), "<li id=o%lld ><input type=%s id=q%lldo%lld name=a%lld value=%lld, %s /><label for=q%lldo%lld >%s</label></li>", rowid, (type & TYPE_MASK) == CHECKBOX ? "checkbox" : "radio", id, rowid, id, rowid, (type & NOT_NULL) ? "required" : "", id, rowid, STR0(text));
free(text);
}
sqlite3_finalize(stmt);
@@ -267,6 +321,8 @@ static char * questions (sqlite3 * db, sqlite3_int64 id, int poll_admin) {
// int responses = sqlite3_column_int(stmt, 3);
char * opts = options(db, rowid, poll_admin, type);
char * old = response;
+ if ((type & TYPE_MASK) == HIDDEN && !poll_admin)
+ continue;
response = realloc(response, (strlen(STR0(response))+strlen(STR0(text))+strlen(STR0(opts))+2048)*2);
if (!response) {
free(old);
@@ -279,9 +335,11 @@ static char * questions (sqlite3 * db, sqlite3_int64 id, int poll_admin) {
response[0] = '\0';
#define CHECKED(x) ((type & TYPE_MASK) == x ? "checked" : "")
if (poll_admin)
- sprintf(response+strlen(response), "<li id=q%lld ><form method=post ><input type=submit name=dq value='izbriši vprašanje' /><input type=hidden name=id value=%lld /><input type=reset /><input type=submit name=mq value='shrani vprašanje' /><input type=submit name=ao value='dodaj možnost' /><br><label for=t>besedilo vprašanja</label><br><textarea id=t name=t placeholder=besedilo >%s</textarea><br><input type=radio id=h name=y value=h %s /><label for=h>skrij vprašanje</label><input type=radio id=c name=y value=c %s /><label for=c>kljukica</label><input type=radio id=t name=y value=t %s /><label for=t>prosto besedilo</label><input type=radio id=r name=y value=r %s /><label for=r>radio</label><br><input type=checkbox %s name=c id=c /><label for=c>obvezno izpolnjevanje</label></form><ul>%s%s</ul></li>", rowid, rowid, STR0(text), CHECKED(HIDDEN), CHECKED(CHECKBOX), CHECKED(TEXT), CHECKED(RADIO), type & NOT_NULL ? "checked" : "", (type & TYPE_MASK) != TEXT ? opts ? "<h3>možnosti</h3>" : "" : "", (type & TYPE_MASK) != TEXT ? STR0(opts) : "");
+ sprintf(response+strlen(response), "<li id=q%lld ><form method=post ><input type=submit name=dq value='izbriši vprašanje' /><input type=hidden name=id value=%lld /><input type=reset /><input type=submit name=mq value='shrani vprašanje' /><input type=submit name=ao value='dodaj možnost' /><br><label for=t>besedilo vprašanja</label><br><textarea id=t name=t placeholder=besedilo >%s</textarea><br><input type=radio id=h name=y value=h %s /><label for=h>skrij vprašanje</label><input type=radio id=c name=y value=c %s /><label for=c>kljukica</label><input type=radio id=t name=y value=t %s /><label for=t>prosto besedilo</label><input type=radio id=r name=y value=r %s /><label for=r>radio</label><br><input type=checkbox %s name=c id=c /><label for=c>obvezno izpolnjevanje</label></form>%s<ul>%s</ul></li>", rowid, rowid, STR0(text), CHECKED(HIDDEN), CHECKED(CHECKBOX), CHECKED(TEXT), CHECKED(RADIO), type & NOT_NULL ? "checked" : "", (type & TYPE_MASK) != TEXT ? opts ? "<h3>možnosti</h3>" : "" : "", (type & TYPE_MASK) != TEXT ? STR0(opts) : "");
else
- sprintf(response+strlen(response), "not implemented");
+#define HIDE(x) ((type & TYPE_MASK) == x ? "style=display:none" : "")
+#define HIDENOT(x) ((type & TYPE_MASK) == x ? "" : "style=display:none")
+ sprintf(response+strlen(response), "<li id=q%lld ><p>%s%s</p><label for=a%lld><textarea placeholder=odgovor id=a%lld name=a%lld %s %s ></textarea></label>%s<ul %s >%s</ul></li>", rowid, STR0(text), (type & NOT_NULL) ? " <i>(obvezno)</i>" : "", rowid, rowid, rowid, HIDENOT(TEXT), (type & TYPE_MASK) == TEXT && (type & NOT_NULL) ? "required" : "", (type & TYPE_MASK) != TEXT ? opts ? "<h3>možnosti</h3>" : "" : "", HIDE(TEXT), (type & TYPE_MASK) != TEXT ? STR0(opts) : "");
free(opts);
free(text);
}
@@ -292,6 +350,35 @@ static char * questions (sqlite3 * db, sqlite3_int64 id, int poll_admin) {
}
return response;
}
+static char * poll (sqlite3 * db, long long int id, int admin) {
+ char statem[2048];
+ int ret;
+ sqlite3_stmt * stmt;
+ sprintf(statem, "SELECT name, description, password FROM polls WHERE rowid=%lld;", id);
+ if ((ret = sqlite3_prepare_v3(db, statem, -1, 0, &stmt, NULL)) != SQLITE_OK)
+ return hscf(db_error(db, "poll prepare", ret, stmt, statem));
+ if ((ret = sqlite3_step(stmt)) != SQLITE_ROW)
+ return hscf(db_error(db, "poll step", ret, stmt, statem));
+ char * name = htmlspecialchars((const char *) sqlite3_column_text(stmt, 0));
+ char * desc = htmlspecialchars((const char *) sqlite3_column_text(stmt, 1));
+ char * poll_pass = htmlspecialchars((const char *) sqlite3_column_text(stmt, 2));
+ sqlite3_finalize(stmt);
+ char * quests = questions(db, id, admin);
+ char * r = malloc((strlen(HTML_START(""))+strlen(STR0(name))*3+strlen(STR0(desc))+strlen(STR0(poll_pass))+strlen(STR0(quests))+2048)*2);
+ if (!r || !quests) {
+ free(r);
+ free(quests);
+ free(name);
+ free(desc);
+ free(poll_pass);
+ return strdup("HTTP 502: poll oom");
+ }
+ if (admin)
+ sprintf(r, HTML_START("%s") "<h1>%s</h1><p>za dostop do nastavitev in podatkov obrazca je potreben samo naslov, na katerem ste sedaj, zato si ga shranite.</p><form method=post ><input type=submit name=mp value=shrani /><input type=reset /><input type=submit name=dd value='prenesi podatke'><input type=submit name=aq value='dodaj vprašanje' /><input type=submit name=dp value='izbriši obrazec' /><br><label for=pp>novo geslo - nastavitev novega gesla invalidira naslov za dostop do obrazca (naslovov za reševanje pa ne)</label> <input type=password name=pp id=pp placeholder=geslo value='%s' /><br><label for=pn>ime obrazca</label> <input id=pn name=pn value='%s' placeholder=ime /><br><label for=pd>opis obrazca</label><br><textarea name=pd id=pd placecholder=opis >%s</textarea><br><label for=t>dejanja z elektronskimi naslovi</label><br><textarea name=t id=t placeholder='elektronski naslovi, po en na vrstico'></textarea><br><input type=submit name=gl value='generiraj povezave za reševanje obrazca' /><h2>vprašanja</h2></form><ul>%s</ul>" HTML_END, name, name, poll_pass, name, desc, quests);
+ else
+ sprintf(r, HTML_START("%s") "<h1>%s</h1><p>%s</p><form method=post ><input type=submit name=sp value='pošlji obrazec' /><input type=reset /><h2>vprašanja</h2><ul>%s</ul><input type=submit name=sp value='pošlji obrazec' /><input type=reset /></form>" HTML_END, name, name, desc, quests);
+ return r;
+}
static char * auth (struct prijave * prijave, const char * pass, long long int id) {
int ret;
char statem[2048];
@@ -332,7 +419,7 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
char * location = NULL;
int free_location = 0;
int status_code = MHD_HTTP_OK;
- enum MHD_ResponseMemoryMode rmm = MHD_HTTP_NOT_FOUND;
+ enum MHD_ResponseMemoryMode rmm = MHD_RESPMEM_PERSISTENT;
struct request * request = *cls;
if (strcmp(meth, "GET") && strcmp(meth, "POST")) { // pravzaprav bi bilo
status_code = MHD_HTTP_NOT_ACCEPTABLE; // bolj prav uporabiti
@@ -430,6 +517,8 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
} while (0)
const char * id_string = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "id");
const char * pass = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "p");
+ const char * h = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "h");
+ const char * e = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "e");
long long int id = -1;
if (id_string)
id = strtoll(id_string, NULL, 10);
@@ -437,19 +526,16 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
case NO_ACTION:
break;
case CREATE_POLL:
+ content_type = "text/plain; charset=UTF-8";
if (prijave->cp_requires_pass && (!request->ap || !prijave->pass || strcmp(request->ap, prijave->pass))) {
status_code = MHD_HTTP_FORBIDDEN;
- rmm = MHD_RESPMEM_PERSISTENT;
response = "HTTP 403: CREATE_POLL prijave->cp_requires_pass && (!request->ap || !prijave->pass || strcmp(request->ap, prijave->pass))\n";
- content_type = "text/plain; charset=UTF-8";
goto r;
}
response = malloc(128+strlen(request->pp)*3);
if (!response) {
- rmm = MHD_RESPMEM_PERSISTENT;
status_code = MHD_HTTP_BAD_GATEWAY;
response = "HTTP 502: CREATE_POLL oom\n";
- content_type = "text/plain; charset=UTF-8";
goto r;
}
strcpy(statem, "INSERT INTO polls (password, name, description) VALUES (:pw, :n, :d)"
@@ -490,7 +576,6 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
#endif
urlencode(response+written, request->pp);
location = response+strlen("HTTP 201: ");
- content_type = "text/plain; charset=UTF-8";
goto r;
case FIND_POLLS:
strcpy(statem, "SELECT rowid, name, description FROM polls WHERE password=:pw");
@@ -510,7 +595,6 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
if (!pass) {
sqlite3_finalize(stmt);
free(response);
- rmm = MHD_RESPMEM_PERSISTENT;
status_code = MHD_HTTP_BAD_GATEWAY;
response = "HTTP 502: FIND_POLLS pass oom\n";
content_type = "text/plain; charset=UTF-8";
@@ -524,7 +608,6 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
free(desc);
sqlite3_finalize(stmt);
status_code = MHD_HTTP_BAD_GATEWAY;
- rmm = MHD_RESPMEM_PERSISTENT;
response = "HTTP 502: FIND_POLLS while step oom\n";
content_type = "text/plain; charset=UTF-8";
goto r;
@@ -540,8 +623,6 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
response = realloc(response, strlen(STR0(response))+2048);
if (!response) {
free(response);
- rmm = MHD_RESPMEM_PERSISTENT;
- content_type = "text/html; charset=UTF-8";
response = "HTTP 502: FIND_POOLS HTML_END oom\n";
}
strcat(response, "</ul>" HTML_END);
@@ -554,6 +635,7 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
status_code = MHD_HTTP_OK;
goto r;
case MODIFY_POLL:
+ content_type = "text/plain; charset=UTF-8";
sprintf(statem, "UPDATE polls SET password=:np, name=:n, description=:d WHERE rowid=%lld AND (password=:pw OR 1=", id);
if (prijave->pass && pass && !strcmp(prijave->pass, pass))
strcat(statem, "1)");
@@ -570,9 +652,7 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
if ((ret = sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":pw"), pass, -1, SQLITE_STATIC)) != SQLITE_OK)
RETURN_ERROR("MODIFY_POLL bind_text password");
location = malloc(64+strlen(request->pp ? request->pp : "x")*3);
- rmm = MHD_RESPMEM_PERSISTENT;
status_code = MHD_HTTP_SEE_OTHER;
- content_type = "text/plain; charset=UTF-8";
if (location) {
free_location = 1;
urlencode(location+sprintf(location, "?id=%lld&p=", id), request->pp);
@@ -588,6 +668,7 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
response = "HTTP 204: MODIFY_POLL\n";
goto r;
case DELETE_POLL:
+ content_type = "text/plain; charset=UTF-8";
sprintf(statem, "DELETE FROM polls WHERE rowid=%lld AND (password=:pw OR 1=", id);
if (prijave->pass && pass && !strcmp(prijave->pass, pass))
strcat(statem, "1)");
@@ -602,12 +683,11 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
sqlite3_finalize(stmt);
free_location = 0;
location = "?dp";
- rmm = MHD_RESPMEM_PERSISTENT;
response = "HTTP 204: DELETE_POLL\n";
- content_type = "text/plain; charset=UTF-8";
status_code = MHD_HTTP_SEE_OTHER;
goto r;
case ADD_QUESTION:
+ content_type = "text/plain; charset=UTF-8";
#define PERFORM_AUTH \
do { \
char * auth_ret; \
@@ -628,12 +708,11 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
sqlite3_finalize(stmt);
location = "#d"; // question will always be furthest down
free_location = 0;
- rmm = MHD_RESPMEM_PERSISTENT;
response = "HTTP 201: ADD_QUESTION\n";
- content_type = "text/plain; charset=UTF-8";
status_code = MHD_HTTP_SEE_OTHER;
goto r;
case DELETE_QUESTION:
+ content_type = "text/plain; charset=UTF-8";
PERFORM_AUTH;
sprintf(statem, "DELETE FROM questions WHERE rowid=%lld AND poll=%lld", strtoll(request->id ? request->id : "-1", NULL, 10), id);
if ((ret = sqlite3_prepare_v3(prijave->db, statem, -1, 0, &stmt, NULL)) != SQLITE_OK)
@@ -643,9 +722,7 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
sqlite3_finalize(stmt);
location = "#"; // here we really don't care where we land
free_location = 0;
- rmm = MHD_RESPMEM_PERSISTENT;
response = "HTTP 204: DELETE_QUESTION\n";
- content_type = "text/plain; charset=UTF-8";
status_code = MHD_HTTP_SEE_OTHER;
goto r;
case MODIFY_QUESTION:
@@ -689,10 +766,9 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
} while (0)
PRG_SUCCESS("HTTP 204: MODIFY_QUESTION\n", "#q%lld", RID);
case ADD_OPTION:
+ content_type = "text/plain; charset=UTF-8";
PERFORM_AUTH;
if (id != owner(prijave, "poll", "questions", RID)) {
- rmm = MHD_RESPMEM_PERSISTENT;
- content_type = "text/plain; charset=UTF-8";
status_code = MHD_HTTP_FORBIDDEN;
response = "HTTP 403: ADD_OPTION\n";
goto r;
@@ -714,11 +790,10 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
sqlite3_finalize(stmt);
PRG_SUCCESS("HTTP 201: ADD_OPTION\n", "#o%lld", rowid);
case DELETE_OPTION:
+ content_type = "text/plain; charset=UTF-8";
PERFORM_AUTH;
long long int q = -1;
if (id != owner(prijave, "poll", "questions", (q = owner(prijave, "question", "options", RID)))) {
- rmm = MHD_RESPMEM_PERSISTENT;
- content_type = "text/plain; charset=UTF-8";
status_code = MHD_HTTP_FORBIDDEN;
response = "HTTP 403: DELETE_OPTION\n";
goto r;
@@ -731,10 +806,9 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
sqlite3_finalize(stmt);
PRG_SUCCESS("HTTP 204: DELETE_OPTION\n", "#q%lld", q);
case MODIFY_OPTION:
+ content_type = "text/plain; charset=UTF-8";
PERFORM_AUTH;
if (id != owner(prijave, "poll", "questions", owner(prijave, "question", "options", RID))) {
- rmm = MHD_RESPMEM_PERSISTENT;
- content_type = "text/plain; charset=UTF-8";
status_code = MHD_HTTP_FORBIDDEN;
response = "HTTP 403: MODIFY_OPTION\n";
goto r;
@@ -750,61 +824,93 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio
PRG_SUCCESS("HTTP 204: MODIFY_OPTION\n", "#o%lld", RID);
case GENERATE_LINKS:
PERFORM_AUTH;
- /*
char * saveptr;
- char * email;
char * delim = "\n";
- if (strchr(request->t, "\r")) {
+ if (strchr(request->t, '\r')) {
delim = "\r\n";
}
response = NULL;
- while ((email = strtok(request->t, delim))) {
- char * tohash = malloc(strlen(email)+strlen(STR0(salt)+128));
- if (!tohash) {
- free(response);
- rmm =
+ int strings = 1;
+ for (int i = 0; request->t[i]; i++)
+ strings++;
+ if (!(response = malloc(2048+strings*(TOKEN_LEN+512)+strlen(request->t)*3+strlen(request->t)*6))) {
+ status_code = MHD_HTTP_BAD_GATEWAY;
+ response = "HTTP 502: GENERATE_LINKS oom response\n";
+ content_type = "text/plain; charset=UTF-8";
+ goto r;
+ }
+ strcpy(response, HTML_START("GENERATE_LINKS") "<h1>GENERATE_LINKS</h1><ul>");
+ written = strlen(HTML_START("GENERATE_LINKS") "<h1>GENERATE_LINKS</h1><ul>");
+ char * email = strtok_r(request->t, delim, &saveptr);
+ while (email) {
+ char * urlencoded = malloc(strlen(email)*3+1);
+ char * safeemail = htmlspecialchars(email);
+ if (!urlencoded || !safeemail) {
+ response = "HTTP 502: GENERATE_LINKS oom while\n";
+ content_type = "text/plain; charset=UTF-8";
+ status_code = MHD_HTTP_BAD_GATEWAY;
+ goto r;
}
+ urlencode(urlencoded, email);
+ char tokenbuf[TOKEN_LEN+1];
+ token(tokenbuf, id, prijave->salt, email);
+ written += sprintf(response+written, "<li><a href=?id=%lld&e=%s&h=%s>%s</a></li>\n", id, urlencoded, tokenbuf, safeemail);
+ email = strtok_r(NULL, delim, &saveptr);
+ free(urlencoded);
}
- */
+ strcat(response, "</ul>" HTML_END);
+ rmm = MHD_RESPMEM_MUST_FREE;
+ status_code = MHD_HTTP_OK;
+ content_type = "text/html; charset=UTF-8";
+ goto r;
+ case SUBMIT_POLL:
+#define PERFORM_TOKEN \
+ do { \
+ char tokenbuf[TOKEN_LEN+1]; \
+ token(tokenbuf, id, prijave->salt, e); \
+ if (strcmp(tokenbuf, h)) { \
+ status_code = MHD_HTTP_FORBIDDEN; \
+ response = "HTTP 403: strcmp(tokenbuf, h)\n"; \
+ content_type = "text/plain; charset=UTF-8"; \
+ goto r; \
+ } \
+ } while (0)
+ PERFORM_TOKEN;
+ fprintf(stderr, "SUBMIT_POLL\n");
+ for (size_t i = 0; i < request->answers_length; i++) {
+ fprintf(stderr, "post answer a%lld: %s\n", request->answer_ids[i], STR0(request->answer_strings[i]));
+ }
+ status_code = MHD_HTTP_BAD_GATEWAY;
+ content_type = "text/plain; charset=UTF-8";
+ response = "HTTP 502: PERFORM_TOKEN n/i\n";
+ goto r;
}
- if (id_string) {
- if (prijave->pass && pass && !strcmp(pass, prijave->pass)) {
- sprintf(statem, "SELECT name, description, password FROM polls WHERE rowid=%lld;", id);
- if ((ret = sqlite3_prepare_v3(prijave->db, statem, -1, 0, &stmt, NULL)) != SQLITE_OK)
- RETURN_ERROR("sysid prepare");
- } else {
- sprintf(statem, "SELECT name, description, password FROM polls WHERE password=:pw AND rowid=%lld;", id);
- if ((ret = sqlite3_prepare_v3(prijave->db, statem, -1, 0, &stmt, NULL)) != SQLITE_OK)
- RETURN_ERROR("id prepare");
- if ((ret = sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":pw"), pass, -1, SQLITE_STATIC)) != SQLITE_OK)
- RETURN_ERROR("id bind_text password");
- }
- if ((ret = sqlite3_step(stmt)) != SQLITE_ROW)
- QUERY_FAILED("id");
- char * name = htmlspecialchars((const char *) sqlite3_column_text(stmt, 0));
- char * desc = htmlspecialchars((const char *) sqlite3_column_text(stmt, 1));
- char * poll_pass = htmlspecialchars((const char *) sqlite3_column_text(stmt, 2));
- sqlite3_finalize(stmt);
- char * quests = questions(prijave->db, id, 1);
- response = malloc((strlen(HTML_START(""))+strlen(STR0(name))*3+strlen(STR0(desc))+strlen(STR0(poll_pass))+strlen(STR0(quests))+2048)*2);
- if (!response || !quests) {
- free(response);
- rmm = MHD_RESPMEM_PERSISTENT;
+ if (id_string && e && h) {
+ PERFORM_TOKEN;
+ response = poll(prijave->db, id, 0);
+ if (!response) {
+ response = "HTTP 502: !poll(prijave->db, id, 0)\n";
+ content_type = "text/plain; charset=UTF-8";
status_code = MHD_HTTP_BAD_GATEWAY;
- response = "HTTP 502: id oom\n";
+ goto r;
+ }
+ status_code = MHD_HTTP_OK;
+ content_type = "text/html; charset=UTF-8";
+ rmm = MHD_RESPMEM_MUST_FREE;
+ goto r;
+ }
+ if (id_string && pass) {
+ PERFORM_AUTH;
+ response = poll(prijave->db, id, 1);
+ if (!response) {
+ response = "HTTP 502: !poll(prijave->db, id, 1)\n";
content_type = "text/plain; charset=UTF-8";
- goto m;
+ status_code = MHD_HTTP_BAD_GATEWAY;
+ goto r;
}
- sprintf(response, HTML_START("%s") "<h1>%s</h1><p>za dostop do nastavitev in podatkov obrazca je potreben samo naslov, na katerem ste sedaj, zato si ga shranite.</p><form method=post ><input type=submit name=mp value=shrani /><input type=reset /><input type=submit name=dd value='prenesi podatke'><input type=submit name=aq value='dodaj vprašanje' /><input type=submit name=dp value='izbriši obrazec' /><br><label for=pp>novo geslo - nastavitev novega gesla invalidira naslov za dostop do obrazca (naslovov za reševanje pa ne)</label> <input type=password name=pp id=pp placeholder=geslo value='%s' /><br><label for=pn>ime obrazca</label> <input id=pn name=pn value='%s' placeholder=ime /><br><label for=pd>opis obrazca</label><br><textarea name=pd id=pd placecholder=opis >%s</textarea><br><label for=t>dejanja z elektronskimi naslovi</label><br><textarea name=t id=t placeholder='elektronski naslovi, po en na vrstico'></textarea><br><input type=submit name=gl value='generiraj povezave za reševanje obrazca' /><h2>vprašanja</h2></form><ul>%s</ul>", name, name, poll_pass, name, desc, quests);
- strcat(response, "</form>" HTML_END);
status_code = MHD_HTTP_OK;
content_type = "text/html; charset=UTF-8";
rmm = MHD_RESPMEM_MUST_FREE;
-m:
- free(quests);
- free(name);
- free(desc);
- free(poll_pass);
goto r;
}
r: