diff --git a/inc/common/common.h b/inc/common/common.h index 074fd87b94972d8a69b397bbd103ee3202cf7da9..03c6323029262e3d1fbb59c6a360feeceff157a4 100644 --- a/inc/common/common.h +++ b/inc/common/common.h @@ -13,6 +13,7 @@ void __unused(void *, ...); long get_mtime(const char *path); void *safe_malloc(size_t size); +void *safe_zero_malloc(size_t size); int is_utf8(const char *string); diff --git a/inc/common/macro.h b/inc/common/macro.h index cb3393ec5df88049776bc6a641be6e34b1316e1d..3e220015527cf73428f3a5799b45d417e6c0b9e5 100644 --- a/inc/common/macro.h +++ b/inc/common/macro.h @@ -70,15 +70,11 @@ #define INI_MAX_SECTION_LEN 80 #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" #define SELF_EXECUTABLE_LINUX "/proc/self/exe" #define SELF_EXECUTABLE_FREEBSD "/proc/curproc/file" #define SELF_EXECUTABLE_SOLARIS "/proc/self/path/a.out" - #define LKT_MAX_SQLITE_STATEMENT 1024 #define PROTECTED_DATABASE "disk" diff --git a/inc/lektor/config.h b/inc/lektor/config.h index 9affc9529330628379d66d95ba60885222b68321..b60bcd73e53b5fb8a4f62a416904f380ea6f6ced 100644 --- a/inc/lektor/config.h +++ b/inc/lektor/config.h @@ -12,7 +12,6 @@ static const char *const lkt_default_config_file = "; generated binary.\n" "[externals]\n" "mkvpropedit = /usr/bin/mkvpropedit\n" - "sqlite3 = /usr/bin/sqlite3\n" "\n" "; Server configuration.\n" "[server]\n" @@ -23,18 +22,25 @@ static const char *const lkt_default_config_file = "; Database configuration.\n" "[database]\n" "kara_dir = /home/kara ; Root for the mkv files\n" - "db_path = /home/kara/kara.db ; Sqlite3 database, must be rw\n" - "init_script = LKT_PREFIX/share/lektor/init.sql ; Init script for the database\n" + "db_path = /home/kara/kara.db ; Sqlite3 database, must be rw\n" + "\n" + "; Repo configuration.\n" + "[repo]\n" + "name = Kurisu ; A pretty name\n" + "url = https://kurisu.iiens.net\n" + "json = https://kurisu.iiens.net/api\n" + "id_json = https://kurisu.iiens.net/api?id=%ld\n" + "id_kara = https://kurisu.iiens.net/download.php?id=%ld\n" "\n" "; Player configuration, the window where the karas\n" "; can be seen.\n" "[player]\n" - "autoclear = true ; Clear the queue when starting\n" "module = module_x11 ; Default module for the window\n" - "def_random = false ; Play at random per default\n" + "autoclear = true ; Clear the queue when starting\n" + "def_random = false ; Play at random per default\n" "def_consume = false ; Consume per default\n" - "def_single = false ; Single per default\n" - "def_repeat = false ; Repeat per default\n" + "def_single = false ; Single per default\n" + "def_repeat = false ; Repeat per default\n" "\n" "; The WinX11 module configuration. Modules are .so files\n" "; loaded by lektor.\n" diff --git a/inc/lektor/database.h b/inc/lektor/database.h index 2923dc854a8616e850d06b0eca577cbec253440f..0cddeaa1a7b2af6f4ae662664f9f25469c0e276d 100644 --- a/inc/lektor/database.h +++ b/inc/lektor/database.h @@ -45,7 +45,7 @@ bool database_queue_get_current_file (volatile sqlite3 *db, char filepath[PATH_M bool database_sync_mpv_state(volatile sqlite3 *db, mpv_handle **mpv); /* Update the database. */ -bool database_update (volatile sqlite3 *db, const char *kara_dir); +bool database_update (volatile sqlite3 *db, const char *kara_dir, int check_timestamp); bool database_update_add (volatile sqlite3 *db, const char *kara_path, struct kara_metadata *mdt, uint64_t id, bool avail); bool database_update_set_available(volatile sqlite3 *db, uint64_t id); diff --git a/inc/lektor/net.h b/inc/lektor/net.h index 1a4e96a780a486f11ab23410574468788560f8f2..0609d473f7a86e4b898c23192d999c2655954ad1 100644 --- a/inc/lektor/net.h +++ b/inc/lektor/net.h @@ -26,19 +26,19 @@ struct lkt_command { /* Repository, e.g. Kurisu */ struct lkt_repo { /* Just the repo */ - const char *name; - const char *base_url; - const char *kara_dir; - const char *get_all_json; - const char *get_id_json; - const char *get_id_file; + char *name; + char *base_url; + char *kara_dir; + char *get_all_json; + char *get_id_json; + char *get_id_file; const uint64_t version; /* The database */ volatile sqlite3 *db; }; -int repo_new (struct lkt_repo *const repo, const char *name, const char *url, volatile sqlite3 *db); +int repo_new (struct lkt_repo *const repo, volatile sqlite3 *db); void repo_free(struct lkt_repo *const repo); int repo_get_id (struct lkt_repo *const repo, const uint64_t id, struct kara_metadata *mdt); diff --git a/src/commands.c b/src/commands.c index f1f3843d91069f1bed7874a3234fed2620635877..22863455515b3aa4d4ab01b21448c40cd035f017 100644 --- a/src/commands.c +++ b/src/commands.c @@ -48,7 +48,7 @@ static inline void * __rescan(void *arg) { struct lkt_state *srv = arg; - database_update(srv->db, srv->kara_prefix); + database_update(srv->db, srv->kara_prefix, true); return NULL; } @@ -85,14 +85,14 @@ command_currentsong(struct lkt_state *srv, size_t c) out = lkt_message_new(); idx = safe_snprintf(out->data, LKT_MESSAGE_MAX, - "Title: %s\n" - "Author: %s\n" - "Source: %s\n" - "Type: %s%d\n" - "Category: %s\n" - "Language: %s\n", - kara.song_name, kara.author_name, kara.source_name, kara.song_type, - kara.song_number, kara.category, kara.language); + "Title: %s\n" + "Author: %s\n" + "Source: %s\n" + "Type: %s%d\n" + "Category: %s\n" + "Language: %s\n", + kara.song_name, kara.author_name, kara.source_name, kara.song_type, + kara.song_number, kara.category, kara.language); out->data_len = idx; lkt_state_send(srv, c, out); @@ -120,21 +120,21 @@ command_status(struct lkt_state *srv, size_t c) ? "stop" : (queue_state.paused ? "pause" : "play"); out->data_len = safe_snprintf(out->data, LKT_MESSAGE_MAX, - "volume: %d\n" - "repeat: %d\n" - "random: %d\n" - "single: %d\n" - "consume: %d\n" - "state: %s\n" - "song: %d\n" - "playlistlength: %d\n" - "elapsed: %d\n" - "duration: %d\n" - "songid: %d\n", - queue_state.volume, queue_state.repeat, queue_state.random, - queue_state.single, queue_state.consume, play_state, - queue_state.current < 0 ? -1 : queue_state.current - 1, - queue_state.length, elapsed, duration, songid); + "volume: %d\n" + "repeat: %d\n" + "random: %d\n" + "single: %d\n" + "consume: %d\n" + "state: %s\n" + "song: %d\n" + "playlistlength: %d\n" + "elapsed: %d\n" + "duration: %d\n" + "songid: %d\n", + queue_state.volume, queue_state.repeat, queue_state.random, + queue_state.single, queue_state.consume, play_state, + queue_state.current < 0 ? -1 : queue_state.current - 1, + queue_state.length, elapsed, duration, songid); lkt_state_send(srv, c, out); return true; } diff --git a/src/common.c b/src/common.c index 636bf3d5459a7f8a8810b99c27418ef7994f60c7..23a0ca394a144c3a530465ac719121b825ef6934 100644 --- a/src/common.c +++ b/src/common.c @@ -151,6 +151,14 @@ safe_malloc(size_t size) return tmp; } +void * +safe_zero_malloc(size_t size) +{ + void *ret = safe_malloc(size); + memset(ret, 0, size); + return ret; +} + int read_self_exe(char *path, size_t len) { diff --git a/src/config.c b/src/config.c index 707c48ecd7d904405b0863e7467cda4942b4b1b4..4d2a0a3089f384d6d6622baa2a5d58552516b29a 100644 --- a/src/config.c +++ b/src/config.c @@ -156,10 +156,10 @@ load_module_by_name(volatile sqlite3 *db, const char *name, void *mod) inline static int validate_conf(volatile sqlite3 *db) { -#define CHK_OPTION(section, name) \ - if (!database_config_exists(db, section, name)) { \ - LOG_ERROR("%s", "Missing option "name" in section "section); \ - return 1; \ +#define CHK_OPTION(section, name) \ + if (!database_config_exists(db, section, name)) { \ + LOG_ERROR("%s", "Missing option \""name"\" in section \""section"\""); \ + return 1; \ } CHK_OPTION("externals", "mkvpropedit"); @@ -171,6 +171,12 @@ validate_conf(volatile sqlite3 *db) CHK_OPTION("database", "kara_dir"); CHK_OPTION("database", "db_path"); + CHK_OPTION("repo", "name"); + CHK_OPTION("repo", "url"); + CHK_OPTION("repo", "json"); + CHK_OPTION("repo", "id_json"); + CHK_OPTION("repo", "id_kara"); + CHK_OPTION("player", "autoclear"); CHK_OPTION("player", "def_random"); CHK_OPTION("player", "def_consume"); diff --git a/src/database/stickers.c b/src/database/stickers.c index a0a7c7f001c9961549b5f016f6e859501e04bbe0..8863b827b0d3ac61f982c31ff1d42f0180c3d811 100644 --- a/src/database/stickers.c +++ b/src/database/stickers.c @@ -100,7 +100,7 @@ database_sticker_delete_specify(volatile sqlite3 *db, const char *type, int uri, } safe_snprintf(SQL, LKT_MAX_SQLITE_STATEMENT, "DELETE FROM 'stickers.%s' " - "WHERE 'stickers.%s' = ? ", type, type); + "WHERE 'stickers.%s' = ? ", type, type); /* If there is a name specified. */ if (!name) { diff --git a/src/database/update.c b/src/database/update.c index 145a60199a5eccdded3248c6c834ae3e27ab8145..369df055ec700de599b43b47300194508d5c0f5c 100644 --- a/src/database/update.c +++ b/src/database/update.c @@ -21,21 +21,44 @@ database_add_kara(volatile sqlite3 *db, const char *filename) "INSERT INTO " "kara (song_name, source_name, category, song_type, language, file_path, is_new, author_name, author_year, song_number)" "SELECT ?, ?, ?, ?, ?, ?, ?, ?, strftime('%s','now'), ?"; + static const char *SQL_STMT_WITH_ID = + "INSERT INTO " + "kara (song_name, source_name, category, song_type, language, file_path, is_new, author_name, author_year, song_number, id)" + "SELECT ?, ?, ?, ?, ?, ?, ?, ?, strftime('%s','now'), ?, ?"; sqlite3_stmt *stmt = NULL; - int code = SQLITE_OK, status = false; + long code = SQLITE_OK, status = false, kara_id; struct kara_metadata data; time_t the_time = time(NULL); struct tm *the_local_time = localtime(&the_time); - char year[10]; + char year[10], path[PATH_MAX], *saveptr = NULL, *token, *id = NULL; + + /* A timestamp */ code = safe_snprintf(year, 10, "%d", the_local_time->tm_year + 1900); RETURN_IF(code < 0 || code >= 10, "Failed to get the year of the current date", false); + /* Metadata */ if (kara_metadata_read(&data, filename) != 0) { LOG_ERROR("Failed to get mdt for the kara '%s'", filename); return false; } - SQLITE_PREPARE(db, stmt, SQL_STMT, error); + /* Try to find an id in the filename, reuse of variables, it's ugly */ + path[PATH_MAX - 1] = '\0'; + memcpy(path, filename, (strlen(filename) + 1) * sizeof(char)); + while (NULL != (token = strtok_r(path, "/", &saveptr))) + id = token; + size_t id_len = strspn(id, "0123456789"); + id[id_len] = '\0'; /* Replace the . of .mkv */ + STRTOL(kara_id, id, token, id_len); + if (!id_len && STR_MATCH(&token[1], "mkv")) { + /* Use the found id, most of the time, normally */ + LOG_INFO_SCT("DB", "Found id '%ld' in kara '%s'", kara_id, filename); + SQLITE_PREPARE(db, stmt, SQL_STMT_WITH_ID, error); + SQLITE_BIND_INT(db, stmt, 10, (int) kara_id, error); + } else { + /* Generate a new id */ + SQLITE_PREPARE(db, stmt, SQL_STMT, error); + } if ((sqlite3_bind_text(stmt, 1, data.song_name, -1, 0) != SQLITE_OK) || (sqlite3_bind_text(stmt, 2, data.source_name, -1, 0) != SQLITE_OK) || @@ -50,7 +73,6 @@ database_add_kara(volatile sqlite3 *db, const char *filename) LOG_ERROR_SCT("DB", "Failed to bind for kara %s: %s", filename, sqlite3_errmsg((sqlite3 *) db)); goto error; } - SQLITE_STEP_DONE(db, stmt, error); status = true; error: @@ -121,7 +143,7 @@ error_no_sqlite: } bool -database_update(volatile sqlite3 *db, const char *kara_dir) +database_update(volatile sqlite3 *db, const char *kara_dir, int check_timestamp) { DIR *d; struct dirent *dir; @@ -139,8 +161,10 @@ database_update(volatile sqlite3 *db, const char *kara_dir) strncat(path, dir->d_name, PATH_MAX - 1); if (dir->d_type == DT_REG) { - if (get_mtime(path) < database_get_timestamp(db)) + if (check_timestamp && get_mtime(path) < database_get_timestamp(db)) { + LOG_INFO_SCT("DB", "Skip update of kara '%s' be cause of timestamps", path); continue; + } database_add_kara(db, path); database_stamp(db); } @@ -148,7 +172,7 @@ database_update(volatile sqlite3 *db, const char *kara_dir) else if (dir->d_type == DT_DIR && !STR_MATCH(dir->d_name, ".") && !STR_MATCH(dir->d_name, "..")) - database_update(db, path); + database_update(db, path, check_timestamp); } LOG_INFO("Passed directory '%s'", kara_dir); diff --git a/src/main/lktadm.c b/src/main/lktadm.c index d4b25a85a70ef67216438c99410045e56ca384cf..78d00eb952b91342a822b58675804d961aa6ef64 100644 --- a/src/main/lktadm.c +++ b/src/main/lktadm.c @@ -34,8 +34,7 @@ fail(const char *format, ...) * ----------------- */ static sqlite3 *db = NULL; -static char kara_dir[PATH_MAX], db_path[PATH_MAX], mkvpropedit[PATH_MAX], sqlite3_bin[PATH_MAX], - init_script[PATH_MAX], buf[100]; +static char kara_dir[PATH_MAX], db_path[PATH_MAX], mkvpropedit[PATH_MAX], buf[100]; void open_db(void) @@ -49,17 +48,11 @@ open_db(void) if (!database_config_get_text(db, "externals", "mkvpropedit", mkvpropedit, PATH_MAX)) fail("Not found externals->mkvpropedit"); - if (!database_config_get_text(db, "externals", "sqlite3", sqlite3_bin, PATH_MAX)) - fail("Not found externals->sqlite3"); - if (!database_config_get_text(db, "database", "db_path", db_path, PATH_MAX)) fail("Not found database->db_path"); if (!database_config_get_text(db, "database", "kara_dir", kara_dir, PATH_MAX)) fail("Not found database->kara_dir"); - - if (!database_config_get_text(db, "database", "init_script", init_script, PATH_MAX)) - fail("Not found database->init_script"); } noreturn void @@ -108,7 +101,7 @@ init_populate__(struct lkt_cmd_args *args) open_db(); if (!database_open(db, db_path)) fail("Failed to open database"); - database_update(db, kara_dir); + database_update(db, kara_dir, false); sqlite3_close(db); exit(EXIT_SUCCESS); } @@ -171,8 +164,11 @@ get__(struct lkt_cmd_args *args) fail("Invalid argument"); int i = atoi(args->argv[0]); + open_db(); + if (!database_open(db, db_path)) + fail("Failed to open database"); - if (repo_new(&repo, "kurisu", "https://kurisu.iiens.net", NULL)) + if (repo_new(&repo, db)) fail("Cound not create repo"); if (repo_get_id(&repo, i, &data)) @@ -208,8 +204,11 @@ download__(struct lkt_cmd_args *args) struct lkt_repo repo; struct kara_metadata data; int i = atoi(args->argv[0]); + open_db(); + if (!database_open(db, db_path)) + fail("Failed to open database"); - if (repo_new(&repo, "kurisu", "https://kurisu.iiens.net", NULL)) + if (repo_new(&repo, db)) fail("Could not create the repo"); if (repo_download_id_sync(&repo, i, args->argv[1], &data)) @@ -259,6 +258,12 @@ source__(struct lkt_cmd_args *args) CHK_OPTION("player", "def_single"); CHK_OPTION("player", "def_repeat"); + CHK_OPTION("repo", "name"); + CHK_OPTION("repo", "url"); + CHK_OPTION("repo", "json"); + CHK_OPTION("repo", "id_json"); + CHK_OPTION("repo", "id_kara"); + CHK_OPTION("database", "kara_dir"); CHK_OPTION("database", "db_path"); diff --git a/src/net/downloader.c b/src/net/downloader.c index 9645a50b446424eccad001a8fae29b33cb9841e7..b25ebac890df8e24b9ce60e3f6a43c0010beda0b 100644 --- a/src/net/downloader.c +++ b/src/net/downloader.c @@ -52,8 +52,9 @@ write_disk__(char *data, size_t size, size_t nmem, void *user) } int -repo_new(struct lkt_repo *const repo_, const char *name_, const char *url_, volatile sqlite3 *db) +repo_new(struct lkt_repo *const repo_, volatile sqlite3 *db) { + RETURN_UNLESS(db, "Invalid argument", 1); if (!curl_init) { curl_global_init(CURL_GLOBAL_ALL); curl_init = 1; @@ -61,19 +62,24 @@ repo_new(struct lkt_repo *const repo_, const char *name_, const char *url_, vola ++curl_init; struct lkt_repo repo = { - /* Just the 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", // TODO - .kara_dir = "/home/kara/", // TODO .version = 1, - - /* The db */ .db = db, + .name = safe_zero_malloc(INI_MAX_LINE_LEN * sizeof(char)), + .kara_dir = safe_zero_malloc(PATH_MAX * sizeof(char)), + .get_id_json = safe_zero_malloc(URL_MAX_LEN * sizeof(char)), + .get_id_file = safe_zero_malloc(URL_MAX_LEN * sizeof(char)), + .get_all_json = safe_zero_malloc(URL_MAX_LEN * sizeof(char)), + .base_url = safe_zero_malloc(URL_MAX_LEN * sizeof(char)), }; + /* Copies */ + if (!database_config_get_text(db, "database", "kara_dir", repo.kara_dir, PATH_MAX - 1) || + !database_config_get_text(db, "repo", "name", repo.name, INI_MAX_LINE_LEN) || + !database_config_get_text(db, "repo", "url", repo.base_url, URL_MAX_LEN) || + !database_config_get_text(db, "repo", "id_json", repo.get_id_json, URL_MAX_LEN) || + !database_config_get_text(db, "repo", "id_kara", repo.get_id_file, URL_MAX_LEN) || + !database_config_get_text(db, "repo", "json", repo.get_all_json, URL_MAX_LEN)) + return 1; memcpy(repo_, &repo, sizeof(struct lkt_repo)); return 0; } @@ -85,6 +91,11 @@ repo_free(struct lkt_repo *const repo) --curl_init; if (!curl_init) curl_global_cleanup(); + free(repo->kara_dir); + free(repo->get_id_json); + free(repo->get_id_file); + free(repo->base_url); + free(repo->get_all_json); } int @@ -137,11 +148,9 @@ int __json_sync(struct lkt_repo *const repo, struct json_object **json) { RETURN_UNLESS(json, "Invalid argument", 1); - CURL *curl_handle; CURLcode res; int ret = 1; - struct memory file = { .mem = NULL, .size = 0. @@ -170,14 +179,12 @@ err: int repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata *mdt) { + RETURN_UNLESS(mdt, "Invalid argument", 1); CURL *curl_handle; CURLcode res; struct json_object *jobj, *field; int ret = 1, err = 0; char url[URL_MAX_LEN]; - - RETURN_UNLESS(mdt, "Invalid argument", 1); - struct memory file = { .mem = NULL, .size = 0, @@ -203,41 +210,19 @@ repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata /* Read the json. */ jobj = json_tokener_parse(file.mem); - if (json_object_object_get_ex(jobj, "message", &field)) { LOG_ERROR("Kara with id %lu not found, message is: %s", id, json_object_get_string(field)); goto err; } LOG_INFO("Got kara with id %lu", 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)) { - LOG_ERROR("%s", "No object with key 'song_number' in json, error"); - goto err; - } - - mdt->song_number = json_object_get_int(field); - - if (errno == EINVAL) { - LOG_ERROR("%s", "Invalid integer for field with key 'song_number'"); - goto err; - } - - if (mdt->song_number == INT32_MAX || mdt->song_number == INT32_MIN) { - LOG_ERROR("Out of bound int32_t '%d' for field with key 'song_number'", mdt->song_number); - goto err; - } - - + 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); + GOTO_IF(err || safe_json_get_int32(jobj, "song_number", &mdt->song_number), "Invalid json", err); ret = 0; err: json_object_put(jobj); /* Delete object. */ @@ -337,7 +322,7 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec size_t i, len = json_object_array_length(json); struct json_object *kara_json; int32_t integer, err; - struct kara *kara; + struct kara kara; char url[URL_MAX_LEN]; long filestamp, timestamp; RETURN_UNLESS(len > 0 && json_object_get_array(json), "Json invalid or array empty", NOTHING); @@ -345,74 +330,61 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec LOG_INFO_SCT("REPO", "Starting to process json for repo %s", repo->name); for (i = 0; i < len; ++i) { kara_json = json_object_array_get_idx(json, i); - kara = calloc(1, sizeof(struct kara)); - RETURN_UNLESS(kara, "Out of memory", NOTHING); err = 0; /* Get the id of the kara. */ if (safe_json_get_int32(kara_json, "id", &integer)) continue; - kara->id = integer; + kara.id = integer; /* Craft a fake filepath here, it will be used later. */ size_t kara_dir_len = strlen(repo->kara_dir); - memcpy(kara->filename, repo->kara_dir, sizeof(char) * (kara_dir_len + 1)); - if (kara->filename[kara_dir_len - 1] != '/') { - strncat(kara->filename, "/", PATH_MAX - 1); - kara->filename[++kara_dir_len] = 0; + memcpy(kara.filename, repo->kara_dir, sizeof(char) * (kara_dir_len + 1)); + if (kara.filename[kara_dir_len - 1] != '/') { + strncat(kara.filename, "/", PATH_MAX - 1); + kara.filename[++kara_dir_len] = 0; } - safe_snprintf(kara->filename + kara_dir_len, PATH_MAX - kara_dir_len, "%d.mkv", integer); - LOG_INFO_SCT("REPO", "Crafted filename is '%s'", kara->filename); + safe_snprintf(kara.filename + kara_dir_len, PATH_MAX - kara_dir_len, "%d.mkv", integer); /* Timestamp verification */ if (safe_json_get_long(kara_json, "unix_timestamp", ×tamp)) continue; - filestamp = get_mtime(kara->filename); - if (database_get_timestamp(db) < filestamp) { - LOG_WARN_SCT("REPO", "Kara file %s is more recent than database timestamp, download it", kara->filename); - goto do_it; - } - if (filestamp > timestamp) { - LOG_INFO_SCT("REPO", "Ignore kara '%ld', last timestamp was %ld, new is %ld", kara->id, filestamp, timestamp); + filestamp = get_mtime(kara.filename); + if (database_get_timestamp(db) >= filestamp && filestamp > timestamp) { + LOG_INFO_SCT("REPO", "Ignore kara '%ld' with path '%s'", kara.id, kara.filename); continue; } -do_it: - - err |= safe_json_get_string(kara_json, "song_name", kara->mdt.song_name, LEKTOR_TAG_MAX); - err |= safe_json_get_string(kara_json, "source_name", kara->mdt.source_name, LEKTOR_TAG_MAX); - err |= safe_json_get_string(kara_json, "category", kara->mdt.category, LEKTOR_TAG_MAX); - err |= safe_json_get_string(kara_json, "language", kara->mdt.language, LEKTOR_TAG_MAX); - err |= safe_json_get_string(kara_json, "author_name", kara->mdt.author_name, LEKTOR_TAG_MAX); - err |= safe_json_get_string(kara_json, "song_type", kara->mdt.song_type, LEKTOR_TAG_MAX); - GOTO_IF(err, "Invalid json", err); - - if (safe_json_get_int32(kara_json, "song_number", &kara->mdt.song_number)) - goto err; - - if (!database_update_add((sqlite3 *) db, kara->filename, &kara->mdt, kara->id, false)) { - LOG_ERROR_SCT("REPO", "Could not add unavailable kara %ld to db", kara->id); + LOG_WARN_SCT("REPO", "Download kara '%ld' with path '%s'", kara.id, kara.filename); + + err |= safe_json_get_string(kara_json, "song_name", kara.mdt.song_name, LEKTOR_TAG_MAX); + err |= safe_json_get_string(kara_json, "source_name", kara.mdt.source_name, LEKTOR_TAG_MAX); + err |= safe_json_get_string(kara_json, "category", kara.mdt.category, LEKTOR_TAG_MAX); + err |= safe_json_get_string(kara_json, "language", kara.mdt.language, LEKTOR_TAG_MAX); + err |= safe_json_get_string(kara_json, "author_name", kara.mdt.author_name, LEKTOR_TAG_MAX); + err |= safe_json_get_string(kara_json, "song_type", kara.mdt.song_type, LEKTOR_TAG_MAX); + RETURN_IF(err || safe_json_get_int32(kara_json, "song_number", &kara.mdt.song_number), + "Invalid json", NOTHING); + + if (!database_update_add((sqlite3 *) db, kara.filename, &kara.mdt, kara.id, false)) { + LOG_ERROR_SCT("REPO", "Could not add unavailable kara %ld to db", kara.id); continue; } - safe_snprintf(url, URL_MAX_LEN, repo->get_id_file, kara->id); + safe_snprintf(url, URL_MAX_LEN, repo->get_id_file, kara.id); - if (__download_kara(url, kara->filename, true)) { - LOG_WARN_SCT("REPO", "Could not download kara %ld at path '%s'", kara->id, kara->filename); + if (__download_kara(url, kara.filename, true)) { + LOG_WARN_SCT("REPO", "Could not download kara %ld at path '%s'", kara.id, kara.filename); continue; } - if (!database_update_set_available((sqlite3 *) db, kara->id)) { - LOG_WARN_SCT("REPO", "Could not set kara %ld available", kara->id); + if (!database_update_set_available((sqlite3 *) db, kara.id)) { + LOG_WARN_SCT("REPO", "Could not set kara %ld available", kara.id); continue; } database_stamp(db); - - LOG_INFO_SCT("REPO", "Added kara %ld from repo %s, filepath is %s", kara->id, repo->name, kara->filename); + LOG_INFO_SCT("REPO", "Added kara %ld from repo %s, filepath is %s", kara.id, repo->name, kara.filename); } - -err: - free(kara); } void * @@ -421,7 +393,7 @@ __repo_get_all_id_async(void *arg) struct json_object *json; struct lkt_repo *const repo = arg; LOG_INFO_SCT("REPO", "Download kara list from %s (%s), directory is %s", - repo->name, repo->base_url, repo->kara_dir); + repo->name, repo->get_all_json, repo->kara_dir); __json_sync(repo, &json); __handle_got_json(repo->db, repo, json); LOG_INFO_SCT("REPO", "%s", "Finished to download and insert kara list"); diff --git a/src/net/listen.c b/src/net/listen.c index 84ec3db308ef37eaa5a69c25adb0c7eca123369e..a31deb4425083a4274d3bd33b79f796b34d8f341 100644 --- a/src/net/listen.c +++ b/src/net/listen.c @@ -738,9 +738,9 @@ lkt_listen(void) if (autoclear) database_queue_clear(srv.db); - RETURN_IF (repo_new(&srv.repo, "kurisu", "https://kurisu.iiens.net", srv.db), "Failed to create repo", 4); - RETURN_UNLESS(load_module_by_name(srv.db, player_mod, &srv.win), "Can't load module", 3); - RETURN_UNLESS(srv.win.new(&srv.win), "Can't create window", 3); + RETURN_IF (repo_new(&srv.repo, srv.db), "Failed to create repo", 4); + RETURN_UNLESS(load_module_by_name(srv.db, player_mod, &srv.win), "Can't load module", 3); + RETURN_UNLESS(srv.win.new(&srv.win), "Can't create window", 3); srv.win.attach(&srv.win, &srv); for (;;) {