Skip to content
Extraits de code Groupes Projets
Sélectionner une révision Git
  • d990bbbb9975a5f90182357085bfd290f7ab2506
  • master par défaut
  • 1-baka-export
  • meson
  • assdraw
  • old-master
  • v3.2.2
  • v3.2.1
  • v3.2.0
  • v3.1.3
  • v3.1.2
  • v3.1.1
  • v3.1.0
  • v3.0.4
  • v3.0.3
  • v3.0.2
  • v3.0.1
  • v3.0.0
  • v2.1.3
  • v2.1.4
  • v2.1.5
  • v2.1.6
  • v2.1.0
  • v2.1.1
  • v2.1.2
  • v2.1.7
26 résultats

auto4_lua_dialog.cpp

Blame
  • curl.c 10,23 Kio
    #define _POSIX_C_SOURCE 200809L
    
    #include <lektor/repo.h>
    #include <lektor/database.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    static volatile unsigned int curl_init = false;
    
    #define URL_MAX_LEN 1024
    #define DEFAULT_URL "https://kurisu.iiens.net"
    #define GET_ID_JSON DEFAULT_URL "/api_karas.php?id=%ld"
    #define GET_ID_FILE DEFAULT_URL "/download.php?id=%ld"
    
    struct memory {
        void *mem;
        size_t size;
    };
    
    struct file {
        const char *path;
        int fd;
    };
    
    static size_t
    write_mem__(char *data, size_t size, size_t nmem, void *user)
    {
        size_t realsize = size * nmem;
        struct memory *mem = (struct memory *) user;
    
        void *ptr = realloc(mem->mem, mem->size + realsize);
        if (ptr == NULL) {
            fprintf(stderr, " ! write_mem__: not enough memory (realloc returned NULL)\n");
            return 0;
        }
    
        mem->mem = ptr;
        memcpy(((uint8_t *) mem->mem) + mem->size, data, realsize);
        mem->size += realsize;
    
        return realsize;
    }
    
    static size_t
    write_disk__(char *data, size_t size, size_t nmem, void *user)
    {
        ssize_t realsize = size * nmem;
        struct file *file = (struct file *) user;
    
        if (write(file->fd, data, realsize) != realsize) {
            fprintf(stderr, " ! write_disk__: failed to write to '%s'\n", file->path);
            return 0;
        }
    
        return realsize;
    }
    
    int
    repo_new(struct lkt_repo *const repo_, const char *name_, const char *url_)
    {
        if (!curl_init) {
            curl_global_init(CURL_GLOBAL_ALL);
            curl_init = 1;
        } else
            ++curl_init;
    
        const size_t init_size = 30;
        uint64_t *calloc1 = calloc(init_size, sizeof(uint64_t));
    
        if (!calloc1) {
            fprintf(stderr, " ! repo_new: Out of memory\n");
            return ENOMEM;
        }
    
        uint64_t *calloc2 = calloc(init_size, sizeof(uint64_t));
    
        if (!calloc2) {
            free(calloc1);
            fprintf(stderr, " ! repo_new: Out of memory\n");
            return ENOMEM;
        }
    
        struct lkt_repo repo = {
            .name = name_,
            .base_url = url_,
            .get_id_json = GET_ID_JSON,
            .get_id_file = GET_ID_FILE,
            .get_all_json = DEFAULT_URL "/api_karas.php",
            .kara_dir = "/home/kara/", // TODO
            .version = 1,
        };
    
        memcpy(repo_, &repo, sizeof(struct lkt_repo));
        return 0;
    }
    
    void
    repo_free(struct lkt_repo *const repo)
    {
        --curl_init;
    
        free((void *) repo->base_url);
        free((void *) repo->kara_dir);
    
        if (!curl_init)
            curl_global_cleanup();
    }
    
    int
    safe_json_get_string(struct json_object *jobj, const char *key, char *content, const size_t len)
    {
        int ret = 1;
        const char *got;
        struct json_object *field;
    
        if (!json_object_object_get_ex(jobj, key, &field)) {
            fprintf(stderr, " ! safe_json_get_string: No object with key %s in json\n", key);
            goto err;
        }
    
        got = json_object_get_string(field);
    
        if (!got) {
            fprintf(stderr, " ! safe_json_get_string: Got a NULL for key %s, may be an error\n", key);
            goto err;
        }
    
        strncpy(content, got, len - 1);
        content[len - 1] = 0;
    
        ret = 0;
    err:
        return ret;
    }
    
    int
    safe_json_get_int32(struct json_object *json, const char *key, int32_t *ret)
    {
        struct json_object *field;
    
        if (!json_object_object_get_ex(json, key, &field)) {
            fprintf(stderr, " . safe_json_get_int32: No object with key '%s' in json, error\n", key);
            goto err;
        }
    
        errno = 0;
        *ret = json_object_get_int(field);
    
        if (errno == EINVAL) {
            fprintf(stderr, " . __handle_got_json: Invalid integer for field with key 'song_number'\n");
            goto err;
        }
    
        if (*ret == INT32_MAX || *ret == INT32_MIN) {
            fprintf(stderr, " . __handle_got_json: Out of bound integer for field with key 'song_number'\n");
            goto err;
        }
    
        return 0;
    err:
        return 1;
    }
    
    int
    repo_get_alljson_sync(struct lkt_repo *const repo, struct json_object **json)
    {
        if (!json) {
            fprintf(stderr, " ! repo_get_alljson_sync: Invalid argument\n");
            return 1;
        }
    
        CURL *curl_handle;
        CURLcode res;
        int ret = 1;
    
        struct memory file = {
            .mem = NULL,
            .size = 0.
        };
    
        curl_handle = curl_easy_init();
        curl_easy_setopt(curl_handle, CURLOPT_URL, repo->get_all_json);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_mem__);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &file);
        curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
        res = curl_easy_perform(curl_handle);
    
        if (res != CURLE_OK) {
            fprintf(stderr, " ! repo_get_alljson_sync: curl_easy_perform failed: %s\n",
                    curl_easy_strerror(res));
            free(file.mem);
            goto err;
        }
    
        *json = json_tokener_parse(file.mem);
    
        ret = 0;
    err:
        curl_easy_cleanup(curl_handle);
        return ret;
    }
    
    int
    repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata *mdt)
    {
        CURL *curl_handle;
        CURLcode res;
        struct json_object *jobj, *field;
        int ret = 1, err = 0;
    
        if (!mdt)
            fprintf(stderr, " ! repo_get_id: invalid argument\n");
    
        char *url = calloc(URL_MAX_LEN, sizeof(char));
    
        if (!url) {
            fprintf(stderr, " ! repo_get_id: out of memory\n");
            return ENOMEM;
        }
    
        struct memory file = {
            .mem = NULL,
            .size = 0,
        };
    
        memset(url, 0, URL_MAX_LEN * sizeof(char));
        snprintf(url, URL_MAX_LEN - 1, repo->get_id_json, id);
        url[URL_MAX_LEN - 1] = 0;
        curl_handle = curl_easy_init();
        curl_easy_setopt(curl_handle, CURLOPT_URL, url);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_mem__);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &file);
        curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
        res = curl_easy_perform(curl_handle);
    
        if (res != CURLE_OK) {
            fprintf(stderr, " ! repo_get_id: curl_easy_perform failed: %s\n", curl_easy_strerror(res));
            free(url);
            free(file.mem);
            curl_easy_cleanup(curl_handle);
            return 1;
        }
    
        curl_easy_cleanup(curl_handle);
    
        /* Read the json. */
    
        jobj = json_tokener_parse(file.mem);
    
        if (json_object_object_get_ex(jobj, "message", &field)) {
            fprintf(stderr, " * repo_get_id: Kara with id %lu not found, message is: %s\n",
                    id, json_object_get_string(field));
            goto err;
        }
    
        fprintf(stderr, " . repo_get_id: Got kara with id %lu\n", id);
    
        err |= safe_json_get_string(jobj, "song_name", mdt->song_name, LEKTOR_TAG_MAX);
        err |= safe_json_get_string(jobj, "source_name", mdt->source_name, LEKTOR_TAG_MAX);
        err |= safe_json_get_string(jobj, "category", mdt->category, LEKTOR_TAG_MAX);
        err |= safe_json_get_string(jobj, "language", mdt->language, LEKTOR_TAG_MAX);
        err |= safe_json_get_string(jobj, "author_name", mdt->author_name, LEKTOR_TAG_MAX);
        err |= safe_json_get_string(jobj, "song_type", mdt->song_type, LEKTOR_TAG_MAX);
    
        errno = 0;
    
        if (!json_object_object_get_ex(jobj, "song_number", &field)) {
            fprintf(stderr, " * repo_get_id: No object with key 'song_number' in json, error\n");
            goto err;
        }
    
        mdt->song_number = json_object_get_int(field);
    
        if (errno == EINVAL) {
            fprintf(stderr, " * repo_get_id: Invalid integer for field with key 'song_number'\n");
            goto err;
        }
    
        if (mdt->song_number == INT32_MAX || mdt->song_number == INT32_MIN) {
            fprintf(stderr, " * repo_get_id: Out of bound integer for field with key 'song_number'\n");
            goto err;
        }
    
    
        ret = 0;
    err:
        free(url);
        json_object_put(jobj); /* Delete object. */
        return ret;
    }
    
    int
    repo_download_id_sync(struct lkt_repo *const repo, sqlite3 *db, const uint64_t id, const char *kara_path,
                          struct kara_metadata *mdt_ret)
    {
        if (!kara_path) {
            fprintf(stderr, " ! repo_download_id_sync: Can't download kara to a NULL path\n");
            return 1;
        }
    
        struct kara_metadata mdt;
        CURL *curl_handle;
        int ret = 1, fd;
        char *url = calloc(URL_MAX_LEN, sizeof(char));
        char *ct;
    
        if (!url) {
            fprintf(stderr, " ! repo_download_id_sync: Out of memory\n");
            errno = ENOMEM;
            return ENOMEM;
        }
    
        if (repo_get_id(repo, id, mdt_ret ? mdt_ret : &mdt)) {
            fprintf(stderr, " ! repo_download_id_sync: Failed to get kara metadata from kurisu\n");
            goto err_no_curl;
        }
    
        errno = 0;
        fd = open(kara_path,
                  O_WRONLY | O_APPEND | O_CREAT | O_EXCL | O_NOFOLLOW,
                  S_IRUSR | S_IWUSR);
    
        if (fd < 0) {
            if (errno == EEXIST)
                fprintf(stderr, " ! repo_download_id_sync: file '%s' already exists\n", kara_path);
    
            else
                fprintf(stderr, " ! repo_download_id_sync: could not open file '%s'\n", kara_path);
    
            goto err_no_curl;
        }
    
        /* Download the kara... (TODO) */
    
        struct file file = {
            .path = kara_path,
            .fd = fd,
        };
    
        memset(url, 0, URL_MAX_LEN * sizeof(char));
        snprintf(url, URL_MAX_LEN - 1, repo->get_id_file, id);
        url[URL_MAX_LEN - 1] = 0;
        curl_handle = curl_easy_init();
        curl_easy_setopt(curl_handle, CURLOPT_URL, url);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_disk__);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &file);
        curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
        ret = curl_easy_perform(curl_handle);
    
        if (ret != CURLE_OK) {
            fprintf(stderr, " ! repo_download_id_sync: curl_easy_perform failed: %s\n",
                    curl_easy_strerror(ret));
            goto err;
        }
    
        if (CURLE_OK == ( ret = curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_TYPE, &ct)))
            fprintf(stderr, " . repo_download_id_sync: Content-Type is '%s'\n", ct);
        else {
            fprintf(stderr, " ! repo_download_id_sync: failed to get Content-Type: %s\n",
                    curl_easy_strerror(ret));
            goto err;
        }
    
        if (!db) {
            fprintf(stderr, " . repo_download_id_sync: Skip database update here\n");
            goto no_db_update;
        }
    
        if (! database_update_add(db, kara_path, mdt_ret ? mdt_ret : &mdt, id, true)) {
            fprintf(stderr, " ! repo_download_id_sync: Failed to add kara to database\n");
            goto err;
        }
    
    no_db_update:
        ret = 0;
    err:
        curl_easy_cleanup(curl_handle);
    err_no_curl:
        free(url);
        return ret;
    }