예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #4
0
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;
}
예제 #5
0
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);
    }
}