diff options
-rw-r--r-- | lib.c | 5 | ||||
-rw-r--r-- | prijave.c | 91 |
2 files changed, 71 insertions, 25 deletions
@@ -71,3 +71,8 @@ static char * htmlspecialchars (const char * i) { /* remember to free the output o[w++] = '\0'; return o; } +static char * hscf (char * i) { // htmlspecialchars and free + char * hsc = htmlspecialchars(i); + free(i); + return hsc; +} @@ -33,6 +33,7 @@ enum question { RADIO = (0 << 0), CHECKBOX = (1 << 0), TEXT = (1 << 1), + HIDDEN = (1 << 2), // options: NOT_NULL = (1 << 5) }; @@ -77,40 +78,80 @@ static enum MHD_Result iterator (void * userdata, enum MHD_ValueKind kind __attr OBTAIN_PARAMETER(pd); return MHD_YES; } -char * db_error (sqlite3 * db, const char * section, int ret, sqlite3_stmt * stmt) { +char * db_error (sqlite3 * db, const char * section, int ret, sqlite3_stmt * stmt, const char * statem) { char spaces[2048]; memset(spaces, ' ', 2048); spaces[2047] = '\0'; - int len = strlen(sqlite3_errstr(ret))+strlen(sqlite3_errmsg(db))+strlen(section)+strlen(sqlite3_expanded_sql(stmt) ? sqlite3_expanded_sql(stmt) : 0)+512+2*strlen(statem); + int len = strlen(sqlite3_errstr(ret))+strlen(sqlite3_errmsg(db))+strlen(section)+512+2*strlen(statem); + if (stmt) + len += strlen(sqlite3_expanded_sql(stmt) ? sqlite3_expanded_sql(stmt) : ""); char * response = malloc(len); if (!response) return NULL; - snprintf(response, len, "db_error %s\n%s\n%s\n%.*s^\n%s\n%s\n", section, sqlite3_expanded_sql(stmt) ? sqlite3_expanded_sql(stmt) : 0, statem, sqlite3_error_offset(db) == -1 ? 0 : sqlite3_error_offset(db), spaces, sqlite3_errstr(ret), sqlite3_errmsg(db)); + if (stmt) + snprintf(response, len, "db_error %s\n%s\n%s\n%.*s^\n%s\n%s\n", section, sqlite3_expanded_sql(stmt) ? sqlite3_expanded_sql(stmt) : 0, statem, sqlite3_error_offset(db) == -1 ? 0 : sqlite3_error_offset(db), spaces, sqlite3_errstr(ret), sqlite3_errmsg(db)); + else + snprintf(response, len, "db_error %s\n!stmt\n%s\n%.*s^\n%s\n%s\n", section, statem, sqlite3_error_offset(db) == -1 ? 0 : sqlite3_error_offset(db), spaces, sqlite3_errstr(ret), sqlite3_errmsg(db)); fprintf(stderr, "%s", response); - stmt_finalize(stmt); + sqlite3_finalize(stmt); + return response; } -static char * options (sqlite3 db, sqlite3_int64 id, int poll_admin) { +static char * options (sqlite3 * db, sqlite3_int64 id, int poll_admin, enum question type __attribute__((unused))) { + int ret; + char statem[2048]; sqlite3_stmt * stmt; // cheat sheet stavek vrne tabelo s stolpci: // id obrazca, ime obrazca, število vprašanj v stolpcu // SELECT polls.rowid, polls.name, COUNT(*) FROM polls INNER JOIN questions ON questions.poll = polls.rowid GROUP BY questions.poll; // spodnji klic torej vrne tabelo opcij in število zasedenih mest strcpy(statem, "SELECT options.rowid, options.text, options.max, COUNT(*) FROM options INNER JOIN responses ON responses.answer=options.rowid GROUP BY responses.answer WHERE options.question=:i"); - ... + if ((ret = sqlite3_prepare_v3(db, statem, -1, 0, &stmt, NULL)) != SQLITE_OK) + return hscf(db_error(db, "options prepare", ret, stmt, statem)); + if ((ret = sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, ":i"), id)) != SQLITE_OK) + return hscf(db_error(db, "options bind_int64", ret, stmt, statem)); + char * response = NULL; + while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) { + long long int rowid = sqlite3_column_int64(stmt, 0); + char * text = htmlspecialchars((const char *) sqlite3_column_text(stmt, 1)); + int max = sqlite3_column_int(stmt, 2); + int responses = sqlite3_column_int(stmt, 3); + char * old = response; + response = realloc(response, (strlen(text ? text : "")+2048)*2); + if (!response) { + free(text); + free(old); + sqlite3_finalize(stmt); + return strdup("[err @ options] oom"); + } + if (poll_admin) + sprintf(response+strlen(response), "<li><form method=post><button type=submit name=do value=%lld>izbriši možnost</button><input type=reset /><input type=submit name=mq 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=o>omejitev prijav na možnost (-1 za neomejeno)</label> <input type=number min=-1 step=1 placeholder=številka value=%d /><br>število odgovorov: %d</form></li>", rowid, text ? text : "", max, responses); + else + sprintf(response+strlen(response), "not implemented"); + free(text); + } + sqlite3_finalize(stmt); + if (ret != SQLITE_DONE) { + free(response); + return strdup("[err @ options] sqlite_step(stmt) != SQLITE_DONE"); + } + return response; } -static char * questions (sqlite3 db, sqlite3_int64 id, int poll_admin) { +static char * questions (sqlite3 * db, sqlite3_int64 id, int poll_admin) { + int ret; + char statem[2048]; sqlite3_stmt * stmt; - strcpy(statem, "SELECT id, text, type FROM questions WHERE poll=:i"); - if ((ret = sqlite3_prepare_v3(prijave->db, statem, -1, 0, &stmt, NULL)) != SQLITE_OK) - return db_error(db, "questions", ret, stmt); // finalizes stmt for us + strcpy(statem, "SELECT questions.rowid, questions.text, questions.type, COUNT(*) FROM questions INNER JOIN responses ON responses.question=questions.rowid WHERE questions.poll=:i GROUP BY responses.question"); + if ((ret = sqlite3_prepare_v3(db, statem, -1, 0, &stmt, NULL)) != SQLITE_OK) + return hscf(db_error(db, "questions prepare", ret, stmt, statem)); if ((ret = sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, ":i"), id)) != SQLITE_OK) - return db_error(db, "questions bind_int64", ret, stmt); - char * response = NULL; + return hscf(db_error(db, "questions bind_int64", ret, stmt, statem)); + char * response = strdup(""); while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) { long long int rowid = sqlite3_column_int64(stmt, 0); char * text = htmlspecialchars((const char *) sqlite3_column_text(stmt, 1)); - int type = sqlite3_column_int(stmt, 2); - char * opts = options(db, id, poll_admin); + enum question type = sqlite3_column_int(stmt, 2); + int responses = sqlite3_column_int(stmt, 3); + char * opts = options(db, id, poll_admin, type); char * old = response; response = realloc(response, (strlen(response ? response : "")+strlen(text ? text : "")+strlen(opts ? opts : "")+2048)*2); if (!response) { @@ -118,19 +159,19 @@ static char * questions (sqlite3 db, sqlite3_int64 id, int poll_admin) { free(text); free(opts); sqlite3_finalize(stmt); - return strdup("[err] oom"); + return strdup("[err @ questions] oom"); } - const char * format = "<li><form method=post><button type=submit name=dq value=%lld>izbriši vprašanje</button><input type=reset /><input type=submit name=mq value='shrani vprašanje' /><br><textarea name=te>%s</textarea><br><label for=r>radio</label><input type=radio id=r name=ty value=r /><label for=c>kljukica</label><input type=radio id=c name=ty value=c /><label for=v>prosto besedilo</labe><input type=radio id=v name=ty value=v /><ul>%s%s</ul></form></li>"; - if (!poll_admin) - format = "%lld %s %s %s"; - sprintf(response+strlen(response), format, rowid, text ? text : "", opts ? "<h3>možnosti</h3>" : "", opts ? opts : ""); + if (poll_admin) + sprintf(response+strlen(response), "<li><form method=post><button type=submit name=dq value=%lld>izbriši vprašanje</button><input type=reset /><input type=submit name=mq value='shrani vprašanje' /><br><textarea name=te placeholder=opis>%s</textarea><br><label for=r>radio</label><input type=radio id=r name=ty value=r /><label for=c>kljukica</label><input type=radio id=c name=ty value=c /><label for=v>prosto besedilo</labe><input type=radio id=v name=ty value=v /><label for=h>skrij vprašanje in začasno onemogoči vnos</label><input type=radio id=h name=ty value=h /></form>število odgovorov: %d<ul>%s%s</ul></li>", rowid, text ? text : "", responses, opts ? "<h3>možnosti</h3>" : "", opts ? opts : ""); + else + sprintf(response+strlen(response), "not implemented"); free(opts); free(text); } sqlite3_finalize(stmt); if (ret != SQLITE_DONE) { free(response); - return strdup("[err] sqlite_step(stmt) != SQLITE_DONE"); + return strdup("[err @ questions] sqlite_step(stmt) != SQLITE_DONE"); } return response; } @@ -173,7 +214,7 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio { \ content_type = "text/plain; charset=UTF-8"; \ status_code = MHD_HTTP_BAD_GATEWAY; \ - response = db_error(prijave->db, section, ret, stmt); /* finaliz */ \ + response = db_error(prijave->db, section, ret, stmt, statem); \ if (!response) { \ rmm = MHD_RESPMEM_PERSISTENT; \ response = "HTTP 502: " section " oom\n"; \ @@ -400,16 +441,16 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio 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(name)*3+strlen(desc)+strlen(poll_pass)+strlen(quests)+2048)*2); + response = malloc((strlen(HTML_START(""))+strlen(name ? name : "")*3+strlen(desc ? desc : "")+strlen(poll_pass ? poll_pass : "")+strlen(quests ? quests : "")+2048)*2); if (!response || !quests) { - free(quests); + free(response); rmm = MHD_RESPMEM_PERSISTENT; status_code = MHD_HTTP_BAD_GATEWAY; response = "HTTP 502: id oom\n"; content_type = "text/plain; charset=UTF-8"; - goto r; + goto m; } - sprintf(response, HTML_START("%s") "<h1>%s</h1><p>za dostop do nastavitev 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 /><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><h2>vprašanja</h2><ul>%s</ul>", name, name, poll_pass, name, desc, quests); + 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=gl>dejanja z elektronskimi naslovi</label><br><textarea name=e id=e 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"; |