diff --git a/src/abstract_data_layer.c b/src/abstract_data_layer.c index f30d2c6..04182b0 100644 --- a/src/abstract_data_layer.c +++ b/src/abstract_data_layer.c @@ -82,9 +82,12 @@ struct layer_context { uint32_t enough_space[14]; }; // 14*4 byte context is probably enough for any engine needs +enum sorting_seq {DESC = 0, ASC}; + struct list_filter { unix_epoch from; // unixtime unix_epoch to; + enum sorting_seq sort; char **tags; }; diff --git a/src/abstract_data_layer_fileno.c b/src/abstract_data_layer_fileno.c index 92de847..3384966 100644 --- a/src/abstract_data_layer_fileno.c +++ b/src/abstract_data_layer_fileno.c @@ -153,6 +153,7 @@ void deinitialize_engine_fileno(void *context) { struct fileno_scandir_pass { unix_epoch from; unix_epoch to; + enum sorting_seq sort; int dirfd; }; @@ -163,8 +164,14 @@ static int comparator(const struct dirent **d1, const struct dirent **d2, void * fstatat(fpass->dirfd, (*d2)->d_name, s + 1, 0); if (s[0].st_mtim.tv_sec == s[1].st_mtim.tv_sec and s[0].st_mtim.tv_nsec == s[1].st_mtim.tv_nsec) return 0; - if (abiggerb_timespec(s[0].st_mtim, s[1].st_mtim)) return 1; - return -1; + + if (fpass->sort == ASC) { + if (abiggerb_timespec(s[0].st_mtim, s[1].st_mtim)) return 1; + return -1; + } + + if (abiggerb_timespec(s[0].st_mtim, s[1].st_mtim)) return -1; + return 1; } static void scanfree(struct dirent **e, int amount) { @@ -174,7 +181,7 @@ static void scanfree(struct dirent **e, int amount) { free(e); } -// This filter is NOT REENTRANT! Use scandir() with mutextes to make it thread-safe +// This filter is REENTRANT 😍😍😍! Because we're using specific custom-mate scandir()! static int filter_fun(const struct dirent *d, void *pass) { static const int keep = 1; static const int away = 0; @@ -188,7 +195,7 @@ static int filter_fun(const struct dirent *d, void *pass) { return keep; } -// SELECT record_id from records WHERE modified_time > from and modified_time < to LIMIT amount OFFSET offset sort by modified_time; +// SELECT record_id from records WHERE modified_time > from and modified_time < to LIMIT amount OFFSET sort by modified_time; bool list_records_fileno(unsigned *amount,// Pointer that could be used for limiting amount of results in list. After executing places amount of results. unsigned long *result_list, // Array that will be filled with results unsigned offset, // Skip some amount rows/records/results @@ -214,7 +221,7 @@ bool list_records_fileno(unsigned *amount,// Pointer that could be used for limi } while(0); struct dirent **dirent; - struct fileno_scandir_pass fpass = {.from = filter.from, .to = filter.to, .dirfd = scanfd}; + struct fileno_scandir_pass fpass = {.from = filter.from, .to = filter.to, .sort = filter.sort, .dirfd = scanfd}; int ret = scandir_r(scanaddr, &dirent, filter_fun, comparator, &fpass); unsigned limit = *amount; // 8 lines below could be refactored... Or now. IDK. @@ -272,7 +279,13 @@ static size_t taglen(const char *str) { } static char *tag_processing(char *comma_separated_tags, struct blog_record *r) { - size_t tags_amount = char_occurences(comma_separated_tags, ',') + 1; + size_t tags_amount; + if (comma_separated_tags[0] == '\n') { + tags_amount = 0; + } else { + tags_amount = char_occurences(comma_separated_tags, ',') + 1; + } + size_t stack_ptrs_space = sizeof(void *) * (tags_amount + 1); char *put = (char *) r->stack + stack_ptrs_space; r->tags = r->stack; @@ -380,7 +393,7 @@ bool parse_metadata(int fd, struct metadata_strings *meta_strings, const char ** meta_strings->title == NULL or meta_strings->data == NULL or meta_strings->datasource == NULL or - meta_strings->tags == NULL or +// meta_strings->tags == NULL or meta_strings->creation_unixepoch == NULL or meta_strings->modificated_unixepoch == NULL ) OUCH_ERROR(data_layer_error_metadata_corrupted, return false); @@ -572,6 +585,10 @@ static void add_to_tag(const char *tag, struct fileno_context *f, struct blog_re void tag_writer(int fd, char **tags, struct fileno_context *f, struct blog_record *r) { write(fd, "tags: ", strizeof("tags: ")); + if (tags == NULL) { + write(fd, "\n", 1); + return; + } bool commaspace = false; while(*tags) { if (commaspace == true) {write(fd, ", ", 2);} else {commaspace = true;} @@ -589,7 +606,7 @@ static bool flush_files(int meta, struct fileno_context *f, struct blog_record * normalize_filename(name); size_t len = strlen(name); - if (r->stack_space < len + NAME_MAX) OUCH_ERROR(data_layer_error_not_enough_stack_space, return false); +// if (r->stack_space < len + NAME_MAX) OUCH_ERROR(data_layer_error_not_enough_stack_space, return false); int fd, sfd; @@ -648,7 +665,7 @@ static bool flush_files(int meta, struct fileno_context *f, struct blog_record * return true; } -static bool last_prepare(int fd, char str[CBL_UINT32_STR_MAX], unsigned long *val, const char **error) { +static bool last_prepare(int fd, char str[CBL_UINT32_STR_MAX + 1], unsigned long *val, const char **error) { ssize_t got; if (fd < 0 or (got = read(fd, str, CBL_UINT32_STR_MAX)) < 0) OUCH_ERROR(strerror(errno), return false); @@ -656,6 +673,7 @@ static bool last_prepare(int fd, char str[CBL_UINT32_STR_MAX], unsigned long *va if (emb_isdigit(str[0]) == false) OUCH_ERROR(data_layer_error_metadata_corrupted, return false); str[got] = '\0'; *val = strtoul(str, NULL, 10); + sprintf(str, "%lu", *val); return true; } @@ -671,11 +689,11 @@ bool insert_record_fileno(struct blog_record *r, void *context, const char **err if (r->titlelen > NAME_MAX or r->titlelen == 0) OUCH_ERROR(data_layer_error_invalid_argument, return false); if (display_enum_to_str(r->display) == NULL) OUCH_ERROR(data_layer_error_invalid_argument, return false); - if (utf8_check(r->title) != NULL) OUCH_ERROR(data_layer_error_invalid_argument_utf8, return false); + if (utf8_check(r->title, r->titlelen) != NULL) OUCH_ERROR(data_layer_error_invalid_argument_utf8, return false); if (r->datalen == 0 and r->datasourcelen == 0) OUCH_ERROR(data_layer_error_invalid_argument, return false); int last_record_storage_fd = openat(f->dfd, fileno_last_record_file, O_RDWR | O_CREAT, DEFAULT_FILE_MODE); - char last_record_str[CBL_UINT32_STR_MAX]; + char last_record_str[CBL_UINT32_STR_MAX + 1]; if (last_prepare(last_record_storage_fd, last_record_str, &(r->chosen_record), error) == false) { close(last_record_storage_fd); return false; @@ -701,10 +719,6 @@ bool insert_record_fileno(struct blog_record *r, void *context, const char **err return true; } -void special_markdown_case(int fd, struct blog_record *old, struct blog_record *r, struct fileno_context *f) { - -} - #define METADATA_FMT_WITH_TAGS_LIMITED METADATA_VER "\ndisplay: %s\nunix access: %03"PRIu32"\nuser id: %"PRIu32"\ngroup id: %"PRIu32"\ntitle: %.*s" \ "\ndata: %.*s\ndatasource: %.*s\ncreation_unixepoch: %lu\nmodificated_unixepoch: %lu\ntags: %.*s\n" diff --git a/src/app.c b/src/app.c index 0a1b8a4..4618648 100644 --- a/src/app.c +++ b/src/app.c @@ -74,6 +74,8 @@ void (*app_read) (void *, unsigned long *, void *); const char default_header_content_type[] = "Content-Type: text/html;charset=utf-8"; const char default_header_server_type[] = "Server: cblog app operator"; const char default_header_location_slash[] = "Location: /"; +const char default_header_location_user[] = "Location: /user"; +const char default_header_location_page[] = "Location: /page"; const char default_header_nocache_1[] = "Cache-Control: no-cache, no-store, must-revalidate"; const char default_header_nocache_2[] = "Pragma: no-cache"; const char default_header_nocache_3[] = "Expires: 0"; @@ -456,7 +458,7 @@ static void title(reqargs a) { .datasource = config->title_page_content, .datasourcelen = config->title_page_content_len, }; - struct list_filter filter = {.from.t = 0l, .to.t = 2147483647l}; // (unix_epoch) 0l, (unix_epoch) 2147483647l + struct list_filter filter = {.from.t = 0l, .to.t = 2147483647l, .sort = DESC}; // (unix_epoch) 0l, (unix_epoch) 2147483647l const unsigned offset = 0; selector(a, HOW_MANY_RECORDS_U_WANT_TO_SEE_ON_TITLEPAGE, offset, filter, &b, true); } @@ -512,6 +514,7 @@ static inline void record_show_tag_processing(reqargs a, int32_t tag, struct blo case TAGS_PAGE_PART: { char **tags = b.tags; + if (tags == NULL) break; while(*tags) { size_t taglen = strlen(*tags); APP_WRITE(LI_AND_A_TAGS_PREF, strizeof(LI_AND_A_TAGS_PREF)); @@ -568,7 +571,7 @@ static void show_record(reqargs a, uint32_t record) { } static bool minimum_passwd_requirements(char *password, size_t passwd_minlen, bool passwd_specialchar) { - if (utf8_check(password) != NULL) return false; + if (utf8_check(password, strlen(password)) != NULL) return false; size_t passwd_len = 0; bool passwd_specialchar_presence = false; @@ -713,7 +716,7 @@ void user_login(reqargs a) { sprintf(cookie, "Set-Cookie: id=%s%s", key, SMCOL_EXPIRES); headers_table_append(headers_table, cookie); headers_table_append(headers_table, default_header_location_slash); - SET_HTTP_STATUS_AND_HDR(301, headers_table); + SET_HTTP_STATUS_AND_HDR(302, headers_table); APP_WRITECS("Redirecting: /"); return; } @@ -736,8 +739,10 @@ void user_login(reqargs a) { if (user_logged_in) { headers_table_append(headers_table, default_header_location_slash); - SET_HTTP_STATUS_AND_HDR(301, headers_table); + SET_HTTP_STATUS_AND_HDR(302, headers_table); APP_WRITECS("Redirecting: /"); + + return; } size_t freespace = CONTEXTAPPBUFFERSIZE - (con->freebuffer - (char *) con); @@ -753,14 +758,14 @@ void user_login(reqargs a) { freespace -= size; if (freespace < sizeof(struct usr)) return internal_server_error(a, data_layer_error_not_enough_stack_space); size_t namelen; - char *name = http_query_finder("name", con->freebuffer, size, &namelen, false); + char *name = http_query_finder("name", post_data, size, &namelen, false); if (name == NULL or namelen >= sizeof(u->display_name)) { out[TITLE_PAGE_PART] = data_layer_error_invalid_argument; outsizes[TITLE_PAGE_PART] = strizeof(data_layer_error_invalid_argument); break; } size_t passwordlen; - char *password = http_query_finder("password", con->freebuffer, size, &passwordlen, false); + char *password = http_query_finder("password", post_data, size, &passwordlen, false); if (password == NULL) { out[TITLE_PAGE_PART] = data_layer_error_invalid_argument; outsizes[TITLE_PAGE_PART] = strizeof(data_layer_error_invalid_argument); @@ -813,11 +818,11 @@ void user_logout(reqargs a) { headers_table_append(logout_headers_table, cookie); } - SET_HTTP_STATUS_AND_HDR(301, logout_headers_table); + SET_HTTP_STATUS_AND_HDR(302, logout_headers_table); APP_WRITECS("Redirecting: /"); } -static inline void editor_processing(reqargs a, int32_t tag, struct usr *u) { +static inline void editor_processing(reqargs a, int32_t tag, struct usr *u, char *error, size_t errorlen) { struct appcontext *con = CONTEXT; // essb *e = &con->templates; // struct layer_context *l = &con->layer; @@ -833,14 +838,19 @@ static inline void editor_processing(reqargs a, int32_t tag, struct usr *u) { APP_WRITECS("Add/edit page/record"); break; case CONTENT_PAGE_PART: + if (error != NULL and errorlen > 0) { + APP_WRITECS("Error: "); + APP_WRITE(error, errorlen); + APP_WRITECS("

"); + } APP_WRITE(default_add_edit_form_html, strizeof(default_add_edit_form_html)); break; -// case USER_PAGE_PART: -// APP_WRITE(LI_AND_A_USER, strizeof(LI_AND_A_USER)); -// APP_WRITE(u->display_name, strlen(u->display_name)); -// APP_WRITE(LI_A_SUFF, strizeof(LI_A_SUFF)); -// APP_WRITE(LI_AND_A_LOGOUT_FULL_STR, strizeof(LI_AND_A_LOGOUT_FULL_STR)); -// break; + case USER_PAGE_PART: + APP_WRITE(LI_AND_A_USER, strizeof(LI_AND_A_USER)); + APP_WRITE(u->display_name, strlen(u->display_name)); + APP_WRITE(LI_A_SUFF, strizeof(LI_A_SUFF)); + APP_WRITE(LI_AND_A_LOGOUT_FULL_STR, strizeof(LI_AND_A_LOGOUT_FULL_STR)); + break; default: return; } @@ -849,18 +859,105 @@ static inline void editor_processing(reqargs a, int32_t tag, struct usr *u) { void page(reqargs a) { struct appcontext *con = CONTEXT; essb *e = &con->templates; -// struct layer_context *l = &con->layer; + struct layer_context *l = &con->layer; // struct appconfig *config = con->config; const char *headers_table[] = {default_header_nocache_1, default_header_nocache_2, default_header_nocache_3, - default_header_content_type, default_header_server_type, NULL}; - SET_HTTP_STATUS_AND_HDR(200, headers_table); + default_header_content_type, default_header_server_type, NULL, NULL, NULL}; + char cookie[sizeof(SETCOOKIEID SMCOL_EXPIRES) + KEY_VAL_MAXKEYLEN]; - for (unsigned i = 0; i < e->records_amount; i++) { - if (e->record_size[i] < 0) editor_processing(a, e->record_size[i], NULL); - else APP_WRITE(&e->records[e->record_seek[i]], e->record_size[i]); + bool user_logged_in = false; + struct usr logged_in_user; + do{ + char key[KEY_VAL_MAXKEYLEN]; + if (find_cookie_existence(a, "id", key) == 0) break; + + ssize_t size = - ((ssize_t) sizeof(logged_in_user)); + bool ret = key_val(key, &logged_in_user, &size, l, NULL); + if (ret == false or is_user_legit(l, &logged_in_user) == false) { + sprintf(cookie, "Set-Cookie: id=%s%s", key, SMCOL_EXPIRES); + headers_table_append(headers_table, cookie); + headers_table_append(headers_table, default_header_location_user); + SET_HTTP_STATUS_AND_HDR(302, headers_table); + APP_WRITECS("Redirecting: /user"); + return; + } + + user_logged_in = true; + } while(0); + + if (user_logged_in == false) { + headers_table_append(headers_table, default_header_location_user); + SET_HTTP_STATUS_AND_HDR(302, headers_table); + APP_WRITECS("Redirecting: /user"); + return; + } + + size_t freespace = CONTEXTAPPBUFFERSIZE - (con->freebuffer - (char *) con); + char *input_data = con->freebuffer; + + if (METHOD == GET) { + SET_HTTP_STATUS_AND_HDR(200, headers_table); + size_t size = 0; + char *find = http_query_finder("error", QUERY, QUERY_LEN, &size, false); + memcpy(input_data, find, size); + input_data[size] = '\0'; + size = urldecode2(input_data, input_data) - input_data; + + for (unsigned i = 0; i < e->records_amount; i++) { + if (e->record_size[i] < 0) editor_processing(a, e->record_size[i], &logged_in_user, input_data, size); + else APP_WRITE(&e->records[e->record_seek[i]], e->record_size[i]); + } + + return; + } + + size_t size = freespace; + APP_READ(input_data, &size); + + if (size == 0) { + headers_table_append(headers_table, default_header_location_page); + SET_HTTP_STATUS_AND_HDR(302, headers_table); + APP_WRITECS("Redirecting: /page"); + return; } + + input_data[size] = '\0'; + size = urldecode2(input_data, input_data) - input_data; + input_data[size] = '\0'; + + size_t titlelen; + char *title = http_query_finder("title", input_data, size, &titlelen, false); + + size_t datalen; + char *data = http_query_finder("data", input_data, size, &datalen, false); + + if (title == NULL or data == NULL) { + headers_table_append(headers_table, default_header_location_page); + SET_HTTP_STATUS_AND_HDR(302, headers_table); + APP_WRITECS("Redirecting: /page"); + return; + } + + struct blog_record b = {.title = title, .titlelen = titlelen, .data = data, .datalen = datalen, .display = DISPLAY_DATASOURCE}; + const char *error; + bool result = insert_record(&b, l, &error); + char strhdr[200]; + if (result == false) { + printf("error: %s\n", error); + snprintf(strhdr, sizeof(strhdr), "Location: /page?error=%s", error); + + headers_table_append(headers_table, strhdr); + SET_HTTP_STATUS_AND_HDR(302, headers_table); + APP_WRITECS("Redirecting: /page"); + return; + } + + snprintf(strhdr, sizeof(strhdr), "Location: /newpage-%lu", b.chosen_record); + headers_table_append(headers_table, strhdr); + SET_HTTP_STATUS_AND_HDR(302, headers_table); + APP_WRITECS("Redirecting: /newpage..."); } //#define IFREQ(page, fun) do{if(REQUEST_LEN==strizeof(page) and memcmp(REQUEST, page, strizeof(page)) == STREQ) return fun(a);}while(0) diff --git a/src/default_rodata.h b/src/default_rodata.h index 117ff93..21cecdc 100644 --- a/src/default_rodata.h +++ b/src/default_rodata.h @@ -26,7 +26,7 @@ const bool default_password_specialchars_needed = false; const char default_form_html[] = "


"; size_t default_form_html_len = strizeof(default_form_html); -const char default_add_edit_form_html[] = "


"; +const char default_add_edit_form_html[] = "


"; const char default_welcome_after_login_title[] = "Welcome!"; const char default_welcome_after_login[] = "You can visit home page or user panel"; diff --git a/src/util.c b/src/util.c index cd67465..82a5455 100644 --- a/src/util.c +++ b/src/util.c @@ -178,9 +178,11 @@ char strpartcmp(char *str, char *part) { } } -const unsigned char *utf8_check(const void *a){ +const unsigned char *utf8_check(const void *a, size_t len){ const unsigned char *s = a; - while(*s) { +// while(*s) { + for (size_t i = 0; i < len; len++) { + if (*s == '\0') break; if (*s < 0x80) /* 0xxxxxxx */ s++; @@ -375,6 +377,7 @@ void unsafe_rand(void *ptr, size_t width) { char *urldecode2(char *dst, const char *src) { + if (src == NULL or dst == NULL) return NULL; char a, b; while(*src) { if ((*src == '%') &&