lander/src/lander/lander_post.c

150 lines
4.0 KiB
C

#include <string.h>
#include "lnm/http/req.h"
#include "lnm/loop.h"
#include "lsm/store.h"
#include "lander.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, bool secure) {
lnm_http_loop_gctx *gctx = ctx->g;
lander_gctx *c_gctx = gctx->c;
lander_ctx *c_ctx = ctx->c;
const char *key_s;
size_t key_len = lnm_http_req_route_segment(&key_s, &ctx->req, "key");
lsm_str *key;
if (key_len == 0) {
// Generate a random key to insert
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 {
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;
}
static lnm_http_step_err __lander_post_redirect(lnm_http_conn *conn,
bool secure) {
lnm_http_loop_ctx *ctx = conn->ctx;
lander_ctx *c_ctx = ctx->c;
if (!lander_insert_entry(ctx, secure)) {
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(lnm_http_conn *conn) {
return __lander_post_redirect(conn, false);
}
lnm_http_step_err lander_post_redirect_secure(lnm_http_conn *conn) {
return __lander_post_redirect(conn, true);
}
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;
}
static lnm_http_step_err __lander_post_paste(lnm_http_conn *conn, bool secure) {
lnm_http_loop_ctx *ctx = conn->ctx;
lander_ctx *c_ctx = ctx->c;
if (!lander_insert_entry(ctx, secure)) {
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_paste(lnm_http_conn *conn) {
return __lander_post_paste(conn, false);
}
lnm_http_step_err lander_post_paste_secure(lnm_http_conn *conn) {
return __lander_post_paste(conn, true);
}
static lnm_http_step_err __lander_post_file(lnm_http_conn *conn, bool secure) {
lnm_http_loop_ctx *ctx = conn->ctx;
lander_ctx *c_ctx = ctx->c;
if (!lander_insert_entry(ctx, secure)) {
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;
}
lnm_http_step_err lander_post_file(lnm_http_conn *conn) {
return __lander_post_file(conn, false);
}
lnm_http_step_err lander_post_file_secure(lnm_http_conn *conn) {
return __lander_post_file(conn, true);
}