2023-07-03 14:58:09 +03:00
|
|
|
#include "printf.h"
|
|
|
|
#include "string_buffer.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "comment.h"
|
|
|
|
#include "cgic.h"
|
|
|
|
#include "driver.h"
|
2023-07-03 16:39:36 +03:00
|
|
|
#include "drivers/unix_fs/unix_fs_driver.h"
|
2023-07-03 14:58:09 +03:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#define COMMENTS_PER_PAGE 20
|
|
|
|
#define MAX_NAME 1024
|
|
|
|
|
2023-07-03 16:39:36 +03:00
|
|
|
#define QMENTS_PATH "qments-storage"
|
|
|
|
#define DRIVER_DATA { QMENTS_PATH }
|
|
|
|
#define DRIVER unix_fs_driver
|
|
|
|
|
2023-07-03 14:58:09 +03:00
|
|
|
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;
|
2023-07-03 16:39:36 +03:00
|
|
|
sb_init_empty(buffer);
|
|
|
|
|
|
|
|
fctprintf(fct_callback, buffer, "<div class=\"comment\" id=comment_%d>\n", comment->id);
|
2023-07-03 14:58:09 +03:00
|
|
|
|
|
|
|
/* begin header */
|
|
|
|
fctprintf(fct_callback, buffer, "<div class=\"comment-header\">\n");
|
2023-07-03 16:39:36 +03:00
|
|
|
fctprintf(fct_callback, buffer, "Posted by: %s\n", comment->header->user_displayname);
|
2023-07-03 14:58:09 +03:00
|
|
|
fctprintf(fct_callback, buffer, "</div>\n");
|
|
|
|
/* end header */
|
|
|
|
|
|
|
|
fctprintf(fct_callback, buffer, "%s", comment->text);
|
|
|
|
|
|
|
|
fctprintf(fct_callback, buffer, "</div>\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);
|
|
|
|
}
|
|
|
|
|
2023-07-03 16:39:36 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2023-07-03 14:58:09 +03:00
|
|
|
int
|
|
|
|
fetch_comment(int id, Driver *driver, void *driver_data, Comment *comment)
|
|
|
|
{
|
|
|
|
int retval;
|
|
|
|
comment->id = id;
|
|
|
|
|
2023-07-03 16:39:36 +03:00
|
|
|
allocate_comment(comment);
|
2023-07-03 14:58:09 +03:00
|
|
|
|
2023-07-03 16:39:36 +03:00
|
|
|
retval = driver->get_header(driver_data, comment->header, id);
|
2023-07-03 14:58:09 +03:00
|
|
|
if (retval < 0) {
|
|
|
|
goto defer;
|
|
|
|
}
|
|
|
|
comment->text = malloc(comment->header->text_length + 1);
|
|
|
|
|
2023-07-03 16:39:36 +03:00
|
|
|
retval = driver->get_text(driver_data, comment->text, id);
|
2023-07-03 14:58:09 +03:00
|
|
|
defer:
|
|
|
|
if (retval < 0) {
|
2023-07-03 16:39:36 +03:00
|
|
|
free_comment(comment);
|
2023-07-03 14:58:09 +03:00
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2023-07-03 16:39:36 +03:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-03 14:58:09 +03:00
|
|
|
int
|
|
|
|
cgiMain()
|
|
|
|
{
|
|
|
|
cgiHeaderContentType("text/html");
|
|
|
|
|
|
|
|
fprintf(cgiOut, "<html>\n");
|
|
|
|
|
|
|
|
fprintf(cgiOut, "<head>\n");
|
|
|
|
fprintf(cgiOut, "<title> Simple discuss powered by qments\n");
|
|
|
|
fprintf(cgiOut, "</head>\n");
|
|
|
|
|
|
|
|
fprintf(cgiOut, "<body>\n");
|
2023-07-03 16:39:36 +03:00
|
|
|
|
|
|
|
/* print_submit_form(); */
|
|
|
|
|
|
|
|
fprintf(cgiOut, "<div class=\"comment-section\">\n");
|
|
|
|
print_page();
|
|
|
|
fprintf(cgiOut, "</div>\n");
|
|
|
|
|
2023-07-03 14:58:09 +03:00
|
|
|
fprintf(cgiOut, "</body>\n");
|
|
|
|
|
|
|
|
fprintf(cgiOut, "</html>\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|