diff --git a/inc/common/common.h b/inc/common/common.h index 501996fc78aba176e750d2d641b9033bde8bcfdb..074fd87b94972d8a69b397bbd103ee3202cf7da9 100644 --- a/inc/common/common.h +++ b/inc/common/common.h @@ -36,3 +36,5 @@ char *trim(char *str, size_t len, char c); int get_stdin_line(const char *prompt, char *buf, size_t len); int read_self_exe(char *path, size_t len); + +int safe_snprintf(char *dest, const size_t max_len, const char *format, ...); diff --git a/inc/common/macro.h b/inc/common/macro.h index cc89cf2431af3263d8c6aa0eba34bf5e531d3d35..cb3393ec5df88049776bc6a641be6e34b1316e1d 100644 --- a/inc/common/macro.h +++ b/inc/common/macro.h @@ -169,3 +169,6 @@ typedef volatile enum { #define SQLITE_DO_ROLLBACK(db) \ sqlite3_exec((sqlite3 *) db, "ROLLBACK TRANSACTION;\n", NULL, NULL, NULL); + +#define STR_MATCH(str1, str2) (! strcasecmp(str1, str2)) +#define STR_NMATCH(str1, str2, n) (! strncasecmp(str1, str2, n)) diff --git a/inc/lektor/commands.h b/inc/lektor/commands.h index ba3cb7af0435577c45810c65413a68aaa5db95e2..53067fe5f6c6752625b7d1d1e0bc08dae8444828 100644 --- a/inc/lektor/commands.h +++ b/inc/lektor/commands.h @@ -28,7 +28,8 @@ bool command_stop (volatile sqlite3 *db, struct lkt_win *win, bool command_set_pos(volatile sqlite3 *db, struct lkt_win *win, mpd_idle_flag *watch_mask_ptr, int index); /* The queue */ -bool command_add (volatile sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr, int priority); +bool command_add (volatile sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr, + int priority); bool command_addid (volatile sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr); bool command_del (volatile sqlite3 *db, struct lkt_win *win, char *pos_range, mpd_idle_flag *watch_mask_ptr); bool command_delid (volatile sqlite3 *db, struct lkt_win *win, char *id, mpd_idle_flag *watch_mask_ptr); @@ -60,7 +61,7 @@ bool command_noidle(struct lkt_state *srv, size_t c); /* Find and send karas in the db that match the search expression */ bool command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], long continuation, - bool (*init)(volatile sqlite3 *, char *, char *, struct lkt_search *)); + bool (*init)(volatile sqlite3 *, struct lkt_search *)); /* Set options for the lektor such as `random`, `single`, `repeat`, etc */ enum lkt_playback_option { diff --git a/inc/lektor/database.h b/inc/lektor/database.h index 4da2d086ac7ee9ca666078a5a341594198ef4f21..2923dc854a8616e850d06b0eca577cbec253440f 100644 --- a/inc/lektor/database.h +++ b/inc/lektor/database.h @@ -96,6 +96,9 @@ struct lkt_search { const char *name; /* Stickers and playlists */ int st_value; /* The value of a sticker */ int st_uri; /* URI of a sticker */ + char st_op; /* Comparaison operator for stickers */ + char *st_type; /* Type of sticker */ + char *ka_rgx; /* Regex for the content of the selected column */ }; typedef bool (*lkt_search_init_add_func)(volatile sqlite3 *, struct lkt_uri *, int); @@ -103,9 +106,9 @@ typedef bool (*lkt_search_database_func)(struct lkt_state *srv, size_t c, int id typedef bool (*lkt_search_queue_func) (struct lkt_state *srv, size_t c, int id, int id_len, const char *row); typedef bool (*lkt_search_sticker_func) (struct lkt_state *srv, size_t c, const char *sticker, const char *type, int uri, int value); -bool database_search_database_init(volatile sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret); -bool database_search_queue_init (volatile sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret); -bool database_search_sticker_init (volatile sqlite3 *db, char *type, char *name, struct lkt_search *ret); +bool database_search_database_init(volatile sqlite3 *db, struct lkt_search *ret); +bool database_search_queue_init (volatile sqlite3 *db, struct lkt_search *ret); +bool database_search_sticker_init (volatile sqlite3 *db, struct lkt_search *ret); bool database_search_iter(struct lkt_search *item); /* Next and prev operation on the queue. */ @@ -147,17 +150,7 @@ bool database_user_authentificate(volatile sqlite3 *db, const char *password); bool database_user_add(volatile sqlite3 *db, const char *username, const char *password); /* Stickers manipulations. */ -struct sticker_callback { - struct lkt_state *srv; - size_t c; - int uri, value, is_ok; - const char *name; - bool (*call)(void *args, const char *sticker, const char *type, int uri, int value); -}; - bool database_sticker_create (volatile sqlite3 *db, const char *name); bool database_sticker_delete (volatile sqlite3 *db, const char *name); bool database_sticker_delete_specify(volatile sqlite3 *sb, const char *type, int uri, const char *name); -bool database_sticker_list (volatile sqlite3 *db, const char *type, struct sticker_callback *call); bool database_sticker_set (volatile sqlite3 *db, const char *type, const char *name, int uri, int value); -bool database_sticker_get (volatile sqlite3 *db, const char *type, const char *name, int uri, struct sticker_callback *call); diff --git a/scripts/init.sql b/scripts/init.sql index 040b0ff1005adb785082cc1a462f9e2436df7318..d4e3e1c3c422e4be0017a0f470a40ef6b6e760b6 100644 --- a/scripts/init.sql +++ b/scripts/init.sql @@ -3,7 +3,6 @@ PRAGMA encoding = 'UTF-8'; PRAGMA recursive_triggers = true; PRAGMA foreign_keys = true; - -- Definition of a kara CREATE TABLE IF NOT EXISTS kara @@ -98,6 +97,7 @@ INSERT OR REPLACE INTO users (username, password) VALUES ('sakura', 'hashire'); -- Used to implement the stickers MPD functionnality, documentation can be found -- here: https://www.musicpd.org/doc/html/protocol.html#stickers. Need to be -- authentified to use stickers commands. Support tags for `song` and `plt`. +-- URIs in stickers are kara/playlist IDs. CREATE TABLE IF NOT EXISTS 'stickers' ( id INTEGER PRIMARY KEY diff --git a/src/commands.c b/src/commands.c index 4e2b1a5b585ca60cc51a95184d2eca6f70f1671a..f1f3843d91069f1bed7874a3234fed2620635877 100644 --- a/src/commands.c +++ b/src/commands.c @@ -84,15 +84,15 @@ command_currentsong(struct lkt_state *srv, size_t c) LOG_ERROR_SCT("COMMAND", "%s", "Failed to get information about the current kara"); out = lkt_message_new(); - idx = snprintf(out->data, LKT_MESSAGE_MAX, + 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.category, - kara.song_number, kara.song_type, kara.language); + 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); @@ -119,7 +119,7 @@ command_status(struct lkt_state *srv, size_t c) play_state = queue_state.current <= 0 ? "stop" : (queue_state.paused ? "pause" : "play"); - out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, + out->data_len = safe_snprintf(out->data, LKT_MESSAGE_MAX, "volume: %d\n" "repeat: %d\n" "random: %d\n" @@ -312,10 +312,8 @@ bool command_help(struct lkt_state *srv, size_t c) { struct lkt_message *out; - int idx; out = lkt_message_new(); - idx = snprintf(out->data, LKT_MESSAGE_MAX, "HELP\n"); - out->data_len = idx; + out->data_len = safe_snprintf(out->data, LKT_MESSAGE_MAX, "HELP\n"); lkt_state_send(srv, c, out); return true; } @@ -329,29 +327,29 @@ command_idle(struct lkt_state *srv, size_t c, struct lkt_command *cmd) for (size_t i = 0; cmd->args[i]; ++i) { once |= true; - if (strcmp(cmd->args[i], "database") == 0) + if (STR_MATCH(cmd->args[i], "database")) *clt_mask |= MPD_IDLE_DATABASE; - else if (strcmp(cmd->args[i], "update") == 0) + else if (STR_MATCH(cmd->args[i], "update")) *clt_mask |= MPD_IDLE_UPDATE; - else if (strcmp(cmd->args[i], "stored_playlist") == 0) + else if (STR_MATCH(cmd->args[i], "stored_playlist")) *clt_mask |= MPD_IDLE_STORED_PLAYLIST; - else if (strcmp(cmd->args[i], "playlist") == 0) + else if (STR_MATCH(cmd->args[i], "playlist")) *clt_mask |= MPD_IDLE_PLAYLIST; - else if (strcmp(cmd->args[i], "player") == 0) + else if (STR_MATCH(cmd->args[i], "player")) *clt_mask |= MPD_IDLE_PLAYER; - else if (strcmp(cmd->args[i], "mixer") == 0) + else if (STR_MATCH(cmd->args[i], "mixer")) *clt_mask |= MPD_IDLE_MIXER; - else if (strcmp(cmd->args[i], "output") == 0) + else if (STR_MATCH(cmd->args[i], "output")) *clt_mask |= MPD_IDLE_OUTPUT; - else if (strcmp(cmd->args[i], "options") == 0) + else if (STR_MATCH(cmd->args[i], "options")) *clt_mask |= MPD_IDLE_OPTIONS; - else if (strcmp(cmd->args[i], "partition") == 0) + else if (STR_MATCH(cmd->args[i], "partition")) *clt_mask |= MPD_IDLE_PARTITION; - else if (strcmp(cmd->args[i], "sticker") == 0) + else if (STR_MATCH(cmd->args[i], "sticker")) *clt_mask |= MPD_IDLE_STICKER; - else if (strcmp(cmd->args[i], "subscription") == 0) + else if (STR_MATCH(cmd->args[i], "subscription")) *clt_mask |= MPD_IDLE_SUBSCRIPTION; - else if (strcmp(cmd->args[i], "message") == 0) + else if (STR_MATCH(cmd->args[i], "message")) *clt_mask |= MPD_IDLE_MESSAGE; else *clt_mask = MPD_IDLE_ALL; @@ -380,7 +378,7 @@ lkt_callback_send_row_v1(void *_args, int pos_len, int pos, int id, int id_len, struct lkt_callback *args = (struct lkt_callback *) _args; struct lkt_message *out; out = lkt_message_new(); - out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "%*d: %*d %s\n", pos_len, pos, id_len, id, sql_row); + out->data_len = safe_snprintf(out->data, LKT_MESSAGE_MAX, "%*d: %*d %s\n", pos_len, pos, id_len, id, sql_row); lkt_state_send(args->srv, args->c, out); return true; } @@ -389,16 +387,16 @@ bool lkt_callback_send_row_v2(struct lkt_state *srv, size_t c, int id, int id_len, const char *sql_row) { struct lkt_message *out = lkt_message_new(); - out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "%*d %s\n", id_len, id, sql_row); + out->data_len = safe_snprintf(out->data, LKT_MESSAGE_MAX, "%*d %s\n", id_len, id, sql_row); lkt_state_send(srv, c, out); return true; } bool command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], long continuation, - bool(*init)(volatile sqlite3 *, char *, char *, struct lkt_search *)) + bool(*init)(volatile sqlite3 *, struct lkt_search *)) { - char rgx[PATH_MAX], *col_name, *mpd_tag; + char rgx[PATH_MAX], *mpd_tag; int count; struct lkt_search search = { .srv = srv, @@ -406,6 +404,7 @@ command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MA .continuation = continuation, .msg_count = lkt_remaining_msg(srv, c) - 3, /* Reserve slots for OK/ACK and continue: */ .call = (void(*)(void)) lkt_callback_send_row_v2, + .ka_rgx = rgx, }; /* Check args */ @@ -413,20 +412,26 @@ command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MA /* Select the right column */ mpd_tag = cmd_args[0]; - if (!strcasecmp("any", mpd_tag) || !strcasecmp("all", mpd_tag) || !strcasecmp("query", mpd_tag) || - !strcasecmp("source", mpd_tag) || !strcasecmp("title", mpd_tag)) { - col_name = LKT_DATABASE_KARA_COLUMNT_ANY; - } else if (!strcasecmp("author", mpd_tag)) { - col_name = LKT_DATABASE_NAME_KAUTHOR; - } else if (!strcasecmp("category", mpd_tag) || !strcasecmp("cat", mpd_tag)) { - col_name = LKT_DATABASE_NAME_KCAT; - } else if (!strcasecmp("type", mpd_tag)) { - col_name = LKT_DATABASE_NAME_KTYPE; - } else if (!strcasecmp("language", mpd_tag) || !strcasecmp("lang", mpd_tag)) { - col_name = LKT_DATABASE_NAME_KLANG; - } else if (!strcasecmp("id", mpd_tag)) { - col_name = LKT_DATABASE_NAME_KID; - } else + if (STR_MATCH("any", mpd_tag) || STR_MATCH("all", mpd_tag) || STR_MATCH("query", mpd_tag) || + STR_MATCH("source", mpd_tag) || STR_MATCH("title", mpd_tag)) + search.name = LKT_DATABASE_KARA_COLUMNT_ANY; + + else if (STR_MATCH("author", mpd_tag)) + search.name = LKT_DATABASE_NAME_KAUTHOR; + + else if (STR_MATCH("category", mpd_tag) || STR_MATCH("cat", mpd_tag)) + search.name = LKT_DATABASE_NAME_KCAT; + + else if (STR_MATCH("type", mpd_tag)) + search.name = LKT_DATABASE_NAME_KTYPE; + + else if (STR_MATCH("language", mpd_tag) || STR_MATCH("lang", mpd_tag)) + search.name = LKT_DATABASE_NAME_KLANG; + + else if (STR_MATCH("id", mpd_tag)) + search.name = LKT_DATABASE_NAME_KID; + + else return false; /* Get the regex */ @@ -440,7 +445,7 @@ command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MA } /* Make the search langand do the right action */ - RETURN_UNLESS(init(srv->db, col_name, rgx, &search), "Failed to init search", false); + RETURN_UNLESS(init(srv->db, &search), "Failed to init search", false); for (count = 0; database_search_iter(&search); ++count) continue; @@ -713,82 +718,11 @@ command_user_add(struct lkt_state *srv, size_t c, volatile sqlite3 *db, char *ar /* Stickers */ static bool -sticker_send_one_value(void *_args, const char *sticker, const char *type, int uri, int value) -{ - UNUSED(sticker, type, uri); - struct sticker_callback *args = (struct sticker_callback *) _args; - struct lkt_message *out = lkt_message_new(); - out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "value: %d\n", value); - lkt_state_send(args->srv, args->c, out); - return false; -} - -static bool -sticker_send_all(void *_args, const char *sticker, const char *type, int uri, int value) -{ - struct sticker_callback *args = (struct sticker_callback *) _args; - struct lkt_message *out = lkt_message_new(); - out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "%s: %d\nsticker: %s\nvalue: %d\n", - type, uri, sticker, value); - lkt_state_send(args->srv, args->c, out); - return true; -} - -static bool -sticker_send_check_uri(void *_args, const char *sticker, const char *type, int uri, int value) -{ - struct sticker_callback *args = (struct sticker_callback *) _args; - UNUSED(type); - - if (uri == args->uri) { - struct lkt_message *out = lkt_message_new(); - out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "%s: %d\n", sticker, value); - lkt_state_send(args->srv, args->c, out); - } - - return true; -} - -static bool -sticker_send_value_check_uri_name(void *_args, const char *sticker, const char *type, int uri, int value) -{ - struct sticker_callback *args = (struct sticker_callback *) _args; - struct lkt_message *out; - UNUSED(type); - - if (uri == args->uri || !strcasecmp(sticker, args->name)) { - out = lkt_message_new(); - out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "value: %d\n", value); - lkt_state_send(args->srv, args->c, out); - } - - return true; -} - -static bool -sticker_check_is_present_eq(void *_args, const char *sticker, const char *type, int uri, int value) -{ - UNUSED(type); - struct sticker_callback *args = (struct sticker_callback *) _args; - args->is_ok |= (uri == args->uri) && !strcasecmp(sticker, args->name) && (value == args->value); - return true; -} - -static bool -sticker_check_is_present_lt(void *_args, const char *sticker, const char *type, int uri, int value) -{ - UNUSED(type); - struct sticker_callback *args = (struct sticker_callback *) _args; - args->is_ok |= (uri == args->uri) && !strcasecmp(sticker, args->name) && (value < args->value); - return true; -} - -static bool -sticker_check_is_present_gt(void *_args, const char *sticker, const char *type, int uri, int value) +sticker_send(struct lkt_state *srv, size_t c, char *name, int id, int value) { - UNUSED(type); - struct sticker_callback *args = (struct sticker_callback *) _args; - args->is_ok |= (uri == args->uri) && !strcasecmp(sticker, args->name) && (value > args->value); + struct lkt_message *msg = lkt_message_new(); + msg->data_len = safe_snprintf(msg->data, LKT_MESSAGE_ARGS_MAX, "%d: %s . %d", id, name, value); + lkt_state_send(srv, c, msg); return true; } @@ -796,16 +730,22 @@ bool command_sticker_get(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]) { RETURN_UNLESS(argv[0] && argv[1] && argv[2] && !argv[3], "Invalid argument", false); - int uri, err; - char *endptr; + long uri; + char *endptr, err; STRTOL(uri, argv[1], endptr, err); RETURN_IF(err, "STRTOL failed", false); - struct sticker_callback cb = { + struct lkt_search cb = { + .call = (void(*)(void)) sticker_send, .srv = srv, .c = c, - .call = sticker_send_one_value, + .name = argv[2], + .st_type = argv[0], + .st_uri = (int) uri, }; - RETURN_UNLESS(database_sticker_get(srv->db, argv[0], argv[2], uri, &cb), "Failed to get sticker", false); + if (!database_search_sticker_init(srv->db, &cb)) + return false; + while (database_search_iter(&cb)) + continue; return true; } @@ -827,66 +767,54 @@ command_sticker_set(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS bool command_sticker_list(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]) { - struct sticker_callback callback = { + struct lkt_search callback = { .srv = srv, .c = c, + .call = (void(*)(void)) sticker_send, + .st_type = argv[0], }; /* Simple list {type} {uri} command */ - if (argv[0] != NULL && argv[1] != NULL && argv[2] == NULL) - goto simple_list_command; + if (argv[0] != NULL && argv[1] != NULL && argv[2] == NULL) { + callback.st_uri = atoi(argv[1]); + if (database_search_sticker_init(srv->db, &callback)) + goto iter; + } /* list {type} {uri} {name} command */ else if (argv[0] != NULL && argv[1] != NULL && - argv[2] != NULL && argv[3] == NULL) - goto list_stickers_in_uri; + argv[2] != NULL && argv[3] == NULL) { + callback.name = argv[2]; + callback.st_uri = atoi(argv[1]); + if (database_search_sticker_init(srv->db, &callback)) + goto iter; + } /* list {type} {uri} {name} `op` {value} command */ else if (argv[0] != NULL && argv[1] != NULL && argv[2] != NULL && argv[3] != NULL && - argv[4] != NULL && argv[5] == NULL) - goto list_stickers_check_value; + argv[4] != NULL && argv[5] == NULL) { + callback.name = argv[2]; + callback.st_uri = atoi(argv[1]); + callback.st_op = argv[3][0]; + callback.st_value = atoi(argv[4]); + if (database_search_sticker_init(srv->db, &callback)) + goto iter; + } /* Just list all stickers */ - else if ( (argv[0] != NULL && argv[1] == NULL) || argv[0] == NULL ) - goto just_list_all; + else if ( (argv[0] != NULL && argv[1] == NULL) || argv[0] == NULL ) { + if (database_search_sticker_init(srv->db, &callback)) + goto iter; + } else goto unknown; -just_list_all: - callback.call = sticker_send_all; - return database_sticker_list(srv->db, argv[0], &callback); - -simple_list_command: - callback.uri = atoi(argv[1]); /* FIXME: Use strtol. */ - callback.call = sticker_send_check_uri; - return database_sticker_list(srv->db, argv[0], &callback); - -list_stickers_in_uri: - callback.uri = atoi(argv[1]); /* FIXME: Use strtol. */ - callback.name = argv[2]; - callback.call = sticker_send_value_check_uri_name; - return database_sticker_list(srv->db, argv[0], &callback); - return false; - -list_stickers_check_value: - callback.uri = atoi(argv[1]); /* FIXME: Use strtol. */ - callback.value = atoi(argv[4]); /* FIXME: Use strtol. */ - callback.name = argv[2]; - switch (argv[3][0]) { - case '=': - callback.call = sticker_check_is_present_eq; - return database_sticker_list(srv->db, argv[0], &callback); - case '<': - callback.call = sticker_check_is_present_lt; - return database_sticker_list(srv->db, argv[0], &callback); - case '>': - callback.call = sticker_check_is_present_gt; - return database_sticker_list(srv->db, argv[0], &callback); - default: - return 0; - } +iter: + while (database_search_iter(&callback)) + continue; + return true; unknown: LOG_ERROR_SCT("COMMAND", "%s", "Specified command is invalid or unknown"); diff --git a/src/common.c b/src/common.c index f301ac07491d5fc6ca53711aae491f1987c91276..636bf3d5459a7f8a8810b99c27418ef7994f60c7 100644 --- a/src/common.c +++ b/src/common.c @@ -5,6 +5,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stdarg.h> #include <sys/stat.h> void @@ -157,3 +158,14 @@ read_self_exe(char *path, size_t len) (readlink(SELF_EXECUTABLE_FREEBSD, path, len - 1) > 0) || (readlink(SELF_EXECUTABLE_SOLARIS, path, len - 1) > 0); } + +int +safe_snprintf(char *dest, const size_t max_len, const char *format, ...) +{ + va_list ap; + va_start(ap, format); + int ret = vsnprintf(dest, max_len, format, ap); + dest[max_len - 1] = '\0'; + va_end(ap); + return ret; +} diff --git a/src/database/config.c b/src/database/config.c index 00c82c62750cafcf78cfb4fa33f35e0c4738abe9..eb09db8541c459fc983e2f50da364853b18380fd 100644 --- a/src/database/config.c +++ b/src/database/config.c @@ -119,8 +119,7 @@ database_config_queue(volatile sqlite3 *db, const char *option, int value) if (value > 100) value = 100; - snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL_STMT_TMP, option); - SQL_STMT[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + safe_snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT, SQL_STMT_TMP, option); SQLITE_PREPARE(db, stmt, SQL_STMT, error); SQLITE_BIND_INT(db, stmt, 1, value, error); @@ -162,8 +161,7 @@ database_get_config(volatile sqlite3 *db, const char *option, int *value) sqlite3_stmt *stmt = 0; bool ret = false; - snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL_STMT_TMP, option); - SQL_STMT[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + safe_snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT, SQL_STMT_TMP, option); SQLITE_PREPARE(db, stmt, SQL_STMT, error); SQLITE_STEP_ROW(db, stmt, error); *value = sqlite3_column_int(stmt, 0); diff --git a/src/database/find.c b/src/database/find.c index c95a2374aa30b9ff2ad2c5716b0f00da61c56889..8cab8488045c254566baf24ab05c845ff6fff6b3 100644 --- a/src/database/find.c +++ b/src/database/find.c @@ -9,7 +9,7 @@ #include <string.h> bool -database_search_database_init(volatile sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret) +database_search_database_init(volatile sqlite3 *db, struct lkt_search *ret) { RETURN_UNLESS(ret, "Exit because return pointer is NULL", false); static const char *SQL_STMT_TEMPLATE = @@ -22,11 +22,9 @@ database_search_database_init(volatile sqlite3 *db, char *col_name, char *rgx, s ret->type = lkt_search_database; /* Search part */ - snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL_STMT_TEMPLATE, col_name, - ret->msg_count, ret->continuation); - SQL_STMT[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + safe_snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT, SQL_STMT_TEMPLATE, ret->name, ret->msg_count, ret->continuation); SQLITE_PREPARE(db, ret->stmt, SQL_STMT, error); - SQLITE_BIND_TEXT(db, ret->stmt, 1, rgx, error); + SQLITE_BIND_TEXT(db, ret->stmt, 1, ret->ka_rgx, error); ret->db = db; return true; error: @@ -35,7 +33,7 @@ error: } bool -database_search_sticker_init(volatile sqlite3 *db, char *type, char *name, struct lkt_search *ret) +database_search_sticker_init(volatile sqlite3 *db, struct lkt_search *ret) { /* No bound checks in strcats, should be fine. Possible SQL injection, depend on the `type`. */ static const char *SQL_all_types = @@ -47,21 +45,26 @@ database_search_sticker_init(volatile sqlite3 *db, char *type, char *name, struc "ON sts.sticker = 'stickers'.id"; static const char *SQL_one_type = "SELECT name, 'stickers.%s'.id, value " - "FROM 'stickers' " + "FROM 'stickers.%s' AS sts" "LEFT OUTER JOIN 'stickers' " - "ON 'stickers'.id = 'stickers.%s'.sticker"; - static const char *SQL_check_name = " AND name = ?;"; + "ON 'stickers'.id = sts.sticker"; char SQL[LKT_MAX_SQLITE_STATEMENT]; - if (type == NULL) + if (ret->st_type == NULL) memcpy(SQL, SQL_all_types, strlen(SQL_all_types) + 1); else - sprintf(SQL, SQL_one_type, type, type); - strcat(SQL, name ? SQL_check_name : ";"); + sprintf(SQL, SQL_one_type, ret->st_type, ret->st_type); + if (ret->st_uri != 0) + sprintf(SQL, " AND sts.id = %d", ret->st_uri); + if (ret->st_op != 0) + sprintf(SQL, " AND sts.value %s %d", + ret->st_op == '>' ? ">=" : ret->st_op == '<' ? "<=" : "=", + ret->st_value); + strcat(SQL, ret->name ? " AND name = ?;" : ";"); SQLITE_PREPARE(db, ret->stmt, SQL, error); - if (name) - SQLITE_BIND_TEXT(db, ret->stmt, 1, name, error) + if (ret->name) + SQLITE_BIND_TEXT(db, ret->stmt, 1, ret->name, error) return true; error: sqlite3_finalize(ret->stmt); @@ -69,7 +72,7 @@ error: } bool -database_search_queue_init(volatile sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret) +database_search_queue_init(volatile sqlite3 *db, struct lkt_search *ret) { RETURN_UNLESS(ret, "Exit because return pointer is NULL", false); static const char *SQL_STMT_TEMPLATE = @@ -84,11 +87,9 @@ database_search_queue_init(volatile sqlite3 *db, char *col_name, char *rgx, stru ret->type = lkt_search_queue; /* Search part */ - snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL_STMT_TEMPLATE, col_name, - ret->msg_count, ret->continuation); - SQL_STMT[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + safe_snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT, SQL_STMT_TEMPLATE, ret->name, ret->msg_count, ret->continuation); SQLITE_PREPARE(db, ret->stmt, SQL_STMT, error); - SQLITE_BIND_TEXT(db, ret->stmt, 1, rgx, error); + SQLITE_BIND_TEXT(db, ret->stmt, 1, ret->ka_rgx, error); ret->db = db; return true; error: diff --git a/src/database/open.c b/src/database/open.c index 24b9fec3fcb855b49a9700cf81c4a1c71533bebc..9c28886822cbb722d6601585f31646453b383418 100644 --- a/src/database/open.c +++ b/src/database/open.c @@ -78,8 +78,7 @@ __attach(volatile sqlite3 *db, const char *name, const char *path) char SQL_ATTACH[LKT_MAX_SQLITE_STATEMENT]; bool ret = false; - snprintf(SQL_ATTACH, LKT_MAX_SQLITE_STATEMENT - 1, SQL_ATTACH_TEMPLATE, path, name); - SQL_ATTACH[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + safe_snprintf(SQL_ATTACH, LKT_MAX_SQLITE_STATEMENT, SQL_ATTACH_TEMPLATE, path, name); SQLITE_EXEC(db, SQL_ATTACH, err_no_attach); LOG_INFO_SCT("DB", "Attached database '%s' with path '%s'", name, path); ret = true; @@ -94,8 +93,7 @@ __detach(volatile sqlite3 *db, const char *name) char SQL_DETACH[LKT_MAX_SQLITE_STATEMENT]; bool ret = false; - snprintf(SQL_DETACH, LKT_MAX_SQLITE_STATEMENT - 1, SQL_DETACH_TEMPLATE, name); - SQL_DETACH[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + safe_snprintf(SQL_DETACH, LKT_MAX_SQLITE_STATEMENT, SQL_DETACH_TEMPLATE, name); SQLITE_EXEC(db, SQL_DETACH, err_no_detach); LOG_INFO_SCT("DB", "Detached database '%s'", name); ret = true; diff --git a/src/database/playlist.c b/src/database/playlist.c index 96f704f075d18d16f217122741422ef532095640..a805e47b214f86c4d35dbb9eadbd3430f6c3ac36 100644 --- a/src/database/playlist.c +++ b/src/database/playlist.c @@ -108,8 +108,7 @@ database_plt_export(volatile sqlite3 *db, const char *name) GOTO_UNLESS(strcasecmp(name, PROTECTED_DATABASE), "Name '"PROTECTED_DATABASE "' is protected, you can't use it for a playlist name", error); - snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL_SCHEM, name); - SQL_STMT[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + safe_snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT, SQL_SCHEM, name); SQLITE_PREPARE(db, stmt, SQL_STMT, error); code = sqlite3_step(stmt); @@ -141,8 +140,7 @@ database_plt_import(volatile sqlite3 *db, const char *name) GOTO_UNLESS(strcasecmp(name, PROTECTED_DATABASE), "Name '"PROTECTED_DATABASE "' is protected, you can't use it for a playlist name", error); - snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL_SCHEM, name, name, name); - SQL_STMT[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + safe_snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT, SQL_SCHEM, name, name, name); SQLITE_EXEC(db, SQL_STMT, error); ret = true; error: @@ -184,8 +182,7 @@ database_plt_add_uri(volatile sqlite3 *db, const char *name, struct lkt_uri *uri return false; } - snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL, column); - SQL_STMT[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + safe_snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT, SQL, column); SQLITE_PREPARE(db, stmt, SQL_STMT, error); SQLITE_BIND_TEXT(db, stmt, 1, name, error); SQLITE_BIND_TEXT(db, stmt, 2, (char *) uri->value, error); diff --git a/src/database/queue.c b/src/database/queue.c index 550463d5a222530896c618283294b1d6f4a7fd9d..8ff68e8410714f2e5dc0c04859ca77b7832760b5 100644 --- a/src/database/queue.c +++ b/src/database/queue.c @@ -126,8 +126,7 @@ queue_add_with_col_like_str(volatile sqlite3 *db, const char *col, const char *v SQLITE_EXEC(db, "BEGIN TRANSACTION;", error); /* Insert at the end of the queue */ - snprintf(SQL, LKT_MAX_SQLITE_STATEMENT - 1, SQL_STMT, col); - SQL[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + safe_snprintf(SQL, LKT_MAX_SQLITE_STATEMENT, SQL_STMT, col); SQLITE_PREPARE(db, stmt, SQL, error); SQLITE_BIND_INT(db, stmt, 1, priority, error); SQLITE_BIND_TEXT(db, stmt, 2, val, error); @@ -252,21 +251,21 @@ database_queue_add_uri(volatile sqlite3 *db, struct lkt_uri *uri, int priority) bool database_queue_del_id(volatile sqlite3 *db, int id) { + /* FIXME: Can't pop if its the last kara */ #define POS_OF_ID "(SELECT position FROM queue WHERE kara_id = %d)" static const char *SQL_TEMPLATE = "BEGIN TRANSACTION;" "WITH before(pos) AS (SELECT position FROM queue JOIN queue_state WHERE position < current ORDER BY position DESC LIMIT 1) " "UPDATE queue_state SET current = CASE WHEN current IS NULL THEN NULL ELSE (SELECT pos FROM before) END WHERE current > " POS_OF_ID ";" - "UPDATE queue SET position = position - 1 WHERE position > " POS_OF_ID ";" - "DELETE FROM queue WHERE kara_id = %d;" - "COMMIT TRANSACTION;"; + "UPDATE OR REPLACE queue SET position = position - 1 WHERE position > " POS_OF_ID ";" + "COMMIT;"; #undef POS_OF_ID char SQL[LKT_MAX_SQLITE_STATEMENT]; - snprintf(SQL, LKT_MAX_SQLITE_STATEMENT - 1, SQL_TEMPLATE, id, id, id, id); - SQL[LKT_MAX_SQLITE_STATEMENT - 1] = '\0'; + safe_snprintf(SQL, LKT_MAX_SQLITE_STATEMENT, SQL_TEMPLATE, id, id, id, id); SQLITE_EXEC(db, SQL, error); return true; error: + SQLITE_DO_ROLLBACK(db); return false; } @@ -295,8 +294,7 @@ database_queue_next(volatile sqlite3 *db, char filepath[PATH_MAX]) if (code == SQLITE_ROW) { id = MAX(1, sqlite3_column_int(stmt, 1)); - snprintf(SQL_UPDATE, LKT_MAX_SQLITE_STATEMENT - 1, "UPDATE queue_state SET current = %d;", id); - SQL_UPDATE[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + safe_snprintf(SQL_UPDATE, LKT_MAX_SQLITE_STATEMENT, "UPDATE queue_state SET current = %d;", id); if (filepath != NULL) strncpy(filepath, (const char *) sqlite3_column_text(stmt, 0), PATH_MAX); @@ -355,8 +353,7 @@ database_queue_prev(volatile sqlite3 *db, char filepath[PATH_MAX]) if (code == SQLITE_ROW) { id = MAX(1, sqlite3_column_int(stmt, 1)); - snprintf(SQL_UPDATE, LKT_MAX_SQLITE_STATEMENT - 1, "UPDATE queue_state SET current = %d;", id); - SQL_UPDATE[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + safe_snprintf(SQL_UPDATE, LKT_MAX_SQLITE_STATEMENT, "UPDATE queue_state SET current = %d;", id); if (filepath != NULL) strncpy(filepath, (const char *) sqlite3_column_text(stmt, 0), PATH_MAX); @@ -391,10 +388,11 @@ database_queue_clear(volatile sqlite3 *db) "DELETE FROM queue;" "DELETE FROM sqlite_sequence WHERE name = 'queue';" "UPDATE queue_state SET current = NULL;" - "COMMIT TRANSACTION;"; + "COMMIT;"; SQLITE_EXEC(db, SQL_STMT, error); return true; error: + SQLITE_DO_ROLLBACK(db); return false; } @@ -421,7 +419,7 @@ database_queue_move(volatile sqlite3 *db, int from, int to) "BEGIN TRANSACTION;" "UPDATE queue SET position = position + 1 WHERE position >= ?;" "UPDATE queue SET position = ? WHERE position = ?;" - "COMMIT TRANSACTION;"; + "COMMIT;"; sqlite3_stmt *stmt = 0; bool ret = false; int code; @@ -490,9 +488,8 @@ database_queue_set_current_index(volatile sqlite3 *db, int idx) return false; } - RETURN_IF(snprintf(SQL_GET, LKT_MAX_SQLITE_STATEMENT - 1, SQL_GET_TEMPLATE, idx) < 0, "Snprintf failed", - false); - SQL_GET[LKT_MAX_SQLITE_STATEMENT - 1] = 0; + RETURN_IF(safe_snprintf(SQL_GET, LKT_MAX_SQLITE_STATEMENT, SQL_GET_TEMPLATE, idx) < 0, + "Snprintf failed", false); SQLITE_EXEC(db, SQL_GET, error); return true; error: @@ -584,6 +581,7 @@ database_queue_shuffle(volatile sqlite3 *db) SQLITE_EXEC(db, SQL, error); return true; error: + SQLITE_DO_ROLLBACK(db); return false; } diff --git a/src/database/stickers.c b/src/database/stickers.c index 376621987d250e6819dd9feb44637f7a6e44d2ad..a0a7c7f001c9961549b5f016f6e859501e04bbe0 100644 --- a/src/database/stickers.c +++ b/src/database/stickers.c @@ -45,66 +45,6 @@ error: return ret; } -bool -database_sticker_list(volatile sqlite3 *db, const char *type, struct sticker_callback *call) -{ - const char *SQL = NULL; - int ret = false, uri, value; - sqlite3_stmt *stmt; - const char *sticker; - - if (type == NULL) - SQL = - "SELECT name, sts.id, value FROM 'stickers' LEFT OUTER JOIN " - "( SELECT id, sticker, value FROM 'stickers.song'" - " UNION" - " SELECT id, sticker, value FROM 'stickers.plt'" - ") AS sts" - "ON sts.sticker = 'stickers'.id;"; - else if (!strcasecmp(type, "plt")) - SQL = - "SELECT name, 'stickers.plt'.id, value " - "FROM 'stickers' " - "LEFT OUTER JOIN 'stickers' " - "ON 'stickers'.id = 'stickers.plt'.sticker;"; - else if (!strcasecmp(type, "song")) - SQL = - "SELECT name, 'stickers.song'.id, value " - "FROM 'stickers' " - "LEFT OUTER JOIN 'stickers' " - "ON 'stickers'.id = 'stickers.song'.sticker;"; - else { - LOG_ERROR_SCT("DB", "Type '%s' is invalid", type); - return false; - } - - SQLITE_PREPARE(db, stmt, SQL, error); - - for (;;) { - switch (sqlite3_step(stmt)) { - case SQLITE_ROW: - sticker = (const char *) sqlite3_column_text(stmt, 0); - uri = sqlite3_column_int(stmt, 1); - value = sqlite3_column_int(stmt, 2); - if (!call->call(call, sticker, type, uri, value)) - goto end_loop; - continue; - - case SQLITE_DONE: - goto end_loop; - - default: - goto error; - } - } - -end_loop: - ret = true; -error: - sqlite3_finalize(stmt); - return ret; -} - bool database_sticker_set(volatile sqlite3 *db, const char *type, const char *name, int uri, int value) { @@ -146,58 +86,6 @@ error: return ret; } -bool -database_sticker_get(volatile sqlite3 *db, const char *type, const char *name, int uri, struct sticker_callback *call) -{ - const char *SQL = NULL; - sqlite3_stmt *stmt; - int ret = false, value; - - if (!strcasecmp(type, "song")) - SQL = - "SELECT value " - "FROM 'stickers' " - "JOIN 'stickers.song'" - " ON 'stickers'.id = 'stickers.song'.sticker" - " AND 'stickers'.name = ?;\n"; - else if (!strcasecmp(type, "plt")) - SQL = - "SELECT value " - "FROM 'stickers' " - "JOIN 'stickers.plt'" - " ON 'stickers'.id = 'stickers.plt'.sticker" - " AND 'stickers'.name = ?;\n"; - else { - LOG_ERROR_SCT("DB", "Type '%s' is invalid", type); - return false; - } - - SQLITE_PREPARE(db, stmt, SQL, error); - SQLITE_BIND_TEXT(db, stmt, 1, name, error); - - for (;;) { - switch (sqlite3_step(stmt)) { - case SQLITE_ROW: - value = sqlite3_column_int(stmt, 1); - if (!call->call(call, name, type, uri, value)) - goto end_loop; - continue; - - case SQLITE_DONE: - goto end_loop; - - default: - goto error; - } - } - -end_loop: - ret = true; -error: - sqlite3_finalize(stmt); - return ret; -} - bool database_sticker_delete_specify(volatile sqlite3 *db, const char *type, int uri, const char *name) { @@ -211,9 +99,8 @@ database_sticker_delete_specify(volatile sqlite3 *db, const char *type, int uri, return false; } - snprintf(SQL, LKT_MAX_SQLITE_STATEMENT - 1, "DELETE FROM 'stickers.%s' " + safe_snprintf(SQL, LKT_MAX_SQLITE_STATEMENT, "DELETE FROM 'stickers.%s' " "WHERE 'stickers.%s' = ? ", type, type); - SQL[LKT_MAX_SQLITE_STATEMENT - 1] = 0; /* If there is a name specified. */ if (!name) { diff --git a/src/database/update.c b/src/database/update.c index cacb7badeb5217a6cf4aea91aaf457526981849d..145a60199a5eccdded3248c6c834ae3e27ab8145 100644 --- a/src/database/update.c +++ b/src/database/update.c @@ -27,7 +27,7 @@ database_add_kara(volatile sqlite3 *db, const char *filename) time_t the_time = time(NULL); struct tm *the_local_time = localtime(&the_time); char year[10]; - code = snprintf(year, 10, "%d", the_local_time->tm_year + 1900); + 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); if (kara_metadata_read(&data, filename) != 0) { @@ -89,7 +89,7 @@ database_update_add(volatile sqlite3 *db, const char *kara_path, struct kara_met time_t the_time = time(NULL); struct tm *the_local_time = localtime(&the_time); char year[10]; - code = snprintf(year, 10, "%d", the_local_time->tm_year + 1900); + code = safe_snprintf(year, 10, "%d", the_local_time->tm_year + 1900); GOTO_IF(code < 0 || code >= 10, "Failed to get the year of the current date", error_no_sqlite); /* From here we initialize the sqlite stmt. */ @@ -146,8 +146,8 @@ database_update(volatile sqlite3 *db, const char *kara_dir) } else if (dir->d_type == DT_DIR && - strcmp(dir->d_name, ".") != 0 && - strcmp(dir->d_name, "..") != 0) + !STR_MATCH(dir->d_name, ".") && + !STR_MATCH(dir->d_name, "..")) database_update(db, path); } diff --git a/src/main/lkt.c b/src/main/lkt.c index ea03894d8bd2574d6c0eb9acca7b65c1d0bafae6..87282296a414035f9f0bcbd0674441680e2e2348 100644 --- a/src/main/lkt.c +++ b/src/main/lkt.c @@ -26,8 +26,6 @@ #include <limits.h> #define LKT_KEY_VALUE_SEP ": \n\t\0" -#define STR_MATCH(str1, str2) (! strcasecmp(str1, str2)) -#define STR_NMATCH(str1, str2, n) (! strncasecmp(str1, str2, n)) #define fail_if(cond, msg) { if (cond) { LOG_ERROR("%s", msg); exit(EXIT_FAILURE); } } #define fail(msg) { LOG_ERROR("%s", msg); exit(EXIT_FAILURE); } #define lkt_send_and_exit(buffer, len) exit(write_socket(lkt_connect(), buffer, len)) @@ -61,19 +59,14 @@ static const char *LKT_QUEUE_DEFAULT[] = { "10" }; static int lkt_valid_type(const char *type) { - return (STR_MATCH(type, "all") || - STR_MATCH(type, "any") || - STR_MATCH(type, "query") || + return (STR_MATCH(type, "all") || STR_MATCH(type, "any") || STR_MATCH(type, "query") || + STR_MATCH(type, "cat") || STR_MATCH(type, "category") || + STR_MATCH(type, "author") || STR_MATCH(type, "auth") || + STR_MATCH(type, "lang") || STR_MATCH(type, "language") || STR_MATCH(type, "id") || STR_MATCH(type, "title") || STR_MATCH(type, "type") || - STR_MATCH(type, "cat") || - STR_MATCH(type, "category") || - STR_MATCH(type, "author") || - STR_MATCH(type, "auth") || - STR_MATCH(type, "source") || - STR_MATCH(type, "lang") || - STR_MATCH(type, "language")); + STR_MATCH(type, "source")); } static int @@ -82,7 +75,6 @@ read_socket(FILE *sock, char *buff, size_t max_len) size_t i, len; for (i = 0; i < max_len; ++i) { len = fread(buff + i, sizeof(char), 1, sock); - if (buff[i] == '\n' || len != 1) return i; } @@ -136,8 +128,8 @@ create_socket(const char *host, const char *port) if (cx <= 0 || connect(cx, &sock, sock_len)) exit(EXIT_FAILURE); - assert(socket_desc = fdopen(cx, "r+")); - + socket_desc = fdopen(cx, "r+"); + fail_if(!socket_desc, "Failed to connect to lektord"); return socket_desc; } @@ -150,8 +142,7 @@ lkt_connect(void) FILE *sock = create_socket(host, port); recv_len = read_socket(sock, buff, LKT_MESSAGE_MAX); - assert(recv_len > 0); - + fail_if(recv_len == 0, "Failed to connect to lektord"); return sock; } @@ -164,6 +155,20 @@ lkt_skip_key(char *buffer) return ret + len; } +static inline void +send_cmd_with_uri(FILE *sock, char *cmd, int argc, const char **argv) +{ + int i; + char buf[LKT_MESSAGE_MAX] = {0}; + for (i = 1; i < argc - 1; ++i) { + strncat(buf, argv[i], LKT_MESSAGE_MAX - 1); + strncat(buf, " ", LKT_MESSAGE_MAX - 1); + } + strncat(buf, argv[i], LKT_MESSAGE_MAX - 1); + strncat(buf, "\n", LKT_MESSAGE_MAX - 1); + (void) write_socket_format(sock, "%s %s://%s", cmd, argv[0], buf); +} + /* Functions implementing options. */ #define just_send(func, msg) /* Just send a simple string functions */ \ @@ -299,7 +304,7 @@ ping__(struct lkt_cmd_args *args) fail("Failed to send the ping to lektord"); if (read_socket(sock, buff, 6 * sizeof(char)) <= 0) fail("Failed to recieve the response of lektord"); - if (strncmp(buff, "OK", 2)) + if (!STR_NMATCH(buff, "OK", 2)) fail("ACK"); write(1, "OK\n", sizeof("OK\n")); exit(EXIT_SUCCESS); @@ -378,7 +383,7 @@ ok: noreturn void queue_pop__(struct lkt_cmd_args *args) { - fail_if(!args->argc, "Invalid argument"); + fail_if(args->argc, "Invalid argument"); int songid = 0; char buff[LKT_MESSAGE_MAX]; FILE *sock = lkt_connect(); @@ -388,7 +393,7 @@ queue_pop__(struct lkt_cmd_args *args) if (write_socket(sock, "status\n", sizeof("status\n"))) goto error; -#define assign_int(str, var) if (! strncmp(buff, str, len)) { var = (atoi(lkt_skip_key(buff))); continue; } +#define assign_int(str, var) if (STR_NMATCH(buff, str, len)) { var = (atoi(lkt_skip_key(buff))); continue; } for (;;) { memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char)); if (read_socket(sock, buff, LKT_MESSAGE_MAX - 1) <= 0) @@ -409,7 +414,8 @@ queue_pop__(struct lkt_cmd_args *args) sock = lkt_connect(); if (!songid) goto error; - exit(write_socket_format(sock, "next\ndeleteid %d\n", songid)); + write_socket_format(sock, "next\ndeleteid %d\n", songid); + exit_with_status(sock, buff); error: exit(EXIT_FAILURE); } @@ -448,8 +454,8 @@ status__(struct lkt_cmd_args *args) if (STR_NMATCH(buff, "state", len)) { char *it = lkt_skip_key(buff); - play = ! strncmp(it, "play", 4); - stopped = ! strncmp(it, "stop", 4); + play = STR_NMATCH(it, "play", 4); + stopped = STR_NMATCH(it, "stop", 4); continue; } @@ -511,20 +517,6 @@ queue_delete__(struct lkt_cmd_args *args) fail("Invalid argument"); } -static inline void -send_cmd_with_uri(FILE *sock, char *cmd, int argc, const char **argv) -{ - int i; - char buf[LKT_MESSAGE_MAX] = {0}; - for (i = 1; i < argc - 1; ++i) { - strncat(buf, argv[i], LKT_MESSAGE_MAX - 1); - strncat(buf, " ", LKT_MESSAGE_MAX - 1); - } - strncat(buf, argv[i], LKT_MESSAGE_MAX - 1); - strncat(buf, "\n", LKT_MESSAGE_MAX - 1); - (void) write_socket_format(sock, "%s %s://%s", cmd, argv[0], buf); -} - noreturn void queue_add__(struct lkt_cmd_args *args) { @@ -601,7 +593,7 @@ redo: memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char)); assert(read_socket(sock, buff, LKT_MESSAGE_MAX - 1) > 0); - if (! strncmp(buff, "continue:", strlen("continue:"))) { + if (STR_NMATCH(buff, "continue:", strlen("continue:"))) { continuation = atoi(lkt_skip_key(buff)); if (continuation > 0) { fclose(sock); @@ -646,7 +638,7 @@ queue_list__(struct lkt_cmd_args *args) if (write_socket(sock, "status\n", sizeof("status\n"))) fail("Communication error"); -#define assign_int(str, var) if (! strncmp(buff, str, len)) { var = (atoi(lkt_skip_key(buff))); continue; } +#define assign_int(str, var) if (STR_NMATCH(buff, str, len)) { var = (atoi(lkt_skip_key(buff))); continue; } for (;;) { memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char)); if (read_socket(sock, buff, LKT_MESSAGE_MAX - 1) <= 0) @@ -668,8 +660,7 @@ queue_list__(struct lkt_cmd_args *args) continuation = labs(continuation); song_index = MAX(song_index + 1, 1); - snprintf(buff, LKT_MESSAGE_MAX - 1, "%ld:%ld", song_index, song_index + continuation - 1); - buff[LKT_MESSAGE_MAX - 1] = '\0'; + safe_snprintf(buff, LKT_MESSAGE_MAX, "%ld:%ld", song_index, song_index + continuation - 1); args->argc = 1; args->argv[0] = buff; queue_pos__(args); @@ -680,27 +671,11 @@ queue_list__(struct lkt_cmd_args *args) noreturn void plt_add__(struct lkt_cmd_args *args) { - int i; char buff[2]; FILE *sock = lkt_connect(); - fail_if(args->argc < 3, "Invalid argument, need at least three arguments: plt add <plt> <query>"); fail_if(!lkt_valid_type(args->argv[1]), "Invalid argument, type for the query is invalid"); - - (void) write_socket(sock, "playlistadd ", strlen("playlistadd ")); - (void) write_socket(sock, args->argv[0], strlen(args->argv[0])); - (void) write_socket(sock, " ", sizeof(char)); - (void) write_socket(sock, args->argv[1], strlen(args->argv[1])); - (void) write_socket(sock, "://", 3 * sizeof(char)); - - for (i = 2; i < args->argc - 1; ++i) { - (void) write_socket(sock, args->argv[i], strlen(args->argv[i])); - (void) write_socket(sock, " ", sizeof(char)); - } - - /* Here we have `i == argc - 1`. */ - (void) write_socket(sock, args->argv[i], strlen(args->argv[i])); - (void) write_socket(sock, "\n", sizeof(char)); + send_cmd_with_uri(sock, "playlistadd", args->argc, args->argv); exit_with_status(sock, buff); } @@ -709,22 +684,8 @@ plt_delete__(struct lkt_cmd_args *args) { FILE *sock = lkt_connect(); char buff[2]; - int i; - fail_if(args->argc < 1, "Invalid argument"); - - (void) write_socket(sock, "playlistdelete ", strlen("playlistdelete ")); - (void) write_socket(sock, args->argv[0], strlen(args->argv[0])); - (void) write_socket(sock, " ", sizeof(char)); - - for (i = 1; i < args->argc - 1; ++i) { - (void) write_socket(sock, args->argv[i], strlen(args->argv[i])); - (void) write_socket(sock, " ", sizeof(char)); - } - - /* Here we have `i == argc - 1`. */ - (void) write_socket(sock, args->argv[i], strlen(args->argv[i])); - (void) write_socket(sock, "\n", sizeof(char)); + send_cmd_with_uri(sock, "playlistdelete", args->argc, args->argv); exit_with_status(sock, buff); } @@ -732,14 +693,9 @@ noreturn void plt_destroy__(struct lkt_cmd_args *args) { fail_if(args->argc != 1, "Invalid argument"); - FILE *sock = lkt_connect(); char buff[2]; - const char *name = args->argv[0]; - - (void) write_socket(sock, "rm ", 3 * sizeof(char)); - (void) write_socket(sock, name, strlen(name)); - (void) write_socket(sock, "\n", sizeof(char)); + write_socket_format(sock, "rm %s\n", args->argv[0]); exit_with_status(sock, buff); } @@ -750,11 +706,7 @@ plt_create__(struct lkt_cmd_args *args) FILE *sock = lkt_connect(); char buff[2]; - const char *name = args->argv[0]; - - (void) write_socket(sock, "playlistadd ", strlen("playlistadd ")); - (void) write_socket(sock, name, strlen(name)); - (void) write_socket(sock, "\n", sizeof(char)); + write_socket_format(sock, "playlistadd %s\n", args->argv[0]); exit_with_status(sock, buff); } @@ -916,16 +868,12 @@ parse_args(args_t *args, int argc, const char **argv) args->argc = argc - (got + 1); } -/* Functions that make a command happen on lektor. */ - -/* Playlist functions. */ - int main(int argc, const char **argv) { executable_name = "lkt"; - assert(NULL != setlocale(LC_ALL, "en_US.UTF-8")); /* BECAUSE! */ - assert(!signal(SIGPIPE, sigpipe__)); /* Argument checks. */ + assert(NULL != setlocale(LC_ALL, "en_US.UTF-8")); /* BECAUSE! */ + assert(!signal(SIGPIPE, sigpipe__)); args_t args = { .host = "localhost", diff --git a/src/mkv/mkv.c b/src/mkv/mkv.c index a62d536f4603c6a1e8d5c0fce12c0383e53cb0c6..fe1b6fff80086c99968c79fb866793a318fc5800 100644 --- a/src/mkv/mkv.c +++ b/src/mkv/mkv.c @@ -5,6 +5,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <strings.h> #include <unistd.h> #include <lektor/bufferfd.h> @@ -431,20 +432,20 @@ static void kara_add_simple_tag(struct kara_metadata *dst, struct mkv_simple_tag *t, uint64_t target_type_value) { - if (!strcmp("TITLE", t->name)) { + if (STR_MATCH("TITLE", t->name)) { if (target_type_value == 50) strncpy(dst->song_name, t->value, LEKTOR_TAG_MAX - 1); else if (target_type_value == 70) strncpy(dst->source_name, t->value, LEKTOR_TAG_MAX - 1); - } else if (!strcmp("CONTENT_TYPE", t->name)) + } else if (STR_MATCH("CONTENT_TYPE", t->name)) strncpy(dst->category, t->value, LEKTOR_TAG_MAX - 1); - else if (!strcmp("ADDRESS", t->name)) + else if (STR_MATCH("ADDRESS", t->name)) strncpy(dst->language, t->value, LEKTOR_TAG_MAX - 1); - else if (!strcmp("ARTIST", t->name)) + else if (STR_MATCH("ARTIST", t->name)) strncpy(dst->author_name, t->value, LEKTOR_TAG_MAX - 1); - else if (!strcmp("GENRE", t->name)) + else if (STR_MATCH("GENRE", t->name)) strncpy(dst->song_type, t->value, LEKTOR_TAG_MAX - 1); - else if (!strcmp("TRACK", t->name)) + else if (STR_MATCH("TRACK", t->name)) dst->song_number = (int) strtol(t->value, NULL, 10); } diff --git a/src/mkv/write.c b/src/mkv/write.c index c5caa8c0d45cef00fcfa3e4dc6f709487b249051..d366c6bf3dc86999c5bba1357d72b5e771efb711 100644 --- a/src/mkv/write.c +++ b/src/mkv/write.c @@ -3,6 +3,7 @@ #include <common/common.h> #include <lektor/mkv.h> +#include <strings.h> #include <stdbool.h> #include <stdio.h> #include <unistd.h> @@ -204,13 +205,13 @@ metadata_set_directory(const char *kara_dir, const char *mkvpropedit) strncat(path, "/", PATH_MAX - 1); strncat(path, dir->d_name, PATH_MAX - 1); - if (dir->d_type == DT_REG && - metadata_from_path(path, &meta) && + if (dir->d_type == DT_REG && + metadata_from_path(path, &meta) && kara_metadata_write(&meta, path, mkvpropedit)) continue; - else if (dir->d_type == DT_DIR && - strcmp(dir->d_name, ".") != 0 && - strcmp(dir->d_name, "..") != 0) + else if (dir->d_type == DT_DIR && + !STR_MATCH(dir->d_name, ".") && + !STR_MATCH(dir->d_name, "..")) metadata_set_directory(path, mkvpropedit); } diff --git a/src/module/mpv.c b/src/module/mpv.c index b29d71532d5f98becd77e64223070b5c23a43d83..3f101b9c51be6406f9bad78df40378080753b13c 100644 --- a/src/module/mpv.c +++ b/src/module/mpv.c @@ -4,6 +4,7 @@ #include <lektor/module/mpv.h> #include <lektor/commands.h> #include <lektor/database.h> +#include <strings.h> #include <stdio.h> #include <string.h> #include <unistd.h> @@ -88,7 +89,7 @@ lmpv_set_volume(mpv_handle *ctx, int vol) int status; char str[5]; memset(str, 0, 5); - snprintf(str, 4, "%d", vol); + safe_snprintf(str, 4, "%d", vol); const char *cmd[] = {"set", "ao-volume", str, NULL}; if ((status = mpv_command_async(ctx, 0, cmd)) < 0) { LOG_ERROR_SCT("WINDOW", "Failed to execute command: %s", mpv_error_string(status)); @@ -162,24 +163,24 @@ loop: if (prop->format == MPV_FORMAT_NONE) break; // MPV volume (BUG: The flag is not MPV_FORMAT_NONE only at the end of the song...) // - if (!strcmp(prop->name, "ao-volume") + if (STR_MATCH(prop->name, "ao-volume") && prop->format == MPV_FORMAT_INT64) { ao_volume = *(int *) prop->data; database_config_queue(db, "volume", ao_volume); } // File duration // - if (!strcmp(prop->name, "duration") + if (STR_MATCH(prop->name, "duration") && prop->format == MPV_FORMAT_INT64) { *time_duration = *(int *) prop->data; database_config_queue(db, "duration", *(int *) prop->data); } - if (!strcmp(prop->name, "time-pos") + if (STR_MATCH(prop->name, "time-pos") && prop->format == MPV_FORMAT_INT64) { *time_pos = *(int *) prop->data; database_config_queue(db, "elapsed", *(int *) prop->data); } // Pause state // - if (!strcmp(prop->name, "pause") + if (STR_MATCH(prop->name, "pause") && prop->format == MPV_FORMAT_FLAG) database_queue_set_paused(db, *(bool *) prop->data); break; diff --git a/src/net/downloader.c b/src/net/downloader.c index 9df9b1bae07918d97f759d4c2c93d74336d46c0e..9645a50b446424eccad001a8fae29b33cb9841e7 100644 --- a/src/net/downloader.c +++ b/src/net/downloader.c @@ -184,8 +184,7 @@ repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata }; 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; + safe_snprintf(url, URL_MAX_LEN, repo->get_id_json, id); curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle, CURLOPT_URL, url); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_mem__); @@ -315,8 +314,7 @@ repo_download_id_sync(struct lkt_repo *const repo, const uint64_t id, const char } 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; + safe_snprintf(url, URL_MAX_LEN, repo->get_id_file, id); if (__download_kara(url, kara_path, false)) { LOG_ERROR_SCT("REPO", "Failed to download kara '%s' with url '%s'", kara_path, url); @@ -363,8 +361,7 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec strncat(kara->filename, "/", PATH_MAX - 1); kara->filename[++kara_dir_len] = 0; } - snprintf(kara->filename + kara_dir_len, PATH_MAX - kara_dir_len, "%d.mkv", integer); - kara->filename[PATH_MAX - 1] = 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); /* Timestamp verification */ @@ -397,8 +394,7 @@ do_it: continue; } - snprintf(url, URL_MAX_LEN - 1, repo->get_id_file, kara->id); - url[URL_MAX_LEN - 1] = '\0'; + 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); diff --git a/src/net/listen.c b/src/net/listen.c index 0aa570f4ab740bf10aa4c14bf05b84976c4a90cb..84ec3db308ef37eaa5a69c25adb0c7eca123369e 100644 --- a/src/net/listen.c +++ b/src/net/listen.c @@ -7,6 +7,7 @@ #include <sqlite3.h> +#include <strings.h> #include <sched.h> #include <assert.h> #include <arpa/inet.h> @@ -85,8 +86,7 @@ static inline void send_continue(struct lkt_state *srv, size_t c, int i) { struct lkt_message *cont = lkt_message_new(); - cont->data_len = snprintf(cont->data, LKT_MESSAGE_MAX, "continue: %d\n", i); - cont->data[LKT_MESSAGE_MAX - 1] = '\0'; + cont->data_len = safe_snprintf(cont->data, LKT_MESSAGE_MAX, "continue: %d\n", i); lkt_state_send(srv, c, cont); } @@ -151,111 +151,111 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd) switch (*lkt_client_get_mask(srv, c)) { case MPD_IDLE_NONE: /* Commands that requires authentification. */ - if (!strcmp(cmd.name, "__adduser")) + if (STR_MATCH(cmd.name, "__adduser")) err = ! command_user_add(srv, c, (sqlite3 *) srv->db, cmd.args); - else if (!strcmp(cmd.name, "__restart")) + else if (STR_MATCH(cmd.name, "__restart")) err = ! command_restart(srv, c); - else if (!strcmp(cmd.name, "kill")) + else if (STR_MATCH(cmd.name, "kill")) err = ! command_kill(srv, c); - else if (!strcmp(cmd.name, "update")) + else if (STR_MATCH(cmd.name, "update")) err = ! command_update(srv, c, cmd.args); - else if (!strcmp(cmd.name, "rescan")) + else if (STR_MATCH(cmd.name, "rescan")) err = ! command_rescan(srv, c, cmd.args); /* Commands that are available if not in idle mode */ - else if (!strcmp(cmd.name, "currentsong")) + else if (STR_MATCH(cmd.name, "currentsong")) err = !command_currentsong(srv, c); - else if (!strcmp(cmd.name, "status")) + else if (STR_MATCH(cmd.name, "status")) err = !command_status(srv, c); - else if (!strcmp(cmd.name, "close")) + else if (STR_MATCH(cmd.name, "close")) err = !lkt_close_client(srv, c); - else if (!strcmp(cmd.name, "ping")) + else if (STR_MATCH(cmd.name, "ping")) err = 0; - else if (!strcmp(cmd.name, "next")) + else if (STR_MATCH(cmd.name, "next")) err = !command_next((sqlite3 *) srv->db, &srv->win, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "pause")) + else if (STR_MATCH(cmd.name, "pause")) err = !command_pause((sqlite3 *) srv->db, &srv->win, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "previous")) + else if (STR_MATCH(cmd.name, "previous")) err = !command_previous((sqlite3 *) srv->db, &srv->win, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "play")) + else if (STR_MATCH(cmd.name, "play")) err = ! command_play((sqlite3 *) srv->db, &srv->win, cmd.args, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "playid")) + else if (STR_MATCH(cmd.name, "playid")) err = ! command_playid((sqlite3 *) srv->db, &srv->win, cmd.args, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "stop")) + else if (STR_MATCH(cmd.name, "stop")) err = !command_stop((sqlite3 *) srv->db, &srv->win, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "clear")) + else if (STR_MATCH(cmd.name, "clear")) err = !command_clear((sqlite3 *) srv->db, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "crop")) + else if (STR_MATCH(cmd.name, "crop")) err = !command_crop((sqlite3 *) srv->db, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "moveid")) + else if (STR_MATCH(cmd.name, "moveid")) err = !command_move((sqlite3 *) srv->db, cmd.args, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "shuffle")) + else if (STR_MATCH(cmd.name, "shuffle")) err = !command_shuffle((sqlite3 *) srv->db, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "playlist") || !strcmp(cmd.name, "playlistinfo")) + else if (STR_MATCH(cmd.name, "playlist") || STR_MATCH(cmd.name, "playlistinfo")) err = !command_queue_list(srv, c, cmd.args); - else if (!strcmp(cmd.name, "playlistfind") || !strcmp(cmd.name, "playlistsearch")) + else if (STR_MATCH(cmd.name, "playlistfind") || STR_MATCH(cmd.name, "playlistsearch")) err = ! command_find(srv, c, cmd.args, cmd.cont, database_search_queue_init); - else if (!strcmp(cmd.name, "sticker") && cmd.args[0]) { - if (!strcmp(cmd.args[0], "get")) + else if (STR_MATCH(cmd.name, "sticker") && cmd.args[0]) { + if (STR_MATCH(cmd.args[0], "get")) err = ! command_sticker_get(srv, c, &cmd.args[1]); - else if (!strcmp(cmd.args[0], "set")) + else if (STR_MATCH(cmd.args[0], "set")) err = ! command_sticker_set(srv, c, &cmd.args[1]); - else if (!strcmp(cmd.args[0], "delete")) + else if (STR_MATCH(cmd.args[0], "delete")) err = ! command_sticker_delete(srv, c, &cmd.args[1]); - else if (!strcmp(cmd.args[0], "list") || !strcmp(cmd.args[0], "find")) + else if (STR_MATCH(cmd.args[0], "list") || STR_MATCH(cmd.args[0], "find")) err = ! command_sticker_delete(srv, c, &cmd.args[1]); } - else if (!strcmp(cmd.name, "help")) + else if (STR_MATCH(cmd.name, "help")) err = !command_help(srv, c); - else if (!strcmp(cmd.name, "__insert")) + else if (STR_MATCH(cmd.name, "__insert")) err = !command_add((sqlite3 *) srv->db, &srv->win, cmd.args, &srv->mpd_idle_events, 5); - else if (!strcmp(cmd.name, "searchadd") || !strcmp(cmd.name, "findadd") || !strcmp(cmd.name, "add")) + else if (STR_MATCH(cmd.name, "searchadd") || STR_MATCH(cmd.name, "findadd") || STR_MATCH(cmd.name, "add")) err = !command_add((sqlite3 *) srv->db, &srv->win, cmd.args, &srv->mpd_idle_events, 1); - else if (!strcmp(cmd.name, "addid")) + else if (STR_MATCH(cmd.name, "addid")) err = !command_addid((sqlite3 *) srv->db, &srv->win, cmd.args, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "deleteid")) + else if (STR_MATCH(cmd.name, "deleteid")) err = ! (cmd.args[0] != NULL && command_delid((sqlite3 *) srv->db, &srv->win, cmd.args[0], &srv->mpd_idle_events)); - else if (!strcmp(cmd.name, "playlistclear")) + else if (STR_MATCH(cmd.name, "playlistclear")) err = ! command_plt_clear((sqlite3 *) srv->db, cmd.args, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "rename")) + else if (STR_MATCH(cmd.name, "rename")) err = ! command_plt_rename((sqlite3 * ) srv->db, cmd.args, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "playlistdelete")) + else if (STR_MATCH(cmd.name, "playlistdelete")) err = ! command_plt_remove((sqlite3 *) srv->db, cmd.args, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "playlistadd")) + else if (STR_MATCH(cmd.name, "playlistadd")) err = ! command_plt_add((sqlite3 *) srv->db, cmd.args, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "rm") && cmd.args[0] != NULL && cmd.args[1] == NULL) + else if (STR_MATCH(cmd.name, "rm") && cmd.args[0] != NULL && cmd.args[1] == NULL) err = ! command_plt_remove((sqlite3 *) srv->db, cmd.args, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "save")) + else if (STR_MATCH(cmd.name, "save")) err = ! command_plt_export((sqlite3 *) srv->db, cmd.args, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "__import")) + else if (STR_MATCH(cmd.name, "__import")) err = ! command_plt_import((sqlite3 *) srv->db, cmd.args, &srv->mpd_idle_events); - else if (!strcmp(cmd.name, "random")) + else if (STR_MATCH(cmd.name, "random")) err = !command_set_playback_option(srv, c, lkt_playback_option_random, cmd.args); - else if (!strcmp(cmd.name, "repeat")) + else if (STR_MATCH(cmd.name, "repeat")) err = !command_set_playback_option(srv, c, lkt_playback_option_repeat, cmd.args); - else if (!strcmp(cmd.name, "setvol")) + else if (STR_MATCH(cmd.name, "setvol")) err = !command_set_playback_option(srv, c, lkt_playback_option_volume, cmd.args); - else if (!strcmp(cmd.name, "single")) + else if (STR_MATCH(cmd.name, "single")) err = !command_set_playback_option(srv, c, lkt_playback_option_single, cmd.args); - else if (!strcmp(cmd.name, "consume")) + else if (STR_MATCH(cmd.name, "consume")) err = !command_set_playback_option(srv, c, lkt_playback_option_consume, cmd.args); - else if (!strcmp(cmd.name, "password")) + else if (STR_MATCH(cmd.name, "password")) err = !command_password(srv, c, cmd.args); - else if (!strcmp(cmd.name, "idle")) { + else if (STR_MATCH(cmd.name, "idle")) { err = !command_idle(srv, c, &cmd); goto end_no_send_status; - } else if (!strcmp(cmd.name, "search") || !strcmp(cmd.name, "find")) + } else if (STR_MATCH(cmd.name, "search") || STR_MATCH(cmd.name, "find")) err = ! command_find(srv, c, cmd.args, cmd.cont, database_search_database_init); else err = 2; @@ -264,10 +264,10 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd) default: /* commands available only in idle mode */ - if (!strcmp(cmd.name, "idle")) { + if (STR_MATCH(cmd.name, "idle")) { err = !command_idle(srv, c, &cmd); goto end_no_send_status; - } else if (!strcmp(cmd.name, "noidle")) + } else if (STR_MATCH(cmd.name, "noidle")) err = !command_noidle(srv, c); else err = 2; @@ -314,11 +314,11 @@ handle_command(struct lkt_state *srv, size_t i, struct lkt_command cmd) struct lkt_client *cli = &srv->clients[i - 1]; int err = 0; - if (!strcmp(cmd.name, "command_list_begin")) + if (STR_MATCH(cmd.name, "command_list_begin")) err = command_list_begin(srv, i, 0); - else if (!strcmp(cmd.name, "command_list_ok_begin")) + else if (STR_MATCH(cmd.name, "command_list_ok_begin")) err = command_list_begin(srv, i, 1); - else if (!strcmp(cmd.name, "command_list_end")) + else if (STR_MATCH(cmd.name, "command_list_end")) err = command_list_end(srv, i); else if (cli->command_list_mode != LKT_COMMAND_LIST_OFF) cli->command_list[cli->command_list_len++] = lkt_command_clone(&cmd); diff --git a/src/uri.c b/src/uri.c index ec076ed25e67e30fc1eeb8418efffa51107092f7..4f6fe5690d2946c4e7fbe9e2a9e9f21c7ea1ea0f 100644 --- a/src/uri.c +++ b/src/uri.c @@ -98,19 +98,19 @@ __lkt_to_str(struct lkt_uri *uri, char *ret, size_t len) { switch (uri->type) { case uri_id: - snprintf(ret, len - 1, "id=%s", (char *) uri->value); + safe_snprintf(ret, len, "id=%s", (char *) uri->value); break; case uri_type: - snprintf(ret, len - 1, "type=%s", (char *) uri->value); + safe_snprintf(ret, len, "type=%s", (char *) uri->value); break; case uri_author: - snprintf(ret, len - 1, "author=%s", (char *) uri->value); + safe_snprintf(ret, len, "author=%s", (char *) uri->value); break; case uri_category: - snprintf(ret, len - 1, "cat=%s", (char *) uri->value); + safe_snprintf(ret, len, "cat=%s", (char *) uri->value); break; case uri_query: - snprintf(ret, len - 1, "search=%s", (char *) uri->value); + safe_snprintf(ret, len, "search=%s", (char *) uri->value); break; default: LOG_ERROR("URI type %d may not be supported by kurisu, generate an error", uri->type);