diff --git a/.gitea/workflows/actions.yaml b/.gitea/workflows/actions.yaml index 380ea7c..62a7b43 100644 --- a/.gitea/workflows/actions.yaml +++ b/.gitea/workflows/actions.yaml @@ -9,7 +9,7 @@ jobs: - name: Check out repository code uses: actions/checkout@v3 - name: Building binary with make - run: make -j$(nproc) + run: make USE_SQLITE3=1 -j$(nproc) - name: Testing binary run: make test @@ -25,7 +25,7 @@ jobs: run: | mkdir build && \ cd build && \ - cmake .. && \ + cmake -DUSE_SQLITE3=ON .. && \ make -j$(nproc) - name: Testing binary run: | @@ -41,7 +41,51 @@ jobs: uses: actions/checkout@v3 - name: Building binary with meson run: | - meson setup build && \ + meson setup build -Duse_sqlite3=true && \ + ninja -C build + - name: Testing binary + run: | + cp -v build/auth_service . && ./tests.sh + + Prepare-Build-Testing-With-Make-Without-sqlite3: + runs-on: ubuntu-latest + steps: + - name: Check out repository code + uses: actions/checkout@v3 + - name: Building binary with make + run: make USE_SQLITE3=0 -j$(nproc) + - name: Testing binary + run: make test + + Prepare-Build-Testing-With-CMake-Without-sqlite3: + runs-on: ubuntu-latest + steps: + - name: prepare-container + run: | + apt install -y cmake + - name: Check out repository code + uses: actions/checkout@v3 + - name: Building binary with CMake + run: | + mkdir build && \ + cd build && \ + cmake -DUSE_SQLITE3=OFF .. && \ + make -j$(nproc) + - name: Testing binary + run: | + cp -v build/auth_service . && ./tests.sh + + Prepare-Build-Testing-With-Meson-Without-sqlite3: + runs-on: ubuntu-latest + steps: + - name: prepare-container + run: | + apt install -y meson + - name: Check out repository code + uses: actions/checkout@v3 + - name: Building binary with meson + run: | + meson setup build -Duse_sqlite3=false && \ ninja -C build - name: Testing binary run: | diff --git a/.gitignore b/.gitignore index e911a4c..17909ff 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ build builddir auth_service users.db +users_db.json *.swp *.log .proxy.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 115c0f5..c0f05eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,16 +3,32 @@ project(auth_service LANGUAGES C) set(CMAKE_C_STANDARD 23) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_C_FLAGS "-ffunction-sections -fdata-sections") +set(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections") include_directories(./src/lib/ ${SQLite3_INCLUDE_DIRS}) FILE(GLOB_RECURSE SOURCES src/*.c) -find_package(SQLite3 REQUIRED) +option(USE_SQLITE3 "Enable SQLite3 support" OFF) +option(USE_WERROR "Enable SQLite3 support" OFF) + +if(USE_SQLITE3) + find_package(SQLite3 REQUIRED) + add_definitions(-DUSE_SQLITE3) +endif() + +if(USE_WERROR) + add_definitions(-Werror) +endif() add_executable( auth_service ${SOURCES} ) -target_link_libraries(auth_service ssl crypto sqlite3 pthread) +if(USE_SQLITE3) + target_link_libraries(auth_service ssl crypto sqlite3 pthread) +else() + target_link_libraries(auth_service ssl crypto pthread) +endif() diff --git a/Makefile b/Makefile index c86cfe9..3bbe610 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,24 @@ CC = gcc -CFLAGS = -Wall -g -std=gnu2x -DMG_TLS=MG_TLS_OPENSSL -LDFLAGS = -LIBS = -lpthread -lcrypto -lssl -lsqlite3 +CFLAGS = -Wall -g -std=gnu2x -DMG_TLS=MG_TLS_OPENSSL -ffunction-sections -fdata-sections +LDFLAGS = -Wl,--gc-sections INCLUDES = -I./src/lib -I./src -SRCS = $(wildcard src/*.c src/lib/*.c) +SRCS = $(wildcard src/*/*.c src/*.c) OBJS = $(SRCS:.c=.o) TARGET = auth_service BUILD_DIR=./build CROSS_COMPILE = +LIBS = -lpthread -lcrypto -lssl +USE_SQLITE3 ?= 0 +WERROR ?= 0 + +ifeq ($(USE_SQLITE3), 1) + CFLAGS += -DUSE_SQLITE3 + LIBS += -lsqlite3 +endif + +ifeq ($(WERROR), 1) + CFLAGS += -Werror +endif all: $(TARGET) @@ -18,7 +29,7 @@ $(TARGET): $(OBJS) $(CROSS_COMPILE)$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ clean: - rm -f $(OBJS) $(TARGET) $(shell find . -type f -name '*.log') users.db + rm -f $(OBJS) $(TARGET) $(shell find . -type f -name '*.log') users.db users_db.json test: $(TARGET) bash ./tests.sh diff --git a/config.json b/config.json index cb879a2..1acaa40 100644 --- a/config.json +++ b/config.json @@ -1,7 +1,7 @@ { "database": "users.db", - "address": "localhost:8222", - "tls_address": "localhost:8223", + "address": "0.0.0.0:8222", + "tls_address": "0.0.0.0:8223", "default_users_file": "users.json", "web": "./web", "tls_enabled": true, diff --git a/meson.build b/meson.build index 4c3f6eb..b51d336 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,25 @@ project('auth_service', 'c', default_options: ['c_std=gnu2x']) include_dirs = include_directories('src', 'src/lib') -deps = [dependency('openssl'), dependency('sqlite3')] +deps = [dependency('openssl')] +extra_c_args = ['-ffunction-sections', '-fdata-sections'] +extra_c_link_args = ['-Wl,--gc-sections'] + +sqlite3_dep = dependency('sqlite3', required: false) +use_sqlite3 = get_option('use_sqlite3') +use_werror = get_option('use_werror') + +if use_sqlite3 + if not sqlite3_dep.found() + error('SQLite3 requested but not found') + endif + deps += sqlite3_dep + add_project_arguments('-DUSE_SQLITE3', language: 'c') +endif + +if use_werror + add_project_arguments('-Werror', language: 'c') +endif + executable( 'auth_service', 'src/main.c', @@ -35,4 +54,6 @@ executable( 'src/db_update_user_field.c', include_directories: include_dirs, dependencies: deps, + c_args: extra_c_args, + link_args: extra_c_link_args, ) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..54d2bc5 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,2 @@ +option('use_sqlite3', type: 'boolean', value: false, description: 'Enable SQLite3 support') +option('use_werror', type: 'boolean', value: false, description: 'Build with warning as errors') diff --git a/src/ConfigManager.c b/src/ConfigManager.c index bc13f7f..28b247c 100644 --- a/src/ConfigManager.c +++ b/src/ConfigManager.c @@ -1,9 +1,11 @@ #include "ConfigManager.h" + #include #include #include #include #include + #include "file.h" typedef struct ConfigManager { diff --git a/src/add_user.c b/src/add_user.c index 80b030b..e8c8c2b 100644 --- a/src/add_user.c +++ b/src/add_user.c @@ -33,10 +33,9 @@ void add_user(struct mg_connection *c, struct mg_http_message *hm) { return; } const bool user_is_superuser = is_superuser->valueint ? true : false; - User *new_db_user = db_insert_user( - username->valuestring, email->valuestring, password->valuestring, - group->valuestring, - &user_is_superuser); + User *new_db_user = db_insert_user(username->valuestring, email->valuestring, + password->valuestring, group->valuestring, + &user_is_superuser); if (!new_db_user) { mg_http_reply(c, 500, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), MG_ESC("failed to create user")); @@ -50,7 +49,6 @@ void add_user(struct mg_connection *c, struct mg_http_message *hm) { username->valuestring, email->valuestring, group->valuestring, is_superuser->valueint ? "true" : "false"); - mg_http_reply(c, 200, HTTP_HEADERS, responsedata); cJSON_Delete(payload); } diff --git a/src/config.c b/src/config.c index 20e196a..139bfa8 100644 --- a/src/config.c +++ b/src/config.c @@ -3,5 +3,5 @@ ConfigManager *config = nullptr; void init_config(const char *filename) { - config = cm_new_config_from_file(filename); + config = cm_new_config_from_file(filename); } \ No newline at end of file diff --git a/src/cors.c b/src/cors.c index 85dac94..710966f 100644 --- a/src/cors.c +++ b/src/cors.c @@ -1,5 +1,10 @@ #include "cors.h" void set_cors_headers(struct mg_connection *c, struct mg_http_message *hm) { - mg_http_reply(c, 200, "Access-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: GET,POST,OPTIONS,PUT,DELETE\r\nAccess-Control-Allow-Headers: Authorization,X-Custom,Content-Type", ""); + mg_http_reply( + c, 200, + "Access-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: " + "GET,POST,OPTIONS,PUT,DELETE\r\nAccess-Control-Allow-Headers: " + "Authorization,X-Custom,Content-Type", + ""); } diff --git a/src/database.c b/src/database.c index 17c7aa4..7639e04 100644 --- a/src/database.c +++ b/src/database.c @@ -1,22 +1,36 @@ #include "database.h" + #include #include -#include "sql.h" #include -#include "config.h" -sqlite3* db = nullptr; +#ifdef USE_SQLITE3 +#include "config.h" +#include "sql.h" +#endif + +#ifdef USE_SQLITE3 +sqlite3 *db = nullptr; pthread_mutex_t db_mutex = PTHREAD_MUTEX_INITIALIZER; +#else +pthread_mutex_t users_file_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif void init_db() { - if (sqlite3_open(cm_get_parameter_as_string(config, "database"), &db) != SQLITE_OK) { +#ifdef USE_SQLITE3 + if (sqlite3_open(cm_get_parameter_as_string(config, "database"), &db) != + SQLITE_OK) { fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db)); sqlite3_close(db); exit(1); } +#else + return; +#endif } void migrate_db() { +#ifdef USE_SQLITE3 char *err_msg = 0; pthread_mutex_lock(&db_mutex); if (sqlite3_exec(db, CREATE_TABLE_USERS, nullptr, nullptr, &err_msg) != @@ -27,37 +41,61 @@ void migrate_db() { exit(1); } pthread_mutex_unlock(&db_mutex); +#else + return; +#endif } // Вспомогательная функция для экранирования специальных символов в JSON -char* json_escape(const char* str) { - if (!str) return NULL; - - size_t len = strlen(str); - // Выделяем память с запасом (каждый символ может быть экранирован) - char* escaped = malloc(len * 6 + 1); - if (!escaped) return NULL; - - char* p = escaped; - for (size_t i = 0; i < len; i++) { - switch (str[i]) { - case '\"': strcpy(p, "\\\""); p += 2; break; - case '\\': strcpy(p, "\\\\"); p += 2; break; - case '\b': strcpy(p, "\\b"); p += 2; break; - case '\f': strcpy(p, "\\f"); p += 2; break; - case '\n': strcpy(p, "\\n"); p += 2; break; - case '\r': strcpy(p, "\\r"); p += 2; break; - case '\t': strcpy(p, "\\t"); p += 2; break; - default: - if (str[i] < 0x20) { - sprintf(p, "\\u%04x", (unsigned char)str[i]); - p += 6; - } else { - *p++ = str[i]; - } +char *json_escape(const char *str) { + if (!str) return NULL; + + size_t len = strlen(str); + // Выделяем память с запасом (каждый символ может быть экранирован) + char *escaped = malloc(len * 6 + 1); + if (!escaped) return NULL; + + char *p = escaped; + for (size_t i = 0; i < len; i++) { + switch (str[i]) { + case '\"': + strcpy(p, "\\\""); + p += 2; + break; + case '\\': + strcpy(p, "\\\\"); + p += 2; + break; + case '\b': + strcpy(p, "\\b"); + p += 2; + break; + case '\f': + strcpy(p, "\\f"); + p += 2; + break; + case '\n': + strcpy(p, "\\n"); + p += 2; + break; + case '\r': + strcpy(p, "\\r"); + p += 2; + break; + case '\t': + strcpy(p, "\\t"); + p += 2; + break; + default: + if (str[i] < 0x20) { + sprintf(p, "\\u%04x", (unsigned char) str[i]); + p += 6; + } else { + *p++ = str[i]; } } - *p = '\0'; - - return escaped; -} \ No newline at end of file + } + *p = '\0'; + + return escaped; +} diff --git a/src/database.h b/src/database.h index d518349..da62dda 100644 --- a/src/database.h +++ b/src/database.h @@ -1,11 +1,15 @@ #pragma once -#include #include +#ifdef USE_SQLITE3 +#include extern sqlite3 *db; extern pthread_mutex_t db_mutex; +#else +extern pthread_mutex_t users_file_mutex; +#endif void init_db(); void migrate_db(); -char* json_escape(const char* str); \ No newline at end of file +char *json_escape(const char *str); diff --git a/src/db_delete_user.c b/src/db_delete_user.c index 5781098..039f997 100644 --- a/src/db_delete_user.c +++ b/src/db_delete_user.c @@ -1,8 +1,14 @@ #include "database.h" -#include "sql.h" #include "user.h" +#ifdef USE_SQLITE3 +#include "sql.h" +#else +#include "file.h" +#endif + bool db_delete_user(const int id) { +#ifdef USE_SQLITE3 pthread_mutex_lock(&db_mutex); if (!db) { fprintf(stderr, "Database not initialized\n"); @@ -42,4 +48,32 @@ bool db_delete_user(const int id) { pthread_mutex_unlock(&db_mutex); return true; +#else + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + int index = 0; + bool found = false; + cJSON_ArrayForEach(user, users) { + cJSON *user_id = cJSON_GetObjectItem(user, "id"); + if (user_id->valueint == id) { + cJSON_DeleteItemFromArray(users, index); + found = true; + break; + } + index++; + } + if (!found) { + pthread_mutex_unlock(&users_file_mutex); + return false; + } + char *new_data = cJSON_Print(users); + write_file("users_db.json", new_data); + free(new_data); + free(data); + cJSON_Delete(users); + pthread_mutex_unlock(&users_file_mutex); + return true; +#endif } diff --git a/src/db_get_all_users.c b/src/db_get_all_users.c index f5198f1..2471c96 100644 --- a/src/db_get_all_users.c +++ b/src/db_get_all_users.c @@ -1,9 +1,14 @@ #include "database.h" -#include "sql.h" #include "user.h" -#include + +#ifdef USE_SQLITE3 +#include "sql.h" +#else +#include "file.h" +#endif char *db_get_all_users() { +#ifdef USE_SQLITE3 pthread_mutex_lock(&db_mutex); if (!db) { fprintf(stderr, "Database not initialized\n"); @@ -96,4 +101,10 @@ char *db_get_all_users() { sqlite3_finalize(stmt); pthread_mutex_unlock(&db_mutex); return result; -} \ No newline at end of file +#else + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + pthread_mutex_unlock(&users_file_mutex); + return data; +#endif +} diff --git a/src/db_get_user_by_id.c b/src/db_get_user_by_id.c index acd759e..c25a67e 100644 --- a/src/db_get_user_by_id.c +++ b/src/db_get_user_by_id.c @@ -1,8 +1,15 @@ #include "database.h" -#include "sql.h" #include "user.h" +#ifdef USE_SQLITE3 +#include "sql.h" +#else +#include "cJSON.h" +#include "file.h" +#endif + User *db_get_user_by_id(const int id) { +#ifdef USE_SQLITE3 User *user = nullptr; pthread_mutex_lock(&db_mutex); if (!db) { @@ -41,4 +48,37 @@ User *db_get_user_by_id(const int id) { pthread_mutex_unlock(&db_mutex); return user; +#else + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + User *found = nullptr; + cJSON_ArrayForEach(user, users) { + cJSON *user_id = cJSON_GetObjectItem(user, "id"); + cJSON *user_username = cJSON_GetObjectItem(user, "username"); + cJSON *user_password = cJSON_GetObjectItem(user, "password"); + cJSON *user_email = cJSON_GetObjectItem(user, "email"); + cJSON *user_group = cJSON_GetObjectItem(user, "group"); + cJSON *user_is_superuser = cJSON_GetObjectItem(user, "is_superuser"); + if (user_id->valueint == id) { + found = new_user(user_id->valueint, user_username->valuestring, + user_password->valuestring, user_email->valuestring, + user_group->valuestring, user_is_superuser->valueint); + break; + } + } + if (found == nullptr) { + pthread_mutex_unlock(&users_file_mutex); + // if (user != nullptr) cJSON_Delete(user); + cJSON_Delete(users); + free(data); + return nullptr; + } + pthread_mutex_unlock(&users_file_mutex); + // if (user != nullptr) cJSON_Delete(user); + cJSON_Delete(users); + free(data); + return found; +#endif } diff --git a/src/db_get_user_by_username.c b/src/db_get_user_by_username.c index 90a5544..5dc30a5 100644 --- a/src/db_get_user_by_username.c +++ b/src/db_get_user_by_username.c @@ -1,8 +1,15 @@ #include "database.h" -#include "sql.h" #include "user.h" +#ifdef USE_SQLITE3 +#include "sql.h" +#else +#include "cJSON.h" +#include "file.h" +#endif + User *db_get_user_by_username(const char *username) { +#ifdef USE_SQLITE3 User *user = nullptr; pthread_mutex_lock(&db_mutex); if (!db) { @@ -41,4 +48,37 @@ User *db_get_user_by_username(const char *username) { pthread_mutex_unlock(&db_mutex); return user; +#else + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + User *found = nullptr; + cJSON_ArrayForEach(user, users) { + cJSON *user_id = cJSON_GetObjectItem(user, "id"); + cJSON *user_username = cJSON_GetObjectItem(user, "username"); + cJSON *user_password = cJSON_GetObjectItem(user, "password"); + cJSON *user_email = cJSON_GetObjectItem(user, "email"); + cJSON *user_group = cJSON_GetObjectItem(user, "group"); + cJSON *user_is_superuser = cJSON_GetObjectItem(user, "is_superuser"); + if (!strcmp(user_username->valuestring, username)) { + found = new_user(user_id->valueint, user_username->valuestring, + user_password->valuestring, user_email->valuestring, + user_group->valuestring, user_is_superuser->valueint); + break; + } + } + if (found == nullptr) { + pthread_mutex_unlock(&users_file_mutex); + // if (user != nullptr) cJSON_Delete(user); + cJSON_Delete(users); + free(data); + return nullptr; + } + pthread_mutex_unlock(&users_file_mutex); + // if (user != nullptr) cJSON_Delete(user); + cJSON_Delete(users); + free(data); + return found; +#endif } diff --git a/src/db_get_user_field_by_id.c b/src/db_get_user_field_by_id.c index 7c70125..bb74908 100644 --- a/src/db_get_user_field_by_id.c +++ b/src/db_get_user_field_by_id.c @@ -1,9 +1,15 @@ #include #include "database.h" -#include "sql.h" #include "user.h" +#ifdef USE_SQLITE3 +#include "sql.h" +#else +#include "file.h" +#endif + char *db_get_user_field_by_id(const int id, const char *field) { +#ifdef USE_SQLITE3 char *password = nullptr; pthread_mutex_lock(&db_mutex); if (!db) { @@ -42,4 +48,37 @@ char *db_get_user_field_by_id(const int id, const char *field) { } pthread_mutex_unlock(&db_mutex); return password; +#else + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + User *found = nullptr; + cJSON_ArrayForEach(user, users) { + cJSON *user_id = cJSON_GetObjectItem(user, "id"); + cJSON *user_username = cJSON_GetObjectItem(user, "username"); + cJSON *user_password = cJSON_GetObjectItem(user, "password"); + cJSON *user_email = cJSON_GetObjectItem(user, "email"); + cJSON *user_group = cJSON_GetObjectItem(user, "group"); + cJSON *user_is_superuser = cJSON_GetObjectItem(user, "is_superuser"); + if (user_id->valueint == id) { + found = new_user(user_id->valueint, user_username->valuestring, + user_password->valuestring, user_email->valuestring, + user_group->valuestring, user_is_superuser->valueint); + break; + } + } + if (found == nullptr) { + pthread_mutex_unlock(&users_file_mutex); + // if (user != nullptr) cJSON_Delete(user); + cJSON_Delete(users); + free(data); + return nullptr; + } + pthread_mutex_unlock(&users_file_mutex); + // if (user != nullptr) cJSON_Delete(user); + cJSON_Delete(users); + free(data); + return found->password; +#endif } diff --git a/src/db_get_users_from_file.c b/src/db_get_users_from_file.c index c7956e0..1730021 100644 --- a/src/db_get_users_from_file.c +++ b/src/db_get_users_from_file.c @@ -1,5 +1,4 @@ #include -#include #include "file.h" #include "user.h" diff --git a/src/db_insert_user.c b/src/db_insert_user.c index d293129..b32f0c2 100644 --- a/src/db_insert_user.c +++ b/src/db_insert_user.c @@ -1,10 +1,17 @@ #include "database.h" -#include "sql.h" #include "user.h" +#ifdef USE_SQLITE3 +#include "sql.h" +#else +#include "cJSON.h" +#include "file.h" +#endif + User *db_insert_user(const char *username, const char *email, const char *password, const char *group, const bool *is_superuser) { +#ifdef USE_SQLITE3 pthread_mutex_lock(&db_mutex); if (!db) { fprintf(stderr, "Databse not initialized\n"); @@ -60,4 +67,53 @@ User *db_insert_user(const char *username, const char *email, User *new_db_user = new_user(inserted_id, username, email, password, group, is_superuser); return new_db_user; +#else + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + int users_size = 0; + bool found = false; + cJSON_ArrayForEach(user, users) { + cJSON *user_username = cJSON_GetObjectItem(user, "username"); + cJSON *user_password = cJSON_GetObjectItem(user, "password"); + cJSON *user_email = cJSON_GetObjectItem(user, "email"); + cJSON *user_group = cJSON_GetObjectItem(user, "group"); + if (!strcmp(user_username->valuestring, username) && + !strcmp(user_password->valuestring, password) && + !strcmp(user_email->valuestring, email) && + !strcmp(user_group->valuestring, group)) { + found = true; + } + users_size++; + } + if (found == true) { + pthread_mutex_unlock(&users_file_mutex); + return nullptr; + } + cJSON *new_user_data = cJSON_CreateObject(); + cJSON_AddNumberToObject(new_user_data, "id", users_size); + cJSON_AddStringToObject(new_user_data, "username", username); + cJSON_AddStringToObject(new_user_data, "password", password); + cJSON_AddStringToObject(new_user_data, "email", email); + cJSON_AddStringToObject(new_user_data, "group", group); + cJSON_AddBoolToObject(new_user_data, "is_superuser", *is_superuser); + char *new_user_data_string = cJSON_Print(new_user_data); + if (users_size == 0) { + users = cJSON_CreateArray(); + } + cJSON_AddItemToArray(users, new_user_data); + char *new_data = cJSON_Print(users); + write_file("users_db.json", new_data); + pthread_mutex_unlock(&users_file_mutex); + User *return_user = + new_user(users_size, username, email, password, group, is_superuser); + free(new_data); + free(data); + free(new_user_data_string); + // cJSON_Delete(new_user_data); + cJSON_Delete(users); + if (user != nullptr) cJSON_Delete(user); + return return_user; +#endif } diff --git a/src/db_update_user.c b/src/db_update_user.c index 9215d22..2707dda 100644 --- a/src/db_update_user.c +++ b/src/db_update_user.c @@ -1,10 +1,18 @@ +#include #include "database.h" -#include "sql.h" #include "user.h" +#ifdef USE_SQLITE3 +#include "sql.h" +#else +#include "cJSON.h" +#include "file.h" +#endif + User *db_update_user(const int userid, const char *username, const char *email, const char *password, const char *group, const bool *is_superuser) { +#ifdef USE_SQLITE3 pthread_mutex_lock(&db_mutex); if (!db) { fprintf(stderr, "Databse not initialized\n"); @@ -52,4 +60,38 @@ User *db_update_user(const int userid, const char *username, const char *email, } pthread_mutex_unlock(&db_mutex); return new_user(userid, username, email, password, group, is_superuser); +#else + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + cJSON_ArrayForEach(user, users) { + cJSON *user_id = cJSON_GetObjectItem(user, "id"); + if (user_id->valueint == userid) { + cJSON *user_username = cJSON_GetObjectItem(user, "username"); + cJSON *user_password = cJSON_GetObjectItem(user, "password"); + cJSON *user_email = cJSON_GetObjectItem(user, "email"); + cJSON *user_group = cJSON_GetObjectItem(user, "group"); + cJSON_SetValuestring(user_username, username); + cJSON_SetValuestring(user_password, password); + cJSON_SetValuestring(user_email, email); + cJSON_SetValuestring(user_group, group); + cJSON_DeleteItemFromObject(user, "is_superuser"); + cJSON_AddBoolToObject(user, "is_superuser", *is_superuser); + char *new_data = cJSON_Print(users); + write_file("users_db.json", new_data); + free(new_data); + free(data); + cJSON_Delete(users); + User *ret = + new_user(userid, username, password, email, group, is_superuser); + pthread_mutex_unlock(&users_file_mutex); + return ret; + } + } + free(data); + cJSON_Delete(users); + pthread_mutex_unlock(&users_file_mutex); + return nullptr; +#endif } diff --git a/src/db_update_user_field.c b/src/db_update_user_field.c index 15379b5..7351093 100644 --- a/src/db_update_user_field.c +++ b/src/db_update_user_field.c @@ -1,8 +1,15 @@ #include "database.h" -#include "sql.h" #include "user.h" +#ifdef USE_SQLITE3 +#include "sql.h" +#else +#include "cJSON.h" +#include "file.h" +#endif + bool db_update_user_field(const int id, const char *field, const char *value) { +#ifdef USE_SQLITE3 pthread_mutex_lock(&db_mutex); if (!db || !field || !value) { fprintf(stderr, "invalid parameters\n"); @@ -26,10 +33,43 @@ bool db_update_user_field(const int id, const char *field, const char *value) { sqlite3_finalize(stmt); if (rc != SQLITE_DONE) { - fprintf(stderr, "execution failed: %s\n", sqlite3_errmsg(db)); - pthread_mutex_unlock(&db_mutex); - return false; + fprintf(stderr, "execution failed: %s\n", sqlite3_errmsg(db)); + pthread_mutex_unlock(&db_mutex); + return false; } pthread_mutex_unlock(&db_mutex); return sqlite3_changes(db) > 0; +#else + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + cJSON_ArrayForEach(user, users) { + cJSON *user_id = cJSON_GetObjectItem(user, "id"); + if (user_id->valueint == id) { + cJSON *user_field = cJSON_GetObjectItem(user, field); + if (cJSON_IsNumber(user_field)) { + // cJSON_SetNumberValue(user_field, value); + return false; + } else if (cJSON_IsBool(user_field)) { + // cJSON_DeleteItemFromObject(user, field); + // cJSON_AddBoolToObject(user, field, value); + return false; + } else if (cJSON_IsString(user_field)) { + cJSON_SetValuestring(user_field, value); + } + char *new_data = cJSON_Print(users); + write_file("users_db.json", new_data); + free(new_data); + free(data); + cJSON_Delete(users); + pthread_mutex_unlock(&users_file_mutex); + return true; + } + } + free(data); + cJSON_Delete(users); + pthread_mutex_unlock(&users_file_mutex); + return false; +#endif } diff --git a/src/delete_user.c b/src/delete_user.c index 1856d15..cedb534 100644 --- a/src/delete_user.c +++ b/src/delete_user.c @@ -4,20 +4,20 @@ void delete_user(struct mg_connection *c, struct mg_http_message *hm) { if (hm->body.len == 0) { - mg_http_reply(c, 400, HTTP_HEADERS, "{%m:%m}", - MG_ESC("error"), MG_ESC("must have token")); + mg_http_reply(c, 400, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC("must have token")); return; } request_with_token *requestdata = check_body(hm); if (requestdata->error != NULL) { - mg_http_reply(c, 403, HTTP_HEADERS, "{%m:%m}", - MG_ESC("error"), MG_ESC(requestdata->error)); + mg_http_reply(c, 403, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC(requestdata->error)); return; } const bool valid = jwt_verifyJWT(requestdata->token, JWT_DEFAULT_SECRET); if (!valid) { - mg_http_reply(c, 403, HTTP_HEADERS, "{%m:%m}", - MG_ESC("error"), MG_ESC("invalid token")); + mg_http_reply(c, 403, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC("invalid token")); free_request_with_token(requestdata); return; } @@ -38,8 +38,8 @@ void delete_user(struct mg_connection *c, struct mg_http_message *hm) { } bool is_superuser = cJSON_GetObjectItem(payload, "is_superuser")->valueint; if (!is_superuser) { - mg_http_reply(c, 403, HTTP_HEADERS, "{%m:%m}", - MG_ESC("error"), MG_ESC("user is not superuser")); + mg_http_reply(c, 403, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC("user is not superuser")); return; } bool user_deleted = db_delete_user(useridfromjson->valueint); diff --git a/src/file.c b/src/file.c index 6df353d..0fd9cc0 100644 --- a/src/file.c +++ b/src/file.c @@ -1,8 +1,13 @@ #include "file.h" + +#include #include #include +#include +#include char *read_file(const char *path) { + create_file_if_not_exists(path); FILE *fp = fopen(path, "rb"); if (fp == NULL) { perror("Error opening file"); @@ -31,4 +36,41 @@ char *read_file(const char *path) { buffer[file_size] = '\0'; fclose(fp); return buffer; -} \ No newline at end of file +} + +char *write_file(const char *path, const char *data) { + create_file_if_not_exists(path); + FILE *fp = fopen(path, "w"); + if (fp == NULL) { + printf("%s\n", path); + perror("Error opening file"); + return nullptr; + } + if (fprintf(fp, "%s", data) < 0) { + perror("Error write file"); + return nullptr; + } + fclose(fp); + char *ret = strdup(data); + return ret; +} + +int create_file_if_not_exists(const char *filename) { + if (!check_file_exists(filename)) { + return 0; + } + FILE *file = fopen(filename, "w"); + if (file == nullptr) { + perror("Error creating file"); + return -1; + } + fclose(file); + return 0; +} + +int check_file_exists(const char *filename) { + if (access(filename, F_OK) == 0) { + return 0; + } + return -1; +} diff --git a/src/file.h b/src/file.h index 7503f09..817f267 100644 --- a/src/file.h +++ b/src/file.h @@ -1,3 +1,6 @@ #pragma once -char *read_file(const char *path); \ No newline at end of file +char *read_file(const char *path); +char *write_file(const char *path, const char *data); +int create_file_if_not_exists(const char *filename); +int check_file_exists(const char *filename); diff --git a/src/get_all_users.c b/src/get_all_users.c index a21cc74..1cad438 100644 --- a/src/get_all_users.c +++ b/src/get_all_users.c @@ -5,7 +5,8 @@ void get_all_users(struct mg_connection *c, struct mg_http_message *hm) { request_with_token *data = check_body(hm); if (data->error != NULL) { - mg_http_reply(c, 403, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), MG_ESC(data->error)); + mg_http_reply(c, 403, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC(data->error)); return; } if (!jwt_verifyJWT(data->token, JWT_DEFAULT_SECRET)) { diff --git a/src/get_token.c b/src/get_token.c index 5e3047f..40f5efa 100644 --- a/src/get_token.c +++ b/src/get_token.c @@ -13,7 +13,8 @@ void get_token(struct mg_connection *c, struct mg_http_message *hm) { if (username == NULL || password == NULL) { const char *error_ptr = cJSON_GetErrorPtr(); if (error_ptr != NULL) { - mg_http_reply(c, 400, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), MG_ESC(error_ptr)); + mg_http_reply(c, 400, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC(error_ptr)); return; } mg_http_reply(c, 400, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), @@ -41,7 +42,8 @@ void get_token(struct mg_connection *c, struct mg_http_message *hm) { db_user->id, db_user->username, db_user->email, db_user->group, db_user->is_superuser ? "true" : "false"); char *token = jwt_createJWT(header, payload, JWT_DEFAULT_SECRET); - mg_http_reply(c, 200, HTTP_HEADERS, "{%m:%m}", MG_ESC("token"), MG_ESC(token)); + mg_http_reply(c, 200, HTTP_HEADERS, "{%m:%m}", MG_ESC("token"), + MG_ESC(token)); free_user(db_user); free(token); } diff --git a/src/get_user.c b/src/get_user.c index 3540a7e..f3c7626 100644 --- a/src/get_user.c +++ b/src/get_user.c @@ -10,7 +10,8 @@ void get_user(struct mg_connection *c, struct mg_http_message *hm) { } request_with_token *requestdata = check_body(hm); if (requestdata->error != NULL) { - mg_http_reply(c, 403, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), MG_ESC(requestdata->error)); + mg_http_reply(c, 403, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC(requestdata->error)); return; } if (!jwt_verifyJWT(requestdata->token, JWT_DEFAULT_SECRET)) { diff --git a/src/jwt.c b/src/jwt.c index f5c8c3b..ca56b1d 100644 --- a/src/jwt.c +++ b/src/jwt.c @@ -1,4 +1,5 @@ #include "jwt.h" + #include #include #include @@ -57,7 +58,7 @@ char *jwt_base64url_encode(const unsigned char *input, const int length) { BUF_MEM *bufferPtr; BIO_get_mem_ptr(bio, &bufferPtr); - const auto result = (char *) malloc(bufferPtr->length + 1); + const auto result = (char *)malloc(bufferPtr->length + 1); memcpy(result, bufferPtr->data, bufferPtr->length); result[bufferPtr->length] = '\0'; @@ -73,7 +74,7 @@ unsigned char *jwt_base64url_decode(const char *input, int input_len, if (input_len == 0) input_len = strlen(input); // Создаем копию для преобразования - const auto input_copy = (char *) malloc(input_len + 1); + const auto input_copy = (char *)malloc(input_len + 1); strncpy(input_copy, input, input_len); input_copy[input_len] = '\0'; @@ -85,7 +86,7 @@ unsigned char *jwt_base64url_decode(const char *input, int input_len, BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); - const auto buffer = (unsigned char *) malloc(input_len); + const auto buffer = (unsigned char *)malloc(input_len); const int len = BIO_read(bio, buffer, input_len); BIO_free_all(bio); @@ -104,13 +105,13 @@ unsigned char *jwt_base64url_decode(const char *input, int input_len, // Создание JWT токена char *jwt_createJWT(const char *header_json, const char *payload_json, const char *secret) { - char *encodedHeader = jwt_base64url_encode( - (const unsigned char *) header_json, strlen(header_json)); + char *encodedHeader = jwt_base64url_encode((const unsigned char *)header_json, + strlen(header_json)); char *encodedPayload = jwt_base64url_encode( - (const unsigned char *) payload_json, strlen(payload_json)); + (const unsigned char *)payload_json, strlen(payload_json)); char *unsignedToken = - (char *) malloc(strlen(encodedHeader) + strlen(encodedPayload) + 2); + (char *)malloc(strlen(encodedHeader) + strlen(encodedPayload) + 2); sprintf(unsignedToken, "%s.%s", encodedHeader, encodedPayload); unsigned int digest_len; @@ -119,7 +120,7 @@ char *jwt_createJWT(const char *header_json, const char *payload_json, char *encodedSignature = jwt_base64url_encode(digest, digest_len); char *jwt = - (char *) malloc(strlen(unsignedToken) + strlen(encodedSignature) + 2); + (char *)malloc(strlen(unsignedToken) + strlen(encodedSignature) + 2); sprintf(jwt, "%s.%s", unsignedToken, encodedSignature); free(encodedHeader); @@ -134,8 +135,8 @@ char *jwt_createJWT(const char *header_json, const char *payload_json, // Генерация HMAC-SHA256 unsigned char *jwt_hmac_sha256(const char *key, int key_len, const char *data, int data_len, unsigned int *digest_len) { - unsigned char *digest = (unsigned char *) malloc(EVP_MAX_MD_SIZE); - HMAC(EVP_sha256(), key, key_len, (const unsigned char *) data, data_len, + unsigned char *digest = (unsigned char *)malloc(EVP_MAX_MD_SIZE); + HMAC(EVP_sha256(), key, key_len, (const unsigned char *)data, data_len, digest, digest_len); return digest; } @@ -150,17 +151,17 @@ bool jwt_verifyJWT(const char *token, const char *secret) { size_t payload_len = dot2 - dot1 - 1; size_t sig_len = strlen(dot2 + 1); - char *header = (char *) malloc(header_len + 1); + char *header = (char *)malloc(header_len + 1); strncpy(header, token, header_len); header[header_len] = '\0'; - char *payload = (char *) malloc(payload_len + 1); + char *payload = (char *)malloc(payload_len + 1); strncpy(payload, dot1 + 1, payload_len); payload[payload_len] = '\0'; char *signature = strndup(dot2 + 1, sig_len); - char *signing_input = (char *) malloc(header_len + payload_len + 2); + char *signing_input = (char *)malloc(header_len + payload_len + 2); sprintf(signing_input, "%s.%s", header, payload); int expected_sig_len; @@ -181,7 +182,7 @@ bool jwt_verifyJWT(const char *token, const char *secret) { int payload_bin_len; unsigned char *payload_bin = jwt_base64url_decode(payload, payload_len, &payload_bin_len); - char *payload_str = (char *) malloc(payload_bin_len + 1); + char *payload_str = (char *)malloc(payload_bin_len + 1); memcpy(payload_str, payload_bin, payload_bin_len); payload_str[payload_bin_len] = '\0'; @@ -190,7 +191,7 @@ bool jwt_verifyJWT(const char *token, const char *secret) { cJSON *exp = cJSON_GetObjectItemCaseSensitive(json_payload, "exp"); if (cJSON_IsNumber(exp)) { time_t now = time(nullptr); - if (now >= (time_t) exp->valuedouble) { + if (now >= (time_t)exp->valuedouble) { exp_valid = false; } } @@ -217,14 +218,14 @@ cJSON *jwt_get_payload(const char *token) { if (!dot1 || !dot2) return nullptr; size_t payload_len = dot2 - dot1 - 1; - char *payload = (char *) malloc(payload_len + 1); + char *payload = (char *)malloc(payload_len + 1); strncpy(payload, dot1 + 1, payload_len); payload[payload_len] = '\0'; int payload_bin_len; unsigned char *payload_bin = jwt_base64url_decode(payload, payload_len, &payload_bin_len); - char *payload_str = (char *) malloc(payload_bin_len + 1); + char *payload_str = (char *)malloc(payload_bin_len + 1); memcpy(payload_str, payload_bin, payload_bin_len); payload_str[payload_bin_len] = '\0'; @@ -243,14 +244,14 @@ cJSON *jwt_get_header(const char *token) { if (!dot1) return nullptr; size_t header_len = dot1 - token; - char *header = (char *) malloc(header_len + 1); + char *header = (char *)malloc(header_len + 1); strncpy(header, token, header_len); header[header_len] = '\0'; int header_bin_len; unsigned char *header_bin = jwt_base64url_decode(header, header_len, &header_bin_len); - char *header_str = (char *) malloc(header_bin_len + 1); + char *header_str = (char *)malloc(header_bin_len + 1); memcpy(header_str, header_bin, header_bin_len); header_str[header_bin_len] = '\0'; diff --git a/src/main.c b/src/main.c index 4b063dc..a0e3754 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,10 @@ #include #include + +#ifdef USE_SQLITE3 #include +#endif + #include "config.h" #include "cors.h" #include "database.h" @@ -25,7 +29,7 @@ static const struct route routes[] = { void ev_handler(struct mg_connection *c, int ev, void *ev_data) { if (ev == MG_EV_ERROR) { - MG_LOG(MG_LL_ERROR, ("Ошибка соединения: %s", (char *) ev_data)); + MG_LOG(MG_LL_ERROR, ("Ошибка соединения: %s", (char *)ev_data)); } const bool tls_enabled = cm_get_parameter_as_bool(config, "tls_enabled"); if (tls_enabled) { @@ -40,7 +44,7 @@ void ev_handler(struct mg_connection *c, int ev, void *ev_data) { } } if (ev == MG_EV_HTTP_MSG) { - const auto hm = (struct mg_http_message *) ev_data; + const auto hm = (struct mg_http_message *)ev_data; bool route_found = false; for (int i = 0; routes[i].path != nullptr; i++) { @@ -66,7 +70,7 @@ int main(void) { migrate_db(); const char *default_users_filename = cm_get_parameter_as_string(config, "default_users_file"); - if (default_users_filename) db_get_users_from_file("users.json"); + if (default_users_filename) db_get_users_from_file(default_users_filename); struct mg_mgr mgr; mg_log_set(MG_LL_DEBUG); @@ -80,8 +84,9 @@ int main(void) { const char *tls_address = cm_get_parameter_as_string(config, "tls_address"); char https_address[64]; snprintf(https_address, sizeof(https_address), "https://%s", tls_address); - tls_address ? mg_http_listen(&mgr, https_address, ev_handler, nullptr) - : mg_http_listen(&mgr, "https://0.0.0.0:8223", ev_handler, nullptr); + tls_address + ? mg_http_listen(&mgr, https_address, ev_handler, nullptr) + : mg_http_listen(&mgr, "https://0.0.0.0:8223", ev_handler, nullptr); } for (;;) { mg_mgr_poll(&mgr, 1000); diff --git a/src/register_user.c b/src/register_user.c index a183e0e..5dc9fc3 100644 --- a/src/register_user.c +++ b/src/register_user.c @@ -2,12 +2,9 @@ void register_user(struct mg_connection *c, struct mg_http_message *hm) { if (hm->body.len == 0) { - mg_http_reply( - c, 400, - HTTP_HEADERS, - "{%m:%m}", MG_ESC("error"), - MG_ESC("must have , , , , ")); + mg_http_reply(c, 400, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC("must have , , , , ")); return; } cJSON *jsonbody = cJSON_Parse(hm->body.buf); @@ -17,12 +14,9 @@ void register_user(struct mg_connection *c, struct mg_http_message *hm) { cJSON *group = cJSON_GetObjectItem(jsonbody, "group"); cJSON *is_superuser = cJSON_GetObjectItem(jsonbody, "is_superuser"); if (username == nullptr || password == nullptr || email == nullptr) { - mg_http_reply( - c, 400, - HTTP_HEADERS, - "{%m:%m}", MG_ESC("error"), - MG_ESC("must have , , , , ")); + mg_http_reply(c, 400, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC("must have , , , , ")); return; } if (group == nullptr) { @@ -34,12 +28,10 @@ void register_user(struct mg_connection *c, struct mg_http_message *hm) { const bool is_superuser_value = is_superuser->valueint ? true : false; User *new_user_data = db_insert_user( username->valuestring, email->valuestring, password->valuestring, - group->valuestring, (const bool *) is_superuser_value); + group->valuestring, &is_superuser_value); if (new_user_data == nullptr) { - mg_http_reply( - c, 500, - HTTP_HEADERS, - "{%m:%m}", MG_ESC("error"), MG_ESC("failed to create user")); + mg_http_reply(c, 500, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC("failed to create user")); return; } char responsedata[2048] = {0}; @@ -49,9 +41,6 @@ void register_user(struct mg_connection *c, struct mg_http_message *hm) { new_user_data->id, new_user_data->username, new_user_data->email, new_user_data->group, new_user_data->is_superuser); - mg_http_reply( - c, 200, - HTTP_HEADERS, - responsedata); + mg_http_reply(c, 200, HTTP_HEADERS, responsedata); free_user(new_user_data); } diff --git a/src/static.c b/src/static.c index af5bb1c..69c5d2a 100644 --- a/src/static.c +++ b/src/static.c @@ -1,7 +1,9 @@ #include "static.h" + #include "config.h" void root_handler(struct mg_connection *c, struct mg_http_message *hm) { - struct mg_http_serve_opts opts = {.root_dir = cm_get_parameter_as_string(config, "web")}; + struct mg_http_serve_opts opts = { + .root_dir = cm_get_parameter_as_string(config, "web")}; mg_http_serve_dir(c, hm, &opts); } \ No newline at end of file diff --git a/src/user.c b/src/user.c index 5699442..21a7d78 100644 --- a/src/user.c +++ b/src/user.c @@ -1,4 +1,5 @@ #include "user.h" + #include #include diff --git a/src/user.h b/src/user.h index 85fb364..381dacc 100644 --- a/src/user.h +++ b/src/user.h @@ -2,7 +2,10 @@ #include #include + +#ifdef USE_SQLITE3 #include +#endif #define HTTP_HEADERS \ "Content-Type: application/json\r\nAccess-Control-Allow-Origin: *\r\n" diff --git a/src/utils.c b/src/utils.c index f35ca32..2c1a018 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,11 +1,13 @@ #include "utils.h" + #include #include + #include "user.h" request_with_token *check_body(const struct mg_http_message *hm) { if (hm->body.len == 0) { - return new_request_with_token(nullptr, nullptr, (char *) "must have token"); + return new_request_with_token(nullptr, nullptr, (char *)"must have token"); } cJSON *json_body = cJSON_Parse(hm->body.buf); @@ -13,9 +15,9 @@ request_with_token *check_body(const struct mg_http_message *hm) { if (token == NULL) { const char *error_ptr = cJSON_GetErrorPtr(); if (error_ptr != NULL) { - return new_request_with_token(nullptr, nullptr, (char *) error_ptr); + return new_request_with_token(nullptr, nullptr, (char *)error_ptr); } - return new_request_with_token(nullptr, nullptr, (char *) "must have token"); + return new_request_with_token(nullptr, nullptr, (char *)"must have token"); } return new_request_with_token(strdup(token->valuestring), json_body, nullptr); } diff --git a/src/verify_token.c b/src/verify_token.c index d34aa63..5ed6237 100644 --- a/src/verify_token.c +++ b/src/verify_token.c @@ -3,16 +3,36 @@ #include "utils.h" void verify_token(struct mg_connection *c, struct mg_http_message *hm) { - const request_with_token *data = check_body(hm); + request_with_token *data = check_body(hm); if (data->error != nullptr) { - mg_http_reply(c, 403, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), MG_ESC(data->error)); + mg_http_reply(c, 403, HTTP_HEADERS, "{%m:false}", MG_ESC("valid")); return; } const bool valid = jwt_verifyJWT(data->token, JWT_DEFAULT_SECRET); if (!valid) { - mg_http_reply(c, 403, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), - MG_ESC("invalid token")); + mg_http_reply(c, 403, HTTP_HEADERS, "{%m:false}", MG_ESC("valid")); + free_request_with_token(data); + return; + } + cJSON *payload = jwt_get_payload(data->token); + char *username = + strdup(cJSON_GetObjectItem(payload, "username")->valuestring); + if (!username) { + free_request_with_token(data); + cJSON_Delete(payload); + mg_http_reply(c, 500, HTTP_HEADERS, "{%m:false}", MG_ESC("valid")); + return; + } + User *user = db_get_user_by_username(username); + if (!user) { + free_request_with_token(data); + cJSON_Delete(payload); + free(username); + mg_http_reply(c, 404, HTTP_HEADERS, "{%m:false}", MG_ESC("valid")); return; } mg_http_reply(c, 200, HTTP_HEADERS, "{%m:true}", MG_ESC("valid")); + free_request_with_token(data); + free(username); + free_user(user); } diff --git a/tests.sh b/tests.sh index bc8bcd7..e4e8ea0 100755 --- a/tests.sh +++ b/tests.sh @@ -7,6 +7,8 @@ GREEN="\033[0;32m" RED="\033[0;31m" YELLOW="\033[1;33m" CYAN="\033[0;36m" +HOST="localhost" +PORT="8222" ./auth_service &> auth_service.log & sleep 0.1 @@ -19,7 +21,7 @@ curl \ --silent \ -X POST \ -d '{"username":"tola","password":"e0c7bfa5b8e4ae0cecfc1f14093a71e05c27abd93a3850fc35f008c3baf866b4"}' \ - localhost:8222/api/token &> api_token_test.log + $HOST:$PORT/api/token &> api_token_test.log sleep 0.1 res=$(cat api_token_test.log) if [[ "$res" == *"token"* ]]; then @@ -36,7 +38,7 @@ curl \ --silent \ -X POST \ -d '{"username":"tola","password":"288"}' \ - localhost:8222/api/token &> api_token_wrong_password_test.log + $HOST:$PORT/api/token &> api_token_wrong_password_test.log sleep 0.1 res=$(cat api_token_wrong_password_test.log) if [[ "$res" == *"{\"error\":\"wrong password\"}"* ]]; then @@ -53,7 +55,7 @@ curl \ --silent \ -X POST \ -d '{"username":"toa","password":"2808"}' \ - localhost:8222/api/token &> api_token_wrong_username_test.log + $HOST:$PORT/api/token &> api_token_wrong_username_test.log sleep 0.1 res=$(cat api_token_wrong_username_test.log) if [[ "$res" == *"{\"error\":\"couldn't find user\"}"* ]]; then @@ -70,7 +72,7 @@ curl \ --silent \ -X POST \ -d '' \ - localhost:8222/api/token &> api_token_no_data_test.log + $HOST:$PORT/api/token &> api_token_no_data_test.log sleep 0.1 res=$(cat api_token_no_data_test.log) if [[ "$res" == *"{\"error\":\"must have username and password\"}"* ]]; then @@ -87,7 +89,7 @@ curl \ --silent \ -X POST \ -d '{{asdf}}}asdfasdfasdf""asdf' \ - localhost:8222/api/token &> api_token_not_valid_json_test.log + $HOST:$PORT/api/token &> api_token_not_valid_json_test.log sleep 0.1 res=$(cat api_token_not_valid_json_test.log) if [[ "$res" == *"error"* ]]; then @@ -104,7 +106,7 @@ curl \ --silent \ -X POST \ -d $(cat api_token_test.log) \ - localhost:8222/api/token/verify &> api_token_verify_test.log + $HOST:$PORT/api/token/verify &> api_token_verify_test.log sleep 0.1 res=$(cat api_token_verify_test.log) if [[ "$res" == *'{"valid":true}'* ]]; then @@ -121,10 +123,10 @@ curl \ --silent \ -X POST \ -d '' \ - localhost:8222/api/token/verify &> api_token_verify_no_data_test.log + $HOST:$PORT/api/token/verify &> api_token_verify_no_data_test.log sleep 0.1 res=$(cat api_token_verify_no_data_test.log) -if [[ "$res" == *'{"error":"must have token"}'* ]]; then +if [[ "$res" == *'{"valid":false}'* ]]; then printf "[$GREEN OK $RESET]\n" success=$(($success+1)) else @@ -138,10 +140,10 @@ curl \ --silent \ -X POST \ -d '{"token":"asdf"}' \ - localhost:8222/api/token/verify &> api_token_verify_wrong_token_test.log + $HOST:$PORT/api/token/verify &> api_token_verify_wrong_token_test.log sleep 0.1 res=$(cat api_token_verify_wrong_token_test.log) -if [[ "$res" == *'{"error":"invalid token"}'* ]]; then +if [[ "$res" == *'{"valid":false}'* ]]; then printf "[$GREEN OK $RESET]\n" success=$(($success+1)) else @@ -155,10 +157,10 @@ curl \ --silent \ -X POST \ -d 'asdf[apsdfqopwjf[9qfm93qq89n]]' \ - localhost:8222/api/token/verify &> api_token_verify_wrong_json_test.log + $HOST:$PORT/api/token/verify &> api_token_verify_wrong_json_test.log sleep 0.1 res=$(cat api_token_verify_wrong_json_test.log) -if [[ "$res" == *'error'* ]]; then +if [[ "$res" == *'{"valid":false}'* ]]; then printf "[$GREEN OK $RESET]\n" success=$(($success+1)) else @@ -172,7 +174,7 @@ curl \ --silent \ -X POST \ -d $(cat api_token_test.log) \ - localhost:8222/api/users &> api_users_test.log + $HOST:$PORT/api/users &> api_users_test.log sleep 0.1 res=$(cat api_users_test.log) if [[ "$res" == *'username'* ]]; then @@ -189,7 +191,7 @@ curl \ --silent \ -X POST \ -d '{"token":"asdf"}' \ - localhost:8222/api/users &> api_users_wrong_token_test.log + $HOST:$PORT/api/users &> api_users_wrong_token_test.log sleep 0.1 res=$(cat api_users_wrong_token_test.log) if [[ "$res" == *'{"error":"invalid token"}'* ]]; then @@ -206,7 +208,7 @@ curl \ --silent \ -X POST \ -d '' \ - localhost:8222/api/users &> api_users_no_data_test.log + $HOST:$PORT/api/users &> api_users_no_data_test.log sleep 0.1 res=$(cat api_users_no_data_test.log) if [[ "$res" == *'{"error":"must have token"}'* ]]; then @@ -223,7 +225,7 @@ curl \ --silent \ -X POST \ -d 'ahsdlfhjalighafina[a[][apofj OFFW[Efflja]]]' \ - localhost:8222/api/users &> api_users_wrong_json_test.log + $HOST:$PORT/api/users &> api_users_wrong_json_test.log sleep 0.1 res=$(cat api_users_wrong_json_test.log) if [[ "$res" == *'error'* ]]; then @@ -240,7 +242,7 @@ curl \ --silent \ -X POST \ -d $(cat api_token_test.log) \ - localhost:8222/api/users/user &> api_users_user_test.log + $HOST:$PORT/api/users/user &> api_users_user_test.log sleep 0.1 res=$(cat api_users_user_test.log) if [[ "$res" == *'username'* ]]; then @@ -257,7 +259,7 @@ curl \ --silent \ -X POST \ -d '{"token":"asdf"}' \ - localhost:8222/api/users/user &> api_users_user_wrong_token_test.log + $HOST:$PORT/api/users/user &> api_users_user_wrong_token_test.log sleep 0.1 res=$(cat api_users_user_wrong_token_test.log) if [[ "$res" == *'{"error":"invalid token"}'* ]]; then @@ -274,7 +276,7 @@ curl \ --silent \ -X POST \ -d '' \ - localhost:8222/api/users/user &> api_users_user_no_data_test.log + $HOST:$PORT/api/users/user &> api_users_user_no_data_test.log sleep 0.1 res=$(cat api_users_user_no_data_test.log) if [[ "$res" == *'{"error":"must have token"}'* ]]; then @@ -291,7 +293,7 @@ curl \ --silent \ -X POST \ -d 'alskodjfqjvoq3vn[q90\audv0q j89fvn 2vp]' \ - localhost:8222/api/users/user &> api_users_user_wrong_json_test.log + $HOST:$PORT/api/users/user &> api_users_user_wrong_json_test.log sleep 0.1 res=$(cat api_users_user_wrong_json_test.log) if [[ "$res" == *'error'* ]]; then @@ -315,7 +317,7 @@ curl \ "is_superuser":false, "token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IDEsInVzZXJuYW1lIjogInRvbGEiLCJlbWFpbCI6ICJtYWlsQGV4YW1wbGUuY29tIiwiZ3JvdXAiOiAicm9vdCIsImlzX3N1cGVydXNlciI6IHRydWV9.QGUnCWPmp5hWAtGFTGDMw2SugZqLsYfMboeFU4UQLXQ" }' \ - localhost:8222/api/users/add &> api_users_add_test.log + $HOST:$PORT/api/users/add &> api_users_add_test.log sleep 0.1 res=$(cat api_users_add_test.log) if [[ "$res" == *'username'* ]]; then @@ -332,13 +334,13 @@ reqdata=$(curl \ --silent \ -X POST \ -d '{"username":"asdff","password":"asdf"}' \ - localhost:8222/api/token) + $HOST:$PORT/api/token) sleep 0.1 curl \ --silent \ -X DELETE \ -d $reqdata \ - localhost:8222/api/users &> delete_api_users_test.log + $HOST:$PORT/api/users &> delete_api_users_test.log sleep 0.1 res=$(cat delete_api_users_test.log) if [[ "$res" == *'{"success": true}'* ]]; then @@ -356,7 +358,7 @@ curl \ --silent \ -X DELETE \ -d $reqdata \ - localhost:8222/api/users &> delete_api_users_second_delete_test.log + $HOST:$PORT/api/users &> delete_api_users_second_delete_test.log sleep 0.1 res=$(cat delete_api_users_second_delete_test.log) if [[ "$res" == *'{"success": false}'* ]]; then @@ -373,7 +375,7 @@ curl \ --silent \ -X DELETE \ -d '$reqdata' \ - localhost:8222/api/users &> delete_api_users_wrong_json_test.log + $HOST:$PORT/api/users &> delete_api_users_wrong_json_test.log sleep 0.1 res=$(cat delete_api_users_wrong_json_test.log) if [[ "$res" == *'error'* ]]; then @@ -390,7 +392,7 @@ curl \ --silent \ -X DELETE \ -d '{"token":"asdf"}' \ - localhost:8222/api/users &> delete_api_users_wrong_token_test.log + $HOST:$PORT/api/users &> delete_api_users_wrong_token_test.log sleep 0.1 res=$(cat delete_api_users_wrong_token_test.log) if [[ "$res" == *'{"error":"invalid token"}'* ]]; then @@ -407,7 +409,7 @@ curl \ --silent \ -X DELETE \ -d '' \ - localhost:8222/api/users &> delete_api_users_no_data_test.log + $HOST:$PORT/api/users &> delete_api_users_no_data_test.log sleep 0.1 res=$(cat delete_api_users_no_data_test.log) if [[ "$res" == *'{"error":"must have token"}'* ]]; then @@ -425,7 +427,7 @@ curl \ --silent \ -X POST \ -d "{\"old_password\":\"e0c7bfa5b8e4ae0cecfc1f14093a71e05c27abd93a3850fc35f008c3baf866b4\",\"new_password\":\"1234\",$reqtoken}" \ - localhost:8222/api/users/password &> api_users_password_test.log + $HOST:$PORT/api/users/password &> api_users_password_test.log sleep 0.1 res=$(cat api_users_password_test.log) if [[ "$res" == *'{"success": true}'* ]]; then @@ -442,7 +444,7 @@ curl \ --silent \ -X POST \ -d "" \ - localhost:8222/api/users/password &> api_users_password_no_data_test.log + $HOST:$PORT/api/users/password &> api_users_password_no_data_test.log sleep 0.1 res=$(cat api_users_password_no_data_test.log) if [[ "$res" == *'{"error":"must have token, old_password, new_password"}'* ]]; then @@ -459,7 +461,7 @@ curl \ --silent \ -X POST \ -d "ijansd fu9q303ghq9" \ - localhost:8222/api/users/password &> api_users_password_wrong_json_test.log + $HOST:$PORT/api/users/password &> api_users_password_wrong_json_test.log sleep 0.1 res=$(cat api_users_password_wrong_json_test.log) if [[ "$res" == *'error'* ]]; then @@ -482,7 +484,7 @@ curl \ \"group\":\"admin\", \"is_superuser\":true, $reqtoken}" \ - localhost:8222/api/users &> put_api_users_test.log + $HOST:$PORT/api/users &> put_api_users_test.log sleep 0.1 res=$(cat put_api_users_test.log) if [[ "$res" == *'username'* ]]; then @@ -499,7 +501,7 @@ curl \ --silent \ -X PUT \ -d "" \ - localhost:8222/api/users &> put_api_users_no_data_test.log + $HOST:$PORT/api/users &> put_api_users_no_data_test.log sleep 0.1 res=$(cat put_api_users_no_data_test.log) if [[ "$res" == *'{"error":"must have token, new_user_data"}'* ]]; then @@ -516,7 +518,7 @@ curl \ --silent \ -X PUT \ -d "hiusdf 7qyt0 y qy40" \ - localhost:8222/api/users &> put_api_users_wrong_json_test.log + $HOST:$PORT/api/users &> put_api_users_wrong_json_test.log sleep 0.1 res=$(cat put_api_users_wrong_json_test.log) if [[ "$res" == *'error'* ]]; then @@ -539,7 +541,7 @@ curl \ "group":"users", "is_superuser":false }' \ - localhost:8222/api/register &> api_register_test.log + $HOST:$PORT/api/register &> api_register_test.log sleep 0.1 res=$(cat api_register_test.log) if [[ "$res" == *'username'* ]]; then @@ -561,7 +563,7 @@ curl \ "group":"users", "is_superuser":false }' \ - localhost:8222/api/register &> api_register_without_username_test.log + $HOST:$PORT/api/register &> api_register_without_username_test.log sleep 0.1 res=$(cat api_register_without_username_test.log) if [[ "$res" == *'{"error":"must have , , , , "}'* ]]; then @@ -583,7 +585,7 @@ curl \ "group":"users", "is_superuser":false }' \ - localhost:8222/api/register &> api_register_without_email_test.log + $HOST:$PORT/api/register &> api_register_without_email_test.log sleep 0.1 res=$(cat api_register_without_email_test.log) if [[ "$res" == *'{"error":"must have , , , , "}'* ]]; then @@ -605,7 +607,7 @@ curl \ "group":"users", "is_superuser":false }' \ - localhost:8222/api/register &> api_register_without_password_test.log + $HOST:$PORT/api/register &> api_register_without_password_test.log sleep 0.1 res=$(cat api_register_without_password_test.log) if [[ "$res" == *'{"error":"must have , , , , "}'* ]]; then @@ -627,7 +629,7 @@ curl \ "password":"qwer", "is_superuser":false }' \ - localhost:8222/api/register &> api_register_without_group_test.log + $HOST:$PORT/api/register &> api_register_without_group_test.log sleep 0.1 res=$(cat api_register_without_group_test.log) if [[ "$res" == *'username'* ]]; then @@ -649,7 +651,7 @@ curl \ "password":"zxcv", "group":"users" }' \ - localhost:8222/api/register &> api_register_without_is_superuser_test.log + $HOST:$PORT/api/register &> api_register_without_is_superuser_test.log sleep 0.1 res=$(cat api_register_without_is_superuser_test.log) if [[ "$res" == *'username'* ]]; then @@ -671,7 +673,7 @@ curl \ "password":"zxcv", "group":"users" }' \ - localhost:8222/api/register &> api_register_second_register_test.log + $HOST:$PORT/api/register &> api_register_second_register_test.log sleep 0.1 res=$(cat api_register_second_register_test.log) if [[ "$res" == *'{"error":"failed to create user"}'* ]]; then @@ -688,7 +690,7 @@ curl \ --silent \ -X POST \ -d 'najsnvpnvq234890vn9qq234vqui3v' \ - localhost:8222/api/register &> api_register_wrong_json_test.log + $HOST:$PORT/api/register &> api_register_wrong_json_test.log sleep 0.1 res=$(cat api_register_wrong_json_test.log) if [[ "$res" == *'error'* ]]; then @@ -705,7 +707,7 @@ curl \ --silent \ -X POST \ -d '' \ - localhost:8222/api/register &> api_register_no_data_test.log + $HOST:$PORT/api/register &> api_register_no_data_test.log sleep 0.1 res=$(cat api_register_no_data_test.log) if [[ "$res" == *'{"error":"must have , , , , "}'* ]]; then diff --git a/toolchain_files/aarch64-buildroot-linux-uclibc.cmake b/toolchain_files/aarch64-buildroot-linux-uclibc.cmake new file mode 100644 index 0000000..f989251 --- /dev/null +++ b/toolchain_files/aarch64-buildroot-linux-uclibc.cmake @@ -0,0 +1 @@ +set(CMAKE_C_COMPILER aarch64-buildroot-linux-uclibc-gcc) diff --git a/toolchain_files/aarch64-buildroot-linux-uclibc.toml b/toolchain_files/aarch64-buildroot-linux-uclibc.toml new file mode 100644 index 0000000..96e5398 --- /dev/null +++ b/toolchain_files/aarch64-buildroot-linux-uclibc.toml @@ -0,0 +1,11 @@ +[binaries] +c = 'aarch64-buildroot-linux-uclibc-gcc' +ar = 'aarch64-buildroot-linux-uclibc-ar' +strip = 'aarch64-buildroot-linux-uclibc-strip' +ld = 'aarch64-buildroot-linux-uclibc-ld' + +[host_machine] +system = 'linux' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' diff --git a/toolchain_files/arm-buildroot-linux-uclibcgnueabihf.cmake b/toolchain_files/arm-buildroot-linux-uclibcgnueabihf.cmake new file mode 100644 index 0000000..c909582 --- /dev/null +++ b/toolchain_files/arm-buildroot-linux-uclibcgnueabihf.cmake @@ -0,0 +1 @@ +set(CMAKE_C_COMPILER arm-buildroot-linux-uclibcgnueabihf-gcc) diff --git a/toolchain_files/arm-buildroot-linux-uclibcgnueabihf.toml b/toolchain_files/arm-buildroot-linux-uclibcgnueabihf.toml new file mode 100644 index 0000000..8db3bec --- /dev/null +++ b/toolchain_files/arm-buildroot-linux-uclibcgnueabihf.toml @@ -0,0 +1,11 @@ +[binaries] +c = 'arm-buildroot-linux-uclibcgnueabihf-gcc' +ar = 'arm-buildroot-linux-uclibcgnueabihf-ar' +strip = 'arm-buildroot-linux-uclibcgnueabihf-strip' +ld = 'arm-buildroot-linux-uclibcgnueabihf-ld' + +[host_machine] +system = 'linux' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' diff --git a/toolchain_files/x86_64-buildroot-linux-uclibc.cmake b/toolchain_files/x86_64-buildroot-linux-uclibc.cmake new file mode 100644 index 0000000..695cf6d --- /dev/null +++ b/toolchain_files/x86_64-buildroot-linux-uclibc.cmake @@ -0,0 +1 @@ +set(CMAKE_C_COMPILER x86_64-buildroot-linux-uclibc-gcc) diff --git a/toolchain_files/x86_64-buildroot-linux-uclibc.toml b/toolchain_files/x86_64-buildroot-linux-uclibc.toml new file mode 100644 index 0000000..dc8f824 --- /dev/null +++ b/toolchain_files/x86_64-buildroot-linux-uclibc.toml @@ -0,0 +1,11 @@ +[binaries] +c = 'x86_64-buildroot-linux-uclibc-gcc' +ar = 'x86_64-buildroot-linux-uclibc-ar' +strip = 'x86_64-buildroot-linux-uclibc-strip' +ld = 'x86_64-buildroot-linux-uclibc-ld' + +[host_machine] +system = 'linux' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' diff --git a/web/index.html b/web/index.html index faa0829..174913a 100644 --- a/web/index.html +++ b/web/index.html @@ -215,6 +215,7 @@ + diff --git a/web/js/crypto-js.min.js b/web/js/crypto-js.min.js new file mode 100644 index 0000000..20b3099 --- /dev/null +++ b/web/js/crypto-js.min.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports?module.exports=exports=e():"function"==typeof define&&define.amd?define([],e):t.CryptoJS=e()}(this,function(){var n,o,s,a,h,t,e,l,r,i,c,f,d,u,p,S,x,b,A,H,z,_,v,g,y,B,w,k,m,C,D,E,R,M,F,P,W,O,I,U=U||function(h){var i;if("undefined"!=typeof window&&window.crypto&&(i=window.crypto),"undefined"!=typeof self&&self.crypto&&(i=self.crypto),!(i=!(i=!(i="undefined"!=typeof globalThis&&globalThis.crypto?globalThis.crypto:i)&&"undefined"!=typeof window&&window.msCrypto?window.msCrypto:i)&&"undefined"!=typeof global&&global.crypto?global.crypto:i)&&"function"==typeof require)try{i=require("crypto")}catch(t){}var r=Object.create||function(t){return e.prototype=t,t=new e,e.prototype=null,t};function e(){}var t={},n=t.lib={},o=n.Base={extend:function(t){var e=r(this);return t&&e.mixIn(t),e.hasOwnProperty("init")&&this.init!==e.init||(e.init=function(){e.$super.init.apply(this,arguments)}),(e.init.prototype=e).$super=this,e},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},l=n.WordArray=o.extend({init:function(t,e){t=this.words=t||[],this.sigBytes=null!=e?e:4*t.length},toString:function(t){return(t||c).stringify(this)},concat:function(t){var e=this.words,r=t.words,i=this.sigBytes,n=t.sigBytes;if(this.clamp(),i%4)for(var o=0;o>>2]>>>24-o%4*8&255;e[i+o>>>2]|=s<<24-(i+o)%4*8}else for(var c=0;c>>2]=r[c>>>2];return this.sigBytes+=n,this},clamp:function(){var t=this.words,e=this.sigBytes;t[e>>>2]&=4294967295<<32-e%4*8,t.length=h.ceil(e/4)},clone:function(){var t=o.clone.call(this);return t.words=this.words.slice(0),t},random:function(t){for(var e=[],r=0;r>>2]>>>24-n%4*8&255;i.push((o>>>4).toString(16)),i.push((15&o).toString(16))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>3]|=parseInt(t.substr(i,2),16)<<24-i%8*4;return new l.init(r,e/2)}},a=s.Latin1={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n>>2]>>>24-n%4*8&255;i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>2]|=(255&t.charCodeAt(i))<<24-i%4*8;return new l.init(r,e)}},f=s.Utf8={stringify:function(t){try{return decodeURIComponent(escape(a.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return a.parse(unescape(encodeURIComponent(t)))}},d=n.BufferedBlockAlgorithm=o.extend({reset:function(){this._data=new l.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=f.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(t){var e,r=this._data,i=r.words,n=r.sigBytes,o=this.blockSize,s=n/(4*o),c=(s=t?h.ceil(s):h.max((0|s)-this._minBufferSize,0))*o,n=h.min(4*c,n);if(c){for(var a=0;a>>32-e}function j(t,e,r,i){var n,o=this._iv;o?(n=o.slice(0),this._iv=void 0):n=this._prevBlock,i.encryptBlock(n,0);for(var s=0;s>24&255)?(r=t>>8&255,i=255&t,255===(e=t>>16&255)?(e=0,255===r?(r=0,255===i?i=0:++i):++r):++e,t=0,t+=e<<16,t+=r<<8,t+=i):t+=1<<24,t}function N(){for(var t=this._X,e=this._C,r=0;r<8;r++)E[r]=e[r];e[0]=e[0]+1295307597+this._b|0,e[1]=e[1]+3545052371+(e[0]>>>0>>0?1:0)|0,e[2]=e[2]+886263092+(e[1]>>>0>>0?1:0)|0,e[3]=e[3]+1295307597+(e[2]>>>0>>0?1:0)|0,e[4]=e[4]+3545052371+(e[3]>>>0>>0?1:0)|0,e[5]=e[5]+886263092+(e[4]>>>0>>0?1:0)|0,e[6]=e[6]+1295307597+(e[5]>>>0>>0?1:0)|0,e[7]=e[7]+3545052371+(e[6]>>>0>>0?1:0)|0,this._b=e[7]>>>0>>0?1:0;for(r=0;r<8;r++){var i=t[r]+e[r],n=65535&i,o=i>>>16;R[r]=((n*n>>>17)+n*o>>>15)+o*o^((4294901760&i)*i|0)+((65535&i)*i|0)}t[0]=R[0]+(R[7]<<16|R[7]>>>16)+(R[6]<<16|R[6]>>>16)|0,t[1]=R[1]+(R[0]<<8|R[0]>>>24)+R[7]|0,t[2]=R[2]+(R[1]<<16|R[1]>>>16)+(R[0]<<16|R[0]>>>16)|0,t[3]=R[3]+(R[2]<<8|R[2]>>>24)+R[1]|0,t[4]=R[4]+(R[3]<<16|R[3]>>>16)+(R[2]<<16|R[2]>>>16)|0,t[5]=R[5]+(R[4]<<8|R[4]>>>24)+R[3]|0,t[6]=R[6]+(R[5]<<16|R[5]>>>16)+(R[4]<<16|R[4]>>>16)|0,t[7]=R[7]+(R[6]<<8|R[6]>>>24)+R[5]|0}function q(){for(var t=this._X,e=this._C,r=0;r<8;r++)O[r]=e[r];e[0]=e[0]+1295307597+this._b|0,e[1]=e[1]+3545052371+(e[0]>>>0>>0?1:0)|0,e[2]=e[2]+886263092+(e[1]>>>0>>0?1:0)|0,e[3]=e[3]+1295307597+(e[2]>>>0>>0?1:0)|0,e[4]=e[4]+3545052371+(e[3]>>>0>>0?1:0)|0,e[5]=e[5]+886263092+(e[4]>>>0>>0?1:0)|0,e[6]=e[6]+1295307597+(e[5]>>>0>>0?1:0)|0,e[7]=e[7]+3545052371+(e[6]>>>0>>0?1:0)|0,this._b=e[7]>>>0>>0?1:0;for(r=0;r<8;r++){var i=t[r]+e[r],n=65535&i,o=i>>>16;I[r]=((n*n>>>17)+n*o>>>15)+o*o^((4294901760&i)*i|0)+((65535&i)*i|0)}t[0]=I[0]+(I[7]<<16|I[7]>>>16)+(I[6]<<16|I[6]>>>16)|0,t[1]=I[1]+(I[0]<<8|I[0]>>>24)+I[7]|0,t[2]=I[2]+(I[1]<<16|I[1]>>>16)+(I[0]<<16|I[0]>>>16)|0,t[3]=I[3]+(I[2]<<8|I[2]>>>24)+I[1]|0,t[4]=I[4]+(I[3]<<16|I[3]>>>16)+(I[2]<<16|I[2]>>>16)|0,t[5]=I[5]+(I[4]<<8|I[4]>>>24)+I[3]|0,t[6]=I[6]+(I[5]<<16|I[5]>>>16)+(I[4]<<16|I[4]>>>16)|0,t[7]=I[7]+(I[6]<<8|I[6]>>>24)+I[5]|0}return F=(M=U).lib,n=F.Base,o=F.WordArray,(M=M.x64={}).Word=n.extend({init:function(t,e){this.high=t,this.low=e}}),M.WordArray=n.extend({init:function(t,e){t=this.words=t||[],this.sigBytes=null!=e?e:8*t.length},toX32:function(){for(var t=this.words,e=t.length,r=[],i=0;i>>2]|=t[i]<<24-i%4*8;s.call(this,r,e)}else s.apply(this,arguments)}).prototype=P),function(){var t=U,n=t.lib.WordArray,t=t.enc;t.Utf16=t.Utf16BE={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n>>2]>>>16-n%4*8&65535;i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>1]|=t.charCodeAt(i)<<16-i%2*16;return n.create(r,2*e)}};function s(t){return t<<8&4278255360|t>>>8&16711935}t.Utf16LE={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n>>2]>>>16-n%4*8&65535);i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>1]|=s(t.charCodeAt(i)<<16-i%2*16);return n.create(r,2*e)}}}(),a=(w=U).lib.WordArray,w.enc.Base64={stringify:function(t){var e=t.words,r=t.sigBytes,i=this._map;t.clamp();for(var n=[],o=0;o>>2]>>>24-o%4*8&255)<<16|(e[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|e[o+2>>>2]>>>24-(o+2)%4*8&255,c=0;c<4&&o+.75*c>>6*(3-c)&63));var a=i.charAt(64);if(a)for(;n.length%4;)n.push(a);return n.join("")},parse:function(t){var e=t.length,r=this._map;if(!(i=this._reverseMap))for(var i=this._reverseMap=[],n=0;n>>6-o%4*2,c=s|c,i[n>>>2]|=c<<24-n%4*8,n++)}return a.create(i,n)}(t,e,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},h=(F=U).lib.WordArray,F.enc.Base64url={stringify:function(t,e=!0){var r=t.words,i=t.sigBytes,n=e?this._safe_map:this._map;t.clamp();for(var o=[],s=0;s>>2]>>>24-s%4*8&255)<<16|(r[s+1>>>2]>>>24-(s+1)%4*8&255)<<8|r[s+2>>>2]>>>24-(s+2)%4*8&255,a=0;a<4&&s+.75*a>>6*(3-a)&63));var h=n.charAt(64);if(h)for(;o.length%4;)o.push(h);return o.join("")},parse:function(t,e=!0){var r=t.length,i=e?this._safe_map:this._map;if(!(n=this._reverseMap))for(var n=this._reverseMap=[],o=0;o>>6-o%4*2,c=s|c,i[n>>>2]|=c<<24-n%4*8,n++)}return h.create(i,n)}(t,r,n)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",_safe_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"},function(a){var t=U,e=t.lib,r=e.WordArray,i=e.Hasher,e=t.algo,A=[];!function(){for(var t=0;t<64;t++)A[t]=4294967296*a.abs(a.sin(t+1))|0}();e=e.MD5=i.extend({_doReset:function(){this._hash=new r.init([1732584193,4023233417,2562383102,271733878])},_doProcessBlock:function(t,e){for(var r=0;r<16;r++){var i=e+r,n=t[i];t[i]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8)}var o=this._hash.words,s=t[e+0],c=t[e+1],a=t[e+2],h=t[e+3],l=t[e+4],f=t[e+5],d=t[e+6],u=t[e+7],p=t[e+8],_=t[e+9],y=t[e+10],v=t[e+11],g=t[e+12],B=t[e+13],w=t[e+14],k=t[e+15],m=H(m=o[0],b=o[1],x=o[2],S=o[3],s,7,A[0]),S=H(S,m,b,x,c,12,A[1]),x=H(x,S,m,b,a,17,A[2]),b=H(b,x,S,m,h,22,A[3]);m=H(m,b,x,S,l,7,A[4]),S=H(S,m,b,x,f,12,A[5]),x=H(x,S,m,b,d,17,A[6]),b=H(b,x,S,m,u,22,A[7]),m=H(m,b,x,S,p,7,A[8]),S=H(S,m,b,x,_,12,A[9]),x=H(x,S,m,b,y,17,A[10]),b=H(b,x,S,m,v,22,A[11]),m=H(m,b,x,S,g,7,A[12]),S=H(S,m,b,x,B,12,A[13]),x=H(x,S,m,b,w,17,A[14]),m=z(m,b=H(b,x,S,m,k,22,A[15]),x,S,c,5,A[16]),S=z(S,m,b,x,d,9,A[17]),x=z(x,S,m,b,v,14,A[18]),b=z(b,x,S,m,s,20,A[19]),m=z(m,b,x,S,f,5,A[20]),S=z(S,m,b,x,y,9,A[21]),x=z(x,S,m,b,k,14,A[22]),b=z(b,x,S,m,l,20,A[23]),m=z(m,b,x,S,_,5,A[24]),S=z(S,m,b,x,w,9,A[25]),x=z(x,S,m,b,h,14,A[26]),b=z(b,x,S,m,p,20,A[27]),m=z(m,b,x,S,B,5,A[28]),S=z(S,m,b,x,a,9,A[29]),x=z(x,S,m,b,u,14,A[30]),m=C(m,b=z(b,x,S,m,g,20,A[31]),x,S,f,4,A[32]),S=C(S,m,b,x,p,11,A[33]),x=C(x,S,m,b,v,16,A[34]),b=C(b,x,S,m,w,23,A[35]),m=C(m,b,x,S,c,4,A[36]),S=C(S,m,b,x,l,11,A[37]),x=C(x,S,m,b,u,16,A[38]),b=C(b,x,S,m,y,23,A[39]),m=C(m,b,x,S,B,4,A[40]),S=C(S,m,b,x,s,11,A[41]),x=C(x,S,m,b,h,16,A[42]),b=C(b,x,S,m,d,23,A[43]),m=C(m,b,x,S,_,4,A[44]),S=C(S,m,b,x,g,11,A[45]),x=C(x,S,m,b,k,16,A[46]),m=D(m,b=C(b,x,S,m,a,23,A[47]),x,S,s,6,A[48]),S=D(S,m,b,x,u,10,A[49]),x=D(x,S,m,b,w,15,A[50]),b=D(b,x,S,m,f,21,A[51]),m=D(m,b,x,S,g,6,A[52]),S=D(S,m,b,x,h,10,A[53]),x=D(x,S,m,b,y,15,A[54]),b=D(b,x,S,m,c,21,A[55]),m=D(m,b,x,S,p,6,A[56]),S=D(S,m,b,x,k,10,A[57]),x=D(x,S,m,b,d,15,A[58]),b=D(b,x,S,m,B,21,A[59]),m=D(m,b,x,S,l,6,A[60]),S=D(S,m,b,x,v,10,A[61]),x=D(x,S,m,b,a,15,A[62]),b=D(b,x,S,m,_,21,A[63]),o[0]=o[0]+m|0,o[1]=o[1]+b|0,o[2]=o[2]+x|0,o[3]=o[3]+S|0},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;e[i>>>5]|=128<<24-i%32;var n=a.floor(r/4294967296),r=r;e[15+(64+i>>>9<<4)]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8),e[14+(64+i>>>9<<4)]=16711935&(r<<8|r>>>24)|4278255360&(r<<24|r>>>8),t.sigBytes=4*(e.length+1),this._process();for(var e=this._hash,o=e.words,s=0;s<4;s++){var c=o[s];o[s]=16711935&(c<<8|c>>>24)|4278255360&(c<<24|c>>>8)}return e},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});function H(t,e,r,i,n,o,s){s=t+(e&r|~e&i)+n+s;return(s<>>32-o)+e}function z(t,e,r,i,n,o,s){s=t+(e&i|r&~i)+n+s;return(s<>>32-o)+e}function C(t,e,r,i,n,o,s){s=t+(e^r^i)+n+s;return(s<>>32-o)+e}function D(t,e,r,i,n,o,s){s=t+(r^(e|~i))+n+s;return(s<>>32-o)+e}t.MD5=i._createHelper(e),t.HmacMD5=i._createHmacHelper(e)}(Math),P=(M=U).lib,t=P.WordArray,e=P.Hasher,P=M.algo,l=[],P=P.SHA1=e.extend({_doReset:function(){this._hash=new t.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],c=r[4],a=0;a<80;a++){a<16?l[a]=0|t[e+a]:(h=l[a-3]^l[a-8]^l[a-14]^l[a-16],l[a]=h<<1|h>>>31);var h=(i<<5|i>>>27)+c+l[a];h+=a<20?1518500249+(n&o|~n&s):a<40?1859775393+(n^o^s):a<60?(n&o|n&s|o&s)-1894007588:(n^o^s)-899497514,c=s,s=o,o=n<<30|n>>>2,n=i,i=h}r[0]=r[0]+i|0,r[1]=r[1]+n|0,r[2]=r[2]+o|0,r[3]=r[3]+s|0,r[4]=r[4]+c|0},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return e[i>>>5]|=128<<24-i%32,e[14+(64+i>>>9<<4)]=Math.floor(r/4294967296),e[15+(64+i>>>9<<4)]=r,t.sigBytes=4*e.length,this._process(),this._hash},clone:function(){var t=e.clone.call(this);return t._hash=this._hash.clone(),t}}),M.SHA1=e._createHelper(P),M.HmacSHA1=e._createHmacHelper(P),function(n){var t=U,e=t.lib,r=e.WordArray,i=e.Hasher,e=t.algo,o=[],p=[];!function(){function t(t){return 4294967296*(t-(0|t))|0}for(var e=2,r=0;r<64;)!function(t){for(var e=n.sqrt(t),r=2;r<=e;r++)if(!(t%r))return;return 1}(e)||(r<8&&(o[r]=t(n.pow(e,.5))),p[r]=t(n.pow(e,1/3)),r++),e++}();var _=[],e=e.SHA256=i.extend({_doReset:function(){this._hash=new r.init(o.slice(0))},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],c=r[4],a=r[5],h=r[6],l=r[7],f=0;f<64;f++){f<16?_[f]=0|t[e+f]:(d=_[f-15],u=_[f-2],_[f]=((d<<25|d>>>7)^(d<<14|d>>>18)^d>>>3)+_[f-7]+((u<<15|u>>>17)^(u<<13|u>>>19)^u>>>10)+_[f-16]);var d=i&n^i&o^n&o,u=l+((c<<26|c>>>6)^(c<<21|c>>>11)^(c<<7|c>>>25))+(c&a^~c&h)+p[f]+_[f],l=h,h=a,a=c,c=s+u|0,s=o,o=n,n=i,i=u+(((i<<30|i>>>2)^(i<<19|i>>>13)^(i<<10|i>>>22))+d)|0}r[0]=r[0]+i|0,r[1]=r[1]+n|0,r[2]=r[2]+o|0,r[3]=r[3]+s|0,r[4]=r[4]+c|0,r[5]=r[5]+a|0,r[6]=r[6]+h|0,r[7]=r[7]+l|0},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return e[i>>>5]|=128<<24-i%32,e[14+(64+i>>>9<<4)]=n.floor(r/4294967296),e[15+(64+i>>>9<<4)]=r,t.sigBytes=4*e.length,this._process(),this._hash},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});t.SHA256=i._createHelper(e),t.HmacSHA256=i._createHmacHelper(e)}(Math),r=(w=U).lib.WordArray,F=w.algo,i=F.SHA256,F=F.SHA224=i.extend({_doReset:function(){this._hash=new r.init([3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428])},_doFinalize:function(){var t=i._doFinalize.call(this);return t.sigBytes-=4,t}}),w.SHA224=i._createHelper(F),w.HmacSHA224=i._createHmacHelper(F),function(){var t=U,e=t.lib.Hasher,r=t.x64,i=r.Word,n=r.WordArray,r=t.algo;function o(){return i.create.apply(i,arguments)}var t1=[o(1116352408,3609767458),o(1899447441,602891725),o(3049323471,3964484399),o(3921009573,2173295548),o(961987163,4081628472),o(1508970993,3053834265),o(2453635748,2937671579),o(2870763221,3664609560),o(3624381080,2734883394),o(310598401,1164996542),o(607225278,1323610764),o(1426881987,3590304994),o(1925078388,4068182383),o(2162078206,991336113),o(2614888103,633803317),o(3248222580,3479774868),o(3835390401,2666613458),o(4022224774,944711139),o(264347078,2341262773),o(604807628,2007800933),o(770255983,1495990901),o(1249150122,1856431235),o(1555081692,3175218132),o(1996064986,2198950837),o(2554220882,3999719339),o(2821834349,766784016),o(2952996808,2566594879),o(3210313671,3203337956),o(3336571891,1034457026),o(3584528711,2466948901),o(113926993,3758326383),o(338241895,168717936),o(666307205,1188179964),o(773529912,1546045734),o(1294757372,1522805485),o(1396182291,2643833823),o(1695183700,2343527390),o(1986661051,1014477480),o(2177026350,1206759142),o(2456956037,344077627),o(2730485921,1290863460),o(2820302411,3158454273),o(3259730800,3505952657),o(3345764771,106217008),o(3516065817,3606008344),o(3600352804,1432725776),o(4094571909,1467031594),o(275423344,851169720),o(430227734,3100823752),o(506948616,1363258195),o(659060556,3750685593),o(883997877,3785050280),o(958139571,3318307427),o(1322822218,3812723403),o(1537002063,2003034995),o(1747873779,3602036899),o(1955562222,1575990012),o(2024104815,1125592928),o(2227730452,2716904306),o(2361852424,442776044),o(2428436474,593698344),o(2756734187,3733110249),o(3204031479,2999351573),o(3329325298,3815920427),o(3391569614,3928383900),o(3515267271,566280711),o(3940187606,3454069534),o(4118630271,4000239992),o(116418474,1914138554),o(174292421,2731055270),o(289380356,3203993006),o(460393269,320620315),o(685471733,587496836),o(852142971,1086792851),o(1017036298,365543100),o(1126000580,2618297676),o(1288033470,3409855158),o(1501505948,4234509866),o(1607167915,987167468),o(1816402316,1246189591)],e1=[];!function(){for(var t=0;t<80;t++)e1[t]=o()}();r=r.SHA512=e.extend({_doReset:function(){this._hash=new n.init([new i.init(1779033703,4089235720),new i.init(3144134277,2227873595),new i.init(1013904242,4271175723),new i.init(2773480762,1595750129),new i.init(1359893119,2917565137),new i.init(2600822924,725511199),new i.init(528734635,4215389547),new i.init(1541459225,327033209)])},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],c=r[4],a=r[5],h=r[6],l=r[7],f=i.high,d=i.low,u=n.high,p=n.low,_=o.high,y=o.low,v=s.high,g=s.low,B=c.high,w=c.low,k=a.high,m=a.low,S=h.high,x=h.low,b=l.high,r=l.low,A=f,H=d,z=u,C=p,D=_,E=y,R=v,M=g,F=B,P=w,W=k,O=m,I=S,U=x,K=b,X=r,L=0;L<80;L++){var j,T,N=e1[L];L<16?(T=N.high=0|t[e+2*L],j=N.low=0|t[e+2*L+1]):($=(q=e1[L-15]).high,J=q.low,G=(Q=e1[L-2]).high,V=Q.low,Z=(Y=e1[L-7]).high,q=Y.low,Y=(Q=e1[L-16]).high,T=(T=(($>>>1|J<<31)^($>>>8|J<<24)^$>>>7)+Z+((j=(Z=(J>>>1|$<<31)^(J>>>8|$<<24)^(J>>>7|$<<25))+q)>>>0>>0?1:0))+((G>>>19|V<<13)^(G<<3|V>>>29)^G>>>6)+((j+=J=(V>>>19|G<<13)^(V<<3|G>>>29)^(V>>>6|G<<26))>>>0>>0?1:0),j+=$=Q.low,N.high=T=T+Y+(j>>>0<$>>>0?1:0),N.low=j);var q=F&W^~F&I,Z=P&O^~P&U,V=A&z^A&D^z&D,G=(H>>>28|A<<4)^(H<<30|A>>>2)^(H<<25|A>>>7),J=t1[L],Q=J.high,Y=J.low,$=X+((P>>>14|F<<18)^(P>>>18|F<<14)^(P<<23|F>>>9)),N=K+((F>>>14|P<<18)^(F>>>18|P<<14)^(F<<23|P>>>9))+($>>>0>>0?1:0),J=G+(H&C^H&E^C&E),K=I,X=U,I=W,U=O,W=F,O=P,F=R+(N=(N=(N=N+q+(($=$+Z)>>>0>>0?1:0))+Q+(($=$+Y)>>>0>>0?1:0))+T+(($=$+j)>>>0>>0?1:0))+((P=M+$|0)>>>0>>0?1:0)|0,R=D,M=E,D=z,E=C,z=A,C=H,A=N+(((A>>>28|H<<4)^(A<<30|H>>>2)^(A<<25|H>>>7))+V+(J>>>0>>0?1:0))+((H=$+J|0)>>>0<$>>>0?1:0)|0}d=i.low=d+H,i.high=f+A+(d>>>0>>0?1:0),p=n.low=p+C,n.high=u+z+(p>>>0>>0?1:0),y=o.low=y+E,o.high=_+D+(y>>>0>>0?1:0),g=s.low=g+M,s.high=v+R+(g>>>0>>0?1:0),w=c.low=w+P,c.high=B+F+(w>>>0

>>0?1:0),m=a.low=m+O,a.high=k+W+(m>>>0>>0?1:0),x=h.low=x+U,h.high=S+I+(x>>>0>>0?1:0),r=l.low=r+X,l.high=b+K+(r>>>0>>0?1:0)},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return e[i>>>5]|=128<<24-i%32,e[30+(128+i>>>10<<5)]=Math.floor(r/4294967296),e[31+(128+i>>>10<<5)]=r,t.sigBytes=4*e.length,this._process(),this._hash.toX32()},clone:function(){var t=e.clone.call(this);return t._hash=this._hash.clone(),t},blockSize:32});t.SHA512=e._createHelper(r),t.HmacSHA512=e._createHmacHelper(r)}(),P=(M=U).x64,c=P.Word,f=P.WordArray,P=M.algo,d=P.SHA512,P=P.SHA384=d.extend({_doReset:function(){this._hash=new f.init([new c.init(3418070365,3238371032),new c.init(1654270250,914150663),new c.init(2438529370,812702999),new c.init(355462360,4144912697),new c.init(1731405415,4290775857),new c.init(2394180231,1750603025),new c.init(3675008525,1694076839),new c.init(1203062813,3204075428)])},_doFinalize:function(){var t=d._doFinalize.call(this);return t.sigBytes-=16,t}}),M.SHA384=d._createHelper(P),M.HmacSHA384=d._createHmacHelper(P),function(l){var t=U,e=t.lib,f=e.WordArray,i=e.Hasher,d=t.x64.Word,e=t.algo,A=[],H=[],z=[];!function(){for(var t=1,e=0,r=0;r<24;r++){A[t+5*e]=(r+1)*(r+2)/2%64;var i=(2*t+3*e)%5;t=e%5,e=i}for(t=0;t<5;t++)for(e=0;e<5;e++)H[t+5*e]=e+(2*t+3*e)%5*5;for(var n=1,o=0;o<24;o++){for(var s,c=0,a=0,h=0;h<7;h++)1&n&&((s=(1<>>24)|4278255360&(o<<24|o>>>8);(m=r[n]).high^=s=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),m.low^=o}for(var c=0;c<24;c++){for(var a=0;a<5;a++){for(var h=0,l=0,f=0;f<5;f++)h^=(m=r[a+5*f]).high,l^=m.low;var d=C[a];d.high=h,d.low=l}for(a=0;a<5;a++)for(var u=C[(a+4)%5],p=C[(a+1)%5],_=p.high,p=p.low,h=u.high^(_<<1|p>>>31),l=u.low^(p<<1|_>>>31),f=0;f<5;f++)(m=r[a+5*f]).high^=h,m.low^=l;for(var y=1;y<25;y++){var v=(m=r[y]).high,g=m.low,B=A[y];l=B<32?(h=v<>>32-B,g<>>32-B):(h=g<>>64-B,v<>>64-B);B=C[H[y]];B.high=h,B.low=l}var w=C[0],k=r[0];w.high=k.high,w.low=k.low;for(a=0;a<5;a++)for(f=0;f<5;f++){var m=r[y=a+5*f],S=C[y],x=C[(a+1)%5+5*f],b=C[(a+2)%5+5*f];m.high=S.high^~x.high&b.high,m.low=S.low^~x.low&b.low}m=r[0],k=z[c];m.high^=k.high,m.low^=k.low}},_doFinalize:function(){var t=this._data,e=t.words,r=(this._nDataBytes,8*t.sigBytes),i=32*this.blockSize;e[r>>>5]|=1<<24-r%32,e[(l.ceil((1+r)/i)*i>>>5)-1]|=128,t.sigBytes=4*e.length,this._process();for(var n=this._state,e=this.cfg.outputLength/8,o=e/8,s=[],c=0;c>>24)|4278255360&(h<<24|h>>>8);s.push(a=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8)),s.push(h)}return new f.init(s,e)},clone:function(){for(var t=i.clone.call(this),e=t._state=this._state.slice(0),r=0;r<25;r++)e[r]=e[r].clone();return t}});t.SHA3=i._createHelper(e),t.HmacSHA3=i._createHmacHelper(e)}(Math),Math,F=(w=U).lib,u=F.WordArray,p=F.Hasher,F=w.algo,S=u.create([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13]),x=u.create([5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]),b=u.create([11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6]),A=u.create([8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]),H=u.create([0,1518500249,1859775393,2400959708,2840853838]),z=u.create([1352829926,1548603684,1836072691,2053994217,0]),F=F.RIPEMD160=p.extend({_doReset:function(){this._hash=u.create([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(t,e){for(var r=0;r<16;r++){var i=e+r,n=t[i];t[i]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8)}for(var o,s,c,a,h,l,f=this._hash.words,d=H.words,u=z.words,p=S.words,_=x.words,y=b.words,v=A.words,g=o=f[0],B=s=f[1],w=c=f[2],k=a=f[3],m=h=f[4],r=0;r<80;r+=1)l=o+t[e+p[r]]|0,l+=r<16?(s^c^a)+d[0]:r<32?K(s,c,a)+d[1]:r<48?((s|~c)^a)+d[2]:r<64?X(s,c,a)+d[3]:(s^(c|~a))+d[4],l=(l=L(l|=0,y[r]))+h|0,o=h,h=a,a=L(c,10),c=s,s=l,l=g+t[e+_[r]]|0,l+=r<16?(B^(w|~k))+u[0]:r<32?X(B,w,k)+u[1]:r<48?((B|~w)^k)+u[2]:r<64?K(B,w,k)+u[3]:(B^w^k)+u[4],l=(l=L(l|=0,v[r]))+m|0,g=m,m=k,k=L(w,10),w=B,B=l;l=f[1]+c+k|0,f[1]=f[2]+a+m|0,f[2]=f[3]+h+g|0,f[3]=f[4]+o+B|0,f[4]=f[0]+s+w|0,f[0]=l},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;e[i>>>5]|=128<<24-i%32,e[14+(64+i>>>9<<4)]=16711935&(r<<8|r>>>24)|4278255360&(r<<24|r>>>8),t.sigBytes=4*(e.length+1),this._process();for(var e=this._hash,n=e.words,o=0;o<5;o++){var s=n[o];n[o]=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8)}return e},clone:function(){var t=p.clone.call(this);return t._hash=this._hash.clone(),t}}),w.RIPEMD160=p._createHelper(F),w.HmacRIPEMD160=p._createHmacHelper(F),P=(M=U).lib.Base,_=M.enc.Utf8,M.algo.HMAC=P.extend({init:function(t,e){t=this._hasher=new t.init,"string"==typeof e&&(e=_.parse(e));var r=t.blockSize,i=4*r;(e=e.sigBytes>i?t.finalize(e):e).clamp();for(var t=this._oKey=e.clone(),e=this._iKey=e.clone(),n=t.words,o=e.words,s=0;s>>2];t.sigBytes-=e}},d=(e.BlockCipher=a.extend({cfg:a.cfg.extend({mode:n,padding:l}),reset:function(){var t;a.reset.call(this);var e=this.cfg,r=e.iv,e=e.mode;this._xformMode==this._ENC_XFORM_MODE?t=e.createEncryptor:(t=e.createDecryptor,this._minBufferSize=1),this._mode&&this._mode.__creator==t?this._mode.init(this,r&&r.words):(this._mode=t.call(e,this,r&&r.words),this._mode.__creator=t)},_doProcessBlock:function(t,e){this._mode.processBlock(t,e)},_doFinalize:function(){var t,e=this.cfg.padding;return this._xformMode==this._ENC_XFORM_MODE?(e.pad(this._data,this.blockSize),t=this._process(!0)):(t=this._process(!0),e.unpad(t)),t},blockSize:4}),e.CipherParams=r.extend({init:function(t){this.mixIn(t)},toString:function(t){return(t||this.formatter).stringify(this)}})),l=(t.format={}).OpenSSL={stringify:function(t){var e=t.ciphertext,t=t.salt,e=t?s.create([1398893684,1701076831]).concat(t).concat(e):e;return e.toString(o)},parse:function(t){var e,r=o.parse(t),t=r.words;return 1398893684==t[0]&&1701076831==t[1]&&(e=s.create(t.slice(2,4)),t.splice(0,4),r.sigBytes-=16),d.create({ciphertext:r,salt:e})}},u=e.SerializableCipher=r.extend({cfg:r.extend({format:l}),encrypt:function(t,e,r,i){i=this.cfg.extend(i);var n=t.createEncryptor(r,i),e=n.finalize(e),n=n.cfg;return d.create({ciphertext:e,key:r,iv:n.iv,algorithm:t,mode:n.mode,padding:n.padding,blockSize:t.blockSize,formatter:i.format})},decrypt:function(t,e,r,i){return i=this.cfg.extend(i),e=this._parse(e,i.format),t.createDecryptor(r,i).finalize(e.ciphertext)},_parse:function(t,e){return"string"==typeof t?e.parse(t,this):t}}),t=(t.kdf={}).OpenSSL={execute:function(t,e,r,i){i=i||s.random(8);t=c.create({keySize:e+r}).compute(t,i),r=s.create(t.words.slice(e),4*r);return t.sigBytes=4*e,d.create({key:t,iv:r,salt:i})}},p=e.PasswordBasedCipher=u.extend({cfg:u.cfg.extend({kdf:t}),encrypt:function(t,e,r,i){r=(i=this.cfg.extend(i)).kdf.execute(r,t.keySize,t.ivSize);i.iv=r.iv;i=u.encrypt.call(this,t,e,r.key,i);return i.mixIn(r),i},decrypt:function(t,e,r,i){i=this.cfg.extend(i),e=this._parse(e,i.format);r=i.kdf.execute(r,t.keySize,t.ivSize,e.salt);return i.iv=r.iv,u.decrypt.call(this,t,e,r.key,i)}})}(),U.mode.CFB=((F=U.lib.BlockCipherMode.extend()).Encryptor=F.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize;j.call(this,t,e,i,r),this._prevBlock=t.slice(e,e+i)}}),F.Decryptor=F.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize,n=t.slice(e,e+i);j.call(this,t,e,i,r),this._prevBlock=n}}),F),U.mode.CTR=(M=U.lib.BlockCipherMode.extend(),P=M.Encryptor=M.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize,n=this._iv,o=this._counter;n&&(o=this._counter=n.slice(0),this._iv=void 0);var s=o.slice(0);r.encryptBlock(s,0),o[i-1]=o[i-1]+1|0;for(var c=0;c>>2]|=e<<24-r%4*8,t.sigBytes+=e},unpad:function(t){var e=255&t.words[t.sigBytes-1>>>2];t.sigBytes-=e}},U.pad.Iso10126={pad:function(t,e){e*=4,e-=t.sigBytes%e;t.concat(U.lib.WordArray.random(e-1)).concat(U.lib.WordArray.create([e<<24],1))},unpad:function(t){var e=255&t.words[t.sigBytes-1>>>2];t.sigBytes-=e}},U.pad.Iso97971={pad:function(t,e){t.concat(U.lib.WordArray.create([2147483648],1)),U.pad.ZeroPadding.pad(t,e)},unpad:function(t){U.pad.ZeroPadding.unpad(t),t.sigBytes--}},U.pad.ZeroPadding={pad:function(t,e){e*=4;t.clamp(),t.sigBytes+=e-(t.sigBytes%e||e)},unpad:function(t){for(var e=t.words,r=t.sigBytes-1,r=t.sigBytes-1;0<=r;r--)if(e[r>>>2]>>>24-r%4*8&255){t.sigBytes=r+1;break}}},U.pad.NoPadding={pad:function(){},unpad:function(){}},m=(P=U).lib.CipherParams,C=P.enc.Hex,P.format.Hex={stringify:function(t){return t.ciphertext.toString(C)},parse:function(t){t=C.parse(t);return m.create({ciphertext:t})}},function(){var t=U,e=t.lib.BlockCipher,r=t.algo,h=[],l=[],f=[],d=[],u=[],p=[],_=[],y=[],v=[],g=[];!function(){for(var t=[],e=0;e<256;e++)t[e]=e<128?e<<1:e<<1^283;for(var r=0,i=0,e=0;e<256;e++){var n=i^i<<1^i<<2^i<<3^i<<4;h[r]=n=n>>>8^255&n^99;var o=t[l[n]=r],s=t[o],c=t[s],a=257*t[n]^16843008*n;f[r]=a<<24|a>>>8,d[r]=a<<16|a>>>16,u[r]=a<<8|a>>>24,p[r]=a,_[n]=(a=16843009*c^65537*s^257*o^16843008*r)<<24|a>>>8,y[n]=a<<16|a>>>16,v[n]=a<<8|a>>>24,g[n]=a,r?(r=o^t[t[t[c^o]]],i^=t[t[i]]):r=i=1}}();var B=[0,1,2,4,8,16,32,64,128,27,54],r=r.AES=e.extend({_doReset:function(){if(!this._nRounds||this._keyPriorReset!==this._key){for(var t=this._keyPriorReset=this._key,e=t.words,r=t.sigBytes/4,i=4*(1+(this._nRounds=6+r)),n=this._keySchedule=[],o=0;o>>24]<<24|h[a>>>16&255]<<16|h[a>>>8&255]<<8|h[255&a]):(a=h[(a=a<<8|a>>>24)>>>24]<<24|h[a>>>16&255]<<16|h[a>>>8&255]<<8|h[255&a],a^=B[o/r|0]<<24),n[o]=n[o-r]^a);for(var s=this._invKeySchedule=[],c=0;c>>24]]^y[h[a>>>16&255]]^v[h[a>>>8&255]]^g[h[255&a]]}}},encryptBlock:function(t,e){this._doCryptBlock(t,e,this._keySchedule,f,d,u,p,h)},decryptBlock:function(t,e){var r=t[e+1];t[e+1]=t[e+3],t[e+3]=r,this._doCryptBlock(t,e,this._invKeySchedule,_,y,v,g,l);r=t[e+1];t[e+1]=t[e+3],t[e+3]=r},_doCryptBlock:function(t,e,r,i,n,o,s,c){for(var a=this._nRounds,h=t[e]^r[0],l=t[e+1]^r[1],f=t[e+2]^r[2],d=t[e+3]^r[3],u=4,p=1;p>>24]^n[l>>>16&255]^o[f>>>8&255]^s[255&d]^r[u++],y=i[l>>>24]^n[f>>>16&255]^o[d>>>8&255]^s[255&h]^r[u++],v=i[f>>>24]^n[d>>>16&255]^o[h>>>8&255]^s[255&l]^r[u++],g=i[d>>>24]^n[h>>>16&255]^o[l>>>8&255]^s[255&f]^r[u++],h=_,l=y,f=v,d=g;_=(c[h>>>24]<<24|c[l>>>16&255]<<16|c[f>>>8&255]<<8|c[255&d])^r[u++],y=(c[l>>>24]<<24|c[f>>>16&255]<<16|c[d>>>8&255]<<8|c[255&h])^r[u++],v=(c[f>>>24]<<24|c[d>>>16&255]<<16|c[h>>>8&255]<<8|c[255&l])^r[u++],g=(c[d>>>24]<<24|c[h>>>16&255]<<16|c[l>>>8&255]<<8|c[255&f])^r[u++];t[e]=_,t[e+1]=y,t[e+2]=v,t[e+3]=g},keySize:8});t.AES=e._createHelper(r)}(),function(){var t=U,e=t.lib,i=e.WordArray,r=e.BlockCipher,e=t.algo,h=[57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,27,19,11,3,60,52,44,36,63,55,47,39,31,23,15,7,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,28,20,12,4],l=[14,17,11,24,1,5,3,28,15,6,21,10,23,19,12,4,26,8,16,7,27,20,13,2,41,52,31,37,47,55,30,40,51,45,33,48,44,49,39,56,34,53,46,42,50,36,29,32],f=[1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28],d=[{0:8421888,268435456:32768,536870912:8421378,805306368:2,1073741824:512,1342177280:8421890,1610612736:8389122,1879048192:8388608,2147483648:514,2415919104:8389120,2684354560:33280,2952790016:8421376,3221225472:32770,3489660928:8388610,3758096384:0,4026531840:33282,134217728:0,402653184:8421890,671088640:33282,939524096:32768,1207959552:8421888,1476395008:512,1744830464:8421378,2013265920:2,2281701376:8389120,2550136832:33280,2818572288:8421376,3087007744:8389122,3355443200:8388610,3623878656:32770,3892314112:514,4160749568:8388608,1:32768,268435457:2,536870913:8421888,805306369:8388608,1073741825:8421378,1342177281:33280,1610612737:512,1879048193:8389122,2147483649:8421890,2415919105:8421376,2684354561:8388610,2952790017:33282,3221225473:514,3489660929:8389120,3758096385:32770,4026531841:0,134217729:8421890,402653185:8421376,671088641:8388608,939524097:512,1207959553:32768,1476395009:8388610,1744830465:2,2013265921:33282,2281701377:32770,2550136833:8389122,2818572289:514,3087007745:8421888,3355443201:8389120,3623878657:0,3892314113:33280,4160749569:8421378},{0:1074282512,16777216:16384,33554432:524288,50331648:1074266128,67108864:1073741840,83886080:1074282496,100663296:1073758208,117440512:16,134217728:540672,150994944:1073758224,167772160:1073741824,184549376:540688,201326592:524304,218103808:0,234881024:16400,251658240:1074266112,8388608:1073758208,25165824:540688,41943040:16,58720256:1073758224,75497472:1074282512,92274688:1073741824,109051904:524288,125829120:1074266128,142606336:524304,159383552:0,176160768:16384,192937984:1074266112,209715200:1073741840,226492416:540672,243269632:1074282496,260046848:16400,268435456:0,285212672:1074266128,301989888:1073758224,318767104:1074282496,335544320:1074266112,352321536:16,369098752:540688,385875968:16384,402653184:16400,419430400:524288,436207616:524304,452984832:1073741840,469762048:540672,486539264:1073758208,503316480:1073741824,520093696:1074282512,276824064:540688,293601280:524288,310378496:1074266112,327155712:16384,343932928:1073758208,360710144:1074282512,377487360:16,394264576:1073741824,411041792:1074282496,427819008:1073741840,444596224:1073758224,461373440:524304,478150656:0,494927872:16400,511705088:1074266128,528482304:540672},{0:260,1048576:0,2097152:67109120,3145728:65796,4194304:65540,5242880:67108868,6291456:67174660,7340032:67174400,8388608:67108864,9437184:67174656,10485760:65792,11534336:67174404,12582912:67109124,13631488:65536,14680064:4,15728640:256,524288:67174656,1572864:67174404,2621440:0,3670016:67109120,4718592:67108868,5767168:65536,6815744:65540,7864320:260,8912896:4,9961472:256,11010048:67174400,12058624:65796,13107200:65792,14155776:67109124,15204352:67174660,16252928:67108864,16777216:67174656,17825792:65540,18874368:65536,19922944:67109120,20971520:256,22020096:67174660,23068672:67108868,24117248:0,25165824:67109124,26214400:67108864,27262976:4,28311552:65792,29360128:67174400,30408704:260,31457280:65796,32505856:67174404,17301504:67108864,18350080:260,19398656:67174656,20447232:0,21495808:65540,22544384:67109120,23592960:256,24641536:67174404,25690112:65536,26738688:67174660,27787264:65796,28835840:67108868,29884416:67109124,30932992:67174400,31981568:4,33030144:65792},{0:2151682048,65536:2147487808,131072:4198464,196608:2151677952,262144:0,327680:4198400,393216:2147483712,458752:4194368,524288:2147483648,589824:4194304,655360:64,720896:2147487744,786432:2151678016,851968:4160,917504:4096,983040:2151682112,32768:2147487808,98304:64,163840:2151678016,229376:2147487744,294912:4198400,360448:2151682112,425984:0,491520:2151677952,557056:4096,622592:2151682048,688128:4194304,753664:4160,819200:2147483648,884736:4194368,950272:4198464,1015808:2147483712,1048576:4194368,1114112:4198400,1179648:2147483712,1245184:0,1310720:4160,1376256:2151678016,1441792:2151682048,1507328:2147487808,1572864:2151682112,1638400:2147483648,1703936:2151677952,1769472:4198464,1835008:2147487744,1900544:4194304,1966080:64,2031616:4096,1081344:2151677952,1146880:2151682112,1212416:0,1277952:4198400,1343488:4194368,1409024:2147483648,1474560:2147487808,1540096:64,1605632:2147483712,1671168:4096,1736704:2147487744,1802240:2151678016,1867776:4160,1933312:2151682048,1998848:4194304,2064384:4198464},{0:128,4096:17039360,8192:262144,12288:536870912,16384:537133184,20480:16777344,24576:553648256,28672:262272,32768:16777216,36864:537133056,40960:536871040,45056:553910400,49152:553910272,53248:0,57344:17039488,61440:553648128,2048:17039488,6144:553648256,10240:128,14336:17039360,18432:262144,22528:537133184,26624:553910272,30720:536870912,34816:537133056,38912:0,43008:553910400,47104:16777344,51200:536871040,55296:553648128,59392:16777216,63488:262272,65536:262144,69632:128,73728:536870912,77824:553648256,81920:16777344,86016:553910272,90112:537133184,94208:16777216,98304:553910400,102400:553648128,106496:17039360,110592:537133056,114688:262272,118784:536871040,122880:0,126976:17039488,67584:553648256,71680:16777216,75776:17039360,79872:537133184,83968:536870912,88064:17039488,92160:128,96256:553910272,100352:262272,104448:553910400,108544:0,112640:553648128,116736:16777344,120832:262144,124928:537133056,129024:536871040},{0:268435464,256:8192,512:270532608,768:270540808,1024:268443648,1280:2097152,1536:2097160,1792:268435456,2048:0,2304:268443656,2560:2105344,2816:8,3072:270532616,3328:2105352,3584:8200,3840:270540800,128:270532608,384:270540808,640:8,896:2097152,1152:2105352,1408:268435464,1664:268443648,1920:8200,2176:2097160,2432:8192,2688:268443656,2944:270532616,3200:0,3456:270540800,3712:2105344,3968:268435456,4096:268443648,4352:270532616,4608:270540808,4864:8200,5120:2097152,5376:268435456,5632:268435464,5888:2105344,6144:2105352,6400:0,6656:8,6912:270532608,7168:8192,7424:268443656,7680:270540800,7936:2097160,4224:8,4480:2105344,4736:2097152,4992:268435464,5248:268443648,5504:8200,5760:270540808,6016:270532608,6272:270540800,6528:270532616,6784:8192,7040:2105352,7296:2097160,7552:0,7808:268435456,8064:268443656},{0:1048576,16:33555457,32:1024,48:1049601,64:34604033,80:0,96:1,112:34603009,128:33555456,144:1048577,160:33554433,176:34604032,192:34603008,208:1025,224:1049600,240:33554432,8:34603009,24:0,40:33555457,56:34604032,72:1048576,88:33554433,104:33554432,120:1025,136:1049601,152:33555456,168:34603008,184:1048577,200:1024,216:34604033,232:1,248:1049600,256:33554432,272:1048576,288:33555457,304:34603009,320:1048577,336:33555456,352:34604032,368:1049601,384:1025,400:34604033,416:1049600,432:1,448:0,464:34603008,480:33554433,496:1024,264:1049600,280:33555457,296:34603009,312:1,328:33554432,344:1048576,360:1025,376:34604032,392:33554433,408:34603008,424:0,440:34604033,456:1049601,472:1024,488:33555456,504:1048577},{0:134219808,1:131072,2:134217728,3:32,4:131104,5:134350880,6:134350848,7:2048,8:134348800,9:134219776,10:133120,11:134348832,12:2080,13:0,14:134217760,15:133152,2147483648:2048,2147483649:134350880,2147483650:134219808,2147483651:134217728,2147483652:134348800,2147483653:133120,2147483654:133152,2147483655:32,2147483656:134217760,2147483657:2080,2147483658:131104,2147483659:134350848,2147483660:0,2147483661:134348832,2147483662:134219776,2147483663:131072,16:133152,17:134350848,18:32,19:2048,20:134219776,21:134217760,22:134348832,23:131072,24:0,25:131104,26:134348800,27:134219808,28:134350880,29:133120,30:2080,31:134217728,2147483664:131072,2147483665:2048,2147483666:134348832,2147483667:133152,2147483668:32,2147483669:134348800,2147483670:134217728,2147483671:134219808,2147483672:134350880,2147483673:134217760,2147483674:134219776,2147483675:0,2147483676:133120,2147483677:2080,2147483678:131104,2147483679:134350848}],u=[4160749569,528482304,33030144,2064384,129024,8064,504,2147483679],n=e.DES=r.extend({_doReset:function(){for(var t=this._key.words,e=[],r=0;r<56;r++){var i=h[r]-1;e[r]=t[i>>>5]>>>31-i%32&1}for(var n=this._subKeys=[],o=0;o<16;o++){for(var s=n[o]=[],c=f[o],r=0;r<24;r++)s[r/6|0]|=e[(l[r]-1+c)%28]<<31-r%6,s[4+(r/6|0)]|=e[28+(l[r+24]-1+c)%28]<<31-r%6;s[0]=s[0]<<1|s[0]>>>31;for(r=1;r<7;r++)s[r]=s[r]>>>4*(r-1)+3;s[7]=s[7]<<5|s[7]>>>27}for(var a=this._invSubKeys=[],r=0;r<16;r++)a[r]=n[15-r]},encryptBlock:function(t,e){this._doCryptBlock(t,e,this._subKeys)},decryptBlock:function(t,e){this._doCryptBlock(t,e,this._invSubKeys)},_doCryptBlock:function(t,e,r){this._lBlock=t[e],this._rBlock=t[e+1],p.call(this,4,252645135),p.call(this,16,65535),_.call(this,2,858993459),_.call(this,8,16711935),p.call(this,1,1431655765);for(var i=0;i<16;i++){for(var n=r[i],o=this._lBlock,s=this._rBlock,c=0,a=0;a<8;a++)c|=d[a][((s^n[a])&u[a])>>>0];this._lBlock=s,this._rBlock=o^c}var h=this._lBlock;this._lBlock=this._rBlock,this._rBlock=h,p.call(this,1,1431655765),_.call(this,8,16711935),_.call(this,2,858993459),p.call(this,16,65535),p.call(this,4,252645135),t[e]=this._lBlock,t[e+1]=this._rBlock},keySize:2,ivSize:2,blockSize:2});function p(t,e){e=(this._lBlock>>>t^this._rBlock)&e;this._rBlock^=e,this._lBlock^=e<>>t^this._lBlock)&e;this._lBlock^=e,this._rBlock^=e<192.");var e=t.slice(0,2),r=t.length<4?t.slice(0,2):t.slice(2,4),t=t.length<6?t.slice(0,2):t.slice(4,6);this._des1=n.createEncryptor(i.create(e)),this._des2=n.createEncryptor(i.create(r)),this._des3=n.createEncryptor(i.create(t))},encryptBlock:function(t,e){this._des1.encryptBlock(t,e),this._des2.decryptBlock(t,e),this._des3.encryptBlock(t,e)},decryptBlock:function(t,e){this._des3.decryptBlock(t,e),this._des2.encryptBlock(t,e),this._des1.decryptBlock(t,e)},keySize:6,ivSize:2,blockSize:2});t.TripleDES=r._createHelper(e)}(),function(){var t=U,e=t.lib.StreamCipher,r=t.algo,i=r.RC4=e.extend({_doReset:function(){for(var t=this._key,e=t.words,r=t.sigBytes,i=this._S=[],n=0;n<256;n++)i[n]=n;for(var n=0,o=0;n<256;n++){var s=n%r,s=e[s>>>2]>>>24-s%4*8&255,o=(o+i[n]+s)%256,s=i[n];i[n]=i[o],i[o]=s}this._i=this._j=0},_doProcessBlock:function(t,e){t[e]^=n.call(this)},keySize:8,ivSize:0});function n(){for(var t=this._S,e=this._i,r=this._j,i=0,n=0;n<4;n++){var r=(r+t[e=(e+1)%256])%256,o=t[e];t[e]=t[r],t[r]=o,i|=t[(t[e]+t[r])%256]<<24-8*n}return this._i=e,this._j=r,i}t.RC4=e._createHelper(i);r=r.RC4Drop=i.extend({cfg:i.cfg.extend({drop:192}),_doReset:function(){i._doReset.call(this);for(var t=this.cfg.drop;0>>24)|4278255360&(t[r]<<24|t[r]>>>8);for(var i=this._X=[t[0],t[3]<<16|t[2]>>>16,t[1],t[0]<<16|t[3]>>>16,t[2],t[1]<<16|t[0]>>>16,t[3],t[2]<<16|t[1]>>>16],n=this._C=[t[2]<<16|t[2]>>>16,4294901760&t[0]|65535&t[1],t[3]<<16|t[3]>>>16,4294901760&t[1]|65535&t[2],t[0]<<16|t[0]>>>16,4294901760&t[2]|65535&t[3],t[1]<<16|t[1]>>>16,4294901760&t[3]|65535&t[0]],r=this._b=0;r<4;r++)N.call(this);for(r=0;r<8;r++)n[r]^=i[r+4&7];if(e){var o=e.words,s=o[0],c=o[1],e=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),o=16711935&(c<<8|c>>>24)|4278255360&(c<<24|c>>>8),s=e>>>16|4294901760&o,c=o<<16|65535&e;n[0]^=e,n[1]^=s,n[2]^=o,n[3]^=c,n[4]^=e,n[5]^=s,n[6]^=o,n[7]^=c;for(r=0;r<4;r++)N.call(this)}},_doProcessBlock:function(t,e){var r=this._X;N.call(this),D[0]=r[0]^r[5]>>>16^r[3]<<16,D[1]=r[2]^r[7]>>>16^r[5]<<16,D[2]=r[4]^r[1]>>>16^r[7]<<16,D[3]=r[6]^r[3]>>>16^r[1]<<16;for(var i=0;i<4;i++)D[i]=16711935&(D[i]<<8|D[i]>>>24)|4278255360&(D[i]<<24|D[i]>>>8),t[e+i]^=D[i]},blockSize:4,ivSize:2}),M.Rabbit=F._createHelper(P),F=(M=U).lib.StreamCipher,P=M.algo,W=[],O=[],I=[],P=P.RabbitLegacy=F.extend({_doReset:function(){for(var t=this._key.words,e=this.cfg.iv,r=this._X=[t[0],t[3]<<16|t[2]>>>16,t[1],t[0]<<16|t[3]>>>16,t[2],t[1]<<16|t[0]>>>16,t[3],t[2]<<16|t[1]>>>16],i=this._C=[t[2]<<16|t[2]>>>16,4294901760&t[0]|65535&t[1],t[3]<<16|t[3]>>>16,4294901760&t[1]|65535&t[2],t[0]<<16|t[0]>>>16,4294901760&t[2]|65535&t[3],t[1]<<16|t[1]>>>16,4294901760&t[3]|65535&t[0]],n=this._b=0;n<4;n++)q.call(this);for(n=0;n<8;n++)i[n]^=r[n+4&7];if(e){var o=e.words,s=o[0],t=o[1],e=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),o=16711935&(t<<8|t>>>24)|4278255360&(t<<24|t>>>8),s=e>>>16|4294901760&o,t=o<<16|65535&e;i[0]^=e,i[1]^=s,i[2]^=o,i[3]^=t,i[4]^=e,i[5]^=s,i[6]^=o,i[7]^=t;for(n=0;n<4;n++)q.call(this)}},_doProcessBlock:function(t,e){var r=this._X;q.call(this),W[0]=r[0]^r[5]>>>16^r[3]<<16,W[1]=r[2]^r[7]>>>16^r[5]<<16,W[2]=r[4]^r[1]>>>16^r[7]<<16,W[3]=r[6]^r[3]>>>16^r[1]<<16;for(var i=0;i<4;i++)W[i]=16711935&(W[i]<<8|W[i]>>>24)|4278255360&(W[i]<<24|W[i]>>>8),t[e+i]^=W[i]},blockSize:4,ivSize:2}),M.RabbitLegacy=F._createHelper(P),U}); \ No newline at end of file diff --git a/web/js/security.js b/web/js/security.js index a4a5b23..486df4a 100644 --- a/web/js/security.js +++ b/web/js/security.js @@ -1,8 +1,11 @@ const hashPassword = async (password) => { - const encoder = new TextEncoder() - const data = encoder.encode(password) - const hashBuffer = await crypto.subtle.digest('SHA-256', data) - const hashArray = Array.from(new Uint8Array(hashBuffer)) - const hashHex = hashArray.map(b=>('00' + b.toString(16)).slice(-2)).join('') - return hashHex + if (crypto && crypto.subtle) { + const encoder = new TextEncoder() + const data = encoder.encode(password) + const hashBuffer = await crypto.subtle.digest('SHA-256', data) + const hashArray = Array.from(new Uint8Array(hashBuffer)) + const hashHex = hashArray.map(b=>('00' + b.toString(16)).slice(-2)).join('') + return hashHex + } + return CryptoJS.SHA256(password).toString() } \ No newline at end of file