diff --git a/Makefile b/Makefile index 0ee4c84..5d455f5 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ run: $(BIN) valgrind: $(BIN) LANDER_API_KEY=test \ LANDER_DATA_DIR=data \ - valgrind --track-origins=yes '$(BUILD_DIR)/$(BIN_FILENAME)' + valgrind --track-origins=yes --leak-check=full '$(BUILD_DIR)/$(BIN_FILENAME)' .PHONY: test test: $(TARGETS_TEST) diff --git a/include/lander.h b/include/lander.h index f670234..7fa3199 100644 --- a/include/lander.h +++ b/include/lander.h @@ -13,6 +13,7 @@ typedef struct lander_gctx { lsm_store *store; struct { ltm_template *paste; + ltm_template *index; } templates; } lander_gctx; @@ -32,6 +33,7 @@ typedef enum lander_entry_type : uint8_t { lander_entry_type_redirect = 0, lander_entry_type_paste = 1, lander_entry_type_file = 2, + lander_entry_type_index = 3, } lander_entry_type; void *lander_gctx_init(); @@ -42,7 +44,7 @@ void lander_ctx_reset(lander_ctx *ctx); void lander_ctx_free(lander_ctx *ctx); -lnm_http_step_err lander_get_index(lnm_http_conn *conn); +lnm_http_step_err lander_get_root(lnm_http_conn *conn); lnm_http_step_err lander_get_entry(lnm_http_conn *conn); @@ -58,6 +60,8 @@ lnm_http_step_err lander_remove_entry(lnm_http_conn *conn); lnm_http_step_err lander_post_file(lnm_http_conn *conn); +lnm_http_step_err lander_post_index(lnm_http_conn *conn); + /** * Store the requested header as an attribute, if it's present. */ diff --git a/lsm/include/lsm/store.h b/lsm/include/lsm/store.h index 1b632b9..c16340b 100644 --- a/lsm/include/lsm/store.h +++ b/lsm/include/lsm/store.h @@ -98,6 +98,11 @@ lsm_error lsm_entry_attr_insert_uint8_t(lsm_entry_handle *handle, uint8_t type, lsm_error lsm_entry_attr_remove(lsm_str **out, lsm_entry_handle *handle, uint8_t type); +/** + * Retrieve a pointer to the entry's key. + */ +void lsm_entry_key(const lsm_str **out, lsm_entry_handle *handle); + /** * A store consisting of LSM entries. * diff --git a/lsm/include/lsm/str.h b/lsm/include/lsm/str.h index b3cf965..147e4ed 100644 --- a/lsm/include/lsm/str.h +++ b/lsm/include/lsm/str.h @@ -178,6 +178,15 @@ lsm_error lsm_str_split(lsm_str *s, lsm_str *s2, uint64_t index); * @param s string to append s2 to * @param s2 string to append to s */ -lsm_error lsm_str_append(lsm_str *s, lsm_str *s2); +lsm_error lsm_str_append(lsm_str *s, const lsm_str *s2); + +/** + * Same as `lsm_str_append`, but it takes a C-style string instead. + * + * @param s string to append c_str to + * @param c_str char buffer to append + * @param len length of c_str + */ +lsm_error lsm_str_append_c(lsm_str *s, const char *c_str, uint64_t len); #endif diff --git a/lsm/src/store/lsm_store_entry.c b/lsm/src/store/lsm_store_entry.c index 63d90a7..101641b 100644 --- a/lsm/src/store/lsm_store_entry.c +++ b/lsm/src/store/lsm_store_entry.c @@ -316,3 +316,7 @@ lsm_error lsm_entry_data_open_read(lsm_entry_handle *handle) { return lsm_error_ok; } + +void lsm_entry_key(const lsm_str **out, lsm_entry_handle *handle) { + *out = handle->wrapper->entry->key; +} diff --git a/lsm/src/str/lsm_str.c b/lsm/src/str/lsm_str.c index 217bad7..e152fc1 100644 --- a/lsm/src/str/lsm_str.c +++ b/lsm/src/str/lsm_str.c @@ -215,15 +215,15 @@ bool lsm_str_eq(const lsm_str *s1, const lsm_str *s2) { return memcmp(lsm_str_ptr(s1), lsm_str_ptr(s2), s1->len) == 0; } -lsm_error lsm_str_append(lsm_str *s, lsm_str *s2) { - if (s2->len == 0) { +lsm_error lsm_str_append_c(lsm_str *s, const char *c_str, uint64_t len) { + if (len == 0) { return lsm_error_ok; } - uint64_t new_len = s->len + s2->len; + uint64_t new_len = s->len + len; if (new_len <= 8) { - memcpy(&s->data.val[s->len], s2->data.val, s2->len); + memcpy(&s->data.val[s->len], c_str, len); } else { char *buf; @@ -243,11 +243,15 @@ lsm_error lsm_str_append(lsm_str *s, lsm_str *s2) { } } - memcpy(&buf[s->len], lsm_str_ptr(s2), s2->len); + memcpy(&buf[s->len], c_str, len); s->data.ptr = buf; } - s->len += s2->len; + s->len += len; return lsm_error_ok; } + +lsm_error lsm_str_append(lsm_str *s, const lsm_str *s2) { + return lsm_str_append_c(s, lsm_str_ptr(s2), s2->len); +} diff --git a/src/lander/lander.c b/src/lander/lander.c index 203d71e..0225837 100644 --- a/src/lander/lander.c +++ b/src/lander/lander.c @@ -33,7 +33,7 @@ void lander_ctx_reset(lander_ctx *ctx) { if (ctx->instance != NULL) { ltm_instance_free(ctx->instance); - + ctx->instance = NULL; } } diff --git a/src/lander/lander_get.c b/src/lander/lander_get.c index d59d5e7..d9b47c9 100644 --- a/src/lander/lander_get.c +++ b/src/lander/lander_get.c @@ -20,7 +20,7 @@ static const char index_page[] = " \n" "\n"; -lnm_http_step_err lander_get_index(lnm_http_conn *conn) { +lnm_http_step_err lander_get_root(lnm_http_conn *conn) { lnm_http_loop_ctx *ctx = conn->ctx; lnm_http_res_body_set_buf(&ctx->res, (char *)index_page, @@ -73,7 +73,9 @@ lnm_err lander_entry_data_streamer(uint64_t *written, char *buf, return lnm_err_ok; } -lnm_err lander_template_streamer(size_t *written, char *buf, lnm_http_conn *conn, uint64_t offset, uint64_t len) { +lnm_err lander_template_streamer(size_t *written, char *buf, + lnm_http_conn *conn, uint64_t offset, + uint64_t len) { lnm_http_loop_ctx *ctx = conn->ctx; lander_ctx *c_ctx = ctx->c; @@ -84,9 +86,10 @@ lnm_err lander_template_streamer(size_t *written, char *buf, lnm_http_conn *conn return lnm_err_ok; } -ltm_err lander_data_to_template(size_t *written, char *buf, size_t len, void *data) { +ltm_err lander_data_to_template(size_t *written, char *buf, size_t len, + void *data) { lsm_entry_handle *entry = data; - + lsm_entry_data_read(written, buf, entry, len); return ltm_err_ok; @@ -98,9 +101,11 @@ lnm_http_step_err lander_get_paste(lnm_http_conn *conn) { lander_ctx *c_ctx = ctx->c; ltm_template_instantiate(&c_ctx->instance, c_gctx->templates.paste); - /* ltm_instance_block_add_var(c_ctx->instance, ltm_instance_block_type_buf, lsm_str_ptr(c_ctx->entry)) */ - ltm_instance_block_add_var_fn(c_ctx->instance, "paste", lander_data_to_template, c_ctx->entry, lsm_entry_data_len(c_ctx->entry)); - + /* ltm_instance_block_add_var(c_ctx->instance, ltm_instance_block_type_buf, + * lsm_str_ptr(c_ctx->entry)) */ + ltm_instance_block_add_var_fn(c_ctx->instance, "paste", + lander_data_to_template, c_ctx->entry, + lsm_entry_data_len(c_ctx->entry)); lnm_http_res_body_set_fn(&ctx->res, lander_template_streamer, ltm_instance_size(c_ctx->instance)); @@ -138,6 +143,88 @@ lnm_http_step_err lander_get_file(lnm_http_conn *conn) { return lnm_http_step_err_done; } +lnm_http_step_err lander_get_index(lnm_http_conn *conn) { + lnm_http_loop_ctx *ctx = conn->ctx; + lander_gctx *c_gctx = ctx->g->c; + lander_ctx *c_ctx = ctx->c; + + ltm_template_instantiate(&c_ctx->instance, c_gctx->templates.index); + + const lsm_str *key; + lsm_entry_key(&key, c_ctx->entry); + + ltm_instance_block_add_var(c_ctx->instance, "title_key", + ltm_instance_block_type_buf, + (void *)lsm_str_ptr(key), lsm_str_len(key)); + + lsm_str *prefix; + lsm_str_init_copy_n(&prefix, lsm_str_ptr(key), lsm_str_len(key)); + lsm_str_append_c(prefix, "_", 1); + + uint64_t prefix_len = lsm_str_len(prefix); + + lsm_store_iterator *iter; + lsm_store_iter(&iter, c_gctx->store, prefix); + + lsm_entry_handle *handle; + while (lsm_store_iter_next_read(&handle, iter) == lsm_error_ok) { + const lsm_str *entry_key; + lsm_entry_key(&entry_key, handle); + + lander_entry_type t; + lsm_entry_attr_get_uint8_t((uint8_t *)&t, handle, + lander_attr_type_entry_type); + + ltm_instance *nested; + + switch (t) { + case lander_entry_type_redirect: + ltm_instance_block_add_nested(&nested, c_ctx->instance, "redirect"); + + ltm_instance_block_add_var( + nested, "full_key", ltm_instance_block_type_buf, + (void *)lsm_str_ptr(entry_key), lsm_str_len(entry_key)); + ltm_instance_block_add_var(nested, "short_key", + ltm_instance_block_type_buf, + (void *)(lsm_str_ptr(entry_key) + prefix_len), + lsm_str_len(entry_key) - prefix_len); + break; + case lander_entry_type_file: + ltm_instance_block_add_nested(&nested, c_ctx->instance, "file"); + + ltm_instance_block_add_var( + nested, "full_key", ltm_instance_block_type_buf, + (void *)lsm_str_ptr(entry_key), lsm_str_len(entry_key)); + + lsm_str *filename; + if (lsm_entry_attr_get(&filename, handle, lander_attr_type_file_name)) { + ltm_instance_block_add_var( + nested, "filename", ltm_instance_block_type_buf, + (void *)lsm_str_ptr(filename), lsm_str_len(filename)); + } else { + ltm_instance_block_add_var( + nested, "filename", ltm_instance_block_type_buf, + (void *)(lsm_str_ptr(entry_key) + prefix_len), + lsm_str_len(entry_key) - prefix_len); + } + break; + } + + // TODO this should be done after writing the template + lsm_entry_close(handle); + } + + lnm_http_res_body_set_fn(&ctx->res, lander_template_streamer, + ltm_instance_size(c_ctx->instance)); + lnm_http_res_add_header(&ctx->res, lnm_http_header_content_type, "text/html", + false); + + lsm_store_iter_free(iter); + lsm_str_free(prefix); + + return lnm_http_step_err_done; +} + lnm_http_step_err lander_get_entry(lnm_http_conn *conn) { lnm_http_loop_ctx *ctx = conn->ctx; lander_ctx *c_ctx = ctx->c; @@ -179,6 +266,9 @@ lnm_http_step_err lander_get_entry(lnm_http_conn *conn) { case lander_entry_type_file: res = lander_get_file(conn); break; + case lander_entry_type_index: + res = lander_get_index(conn); + break; } return res; diff --git a/src/lander/lander_post.c b/src/lander/lander_post.c index 1244cb7..d30eb69 100644 --- a/src/lander/lander_post.c +++ b/src/lander/lander_post.c @@ -124,3 +124,21 @@ lnm_http_step_err lander_post_file(lnm_http_conn *conn) { return lnm_http_step_err_done; } + +lnm_http_step_err lander_post_index(lnm_http_conn *conn) { + lnm_http_loop_ctx *ctx = conn->ctx; + lander_ctx *c_ctx = ctx->c; + + if (!lander_insert_entry(ctx)) { + return lnm_http_step_err_res; + } + + lsm_entry_attr_insert_uint8_t(c_ctx->entry, lander_attr_type_entry_type, + lander_entry_type_index); + /* lander_header_to_attr(ctx, "X-Lander-Content-Type", */ + /* lander_attr_type_content_type); */ + /* lander_header_to_attr(ctx, "X-Lander-Filename", + * lander_attr_type_file_name); */ + + return lnm_http_step_err_done; +} diff --git a/src/main.c b/src/main.c index 5a6245f..351db58 100644 --- a/src/main.c +++ b/src/main.c @@ -10,12 +10,34 @@ #include "log.h" const char *lander_server = "lander/" LANDER_VERSION; -const char *paste_template = - "\n" - "\n" - "\n" - "\n" - "

{{ header }}

{{ paste }}
"; +const char *paste_template = + "\n" + "\n" + "\n" + "\n" + "

{{ header }}

{{ paste }}
"; + +const char *index_template = + "\n" + "\n" + "

Index /{{ title_key }}

\n" + "

Redirects

" + "\n" + "

Files

" + "\n" + "\n"; lnm_http_loop *loop_init(lander_gctx *gctx, const char *api_key) { lnm_http_loop *hl; @@ -27,7 +49,7 @@ lnm_http_loop *loop_init(lander_gctx *gctx, const char *api_key) { lnm_http_loop_set_api_key(hl, api_key); lnm_http_loop_set_server(hl, lander_server); - lnm_http_step_init(&step, lander_get_index); + lnm_http_step_init(&step, lander_get_root); lnm_http_route_init_literal(&route, lnm_http_method_get, "/", step); lnm_http_loop_route_add(hl, route); @@ -57,6 +79,14 @@ lnm_http_loop *loop_init(lander_gctx *gctx, const char *api_key) { lnm_http_step_append(&step, step, lander_stream_body_to_entry); lnm_http_loop_route_add(hl, route); + lnm_http_step_init(&step, lnm_http_loop_step_auth); + lnm_http_route_init_regex(&route, lnm_http_method_post, "^/i(l?)/([^/]+)$", 2, + step); + lnm_http_step_append(&step, step, lander_post_index); + /* lnm_http_step_append(&step, step, lnm_http_loop_step_body_to_buf); */ + /* lnm_http_step_append(&step, step, lander_post_redirect_body_to_attr); */ + lnm_http_loop_route_add(hl, route); + lnm_http_step_init(&step, lnm_http_loop_step_auth); lnm_http_route_init_regex(&route, lnm_http_method_delete, "^/([^/]+)$", 1, step); @@ -100,6 +130,7 @@ int main() { c_gctx->data_dir = data_dir_s; ltm_template_compile(&c_gctx->templates.paste, paste_template); + ltm_template_compile(&c_gctx->templates.index, index_template); lsm_str *data_dir; lsm_str_init_copy(&data_dir, (char *)data_dir_s);