#include "string_buffer.h" #include "utils.h" #include "comment.h" #include "cgic.h" #include "driver.h" #include "drivers/unix_fs/unix_fs_driver.h" #include "config.h" #include #include #include int page_by_id(int id) { return id / COMMENTS_PER_PAGE + 1; } void render_comment(const Comment *comment) { char *retval; int rid; fprintf(cgiOut, "
\n", comment->id); /* begin header */ fprintf(cgiOut, "
\n"); fprintf(cgiOut, "Posted by: %s\n", comment->header->user_displayname); rid = comment->header->reply_id; if (rid > 0) { fprintf(cgiOut, " in reply to ", page_by_id(rid), rid); } fprintf(cgiOut, "
\n"); /* end header */ fprintf(cgiOut, "%s", comment->text); fprintf(cgiOut, "
\n"); } void allocate_header(CommentHeader *header) { header->user_sid = malloc(MAX_NAME_SIZE); header->user_displayname = malloc(MAX_NAME_SIZE); } void free_header(CommentHeader *header) { free(header->user_sid); free(header->user_displayname); } void allocate_comment(Comment *comment) { comment->header = malloc(sizeof(CommentHeader)); allocate_header(comment->header); } void free_comment(Comment *comment) { free_header(comment->header); free(comment->header); free(comment->text); } int fetch_comment(int id, Driver *driver, void *driver_data, Comment *comment) { int retval; comment->id = id; allocate_comment(comment); retval = driver->get_header(driver_data, comment->header, id); if (retval < 0) { goto defer; } comment->text = malloc(comment->header->text_length + 1); retval = driver->get_text(driver_data, comment->text, id); defer: if (retval < 0) { free_comment(comment); } return retval; } void print_submit_form() { fputs("
\n" "\n" "
\n" "
\n" "
\n" "\n" "
\n", cgiOut); } /* each page stores comments with ids in [P * (page - 1) + 1, P * page + 1) * if page is not specified, then we'll just print last P comments (for now) * TODO: print errors in div */ void print_page() { int page, max_id; int id_begin, id_end, i; Comment comment; UnixFsDriverData driver_data = DRIVER_DATA; Driver driver = DRIVER; cgiFormInteger("page", &page, 0); if ((max_id = unix_fs_driver_get_max_id(&driver_data)) < 0) { fprintf(cgiOut, "Error fetching comments\n"); return; } if (page <= 0) { id_end = max_id; id_begin = (max_id > COMMENTS_PER_PAGE ? max_id - COMMENTS_PER_PAGE : 1); } else { /* max_id > COMMENTS_PER_PAGE * (page - 1) + 1 * max_id - 1 > COMMENTS_PER_PAGE * (page - 1) * perform this check without overflow */ if ((max_id + COMMENTS_PER_PAGE - 1) / COMMENTS_PER_PAGE <= (page - 1)) { fprintf(cgiOut, "There is no such page\n"); return; } id_begin = COMMENTS_PER_PAGE * (page - 1) + 1; id_end = id_begin + COMMENTS_PER_PAGE; if (id_end > max_id) { id_end = max_id; } } for (i = id_begin; i != id_end; ++i) { if (fetch_comment(i, &driver, &driver_data, &comment) < 0) { fprintf(cgiOut, "Failed to fetch comment %d\n", i); } else { render_comment(&comment); free_comment(&comment); } } } /* TODO: restore fields for user no to lose data */ int handle_submitted_comment() { char displayname[MAX_NAME_SIZE], text[MAX_COMMENT_SIZE], *sanitized_text; int rid, retval; cgiFormResultType err; CommentHeader header; Driver driver = DRIVER; UnixFsDriverData driver_data = DRIVER_DATA; err = cgiFormString("text", text, MAX_COMMENT_SIZE); if (err == cgiFormTruncated) { fprintf(cgiOut, "Comment too long (max %d bytes)\n", MAX_COMMENT_SIZE); goto defer; } if (err == cgiFormNotFound) { fprintf(cgiOut, "Comment text not provided\n"); goto defer; } err = cgiFormString("displayname", displayname, MAX_NAME_SIZE); if (err == cgiFormTruncated) { fprintf(cgiOut, "Name too long (max %d bytes)\n", MAX_NAME_SIZE); goto defer; } if (err == cgiFormNotFound) { fprintf(cgiOut, "Name not provided\n"); goto defer; } if (contain_special(displayname)) { err = cgiFormTruncated; fprintf(cgiOut, "Name must not contain HTML special characters\n"); goto defer; } cgiFormInteger("reply-to", &rid, 0); sanitized_text = mk_specialchars(text); time(&header.creation_time); header.reply_id = rid; header.text_length = strlen(sanitized_text); header.user_sid = "web/anonymous"; header.user_displayname = displayname; if (driver.leave_comment(&driver_data, &header, sanitized_text) < 0) { fprintf(cgiOut, "Failed to leave your comment\n"); } else { fprintf(cgiOut, "Comment successfully left\n"); } free(sanitized_text); defer: return (err == cgiFormSuccess ? 0 : -1); } int cgiMain() { cgiHeaderContentType("text/html"); fprintf(cgiOut, "\n"); fprintf(cgiOut, "\n"); fprintf(cgiOut, " Simple discuss powered by qments \n"); fprintf(cgiOut, "\n"); fprintf(cgiOut, "\n"); if (cgiFormSubmitClicked("submit") == cgiFormSuccess) { handle_submitted_comment(); } print_submit_form(); fprintf(cgiOut, "
\n"); print_page(); fprintf(cgiOut, "
\n"); fprintf(cgiOut, "\n"); fprintf(cgiOut, "\n"); return 0; }