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[] = "