#include "db/problems.h" #include "db/records.h" #include "jwt/jwt.h" #include "server/response.h" #include "server/study.h" #include "server/types.h" #include "server/util.h" #include "db/auth.h" #include "hash/hash.h" #include #include #include #include #include typedef struct { char* action; char* token; int id; int has_id; char* problem; char* answer; char* error; } problem_form_t; static void problem_form_dtor(problem_form_t* form) { if (form->action) free(form->action); if (form->token) free(form->token); if (form->problem) free(form->problem); if (form->answer) free(form->answer); if (form->error) free(form->error); } static int field_found(const char* key, const char* filename, char* path, size_t pathlen, void* user_data) { return MG_FORM_FIELD_HANDLE_GET; } static int field_get(const char* key, const char* value, size_t valuelen, void* user_data) { problem_form_t* form = (problem_form_t*)user_data; if (strcmp(key, "action") == 0) { form->action = kqm_strndup(value, valuelen); } else if (strcmp(key, "token") == 0) { form->token = kqm_strndup(value, valuelen); } else if (strcmp(key, "id") == 0) { char* id_str = kqm_strndup(value, valuelen); form->id = atoi(id_str); form->has_id = 1; free(id_str); } else if (strcmp(key, "problem") == 0) { form->problem = kqm_strndup(value, valuelen); } else if (strcmp(key, "answer") == 0) { form->answer = kqm_strndup(value, valuelen); } else if (strcmp(key, "error") == 0) { form->error = kqm_strndup(value, valuelen); } return MG_FORM_FIELD_HANDLE_GET; } static void impl_add(mg_connection* conn, problem_form_t* form) { if (!form->problem) { res_need_xxx(conn, "problem content"); return; } if (!form->answer) { res_need_xxx(conn, "standard answer"); return; } if (!form->error) { res_need_xxx(conn, "checking error"); return; } int result; int flag = add_problem(form->problem, form->answer, form->error, &result); if (!flag) { res_500(conn, "failed to add a problem"); return; } res_add_problem(conn, result); } static void impl_delete(mg_connection* conn, problem_form_t* form) { if (!form->has_id) { res_need_xxx(conn, "problem id"); return; } int result; if (!has_problem(form->id, &result)) { res_500(conn, "fail to check problem existence"); return; } else if (!result) { res_404(conn, "problem do not exist"); return; } if (!delete_problems(form->id)) { res_500(conn, "fail to delete problem"); return; } res_200(conn, "deleted"); } static void impl_query(mg_connection* conn, problem_form_t* form, int permission) { if (!form->has_id) { res_need_xxx(conn, "problem id"); return; } int result; if (!has_problem(form->id, &result)) { res_500(conn, "fail to check problem existence"); return; } else if (!result) { res_404(conn, "problem do not exist"); return; } char* result1 = NULL; char* result2 = NULL; char* result3 = NULL; char** pr2 = permission == 1 ? &result2 : NULL; if (!get_problem(form->id, &result1, pr2, &result3)) { res_500(conn, "fail to get problem"); return; } if (pr2) { res_query_problem2(conn, result1, result2, result3); free(result2); } else { res_query_problem(conn, result1, result3); } free(result1); free(result3); } static void impl_modify(mg_connection* conn, problem_form_t* form) { if (!form->has_id) { res_need_xxx(conn, "problem id"); return; } if (!form->problem) { res_need_xxx(conn, "problem content"); return; } if (!form->answer) { res_need_xxx(conn, "standard answer"); return; } if (!form->error) { res_need_xxx(conn, "checking error"); return; } int flag = modify_problem(form->id, form->problem, form->answer, form->error); if (!flag) { res_500(conn, "failed to modify the problem"); return; } res_200(conn, "success to modify the problem"); } static void impl_check(mg_connection* conn, problem_form_t* form, const char* user_id) { if (!form->has_id) { res_need_xxx(conn, "problem id"); return; } if (!form->answer) { res_need_xxx(conn, "answer"); return; } int result; if (!has_problem(form->id, &result)) { res_500(conn, "fail to check problem existence"); return; } else if (!result) { res_404(conn, "problem do not exist"); return; } int flag = check_answer(form->id, form->answer, &result); if (!flag) { add_record_uke(user_id, form->id, form->answer); res_500(conn, "fail to check the answer"); return; } if (result) { add_record_ac(user_id, form->id, form->answer); } else { add_record_wa(user_id, form->id, form->answer); } res_check_answer(conn, result); } static void impl_all(mg_connection* conn, problem_form_t* form) { char* result = NULL; int flag = all_problems(&result); if (!flag) { res_500(conn, "fail to get all the problem"); return; } res_all_problems(conn, result); free(result); } int problems_handler(mg_connection* conn, void* cbdata) { const mg_request_info* post_body = mg_get_request_info(conn); if (post_body == NULL) { res_null_req(conn); return 1; } if (strcmp(post_body->request_method, "POST")) { res_must_post(conn); return 1; } problem_form_t form = {NULL, NULL, 0, 0, NULL, NULL, NULL}; mg_form_data_handler problem_callback = { .field_found = field_found, .field_get = field_get, .field_store = NULL, .user_data = &form, }; mg_handle_form_request(conn, &problem_callback); if (!form.action) { res_need_action(conn); } else if (!form.token) { res_need_token(conn); } else { char* user_id = get_payload(form.token); int result; int flag = get_user_permission(user_id, &result); if (!flag) { res_check_permission_fail(conn); } else if (result != 1 && result != 2) { res_permission_denied(conn); } else { if (!strcmp(form.action, "add")) { if (result == 2) { res_permission_denied(conn); } else { impl_add(conn, &form); } } else if (!strcmp(form.action, "delete")) { if (result == 2) { res_permission_denied(conn); } else { impl_delete(conn, &form); } } else if (!strcmp(form.action, "query")) { impl_query(conn, &form, result); } else if (!strcmp(form.action, "modify")) { if (result == 2) { res_permission_denied(conn); } else { impl_modify(conn, &form); } } else if (!strcmp(form.action, "check")) { impl_check(conn, &form, user_id); } else if (!strcmp(form.action, "all")) { impl_all(conn, &form); } else { res_bad_action(conn); } } free(user_id); } problem_form_dtor(&form); return 1; }