Compare commits
	
		
			3 Commits
		
	
	
		
			7a1bfd81f3
			...
			06d5a33495
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 06d5a33495 | |||
| ef4a6dec24 | |||
| ef3af2ec45 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -11,3 +11,5 @@ building/*.svg | ||||
| .idea/ | ||||
| compile_commands.json | ||||
| local.sh | ||||
| 
 | ||||
| iu9-ca-web-chat.db | ||||
|  | ||||
							
								
								
									
										69
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								README.md
									
									
									
									
									
								
							| @ -1,6 +1,61 @@ | ||||
| # ИУ9-21Б Вэб-чат C.A | ||||
| # IU9 C.A. WEB CHAT | ||||
| 
 | ||||
| Сделан на летней практике 5-ю первокурсниками ИУ9  | ||||
| C.A. stands for Collarbone Annihilation. | ||||
| 
 | ||||
| # About | ||||
| 
 | ||||
| Сделан на летней практике 5-ю первокурсниками из ИУ9-21Б. | ||||
| 
 | ||||
| # Dependencies | ||||
| 
 | ||||
| iu9-ca-web-chat использует | ||||
| - GCC | ||||
| - [regexis024-build-system]( | ||||
|   https://gitlab.yyyi.ru/collarbone-annihilation/regexis024-build-system | ||||
|   ) | ||||
| - [libregexis024]( | ||||
|   https://gitlab.yyyi.ru/kme-devline/libregexis024 | ||||
|   ) | ||||
| - [libjsonincpp]( | ||||
|   https://gitlab.yyyi.ru/collarbone-annihilation/libjsonincpp | ||||
|   ) | ||||
| - [sqlite3]( | ||||
|   https://www.sqlite.org | ||||
|   ) | ||||
| 
 | ||||
| Сервис так же использует библиотеки engine_engine_number_9 и new_york_transit_line, | ||||
| размещённые прямо в репозитории. | ||||
| 
 | ||||
| Работает только на unix системах. | ||||
| 
 | ||||
| # Compilation | ||||
| 
 | ||||
| ```sh | ||||
| regexis024_build_system.sh | ||||
| ./building/main bi ./ "absolute/path/to/installation/root" | ||||
| ``` | ||||
| # Usage | ||||
| 
 | ||||
| Помимо самого бинарника нужен файл с настройками сервиса. Формат настроек: JSON. | ||||
| Комментарии не поддерживаются. Пример такого файла находится в example/config.json. | ||||
| Вместе с бинарным фалом так же распространяются ассеты, необъходимые для работы сайта. | ||||
| Их можно найти в папке assets. В настроках (поле `["assets"]`) указывается путь до | ||||
| папки с ассетами. Путь может быть как абсолютным, так и относительным к рабочей директории. | ||||
| Поле настроек `["database"]` указывает как соединиться с базой данных. | ||||
| Поддерживается только база данных sqlite. Поддерживается только хранение в файле. | ||||
| Поле `["database"]["file"]` указывает путь где хранится sqlite база данных. | ||||
| 
 | ||||
| Перед тем как использовать сервис нужно его проинициализировать (а точнее проинициализировать | ||||
| базу данных): | ||||
| 
 | ||||
| `ROOT_PW="<your desired root password>" iu9-ca-web-chat /path/to/config.json initialize` | ||||
| 
 | ||||
| Переменная окружения `ROOT_PW` читается для устаановки пароля root пользователю раз и навсегда. | ||||
| Далее можно запускать сервис: | ||||
| 
 | ||||
| `iu9-ca-web-chat /path/to/config.json run` | ||||
| 
 | ||||
| Для остановки сервиса киньте ему SIGTERM или SIGINT. | ||||
| 
 | ||||
| # Список участников | ||||
| 
 | ||||
| @ -10,3 +65,13 @@ | ||||
| 4. [Каримов Адель](https://gitflic.ru/user/ra1n) | ||||
| 5. [Яковлев Антон](https://gitflic.ru/user/yakovlevanton) | ||||
| 
 | ||||
| # Комментарии (для разработчиков) | ||||
| 
 | ||||
| Зачем писать комментарии в коде, если можно их вынести в отдельные пдф-ки? | ||||
| 
 | ||||
| - [API сервиса]( | ||||
|   https://gitlab.yyyi.ru/collarbone-annihilation/iu9-ca-chat-api) | ||||
| - [Доки New York Transit Line]( | ||||
|   https://gitlab.yyyi.ru/collarbone-annihilation/new_york_transit_line_documentation_rus) | ||||
| 
 | ||||
| О том как работает всё остальное можно только догадываться. | ||||
|  | ||||
| @ -1,10 +0,0 @@ | ||||
| #!/usr/bin/env sh | ||||
| 
 | ||||
| BUILDING_DIR="./building" | ||||
| [ -d "$BUILDING_DIR" ] || exit 1 | ||||
| MAIN_FILE="$BUILDING_DIR/main.cpp" | ||||
| [ -f "$MAIN_FILE" ] || exit 1 | ||||
| 
 | ||||
| COOL_FLAGS="$(pkg-config --cflags regexis024-build-system)" | ||||
| 
 | ||||
| g++ $COOL_FLAGS -o "$BUILDING_DIR/main" "$MAIN_FILE" || exit 1 | ||||
| @ -1,30 +1,21 @@ | ||||
| #include "regexis024_build_system.h" | ||||
| #include <utility> | ||||
| 
 | ||||
| #include "regexis024_build_system.h" | ||||
| 
 | ||||
| std::vector<std::string> getFromPkgConfig(const std::string& req, const std::string& name){ | ||||
|     std::string pc_stdout, pc_stderr; | ||||
|     CommandReturnCode rc = executeCommand_and_save_output({"pkg-config", "--" + req, name}, pc_stdout, pc_stderr); | ||||
|     ASSERT(rc.isOk(), "failed to use pkg-config beacause of:\n" + pc_stderr); | ||||
|     // todo: learn how pkg-config actually stores these options
 | ||||
|     std::vector<std::string> result; | ||||
|     for (char ch: pc_stdout) { | ||||
|         if (result.empty()) | ||||
|             result.emplace_back(); | ||||
|         if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') { | ||||
|             if (!result.back().empty()) | ||||
|                 result.emplace_back(); | ||||
|         } else { | ||||
|             result.back() += ch; | ||||
| std::string make_uppercase(const std::string &source) { | ||||
|     std::string result(source); | ||||
|     for (size_t i = 0; i < source.size(); i++) { | ||||
|         char ch = source[i]; | ||||
|         if ('a' <= ch && ch <= 'z') | ||||
|             result[i] = (char)(ch - 'a' + 'A'); | ||||
|     } | ||||
|     } | ||||
|     if (!result.empty() && result.back().empty()) | ||||
|         result.pop_back(); | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| ExternalLibraryTarget formExternalLibraryTargetWithNativeName(const std::string& name) { | ||||
|     return {name, {getFromPkgConfig("cflags", name), getFromPkgConfig("libs", name)}}; | ||||
| ExternalLibraryTarget formExternalLibraryTargetWithNonNativeName(const std::string& name) { | ||||
|     std::string ev_name = "BSCRIPT_DEP_" + make_uppercase(name); | ||||
|     const char* ev = getenv(ev_name.c_str()); | ||||
|     ASSERT(ev, "No environmaent variable " + ev_name); | ||||
|     return {name, parse_passed_forward_str(ev)}; | ||||
| } | ||||
| 
 | ||||
| struct CAWebChat { | ||||
| @ -64,9 +55,9 @@ struct CAWebChat { | ||||
|         ASSERT(build_type == "release" || build_type == "debug", "Unknown build type"); | ||||
| 
 | ||||
|         std::vector<ExternalLibraryTarget> ext_targets = { | ||||
|             formExternalLibraryTargetWithNativeName("libjsonincpp"), | ||||
|             formExternalLibraryTargetWithNativeName("sqlite3"), | ||||
|             formExternalLibraryTargetWithNativeName("libregexis024"), | ||||
|             formExternalLibraryTargetWithNonNativeName("libjsonincpp"), | ||||
|             formExternalLibraryTargetWithNonNativeName("sqlite3"), | ||||
|             formExternalLibraryTargetWithNonNativeName("libregexis024"), | ||||
|         }; | ||||
| 
 | ||||
|         std::vector<CTarget> my_targets; | ||||
| @ -141,7 +132,13 @@ struct CAWebChat { | ||||
|             T.external_deps = { | ||||
|                 CTargetDependenceOnExternalLibrary{"sqlite3"} | ||||
|             }; | ||||
|             T.units = {"main.cpp"}; | ||||
|             T.units = { | ||||
|                 "main.cpp", | ||||
|                 "initialize.cpp", | ||||
|                 "run.cpp", | ||||
|                 "str_fields_check.cpp", | ||||
|                 "find_db.cpp", | ||||
|             }; | ||||
|             for (std::string& u: T.units) | ||||
|                 u = "web_chat/" + u; | ||||
|             T.include_pr = "web_chat"; | ||||
|  | ||||
							
								
								
									
										9
									
								
								src/web_chat/actions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/web_chat/actions.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| #ifndef IU9_CA_WEB_CHAT_ACTIONS_H | ||||
| #define IU9_CA_WEB_CHAT_ACTIONS_H | ||||
| 
 | ||||
| #include <jsonincpp/jsonobj.h> | ||||
| 
 | ||||
| void run_website(const json::JSON& config); | ||||
| void initialize_website(const json::JSON& config, const std::string& root_pw); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										14
									
								
								src/web_chat/find_db.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/web_chat/find_db.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| #include "find_db.h" | ||||
| 
 | ||||
| int find_db_sqlite_file_path(const json::JSON& config, std::string& res_path) { | ||||
|     const json::JSON& type = config["database"]["type"].g(); | ||||
|     if (!type.isString() && type.asString() == "sqlite3") | ||||
|         return -1; | ||||
|     const json::JSON& path = config["database"]["file"].g(); | ||||
|     if (!path.isString()) | ||||
|         return -1; | ||||
|     if (path.asString().empty() || path.asString()[0] == ':') | ||||
|         return -1; | ||||
|     res_path = path.asString(); | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										8
									
								
								src/web_chat/find_db.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/web_chat/find_db.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| #ifndef IU9_CA_WEB_CHAT_SRC_WEB_CHAT_FIND_DB_H | ||||
| #define IU9_CA_WEB_CHAT_SRC_WEB_CHAT_FIND_DB_H | ||||
| 
 | ||||
| #include <jsonincpp/jsonobj.h> | ||||
| 
 | ||||
| int find_db_sqlite_file_path(const json::JSON& config, std::string& res_path); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										59
									
								
								src/web_chat/initialize.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/web_chat/initialize.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| #include "actions.h" | ||||
| #include <engine_engine_number_9/baza_throw.h> | ||||
| #include "str_fields_check.h" | ||||
| #include <sqlite3.h> | ||||
| #include <engine_engine_number_9/os_utils.h> | ||||
| #include <find_db.h> | ||||
| 
 | ||||
| void sqlite_single_statement(sqlite3* db_hand, const std::string& req_statement) { | ||||
|     sqlite3_stmt* stmt_obj = NULL; | ||||
|     int ret = sqlite3_prepare16_v2(db_hand, req_statement.c_str(), -1, &stmt_obj, NULL); | ||||
|     een9_ASSERT(ret == 0, "Can't compile request expression"); | ||||
|     struct Guard1{sqlite3_stmt*& r; ~Guard1(){if (sqlite3_finalize(r) != 0) {abort();}}} guard1{stmt_obj}; | ||||
|     while (true) { | ||||
|         ret = sqlite3_step(stmt_obj); | ||||
|         if (ret == SQLITE_DONE) | ||||
|             break; | ||||
|         if (ret != SQLITE_ROW) { | ||||
|             printf("sqlite_row error!!!\n"); | ||||
|             printf("%s\n", sqlite3_errmsg(db_hand)); | ||||
|             break; | ||||
|         } | ||||
|         int cc = sqlite3_column_count(stmt_obj); | ||||
|         std::vector<int> types(cc); | ||||
|         for (int i = 0; i < cc; i++) { | ||||
|             types[i] = sqlite3_column_type(stmt_obj, i); | ||||
|         } | ||||
|         printf("Column: |"); | ||||
|         for (int i = 0; i < cc; i++) { | ||||
|             switch (types[i]) { | ||||
| #define ccase(tname) case SQLITE_ ## tname: printf(" " #tname " |"); break; | ||||
|                 ccase(INTEGER) | ||||
|                 ccase(FLOAT) | ||||
|                 ccase(BLOB) | ||||
|                 ccase(NULL) | ||||
|                 case SQLITE3_TEXT: | ||||
|                     printf(" TEXT |"); break; | ||||
|             } | ||||
|         } | ||||
|         printf("\n"); | ||||
|     } | ||||
|     printf("Request steps are done\n"); | ||||
| } | ||||
| 
 | ||||
| void initialize_website(const json::JSON& config, const std::string& root_pw) { | ||||
|     printf("Initialization...\n"); | ||||
|     een9_ASSERT(check_password(root_pw), "Bad root password"); | ||||
|     std::string db_path; | ||||
|     int ret; | ||||
|     ret = find_db_sqlite_file_path(config, db_path); | ||||
|     een9_ASSERT(ret == 0, "Invalid settings[\"database\"] field"); | ||||
|     een9_ASSERT(!een9::isRegularFile(db_path), "Database file exists prior to initialization. " | ||||
|         "Can't preceed withut harming existing data"); | ||||
|     // sqlite3* db_hand = NULL;
 | ||||
|     // ret = sqlite3_open(db_path.c_str(), &db_hand);
 | ||||
|     // een9_ASSERT(ret == 0, "Can't open database");
 | ||||
|     // struct Guard1{sqlite3*& dhp; ~Guard1(){if (sqlite3_close(dhp) != 0) {abort();}}} guard1{db_hand};
 | ||||
|     // sqlite_single_statement(db_hand, "CREATE TABLE tb(a INT, b INT);");
 | ||||
|     // todo: actually write something
 | ||||
| } | ||||
| @ -1,122 +1,40 @@ | ||||
| #include <engine_engine_number_9/baza_throw.h> | ||||
| #include <engine_engine_number_9/running_mainloop.h> | ||||
| #include <engine_engine_number_9/http_structures/response_gen.h> | ||||
| #include <signal.h> | ||||
| #include <engine_engine_number_9/connecting_assets/static_asset_manager.h> | ||||
| #include <engine_engine_number_9/os_utils.h> | ||||
| #include <assert.h> | ||||
| #include <sqlite3.h> | ||||
| #include <jsonincpp/string_representation.h> | ||||
| #include <libregexis024vm/vm_opcodes.h> | ||||
| #include <engine_engine_number_9/form_data_structure/urlencoded_query.h> | ||||
| #include <new_york_transit_line/templater.h> | ||||
| 
 | ||||
| bool termination = false; | ||||
| 
 | ||||
| void sigterm_action(int) { | ||||
|     termination = true; | ||||
| } | ||||
| #include "actions.h" | ||||
| #include <stdexcept> | ||||
| 
 | ||||
| void usage(char** argv) { | ||||
|     printf("Usage: %s <file with settings>\n", argv[0]); | ||||
|     printf("Usage: %s <file with settings> <run|initialize>\n", argv[0]); | ||||
|     exit(1); | ||||
| } | ||||
| 
 | ||||
| std::string unsafe_client_request_stringification(const een9::ClientRequest& req) { | ||||
|     std::string text = "\n\nGot some cool stuff\n"; | ||||
|     text += (req.method + " " + req.uri_path + " " + req.http_version + "\n"); | ||||
|     for (auto& p: req.headers) { | ||||
|         text += p.first; text += ": "; text += p.second; text += "\n"; | ||||
|     } | ||||
|     text += "Body\n"; text += req.body; text += "\n"; | ||||
|     return text; | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char** argv){ | ||||
|     try { | ||||
|         een9_ASSERT_pl(argc > 0); | ||||
|         if (argc < 1 + 1) | ||||
|         if (argc != 1 + 2) | ||||
|             usage(argv); | ||||
|         if (!een9::isRegularFile(argv[1]) || !een9::endsIn(argv[1], ".json")) { | ||||
|         std::string config_file = argv[1]; | ||||
|         if (!een9::isRegularFile(config_file) || !een9::endsIn(config_file, ".json")) { | ||||
|             printf("\"%s\" is not a json file\n", argv[1]); | ||||
|             usage(argv); | ||||
|         } | ||||
|         std::string config_file = argv[1]; | ||||
| 
 | ||||
|         std::string cmd = argv[2]; | ||||
|         std::string config_text; | ||||
|         een9::readFile(config_file, config_text); | ||||
|         json::JSON config = json::parse_str_flawless(config_text); | ||||
|         een9_ASSERT(config.isDictionary(), "config root is not dictionary"); | ||||
|         een9_ASSERT(config["assets"].g().isString(), "config[\"\assets\"] is not string"); | ||||
|         std::string assets_dir = config["assets"].g().asString(); | ||||
|         een9_ASSERT(een9::isDirectory(assets_dir), "\"" + assets_dir + "\" is not a directory"); | ||||
|         const json::JSON config = json::parse_str_flawless(config_text); | ||||
| 
 | ||||
|         een9::StaticAssetManagerSlaveModule samI; | ||||
|         samI.update({ | ||||
|             een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} }, | ||||
|             een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} }, | ||||
|             een9::StaticAssetManagerRule{assets_dir + "/img", "/assets/img", { | ||||
|                 {".jpg", "image/jpg"}, {".png", "image/png"}, {".svg", "image/svg+xml"} | ||||
|             } }, | ||||
|         }); | ||||
| 
 | ||||
|         json::JSON& config_presentation = config["presentation"].g(); | ||||
| 
 | ||||
|         /* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */ | ||||
|         std::vector<std::unique_ptr<nytl::Templater>> templaters_copies(8); | ||||
|         for (int i = 0; i < 8; i++) { | ||||
|             templaters_copies[i] = std::make_unique<nytl::Templater>( | ||||
|                 nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}}); | ||||
|             templaters_copies[i]->update(); | ||||
|         } | ||||
| 
 | ||||
|         // printf("%s\n", templaters_copies[0]->render("list-rooms", {&config_presentation}).c_str());
 | ||||
|         // return 0;
 | ||||
| 
 | ||||
|         een9::MainloopParameters params; | ||||
|         params.guest_core = [&samI, &templaters_copies, config_presentation] | ||||
|         (const een9::SlaveTask& task, const een9::ClientRequest& req, een9::worker_id_t worker_id) -> std::string { | ||||
|             een9_ASSERT_pl(0 <= worker_id && worker_id < templaters_copies.size()); | ||||
|             nytl::Templater& templater = *templaters_copies[worker_id]; | ||||
|             een9::StaticAsset sa; | ||||
|             int ret; | ||||
|             // printf("%s", unsafe_client_request_stringification(req).c_str());
 | ||||
|             // if (req.uri_path == "/output") {
 | ||||
|             //     std::string text = unsafe_client_request_stringification(req);
 | ||||
|             //     return een9::form_http_server_response_200("text/plain", text);
 | ||||
|             // }
 | ||||
|             auto rteee = [&](const std::string& el_name, bool pass_phr) -> std::string { | ||||
|                 std::string page = templater.render(el_name, | ||||
|                     pass_phr ? std::vector<const json::JSON*>{&config_presentation} : std::vector<const json::JSON*>{}); | ||||
|                 return een9::form_http_server_response_200("text/html", page); | ||||
|             }; | ||||
|             if (req.uri_path == "/" || req.uri_path == "/list-rooms") { | ||||
|                 return rteee("list-rooms", true); | ||||
|             } | ||||
|             if (req.uri_path == "/chat") { | ||||
|                 return rteee("chat", false); | ||||
|             } | ||||
|             if (req.uri_path == "/profile") { | ||||
|                 return rteee("profile", false); | ||||
|             } | ||||
|             if (req.uri_path == "/registration") { | ||||
|                 return rteee("registration", false); | ||||
|             } | ||||
|             /* Trying to interpret request as asset lookup */ | ||||
|             ret = samI.get_asset(req.uri_path, sa); | ||||
|             if (ret >= 0) { | ||||
|                 return een9::form_http_server_response_200(sa.type, sa.content); | ||||
|             } | ||||
|             return een9::form_http_server_response_404("text/html", "<h1> Not found! </h1>"); | ||||
|         }; | ||||
| 
 | ||||
|         params.ports_to_listen = {1025}; | ||||
|         params.slave_number = 8; | ||||
|         params.open_admin_listener = false; | ||||
| 
 | ||||
|         signal(SIGINT, sigterm_action); | ||||
|         signal(SIGTERM, sigterm_action); | ||||
| 
 | ||||
|         een9::electric_boogaloo(params, termination); | ||||
|         if (cmd == "initialize") { | ||||
|             const char* ROOT_PW = getenv("ROOT_PW"); | ||||
|             een9_ASSERT(ROOT_PW, "No root password specified." | ||||
|                                  "Assign desired root password value to environment variable ROOT_PW"); | ||||
|             std::string root_pw = ROOT_PW; | ||||
|             initialize_website(config, root_pw); | ||||
|         } else if (cmd == "run") { | ||||
|             run_website(config); | ||||
|         } else | ||||
|             een9_THROW("unknown action (known are 'run', 'initialize')"); | ||||
|     } catch (std::exception& e) { | ||||
|         printf("System failure\n%s\n", e.what()); | ||||
|     } | ||||
|  | ||||
							
								
								
									
										103
									
								
								src/web_chat/run.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/web_chat/run.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| #include "actions.h" | ||||
| 
 | ||||
| #include <engine_engine_number_9/baza_throw.h> | ||||
| #include <engine_engine_number_9/running_mainloop.h> | ||||
| #include <engine_engine_number_9/http_structures/response_gen.h> | ||||
| #include <signal.h> | ||||
| #include <engine_engine_number_9/connecting_assets/static_asset_manager.h> | ||||
| #include <assert.h> | ||||
| #include <engine_engine_number_9/form_data_structure/urlencoded_query.h> | ||||
| #include <new_york_transit_line/templater.h> | ||||
| #include <sqlite3.h> | ||||
| 
 | ||||
| 
 | ||||
| bool termination = false; | ||||
| 
 | ||||
| void sigterm_action(int) { | ||||
|     termination = true; | ||||
| } | ||||
| 
 | ||||
| std::string unsafe_client_request_stringification(const een9::ClientRequest& req) { | ||||
|     std::string text = "\n\nGot some cool stuff\n"; | ||||
|     text += (req.method + " " + req.uri_path + " " + req.http_version + "\n"); | ||||
|     for (auto& p: req.headers) { | ||||
|         text += p.first; text += ": "; text += p.second; text += "\n"; | ||||
|     } | ||||
|     text += "Body\n"; text += req.body; text += "\n"; | ||||
|     return text; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void run_website(const json::JSON& config) { | ||||
|     een9_ASSERT(config["assets"].g().isString(), "config[\"\assets\"] is not string"); | ||||
|     std::string assets_dir = config["assets"].g().asString(); | ||||
|     een9_ASSERT(een9::isDirectory(assets_dir), "\"" + assets_dir + "\" is not a directory"); | ||||
| 
 | ||||
|     een9::StaticAssetManagerSlaveModule samI; | ||||
|         samI.update({ | ||||
|             een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} }, | ||||
|             een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} }, | ||||
|             een9::StaticAssetManagerRule{assets_dir + "/img", "/assets/img", { | ||||
|                 {".jpg", "image/jpg"}, {".png", "image/png"}, {".svg", "image/svg+xml"} | ||||
|             } }, | ||||
|         }); | ||||
| 
 | ||||
|         const json::JSON& config_presentation = config["presentation"].g(); | ||||
| 
 | ||||
|         /* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */ | ||||
|         std::vector<std::unique_ptr<nytl::Templater>> templaters_copies(8); | ||||
|         for (int i = 0; i < 8; i++) { | ||||
|             templaters_copies[i] = std::make_unique<nytl::Templater>( | ||||
|                 nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}}); | ||||
|             templaters_copies[i]->update(); | ||||
|         } | ||||
| 
 | ||||
|         // printf("%s\n", templaters_copies[0]->render("list-rooms", {&config_presentation}).c_str());
 | ||||
|         // return 0;
 | ||||
| 
 | ||||
|         een9::MainloopParameters params; | ||||
|         params.guest_core = [&samI, &templaters_copies, config_presentation] | ||||
|         (const een9::SlaveTask& task, const een9::ClientRequest& req, een9::worker_id_t worker_id) -> std::string { | ||||
|             een9_ASSERT_pl(0 <= worker_id && worker_id < templaters_copies.size()); | ||||
|             nytl::Templater& templater = *templaters_copies[worker_id]; | ||||
|             een9::StaticAsset sa; | ||||
|             int ret; | ||||
|             // printf("%s", unsafe_client_request_stringification(req).c_str());
 | ||||
|             // if (req.uri_path == "/output") {
 | ||||
|             //     std::string text = unsafe_client_request_stringification(req);
 | ||||
|             //     return een9::form_http_server_response_200("text/plain", text);
 | ||||
|             // }
 | ||||
|             auto rteee = [&](const std::string& el_name, bool pass_phr) -> std::string { | ||||
|                 std::string page = templater.render(el_name, | ||||
|                     pass_phr ? std::vector<const json::JSON*>{&config_presentation} : std::vector<const json::JSON*>{}); | ||||
|                 return een9::form_http_server_response_200("text/html", page); | ||||
|             }; | ||||
|             if (req.uri_path == "/" || req.uri_path == "/list-rooms") { | ||||
|                 return rteee("list-rooms", true); | ||||
|             } | ||||
|             if (req.uri_path == "/chat") { | ||||
|                 return rteee("chat", false); | ||||
|             } | ||||
|             if (req.uri_path == "/profile") { | ||||
|                 return rteee("profile", false); | ||||
|             } | ||||
|             if (req.uri_path == "/registration") { | ||||
|                 return rteee("registration", false); | ||||
|             } | ||||
|             /* Trying to interpret request as asset lookup */ | ||||
|             ret = samI.get_asset(req.uri_path, sa); | ||||
|             if (ret >= 0) { | ||||
|                 return een9::form_http_server_response_200(sa.type, sa.content); | ||||
|             } | ||||
|             return een9::form_http_server_response_404("text/html", "<h1> Not found! </h1>"); | ||||
|         }; | ||||
| 
 | ||||
|         params.ports_to_listen = {1025}; | ||||
|         params.slave_number = 8; | ||||
|         params.open_admin_listener = false; | ||||
| 
 | ||||
|         signal(SIGINT, sigterm_action); | ||||
|         signal(SIGTERM, sigterm_action); | ||||
| 
 | ||||
|         een9::electric_boogaloo(params, termination); | ||||
| } | ||||
							
								
								
									
										37
									
								
								src/web_chat/str_fields_check.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/web_chat/str_fields_check.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| #include "str_fields_check.h" | ||||
| #include <jsonincpp/utf8.h> | ||||
| 
 | ||||
| bool isALPHA(char ch) { | ||||
|     return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'); | ||||
| } | ||||
| 
 | ||||
| bool isNUM(char ch) { | ||||
|     return '0' <= ch && ch <= '9'; | ||||
| } | ||||
| 
 | ||||
| bool isUNCHAR(char ch) { | ||||
|     return isALPHA(ch) || isNUM(ch) || ch == '-' || ch == '_'; | ||||
| } | ||||
| 
 | ||||
| bool isSPACE(char ch) { | ||||
|     return ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n'; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool check_password(const std::string &pwd) { | ||||
|     return isUtf8String(pwd) && pwd.size() >= 8; | ||||
| } | ||||
| 
 | ||||
| bool check_name(const std::string &name) { | ||||
|     return isUtf8String(name); | ||||
| } | ||||
| 
 | ||||
| bool check_nickname(const std::string &nickname) { | ||||
|     if (nickname.empty()) | ||||
|         return false; | ||||
|     for (char ch: nickname) { | ||||
|         if (!isUNCHAR(ch)) | ||||
|             return false; | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
							
								
								
									
										10
									
								
								src/web_chat/str_fields_check.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/web_chat/str_fields_check.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| #ifndef IU9_CA_WEB_CHAT_SRC_WEB_CHAT_STR_FIELDS_CHECK_H | ||||
| #define IU9_CA_WEB_CHAT_SRC_WEB_CHAT_STR_FIELDS_CHECK_H | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| bool check_password(const std::string& pwd); | ||||
| bool check_name(const std::string& name); | ||||
| bool check_nickname(const std::string& nickname); | ||||
| 
 | ||||
| #endif | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user