diff --git a/src/main/include/models.h b/src/main/include/models.h index be00e55..b619281 100644 --- a/src/main/include/models.h +++ b/src/main/include/models.h @@ -34,7 +34,7 @@ klist_list *klist_list_init_from_sql(sqlite3_stmt *); klist_list *klist_list_get_by_id(klist *, u_int); klist_list **klist_list_get_all_by_user(klist *, u_int, size_t *); klist_list *klist_list_get_by_user_and_name(klist *, u_int, const char *); -void klist_list_save(klist *, klist_list *); +void klist_list_save(klist *, klist_list *, klist_user *); void klist_list_delete(klist *, klist_list *); void klist_list_deinit(klist_list *); diff --git a/src/main/include/sql.h b/src/main/include/sql.h index 125f11e..e6b475b 100644 --- a/src/main/include/sql.h +++ b/src/main/include/sql.h @@ -11,6 +11,7 @@ enum KLIST_SQL { MOD_USER_NAME, DEL_USER, ADD_LIST, + ADD_USER_LIST, GET_LIST, GET_LISTS, GET_LISTS_BY_USER, diff --git a/src/main/main.c b/src/main/main.c index 003c649..10cf53d 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -66,14 +66,14 @@ int main(int argc, char **argv) { break; } klist_assure_user(ctx, getuid(), getlogin()); - user = klist_user_get_by_local(ctx, getuid()); list = klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); - if (!list) list = klist_list_init(); - list->name = (unsigned char*)strdup(list_ctx->name); + if (!list) + list = klist_list_init(); + list->name = (unsigned char *)strdup(list_ctx->name); if (list->desc) - list->desc = (unsigned char*)strdup(list_ctx->desc); + list->desc = (unsigned char *)strdup(list_ctx->desc); list->is_preset = false; - klist_list_save(ctx, list); + klist_list_save(ctx, list, user); i = 0; for (; i < list_ctx->stages_len; i++) { klist_stage *stage = klist_stage_init(); @@ -94,7 +94,9 @@ int main(int argc, char **argv) { klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); if (list) { lists_len = 1; - lists = &list; + lists = malloc(lists_len * sizeof(klist_list)); + memcpy(lists[0], list, sizeof(klist_list)); + klist_list_deinit(list); }; } else lists = klist_list_get_all_by_user(ctx, user->id, &lists_len); @@ -111,7 +113,9 @@ int main(int argc, char **argv) { for (; i < tasks_len; i++) klist_task_deinit(tasks[i]); free(tasks); + klist_list_deinit(list); } + free(lists); } else if (list_ctx->name) fprintf(stderr, "List '%s' not found.\n", list_ctx->name); else @@ -141,7 +145,6 @@ int main(int argc, char **argv) { // nescessary case TASK_EDIT: klist_assure_user(ctx, getuid(), getlogin()); - user = klist_user_get_by_local(ctx, getuid()); list = klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); if (list) { size_t stages_len = 0; @@ -180,9 +183,13 @@ int main(int argc, char **argv) { klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); if (!task) task = klist_task_init(); - task->name = (unsigned char *)task_ctx->name; + if (task->name) + free(task->name); + task->name = (unsigned char *)strdup(task_ctx->name); + if (task->desc) + free(task->desc); if (task_ctx->desc) - task->desc = (unsigned char *)task_ctx->desc; + task->desc = (unsigned char *)strdup(task_ctx->desc); task->stage_id = stage_id; klist_task_save(ctx, task); klist_task_deinit(task); @@ -324,7 +331,8 @@ void setup(klist *ctx, int argc, char **argv) { char *stage = NULL; while ((stage = strsep(&optarg, ","))) { fprintf(stderr, "found stage %s\n", stage); - list_ctx->stages = realloc(list_ctx->stages, (++list_ctx->stages_len) * sizeof(char *)); + list_ctx->stages = realloc(list_ctx->stages, + (++list_ctx->stages_len) * sizeof(char *)); list_ctx->stages[list_ctx->stages_len - 1] = strdup(stage); } break; @@ -347,11 +355,11 @@ void setup(klist *ctx, int argc, char **argv) { fprintf(stderr, "Prints all lists.\n"); break; } - klist_task_context *task_ctx = malloc(sizeof(struct klist_task_context)); + klist_task_context *task_ctx = klist_task_context_init(ctx); - optind = 3; + optind = 2; - while ((opt = getopt(argc, argv, "aeds:")) != -1) + while ((opt = getopt(argc, argv, "aedl:n:s:")) != -1) switch (opt) { case 'a': task_ctx->cmd = TASK_ADD; @@ -362,6 +370,15 @@ void setup(klist *ctx, int argc, char **argv) { case 'd': task_ctx->cmd = TASK_DELETE; break; + case 'l': + task_ctx->list = strdup(optarg); + break; + case 'n': + task_ctx->name = strdup(optarg); + break; + case 's': + task_ctx->stage = strdup(optarg); + break; default: print_help(argv); fprintf(stderr, diff --git a/src/main/models.c b/src/main/models.c index fdb77ff..3a890a0 100644 --- a/src/main/models.c +++ b/src/main/models.c @@ -16,34 +16,33 @@ klist_user *klist_user_init() { klist_user *klist_user_init_from_sql(sqlite3_stmt *stmt) { klist_user *user = klist_user_init(); - size_t bytes; user->id = sqlite3_column_int(stmt, 0); - if ((bytes = sqlite3_column_bytes(stmt, 1)) > 0) { - user->name = malloc(bytes); - memcpy(user->name, sqlite3_column_text(stmt, 1), bytes); - } + if (sqlite3_column_bytes(stmt, 1) > 0) + user->name = (unsigned char *)strdup((char *)sqlite3_column_text(stmt, 1)); return user; } klist_user *klist_user_get_by_id(klist *ctx, u_int id) { sqlite3_stmt *stmt = ctx->stmts[GET_USER]; + klist_user *user = NULL; sqlite3_bind_int(stmt, 1, id); - if (sqlite3_step(stmt) == SQLITE_ROW) { - sqlite3_clear_bindings(stmt); + if (sqlite3_step(stmt) == SQLITE_ROW) return klist_user_init_from_sql(stmt); - } - return NULL; + sqlite3_reset(stmt); + return user; } klist_user *klist_user_get_by_local(klist *ctx, u_int local_id) { sqlite3_stmt *stmt = ctx->stmts[GET_USER_BY_LOCAL]; + klist_user *user = NULL; sqlite3_bind_int(stmt, 1, local_id); if (sqlite3_step(stmt) == SQLITE_ROW) { - sqlite3_clear_bindings(stmt); - return klist_user_init_from_sql(stmt); - } - fprintf(stderr, "failed to get user by local id %u: %s\n", local_id, sqlite3_errmsg(ctx->db)); - return NULL; + user = klist_user_init_from_sql(stmt); + } else + fprintf(stderr, "failed to get user by local id %u: %s\n", local_id, + sqlite3_errmsg(ctx->db)); + sqlite3_reset(stmt); + return user; } void klist_user_save(klist *ctx, klist_user *user) { @@ -55,7 +54,7 @@ void klist_user_save(klist *ctx, klist_user *user) { else fprintf(stderr, "failed to save user: %s - %d\n", sqlite3_errmsg(ctx->db), result); - sqlite3_clear_bindings(stmt); + sqlite3_reset(stmt); if (user->local_id != -1) { sqlite3_stmt *stmt = ctx->stmts[ADD_LOGIN]; @@ -65,19 +64,21 @@ void klist_user_save(klist *ctx, klist_user *user) { if ((result = sqlite3_step(stmt)) != SQLITE_ROW) fprintf(stderr, "failed to save logins for user: %s - %d\n", sqlite3_errmsg(ctx->db), result); - sqlite3_clear_bindings(stmt); - } else fprintf(stderr, "no local uid saved for user %s", user->name); + sqlite3_reset(stmt); + } else + fprintf(stderr, "no local uid saved for user %s", user->name); } void klist_user_delete(klist *ctx, klist_user *user) { sqlite3_stmt *stmt = ctx->stmts[DEL_USER]; sqlite3_bind_int(stmt, 1, (int)user->id); if (sqlite3_step(stmt) == SQLITE_ROW) - sqlite3_clear_bindings(stmt); + sqlite3_reset(stmt); } void klist_user_deinit(klist_user *user) { - free(user->name); + if (user->name) + free(user->name); free(user); } @@ -92,16 +93,11 @@ klist_stage *klist_stage_init() { klist_stage *klist_stage_init_from_sql(sqlite3_stmt *stmt) { klist_stage *stage = klist_stage_init(); - size_t bytes; stage->id = sqlite3_column_int(stmt, 0); - if ((bytes = sqlite3_column_bytes(stmt, 1)) > 0) { - stage->name = malloc(bytes); - memcpy(stage->name, sqlite3_column_text(stmt, 1), bytes); - } - if ((bytes = sqlite3_column_bytes(stmt, 2)) > 0) { - stage->desc = malloc(bytes); - memcpy(stage->desc, sqlite3_column_text(stmt, 2), bytes); - } + if (sqlite3_column_bytes(stmt, 1) > 0) + stage->name = (unsigned char *)strdup((char *)sqlite3_column_text(stmt, 1)); + if (sqlite3_column_bytes(stmt, 2) > 0) + stage->desc = (unsigned char *)strdup((char *)sqlite3_column_text(stmt, 2)); return stage; } @@ -109,7 +105,7 @@ klist_stage *klist_stage_get_by_id(klist *ctx, u_int id) { sqlite3_stmt *stmt = ctx->stmts[GET_STAGE]; sqlite3_bind_int(stmt, 1, id); if (sqlite3_step(stmt) == SQLITE_ROW) { - sqlite3_clear_bindings(stmt); + sqlite3_reset(stmt); return klist_stage_init_from_sql(stmt); } return NULL; @@ -126,7 +122,7 @@ klist_stage **klist_stage_get_all_for_list(klist *ctx, u_int id, klist_stage **_stages = realloc(stages, stages_len * sizeof(klist_stage *)); if (_stages) { stages = _stages; - stages[stages_len - 1] = klist_stage_init(stmt); + stages[stages_len - 1] = klist_stage_init_from_sql(stmt); } } if (count != NULL) @@ -142,7 +138,7 @@ void klist_stage_save(klist *ctx, klist_stage *stage) { sqlite3_bind_int(stmt, 3, stage->list_id); if ((result = sqlite3_step(stmt)) == SQLITE_ROW || result == SQLITE_DONE) { stage->id = sqlite3_column_int(stmt, 0); - sqlite3_clear_bindings(stmt); + sqlite3_reset(stmt); } else fprintf(stderr, "failed to save stage: %s - %d\n", sqlite3_errmsg(ctx->db), result); @@ -167,16 +163,12 @@ klist_list *klist_list_init() { klist_list *klist_list_init_from_sql(sqlite3_stmt *stmt) { klist_list *list = klist_list_init(); - size_t bytes; list->id = sqlite3_column_int(stmt, 0); - if ((bytes = sqlite3_column_bytes(stmt, 1)) > 0) { - list->name = malloc(bytes); - memcpy(list->name, sqlite3_column_text(stmt, 1), bytes); - } - if ((bytes = sqlite3_column_bytes(stmt, 2)) > 0) { - list->desc = malloc(bytes); - memcpy(list->desc, sqlite3_column_text(stmt, 2), bytes); - } + if (sqlite3_column_bytes(stmt, 1) > 0) + list->name = (unsigned char *)strdup((char *)sqlite3_column_text(stmt, 1)); + if (sqlite3_column_bytes(stmt, 2) > 0) + list->desc = (unsigned char *)strdup((char *)sqlite3_column_text(stmt, 2)); + list->is_preset = sqlite3_column_int(stmt, 3) ? true : false; return list; } @@ -185,7 +177,7 @@ klist_list *klist_list_get_by_id(klist *ctx, u_int id) { sqlite3_stmt *stmt = ctx->stmts[GET_LIST]; sqlite3_bind_int(stmt, 1, id); if (sqlite3_step(stmt) == SQLITE_ROW) { - sqlite3_clear_bindings(stmt); + sqlite3_reset(stmt); return klist_list_init_from_sql(stmt); } return NULL; @@ -202,7 +194,7 @@ klist_list **klist_list_get_all_by_user(klist *ctx, u_int user_id, klist_list **_lists = realloc(lists, lists_len * sizeof(klist_list *)); if (_lists) { lists = _lists; - lists[lists_len - 1] = klist_list_init(stmt); + lists[lists_len - 1] = klist_list_init_from_sql(stmt); } } if (count != NULL) @@ -212,19 +204,20 @@ klist_list **klist_list_get_all_by_user(klist *ctx, u_int user_id, klist_list *klist_list_get_by_user_and_name(klist *ctx, u_int user_id, const char *name) { - sqlite3_stmt *stmt = ctx->stmts[GET_LISTS_BY_USER]; + sqlite3_stmt *stmt = ctx->stmts[GET_LISTS_BY_USER_NAME]; + klist_list *list = NULL; sqlite3_bind_int(stmt, 1, user_id); sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC); - if (sqlite3_step(stmt) == SQLITE_ROW) { - sqlite3_clear_bindings(stmt); - return klist_list_init(stmt); - } - fprintf(stderr, "failed to get lists for user\n"); - return NULL; + if (sqlite3_step(stmt) == SQLITE_ROW) + list = klist_list_init_from_sql(stmt); + else + fprintf(stderr, "failed to get lists for user\n"); + sqlite3_reset(stmt); + return list; } -void klist_list_save(klist *ctx, klist_list *list) { +void klist_list_save(klist *ctx, klist_list *list, klist_user *user) { sqlite3_stmt *stmt = ctx->stmts[ADD_LIST]; int result = 0; sqlite3_bind_text(stmt, 1, (char *)list->name, -1, SQLITE_STATIC); @@ -232,10 +225,20 @@ void klist_list_save(klist *ctx, klist_list *list) { sqlite3_bind_int(stmt, 3, list->is_preset); if ((result = sqlite3_step(stmt)) == SQLITE_ROW) { list->id = sqlite3_column_int(stmt, 0); - sqlite3_clear_bindings(stmt); + sqlite3_reset(stmt); } else fprintf(stderr, "failed to save list: %s - %d\n", sqlite3_errmsg(ctx->db), result); + if (list->id) { + sqlite3_stmt *stmt = ctx->stmts[ADD_USER_LIST]; + sqlite3_bind_int(stmt, 1, list->id); + sqlite3_bind_int(stmt, 2, user->id); + if (sqlite3_step(stmt) == SQLITE_DONE) + sqlite3_reset(stmt); + else + fprintf(stderr, "failed to save user - list relation in join table: %s\n", + sqlite3_errmsg(ctx->db)); + } } void klist_list_deinit(klist_list *list) { @@ -251,21 +254,18 @@ klist_task *klist_task_init() { task->id = -1; task->name = NULL; task->desc = NULL; + task->due = -1; + task->target_stage = -1; return task; } klist_task *klist_task_init_from_sql(sqlite3_stmt *stmt) { klist_task *task = klist_task_init(); - size_t bytes; task->id = sqlite3_column_int(stmt, 0); - if ((bytes = sqlite3_column_bytes(stmt, 1)) > 0) { - task->name = malloc(bytes); - memcpy(task->name, sqlite3_column_text(stmt, 1), bytes); - } - if ((bytes = sqlite3_column_bytes(stmt, 2)) > 0) { - task->desc = malloc(bytes); - memcpy(task->desc, sqlite3_column_text(stmt, 2), bytes); - } + if (sqlite3_column_bytes(stmt, 1) > 0) + task->name = (unsigned char *)strdup((char *)sqlite3_column_text(stmt, 1)); + if (sqlite3_column_bytes(stmt, 2) > 0) + task->desc = (unsigned char *)strdup((char *)sqlite3_column_text(stmt, 2)); return task; } @@ -273,7 +273,7 @@ klist_task *klist_task_get_by_id(klist *ctx, u_int id) { sqlite3_stmt *stmt = ctx->stmts[GET_TASK]; sqlite3_bind_int(stmt, 1, id); if (sqlite3_step(stmt) == SQLITE_ROW) { - sqlite3_clear_bindings(stmt); + sqlite3_reset(stmt); return klist_task_init_from_sql(stmt); } return NULL; @@ -286,10 +286,13 @@ klist_task **klist_task_get_for_list(klist *ctx, u_int list_id, size_t *count) { size_t tasks_len = 0; while (sqlite3_step(stmt) == SQLITE_ROW) { tasks_len++; - tasks = realloc(tasks, tasks_len * sizeof(klist_task *)); - tasks[tasks_len - 1] = klist_task_init_from_sql(stmt); + klist_task **_tasks = realloc(tasks, tasks_len * sizeof(klist_task *)); + if (_tasks) { + tasks = _tasks; + tasks[tasks_len - 1] = klist_task_init_from_sql(stmt); + } } - sqlite3_clear_bindings(stmt); + sqlite3_reset(stmt); *count = tasks_len; return tasks; } @@ -297,14 +300,13 @@ klist_task **klist_task_get_for_list(klist *ctx, u_int list_id, size_t *count) { klist_task *klist_task_get_for_list_by_name(klist *ctx, u_int list_id, const char *name) { sqlite3_stmt *stmt = ctx->stmts[GET_TASKS_FOR_LIST_BY_NAME]; + klist_task *task = NULL; sqlite3_bind_int(stmt, 1, list_id); sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC); - - if (sqlite3_step(stmt) == SQLITE_ROW) { - sqlite3_clear_bindings(stmt); - return klist_task_init(stmt); - } - return NULL; + if (sqlite3_step(stmt) == SQLITE_ROW) + task = klist_task_init_from_sql(stmt); + sqlite3_reset(stmt); + return task; } void klist_task_save(klist *ctx, klist_task *task) { @@ -319,16 +321,16 @@ void klist_task_save(klist *ctx, klist_task *task) { sqlite3_bind_int(stmt, 5, task->target_stage); if ((result = sqlite3_step(stmt)) == SQLITE_ROW) { task->id = sqlite3_column_int(stmt, 0); - sqlite3_clear_bindings(stmt); } else fprintf(stderr, "failed to save list: %s - %d\n", sqlite3_errmsg(ctx->db), result); + sqlite3_reset(stmt); } void klist_task_delete(klist *ctx, klist_task *task) { sqlite3_stmt *stmt = ctx->stmts[DEL_TASK]; sqlite3_bind_int(stmt, 1, task->id); if (sqlite3_step(stmt) == SQLITE_DONE) - sqlite3_clear_bindings(stmt); + sqlite3_reset(stmt); else fprintf(stderr, "failed to delete task: %s\n", sqlite3_errmsg(ctx->db)); } diff --git a/src/main/sql.c b/src/main/sql.c index 1eb19ba..a0cd189 100644 --- a/src/main/sql.c +++ b/src/main/sql.c @@ -56,7 +56,8 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { return "select users.*, user_logins.local_id from users inner join " "user_logins on user_logins.user_id = users.id where users.id = ?1"; case GET_USER_BY_LOCAL: - return "select * from users inner join user_logins on user_logins.user_id = users.id where user_logins.local_id = ?1"; + return "select * from users inner join user_logins on user_logins.user_id " + "= users.id where user_logins.local_id = ?1"; case GET_USERS: return "select * from users"; case MOD_USER_NAME: @@ -64,7 +65,11 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { case DEL_USER: return "delete from users where id = ?1"; case ADD_LIST: - return "insert into lists (name, desc, is_preset) values (?1, ?2, ?3) on conflict (id) do update set name=excluded.name, desc=excluded.desc, is_preset=excluded.is_preset returning id"; + return "insert into lists (name, desc, is_preset) values (?1, ?2, ?3) on " + "conflict (id) do update set name=excluded.name, " + "desc=excluded.desc, is_preset=excluded.is_preset returning id"; + case ADD_USER_LIST: + return "insert into user_lists (user_id, list_id) values (?1, ?2)"; case GET_LIST: return "select * from lists where id = ?1"; case GET_LISTS: @@ -74,13 +79,15 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { "lists.id where user_lists.user_id = ?1"; case GET_LISTS_BY_USER_NAME: return "select * from lists inner join user_lists on user_lists.list_id = " - "lists.id where user_lists.user_id = ?1 and lists.name like '?2'"; + "lists.id where user_lists.user_id = ?1 and lists.name like ?2"; case MOD_LIST_NAME: return "update lists set name = ?1 where id = ?2"; case DEL_LIST: return "delete from lists where id = ?1"; case ADD_STAGE: - return "insert into task_stages (name, desc, list_id) values (?1, ?2, ?3) on conflict (id) do update set name=excluded.name, desc=excluded.desc returning id"; + return "insert into task_stages (name, desc, list_id) values (?1, ?2, ?3) " + "on conflict (id) do update set name=excluded.name, " + "desc=excluded.desc returning id"; case GET_STAGE: return "select * from task_stages where id = ?1"; case GET_STAGES_FOR_LIST: @@ -89,7 +96,9 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { return "delete from task_stages where id = ?1"; case ADD_TASK: return "insert into tasks (name, desc, stage, due, target_stage) values " - "(?1, ?2, ?3, ?4, ?5) on conflict (id) do update set name=excluded.name, desc=excluded.desc, stage=excluded.stage, due=excluded.due, target_stage=excluded.target_stage returning id"; + "(?1, ?2, ?3, ?4, ?5) on conflict (id) do update set " + "name=excluded.name, desc=excluded.desc, stage=excluded.stage, " + "due=excluded.due, target_stage=excluded.target_stage returning id"; case GET_TASK: return "select * from tasks where id = ?1"; case GET_TASKS: diff --git a/src/main/util.c b/src/main/util.c index 2845025..a5fcd35 100644 --- a/src/main/util.c +++ b/src/main/util.c @@ -30,7 +30,7 @@ void klist_deinit(klist *ctx) { // if (ctx->cmd_ctx) free(ctx->cmd_ctx); free(ctx->stmts); free(ctx); -ctx = NULL; + ctx = NULL; } klist_user_context *klist_user_context_init() { @@ -38,8 +38,10 @@ klist_user_context *klist_user_context_init() { ctx->cmd = -1; return ctx; } -void klist_user_context_deinit(klist_user_context *ctx) { free(ctx); -ctx = NULL; } +void klist_user_context_deinit(klist_user_context *ctx) { + free(ctx); + ctx = NULL; +} klist_list_context *klist_list_context_init() { klist_list_context *ctx = malloc(sizeof(klist_list_context)); @@ -65,13 +67,14 @@ void klist_list_context_deinit(klist_list_context *ctx) { free(ctx->stages); } free(ctx); -ctx = NULL; + ctx = NULL; } klist_task_context *klist_task_context_init(klist *list) { klist_task_context *ctx = malloc(sizeof(klist_task_context)); ctx->cmd = -1; ctx->name = NULL; + ctx->desc = NULL; ctx->list = NULL; ctx->stage = NULL; return ctx; @@ -84,7 +87,7 @@ void klist_task_context_deinit(klist_task_context *ctx) { if (ctx->stage) free(ctx->stage); free(ctx); -ctx = NULL; + ctx = NULL; } /*