#include "lnm/loop.h" #include "lsm/store.h" #include "lander.h" #include "log.h" static void randomize_key(char *key, int len) { size_t charset_len = strlen(lander_key_charset); for (int i = 0; i < len; i++) { key[i] = lander_key_charset[rand() % charset_len]; } key[len] = '\0'; } /** * Insert a new entry into the store. * * @return true on success, false otherwise */ bool lander_insert_entry(lnm_http_loop_ctx *ctx) { lnm_http_loop_gctx *gctx = ctx->g; lander_gctx *c_gctx = gctx->c; lander_ctx *c_ctx = ctx->c; lsm_str *key; int key_len; if (ctx->req.path.groups[2].rm_eo == ctx->req.path.groups[2].rm_so) { // Generate a random key to insert bool secure = (ctx->req.path.groups[1].rm_eo - ctx->req.path.groups[1].rm_so) == 1; key_len = secure ? 16 : 4; char *key_s = malloc((key_len + 1) * sizeof(char)); randomize_key(key_s, key_len); lsm_str_init(&key, key_s); } else { const char *key_s = &ctx->req.path.s[ctx->req.path.groups[2].rm_so]; key_len = ctx->req.path.groups[2].rm_eo - ctx->req.path.groups[2].rm_so; lsm_str_init_copy_n(&key, key_s, key_len); } // TODO free key on error switch (lsm_store_insert(&c_ctx->entry, c_gctx->store, key)) { case lsm_error_already_present: ctx->res.status = lnm_http_status_conflict; return false; case lsm_error_ok: break; default: ctx->res.status = lnm_http_status_internal_server_error; return false; } // Add location header char *buf = malloc(key_len + 2); memcpy(&buf[1], lsm_str_ptr(key), key_len); buf[0] = '/'; buf[key_len + 1] = '\0'; lnm_http_res_add_header(&ctx->res, lnm_http_header_location, buf, true); ctx->res.status = lnm_http_status_created; return true; } lnm_http_step_err lander_post_redirect(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_redirect); return lnm_http_step_err_done; } lnm_http_step_err lander_post_redirect_body_to_attr(lnm_http_conn *conn) { lnm_http_loop_ctx *ctx = conn->ctx; lander_ctx *c_ctx = ctx->c; lsm_str *attr_value; lsm_str_init_copy_n(&attr_value, ctx->req.body.buf, ctx->req.body.len); lsm_entry_attr_insert(c_ctx->entry, lander_attr_type_url, attr_value); return lnm_http_step_err_done; } lnm_http_step_err lander_post_paste(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_paste); lander_header_to_attr(ctx, "X-Lander-Filename", lander_attr_type_file_name); return lnm_http_step_err_done; } lnm_http_step_err lander_post_file(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_file); 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; }