#include "printf.h" #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 #define COMMENTS_PER_PAGE 20 #define MAX_NAME 1024 #define QMENTS_PATH "qments-storage" #define DRIVER_DATA { QMENTS_PATH } #define DRIVER unix_fs_driver void fct_callback(char character, void *arg) { sb_add_char((StringBuffer*) arg, character); } char * render_comment(const Comment *comment) { StringBuffer _buffer, *buffer; char *retval; buffer = &_buffer; sb_init_empty(buffer); fctprintf(fct_callback, buffer, "
\n", comment->id); /* begin header */ fctprintf(fct_callback, buffer, "
\n"); fctprintf(fct_callback, buffer, "Posted by: %s\n", comment->header->user_displayname); fctprintf(fct_callback, buffer, "
\n"); /* end header */ fctprintf(fct_callback, buffer, "%s", comment->text); fctprintf(fct_callback, buffer, "
\n"); SB_MOVE(buffer, retval); return retval; } void allocate_header(CommentHeader *header) { header->user_sid = malloc(MAX_NAME); header->user_displayname = malloc(MAX_NAME); } 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; } /* each page stores comments with ids in [P * (page - 1), P * page) * 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 * perform this check without overflow */ if (max_id / page < COMMENTS_PER_PAGE) { fprintf(cgiOut, "There is no such page\n"); return; } id_begin = COMMENTS_PER_PAGE * (page - 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 { char *rendered_comment = render_comment(&comment); fputs(rendered_comment, cgiOut); free(rendered_comment); free_comment(&comment); } } } int cgiMain() { cgiHeaderContentType("text/html"); fprintf(cgiOut, "\n"); fprintf(cgiOut, "\n"); fprintf(cgiOut, " Simple discuss powered by qments\n"); fprintf(cgiOut, "</head>\n"); fprintf(cgiOut, "<body>\n"); /* print_submit_form(); */ fprintf(cgiOut, "<div class=\"comment-section\">\n"); print_page(); fprintf(cgiOut, "</div>\n"); fprintf(cgiOut, "</body>\n"); fprintf(cgiOut, "</html>\n"); return 0; }