TEST_END TEST_START(pushes_buf_kv) { clax_kv_list_t list; clax_kv_list_init(&list); clax_kv_list_pushn(&list, "foo", 3, "bar", 3); ASSERT_EQ(list.size, 1); ASSERT_STR_EQ(clax_kv_list_find(&list, "foo"), "bar"); clax_kv_list_pushn(&list, "", 0, "bar", 3); ASSERT_EQ(list.size, 2); ASSERT_STR_EQ(clax_kv_list_find(&list, ""), "bar"); clax_kv_list_pushn(&list, "baz", 3, "", 0); ASSERT_EQ(list.size, 3); ASSERT_STR_EQ(clax_kv_list_find(&list, "baz"), ""); clax_kv_list_pushn(&list, "", 0, "", 0); ASSERT_EQ(list.size, 4); size_t start = 3; ASSERT_STR_EQ(clax_kv_list_find_all(&list, "", &start), ""); clax_kv_list_free(&list); }
TEST_END TEST_START(sets_new_val) { clax_kv_list_t list; clax_kv_list_init(&list); clax_kv_list_set(&list, "foo", "bar"); ASSERT_STR_EQ(clax_kv_list_find(&list, "foo"), "bar"); clax_kv_list_set(&list, "foo", "baz"); ASSERT_STR_EQ(clax_kv_list_find(&list, "foo"), "baz"); clax_kv_list_free(&list); }
TEST_END TEST_START(finds_kv) { clax_kv_list_t list; clax_kv_list_init(&list); ASSERT(clax_kv_list_find(&list, "foo") == NULL); clax_kv_list_push(&list, "foo", "bar"); clax_kv_list_push(&list, "bar", "baz"); clax_kv_list_push(&list, "bar", "zab"); ASSERT_STR_EQ(clax_kv_list_find(&list, "foo"), "bar"); ASSERT_STR_EQ(clax_kv_list_find(&list, "bar"), "baz"); ASSERT_STR_EQ(clax_kv_list_find(&list, "bar"), "baz"); ASSERT(clax_kv_list_find(&list, "unknown") == NULL); clax_kv_list_free(&list); }
void clax_dispatch_command(clax_ctx_t *clax_ctx, clax_http_request_t *req, clax_http_response_t *res) { memset(&command_ctx, 0, sizeof(command_ctx_t)); char *command = clax_kv_list_find(&req->body_params, "command"); if (!command || !strlen(command)) { clax_dispatch_bad_request(clax_ctx, req, res); return; } strncpy(command_ctx.command, command, sizeof_struct_member(command_ctx_t, command)); char *timeout = clax_kv_list_find(&req->body_params, "timeout"); if (timeout && strlen(timeout)) { command_ctx.timeout = atoi(timeout); } pid_t pid = clax_command_start(&command_ctx); if (pid <= 0) { clax_dispatch_system_error(clax_ctx, req, res); return; } res->status_code = 200; clax_kv_list_push(&res->headers, "Transfer-Encoding", "chunked"); char buf_pid[15]; snprintf(buf_pid, sizeof(buf_pid), "%d", pid); clax_kv_list_push(&res->headers, "Trailer", "X-Clax-Exit"); clax_kv_list_push(&res->headers, "X-Clax-PID", buf_pid); res->body_cb_ctx = &command_ctx; res->body_cb = clax_command_read_cb; }
void clax_dispatch_upload(clax_ctx_t *clax_ctx, clax_http_request_t *req, clax_http_response_t *res) { char *subdir = req->path_info + strlen("/tree/"); if (strlen(subdir)) { struct stat info; if (stat(subdir, &info) == 0 && info.st_mode & S_IFDIR) { } else { clax_log("Output directory '%s' does not exist", subdir); clax_dispatch_bad_request(clax_ctx, req, res); return; } } if (req->continue_expected) { return; } if (strlen(req->multipart_boundary)) { int i; for (i = 0; i < req->multiparts.size; i++) { clax_http_multipart_t *multipart = clax_http_multipart_list_at(&req->multiparts, i); const char *content_disposition = clax_kv_list_find(&multipart->headers, "Content-Disposition"); if (!content_disposition) continue; char prefix[] = "form-data; "; if (strncmp(content_disposition, prefix, strlen(prefix)) != 0) continue; const char *kv = content_disposition + strlen(prefix); size_t name_len; size_t filename_len; const char *name = clax_http_extract_kv(kv, "name", &name_len); const char *filename = clax_http_extract_kv(kv, "filename", &filename_len); if (!name || !filename || (strncmp(name, "file", name_len) != 0)) continue; char *new_name = clax_kv_list_find(&req->query_params, "name"); char *crc32 = clax_kv_list_find(&req->query_params, "crc"); char *time = clax_kv_list_find(&req->query_params, "time"); if (crc32 && strlen(crc32) != 8) { clax_dispatch_bad_request(clax_ctx, req, res); return; } char *fpath; if (new_name && strlen(new_name)) { fpath = clax_strjoin("/", subdir, new_name, NULL); } else { char *p = clax_strndup(filename, filename_len); fpath = clax_strjoin("/", subdir, p, NULL); free(p); } clax_san_path(fpath); int ret = clax_big_buf_write_file(&multipart->bbuf, fpath); if (ret < 0) { clax_log("Saving file failed: %s\n", fpath); clax_dispatch_system_error(clax_ctx, req, res); } else { if (crc32 && strlen(crc32)) { unsigned long got_crc32 = clax_htol(crc32); int fd = open(fpath, O_RDONLY); unsigned long exp_crc32 = clax_crc32_calc_fd(fd); close(fd); if (got_crc32 != exp_crc32) { clax_log("CRC mismatch %u != %u (%s)", exp_crc32, got_crc32, crc32); clax_dispatch_bad_request(clax_ctx, req, res); remove(fpath); free(fpath); return; } else { clax_log("CRC ok %u != %u (%s)", exp_crc32, got_crc32, crc32); } } if (time && strlen(time)) { int mtime = atol(time); struct utimbuf t; t.actime = mtime; t.modtime = mtime; int ok = utime(fpath, &t); if (ok < 0) clax_log("utime on file '%s' failed: %s", fpath, strerror(errno)); } res->status_code = 200; clax_kv_list_push(&res->headers, "Content-Type", "application/json"); clax_big_buf_append_str(&res->body, "{\"message\":\"ok\"}"); } free(fpath); break; } } if (!res->status_code) { clax_dispatch_bad_request(clax_ctx, req, res); } }