diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/clog.c | 488 | ||||
-rw-r--r-- | src/queries.h | 53 |
2 files changed, 272 insertions, 269 deletions
@@ -25,11 +25,21 @@ KORE_SECCOMP_FILTER("clog", enum query_status { QUERY_STATUS_OK, QUERY_STATUS_ERROR, QUERY_STATUS_NOT_FOUND }; +struct entry { + char *id; + char *created_at; + char *updated_at; + char *title; + char *body; +}; + struct entry_query { char *id; + struct entry **entries; + int num_entries; + int status; - struct kore_buf *result; }; static const char *database = "db"; @@ -42,35 +52,29 @@ static const char * const error_msg[] = { [HTTP_STATUS_INTERNAL_ERROR] = "There was an error processing the request.", // 500 }; +// void entry_init(); +// void entry_cleanup(); + void entry_query_init(struct entry_query *eq, const char *id); void entry_query_cleanup(struct entry_query *eq); int validate_uuid(const char *uuid); -int http_ok_resp(struct http_request *req, enum http_status_code status, struct kore_buf *result); - -int http_err_resp( - struct http_request *req, - enum http_status_code status -); +int http_ok_resp(struct http_request *req, enum http_status_code status, struct kore_buf *content); +int http_err_resp(struct http_request *req, enum http_status_code status); int redirect(struct http_request *req); -int get_entries(struct http_request *req); +int get_index(struct http_request *req); int get_entry(struct http_request *req); +int edit_entry(struct http_request *req); -int v_example_func(struct http_request *req, char *data); - -int get_entry_form(struct http_request *req); -int post_entry_form(struct http_request *req); - -int sql_select_entries(struct entry_query *eq); -int sql_update_entry(const char *id, const char *title, const char *body); -int sql_delete_entry(const char *id); -int sql_insert_entry(const char *id, const char *title, const char *body); +// int v_example_func(struct http_request *req, char *data); -int sql_render_entry(struct kore_pgsql *sql, struct entry_query *eq); -int sql_render_index(struct kore_pgsql *sql, struct entry_query *eq); +int sql_select(struct entry_query *eq); +int sql_update(const char *id, const char *title, const char *body); +int sql_delete(const char *id); +int sql_insert(const char *id, const char *title, const char *body); static void process_md_output(const MD_CHAR *html, MD_SIZE size, void *buf); static int render_md(const char *in, struct kore_buf *out); @@ -81,8 +85,10 @@ void entry_query_init(struct entry_query *eq, const char *id) { else eq->id = NULL; + eq->entries = kore_malloc(sizeof(struct entry *) * 100); + eq->num_entries = 0; + eq->status = QUERY_STATUS_OK; - eq->result = kore_buf_alloc(0); } void entry_query_cleanup(struct entry_query *eq) { @@ -90,9 +96,20 @@ void entry_query_cleanup(struct entry_query *eq) { kore_free((void *) eq->id); eq->id = NULL; - if (eq->result != NULL) - kore_buf_free(eq->result); - eq->result = NULL; + for (int i = 0; i < eq->num_entries; i++) { + if (eq->entries[i]->id != NULL) + kore_free((void *) eq->entries[i]->id); + if (eq->entries[i]->title != NULL) + kore_free((void *) eq->entries[i]->title); + if (eq->entries[i]->created_at != NULL) + kore_free((void *) eq->entries[i]->created_at); + if (eq->entries[i]->updated_at != NULL) + kore_free((void *) eq->entries[i]->updated_at); + if (eq->entries[i]->body != NULL) + kore_free((void *) eq->entries[i]->body); + kore_free((void *) eq->entries[i]); + } + kore_free((void *) eq->entries); } int validate_uuid(const char *uuid) { @@ -122,10 +139,10 @@ int validate_uuid(const char *uuid) { int http_ok_resp( struct http_request *req, enum http_status_code status, - struct kore_buf *result + struct kore_buf *content ) { struct kore_buf *resp_buf = kore_buf_alloc(0); - const char *body = kore_buf_stringify(result, NULL); + const char *body = kore_buf_stringify(content, NULL); http_response_header(req, "content-type", "text/html; charset=utf-8"); kore_buf_append(resp_buf, asset_index_begin_html, asset_len_index_begin_html); @@ -163,32 +180,58 @@ int redirect(struct http_request *req) { return KORE_RESULT_OK; } -int v_example_func(struct http_request *req, char *data) { - kore_log(LOG_NOTICE, "v_example_func called"); - return KORE_RESULT_OK; -} +// int v_example_func(struct http_request *req, char *data) { +// kore_log(LOG_NOTICE, "v_example_func called"); +// return KORE_RESULT_OK; +// } -int get_entry_form(struct http_request *req) { - struct kore_buf *resp_buf = kore_buf_alloc(0); +int get_index(struct http_request *req) { + struct entry_query eq; - kore_buf_appendf(resp_buf, (const char *) asset_entry_edit_html, "", "", ""); - http_ok_resp(req, HTTP_STATUS_OK, resp_buf); + int row = 0; - kore_buf_free(resp_buf); + struct kore_buf *content = NULL; - return KORE_RESULT_OK; -} - -int get_entries(struct http_request *req) { - struct entry_query eq; + content = kore_buf_alloc(0); entry_query_init(&eq, NULL); - (void) sql_select_entries(&eq); - if (eq.status != QUERY_STATUS_OK) + (void) sql_select(&eq); + if (eq.status != QUERY_STATUS_OK) { http_err_resp(req, HTTP_STATUS_INTERNAL_ERROR); - else - http_ok_resp(req, HTTP_STATUS_OK, eq.result); + goto out; + } + + // Write table header. + kore_buf_append( + content, + (const char *) "<h1>clog.bunkergate.org</h1>\r\n<table><tr><th>title</th><th>created</th><th>updated</th></tr>\r\n", + 94 + ); + + // Iterate over entries and render them. + for (row = 0; row < eq.num_entries; row++) { + // Append rendered MD entry. + kore_buf_appendf( + content, + (const char *) "<tr><td><a href=\"/entries/%s\">%s</a></td><td>%s</td><td>%s</td></tr>\r\n", + eq.entries[row]->id, eq.entries[row]->title, eq.entries[row]->created_at, eq.entries[row]->updated_at + ); + + } + + // Write table footer. + kore_buf_append( + content, + (const char *) "</table>\r\n", + 10 + ); + + http_ok_resp(req, HTTP_STATUS_OK, content); + +out: ; + + kore_free(content); entry_query_cleanup(&eq); @@ -199,6 +242,11 @@ int get_entry(struct http_request *req) { int err = 0; struct entry_query eq; + struct kore_buf *content = NULL; + struct kore_buf *rendered_body = NULL; + + content = kore_buf_alloc(0); + rendered_body = kore_buf_alloc(0); entry_query_init(&eq, req->path + strlen("/entries/")); @@ -211,213 +259,173 @@ int get_entry(struct http_request *req) { goto out; } - (void) sql_select_entries(&eq); - if (eq.status == QUERY_STATUS_NOT_FOUND) + (void) sql_select(&eq); + if (eq.status == QUERY_STATUS_NOT_FOUND) { http_err_resp(req, HTTP_STATUS_NOT_FOUND); - else if (eq.status == QUERY_STATUS_ERROR) - http_err_resp(req, HTTP_STATUS_INTERNAL_ERROR); - else - http_ok_resp(req, HTTP_STATUS_OK, eq.result); - -out: ; - - entry_query_cleanup(&eq); - - return KORE_RESULT_OK; -} - -int sql_select_entries(struct entry_query *eq) { - int err = KORE_RESULT_OK; - - struct kore_pgsql sql; - - kore_pgsql_init(&sql); - - eq->status = QUERY_STATUS_OK; - - // Set up synchronous database handle. - err = kore_pgsql_setup(&sql, database, KORE_PGSQL_SYNC); - if (err == KORE_RESULT_ERROR) { - eq->status = QUERY_STATUS_ERROR; - kore_pgsql_logerror(&sql); goto out; } - - // Query for entries, check for error. - if (eq->id != NULL) { - // Query an entry. - err = kore_pgsql_query_params( - &sql, - q_select_entry, - 0, // return string data - 1, // param count - KORE_PGSQL_PARAM_TEXT(eq->id) - ); - } else { - // Query for index. - err = kore_pgsql_query( - &sql, - q_select_index - ); + else if (eq.status == QUERY_STATUS_ERROR) { + http_err_resp(req, HTTP_STATUS_INTERNAL_ERROR); + goto out; } + // Render MD. + err = render_md(eq.entries[0]->body, rendered_body); if (err == KORE_RESULT_ERROR) { - eq->status = QUERY_STATUS_ERROR; - kore_pgsql_logerror(&sql); + kore_log(LOG_ERR, "Error rendering markdown for entry %s.", eq.id); goto out; } - // TODO: Add test for this; When database is empty, don't return 404 for base request. - if (eq->id != NULL && kore_pgsql_ntuples(&sql) == 0) { - eq->status = QUERY_STATUS_NOT_FOUND; - goto out; - } + // Append rendered MD entry. + kore_buf_appendf( + content, + (const char *) asset_entry_html, + kore_buf_stringify(rendered_body, NULL) + ); - if (eq->id) { - (void) sql_render_entry(&sql, eq); - } else { - (void) sql_render_index(&sql, eq); - } + http_ok_resp(req, HTTP_STATUS_OK, content); out: ; - kore_pgsql_cleanup(&sql); + entry_query_cleanup(&eq); + + kore_free(rendered_body); + kore_free(content); - return err; + return KORE_RESULT_OK; } -int sql_render_entry(struct kore_pgsql *sql, struct entry_query *eq) { - int err = KORE_RESULT_OK; +int edit_entry(struct http_request *req) { + int err = 0; - int row = 0, rows = 0; + struct entry_query eq; + struct kore_buf *content = NULL; + struct kore_buf *rendered_body = NULL; - struct kore_buf *html_buf = NULL; + char *id = NULL; - const char *id = NULL; - const char *title = NULL; - const char *created_at = NULL; - const char *body = NULL; + content = kore_buf_alloc(0); + rendered_body = kore_buf_alloc(0); - // Allocate a buffer to render the markdown as HTML into. - html_buf = kore_buf_alloc(0); + id = kore_strdup(req->path + strlen("/entries/")); + id[strlen(id) - strlen("/edit")] = '\0'; - // Iterate over entries and render them. - rows = kore_pgsql_ntuples(sql); - for (row = 0; row < rows; row++) { - // Reset buffer. - kore_buf_cleanup(html_buf); - - // Fetch data. - id = kore_pgsql_getvalue(sql, row, 0); - title = kore_pgsql_getvalue(sql, row, 1); - created_at = kore_pgsql_getvalue(sql, row, 2); - body = kore_pgsql_getvalue(sql, row, 3); - kore_log(LOG_DEBUG, "id: %s; title %s; created_at %s", id, title, created_at); - - // Render MD. - err = render_md(body, html_buf); - if (err == KORE_RESULT_ERROR) { - kore_log(LOG_ERR, "Error rendering markdown for entry %s.", id); - continue; - } - - // Append rendered MD entry. - kore_buf_appendf( - eq->result, - (const char *) asset_entry_html, - kore_buf_stringify(html_buf, NULL) - ); + entry_query_init(&eq, (const char*) id); + // Check for valid resource UUID + kore_log(LOG_DEBUG, "Resource id /entries/%s.", eq.id); + err = validate_uuid(eq.id); + if (err == KORE_RESULT_ERROR) { + kore_log(LOG_ERR, "Invalid entry id %s XXX.", eq.id); + http_err_resp(req, HTTP_STATUS_NOT_FOUND); + goto out; } - kore_buf_free(html_buf); - - return KORE_RESULT_OK; -} - - -int sql_render_index(struct kore_pgsql *sql, struct entry_query *eq) { - - int row = 0, rows = 0; - - struct kore_buf *html_buf = NULL; - - const char *id = NULL; - const char *title = NULL; - const char *created_at = NULL; - const char *updated_at = NULL; - - // Allocate a buffer to render the markdown as HTML into. - html_buf = kore_buf_alloc(0); + (void) sql_select(&eq); + if (eq.status == QUERY_STATUS_NOT_FOUND) { + http_err_resp(req, HTTP_STATUS_NOT_FOUND); + goto out; + } + else if (eq.status == QUERY_STATUS_ERROR) { + http_err_resp(req, HTTP_STATUS_INTERNAL_ERROR); + goto out; + } - // Write table header. - kore_buf_append( - eq->result, - (const char *) "<h1>clog.bunkergate.org</h1>\r\n<table><tr><th>Title</th><th>Created</th><th>Updated</th></tr>\r\n", - 94 + kore_buf_appendf( + content, (const char *) asset_entry_edit_html, + eq.entries[0]->id, eq.entries[0]->title, eq.entries[0]->body ); - // Iterate over entries and render them. - rows = kore_pgsql_ntuples(sql); - for (row = 0; row < rows; row++) { - // Reset buffer. - kore_buf_cleanup(html_buf); + // Render MD. + err = render_md(eq.entries[0]->body, rendered_body); + if (err == KORE_RESULT_ERROR) { + kore_log(LOG_ERR, "Error rendering markdown for entry %s.", eq.id); + goto out; + } - // Fetch data. - id = kore_pgsql_getvalue(sql, row, 0); - title = kore_pgsql_getvalue(sql, row, 1); - created_at = kore_pgsql_getvalue(sql, row, 2); - updated_at = kore_pgsql_getvalue(sql, row, 3); - kore_log(LOG_DEBUG, "id: '%s'; title '%s'", id, title); + // Append rendered MD entry. + kore_buf_appendf( + content, + (const char *) asset_entry_html, + kore_buf_stringify(rendered_body, NULL) + ); - // Append rendered MD entry. - kore_buf_appendf( - eq->result, - (const char *) "<tr><td><a href=\"/entries/%s\">%s</a></td><td>%s</td><td>%s</td></tr>\r\n", - id, title, created_at, updated_at - ); + http_ok_resp(req, HTTP_STATUS_OK, content); - } +out: ; - // Write table footer. - kore_buf_append( - eq->result, - (const char *) "</table>\r\n", - 10 - ); + entry_query_cleanup(&eq); - kore_buf_free(html_buf); + kore_free(id); + kore_free(rendered_body); + kore_free(content); return KORE_RESULT_OK; } -int sql_insert_entry(const char *id, const char *title, const char *body) { +int sql_select(struct entry_query *eq) { int err = KORE_RESULT_OK; + int row = 0; + int rows = 0; + struct entry *entry = NULL; struct kore_pgsql sql; + kore_pgsql_init(&sql); + eq->status = QUERY_STATUS_OK; + + // Set up synchronous database handle. err = kore_pgsql_setup(&sql, database, KORE_PGSQL_SYNC); if (err == KORE_RESULT_ERROR) { + eq->status = QUERY_STATUS_ERROR; kore_pgsql_logerror(&sql); goto out; } - if (id == NULL) { - err = kore_pgsql_query_params( - &sql, q_insert_entry, 0, 2, KORE_PGSQL_PARAM_TEXT(title), KORE_PGSQL_PARAM_TEXT(body) + // Query for entries, check for error. + if (eq->id != NULL) { + // Query an entry. + err = kore_pgsql_query_params(&sql, q_select_entry, + 0, // return string data + 1, // param count + KORE_PGSQL_PARAM_TEXT(eq->id) ); } else { - err = kore_pgsql_query_params( - &sql, q_insert_entry_with_id, 0, 3, KORE_PGSQL_PARAM_TEXT(id), KORE_PGSQL_PARAM_TEXT(title), - KORE_PGSQL_PARAM_TEXT(body) - ); + // Query for index. + err = kore_pgsql_query(&sql, q_select_entries); } + if (err == KORE_RESULT_ERROR) { + eq->status = QUERY_STATUS_ERROR; kore_pgsql_logerror(&sql); goto out; } + // TODO: Add test for this; When database is empty, don't return 404 for base request. + if (eq->id != NULL && kore_pgsql_ntuples(&sql) == 0) { + eq->status = QUERY_STATUS_NOT_FOUND; + goto out; + } + + // Iterate over entries and render them. + rows = kore_pgsql_ntuples(&sql); + eq->num_entries = rows; + for (row = 0; row < rows; row++) { + // Fetch & copy data to entry + entry = kore_malloc(sizeof(struct entry)); + entry->id = kore_strdup(kore_pgsql_getvalue(&sql, row, 0)); + entry->title = kore_strdup(kore_pgsql_getvalue(&sql, row, 1)); + entry->created_at = kore_strdup(kore_pgsql_getvalue(&sql, row, 2)); + entry->updated_at = kore_strdup(kore_pgsql_getvalue(&sql, row, 3)); + entry->body = kore_strdup(kore_pgsql_getvalue(&sql, row, 4)); + eq->entries[row] = entry; + kore_log( + LOG_DEBUG, "id: %s; title %s; created_at %s, updated_at %s", + entry->id, entry->title, entry->created_at, entry->updated_at + ); + } + out: ; kore_pgsql_cleanup(&sql); @@ -425,64 +433,64 @@ out: ; return err; } -int sql_update_entry(const char *id, const char *title, const char *body) { - int err = KORE_RESULT_OK; +// int sql_update_entry(const char *id, const char *title, const char *body) { +// int err = KORE_RESULT_OK; - struct kore_pgsql sql; - kore_pgsql_init(&sql); +// struct kore_pgsql sql; +// kore_pgsql_init(&sql); - err = kore_pgsql_setup(&sql, database, KORE_PGSQL_SYNC); - if (err == KORE_RESULT_ERROR) { - kore_pgsql_logerror(&sql); - goto out; - } +// err = kore_pgsql_setup(&sql, database, KORE_PGSQL_SYNC); +// if (err == KORE_RESULT_ERROR) { +// kore_pgsql_logerror(&sql); +// goto out; +// } - err = kore_pgsql_query_params( - &sql, q_update_entry, 0, 3, KORE_PGSQL_PARAM_TEXT(title), KORE_PGSQL_PARAM_TEXT(body), - KORE_PGSQL_PARAM_TEXT(id) - ); - if (err == KORE_RESULT_ERROR) { - kore_pgsql_logerror(&sql); - goto out; - } +// err = kore_pgsql_query_params( +// &sql, q_update_entry, 0, 3, KORE_PGSQL_PARAM_TEXT(title), KORE_PGSQL_PARAM_TEXT(body), +// KORE_PGSQL_PARAM_TEXT(id) +// ); +// if (err == KORE_RESULT_ERROR) { +// kore_pgsql_logerror(&sql); +// goto out; +// } -out: ; +// out: ; - kore_pgsql_cleanup(&sql); +// kore_pgsql_cleanup(&sql); - return err; -} +// return err; +// } -int sql_delete_entry(const char *id) { - int err = KORE_RESULT_OK; +// int sql_delete_entry(const char *id) { +// int err = KORE_RESULT_OK; - struct kore_pgsql sql; - kore_pgsql_init(&sql); +// struct kore_pgsql sql; +// kore_pgsql_init(&sql); - err = kore_pgsql_setup(&sql, database, KORE_PGSQL_SYNC); - if (err == KORE_RESULT_ERROR) { - kore_pgsql_logerror(&sql); - goto out; - } +// err = kore_pgsql_setup(&sql, database, KORE_PGSQL_SYNC); +// if (err == KORE_RESULT_ERROR) { +// kore_pgsql_logerror(&sql); +// goto out; +// } - err = kore_pgsql_query_params( - &sql, - q_delete_entry, - 0, - 1, - KORE_PGSQL_PARAM_TEXT(id) - ); - if (err == KORE_RESULT_ERROR) { - kore_pgsql_logerror(&sql); - goto out; - } +// err = kore_pgsql_query_params( +// &sql, +// q_delete_entry, +// 0, +// 1, +// KORE_PGSQL_PARAM_TEXT(id) +// ); +// if (err == KORE_RESULT_ERROR) { +// kore_pgsql_logerror(&sql); +// goto out; +// } -out: ; +// out: ; - kore_pgsql_cleanup(&sql); +// kore_pgsql_cleanup(&sql); - return err; -} +// return err; +// } static int render_md(const char *in, struct kore_buf *out) { // Not a kore err. diff --git a/src/queries.h b/src/queries.h index c0bd1dc..3956129 100644 --- a/src/queries.h +++ b/src/queries.h @@ -1,40 +1,35 @@ const char *q_select_entry = -"SELECT id, title, created_at::DATE, body " +"SELECT id, title, created_at::DATE, updated_at::DATE, body " "FROM entries " "WHERE id = $1;"; const char *q_select_entries = -"SELECT id, title, created_at::DATE, body " +"SELECT id, title, created_at::DATE, updated_at::DATE, body " "FROM entries " "ORDER BY updated_at DESC;"; -const char *q_select_index = -"SELECT id, title, created_at::DATE, updated_at::DATE " -"FROM entries " -"ORDER BY updated_at DESC;"; +// const char *q_insert_entry = +// "INSERT INTO entries " +// "(title, body) " +// "VALUES " +// "($1, $2) " +// "RETURNING id;"; -const char *q_insert_entry = -"INSERT INTO entries " -"(title, body) " -"VALUES " -"($1, $2) " -"RETURNING id;"; +// const char *q_insert_entry_with_id = +// "INSERT INTO entries " +// "(id, title, body) " +// "VALUES " +// "($1, $2, $3) " +// "RETURNING id;"; -const char *q_insert_entry_with_id = -"INSERT INTO entries " -"(id, title, body) " -"VALUES " -"($1, $2, $3) " -"RETURNING id;"; +// const char *q_update_entry = +// "UPDATE entries " +// "SET title = $1, body = $2, updated_at = NOW() " +// "WHERE id = $3 " +// "RETURNING id;"; -const char *q_update_entry = -"UPDATE entries " -"SET title = $1, body = $2, updated_at = NOW() " -"WHERE id = $3 " -"RETURNING id;"; - -const char *q_delete_entry = -"DELETE " -"FROM entries " -"WHERE id = $1 " -"RETURNING id;"; +// const char *q_delete_entry = +// "DELETE " +// "FROM entries " +// "WHERE id = $1 " +// "RETURNING id;"; |