From 0ed8150c4e585236f4235808ffb1287b653cdbc0 Mon Sep 17 00:00:00 2001 From: Andreev Gregory Date: Sat, 7 Sep 2024 00:31:42 +0300 Subject: [PATCH] Translated to english --- README.md | 25 +++++++ assets/HypertextPages/chat-members.nytl.html | 20 +++--- assets/HypertextPages/chat.nytl.html | 12 ++-- assets/HypertextPages/edit-profile.nytl.html | 22 +++--- assets/HypertextPages/list-rooms.nytl.html | 30 ++++---- assets/HypertextPages/login.nytl.html | 14 ++-- assets/HypertextPages/view-profile.nytl.html | 8 +-- assets/js/chat-members.js | 6 +- assets/js/chat.js | 14 ++-- assets/js/common.js | 3 - assets/js/list-rooms.js | 10 +-- assets/lang/en-US.lang.json | 69 ++++++++++++++++++- assets/lang/ru-RU.lang.json | 18 +++-- .../misc_tests/HypertextPages/test.nytl.html | 6 +- src/http_server/misc_tests/nytl_test1.cpp | 10 +-- .../new_york_transit_line/debug_print.cpp | 7 +- .../new_york_transit_line/parser.cpp | 48 +++++++++---- .../new_york_transit_line/rendering.cpp | 47 ++++++++----- .../new_york_transit_line/templater.cpp | 22 +++--- .../new_york_transit_line/templater.h | 9 ++- .../backend_logic/when_login.cpp | 2 +- .../backend_logic/when_user.cpp | 2 +- 22 files changed, 272 insertions(+), 132 deletions(-) diff --git a/README.md b/README.md index 09f927c..395552e 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,31 @@ regexis024_build_system.sh Утилита `iu9-ca-web-chat-admin-cli` позволяет администратору сервиса контролировать его через сокет (адрес указан в `config["server"]["admin-command-listen"]`). +По адресам `config.server.admin-command-listen` идёт прослушивание так называемых "команд администратора". +iu9cawebchat определяет свой простой протокол для передачи этих команд. +Утилита iu9-ca-web-chat-admin-cli может отправить текст с некой командой на сервер на этот адрес и получить +ответ от сервера. + +```shell +iu9-ca-web-chat-admin-cli [ ...] +``` + +Дополнительные параметры конкатенируются, разделяясь переводом строки. +Команды администратора: + +`updateroopw ` - сменить пароль пользователя с номером 0 + +`adduser ` - зарегистрировать пользователя сайта + +Если нужно ввести пробел или символ `\ ` в любое из этих полей, перед ними нужно поставить `\ `; + +Параметры конфигурации `config.lang.whitelist` и `config.lang.force-order` определяют на +какие языки будет локализован сервер, и какие переводы приоритетнее каких. +На данный момент поддерживаются + - `ru-RU` + - `en-US` +Все переводы хранятся в папке `assets/lang`. + # Список участников 1. [Китанин Фёдор](https://gitflic.ru/user/fed-kit) diff --git a/assets/HypertextPages/chat-members.nytl.html b/assets/HypertextPages/chat-members.nytl.html index 1094ef3..3896ac2 100644 --- a/assets/HypertextPages/chat-members.nytl.html +++ b/assets/HypertextPages/chat-members.nytl.html @@ -8,25 +8,25 @@ - Chat Members + {%w pres.chat-members.members-of %} {%w openedchat.name %} {% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %}
@@ -37,7 +37,9 @@ Go to my profile -

Members list of {% W openedchat.name %} ({% W openedchat.nickname %})

+

+ {%w pres.chat-members.members-list-of %} {% W openedchat.name %} ({% W openedchat.nickname %}) +

Back to chat diff --git a/assets/HypertextPages/chat.nytl.html b/assets/HypertextPages/chat.nytl.html index 582ece8..904c3d5 100644 --- a/assets/HypertextPages/chat.nytl.html +++ b/assets/HypertextPages/chat.nytl.html @@ -18,17 +18,17 @@ - Chat + {%w pres.chat.header-chat %} {%w openedchat.name %} {% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %}
diff --git a/assets/HypertextPages/edit-profile.nytl.html b/assets/HypertextPages/edit-profile.nytl.html index d34aea2..04264da 100644 --- a/assets/HypertextPages/edit-profile.nytl.html +++ b/assets/HypertextPages/edit-profile.nytl.html @@ -7,7 +7,7 @@ - Edit user Profile + {%w pres.edit-profile.header-profile-of %} {%w alienprofile.name %} @@ -29,37 +29,39 @@

{% W alienprofile.name %}

-

Nickname: {% W alienprofile.nickname %}

+

{%w pres.edit-profile.directive-nickname %} {% W alienprofile.nickname %}

{% W alienprofile.bio %}

-
-

Change user attributes

+
+

{%w pres.edit-profile.change-user-attributes %}

- + - +
- + - +
- +
- +
diff --git a/assets/HypertextPages/list-rooms.nytl.html b/assets/HypertextPages/list-rooms.nytl.html index 9b801d4..dc5e0b9 100644 --- a/assets/HypertextPages/list-rooms.nytl.html +++ b/assets/HypertextPages/list-rooms.nytl.html @@ -4,7 +4,7 @@ - List of chat rooms + {%w pres.list-rooms.header %} @@ -17,45 +17,47 @@ let initial_chatListUpdResp = {% PUT jsinsert initial_chatListUpdResp %}; x
diff --git a/assets/HypertextPages/login.nytl.html b/assets/HypertextPages/login.nytl.html index 3a1818b..2283ccd 100644 --- a/assets/HypertextPages/login.nytl.html +++ b/assets/HypertextPages/login.nytl.html @@ -7,7 +7,7 @@ - {% W pres.loginP.header %} + {% W pres.login.header %} {% FOR error IN errors %} @@ -17,25 +17,25 @@ {% ENDFOR %}
-

{% W pres.loginP.header %}

+

{% W pres.login.header %}

- + - +
+ placeholder="{% W pres.login.placeholder-nickname %}" class="one-line-input" required>
+ placeholder="{% W pres.login.placeholder-password %}" class="one-line-input" required>
- +
diff --git a/assets/HypertextPages/view-profile.nytl.html b/assets/HypertextPages/view-profile.nytl.html index c2a1e2e..34598d0 100644 --- a/assets/HypertextPages/view-profile.nytl.html +++ b/assets/HypertextPages/view-profile.nytl.html @@ -7,7 +7,7 @@ - User Profile + {%w pres.view-profile.header-profile-of %} {%w alienprofile.name %} @@ -22,10 +22,10 @@
-

{% W alienprofile.name %}

-

Nickname: {% W alienprofile.nickname %}

+

{%w alienprofile.name %}

+

{%w pres.view-profile.directive-nickname%} {%w alienprofile.nickname %}

- {% W alienprofile.bio %} + {%w alienprofile.bio %}

diff --git a/assets/js/chat-members.js b/assets/js/chat-members.js index d340b0a..cf9f42a 100644 --- a/assets/js/chat-members.js +++ b/assets/js/chat-members.js @@ -62,7 +62,7 @@ function convertMemberStToBox(memberSt){ return; userDeletionWinStoredUId = ID; document.getElementById("user-deletion-win-title").innerText = - "Do you really want to kick user " + memberSt.nickname + "?"; + pres['chat-members']['reask-kick-user-X'] + " " + memberSt.nickname + "?"; activatePopupWindowById("user-deletion-win"); }; box.querySelector(".CM-member-box-leave-btn").style.display = @@ -124,7 +124,7 @@ function configureSummonUserInterface(){ updateLocalStateFromRecv(Recv); }).catch((e) => { console.log(e); - alert("Failed to add user to chat"); + alert(pres['chat-members']["failed-summon-member"]); }); }; @@ -158,7 +158,7 @@ function configureKickUserInterfaceWinPart(){ updateLocalStateFromRecv(Recv); }).catch((e) => { console.log(e); - alert("Failed to kick user from chat"); + alert(pres['chat-members']["failed-kick-member"]); }); } diff --git a/assets/js/chat.js b/assets/js/chat.js index 69a25a7..4db63de 100644 --- a/assets/js/chat.js +++ b/assets/js/chat.js @@ -27,6 +27,7 @@ let storeHiddenMsgIdForDeletionWin = -1; // Positive in production, negative for debug let softZoneSz = -150; let chatPadding = 300; +const msgErased = pres.chat.msgErased; function genSentBase(){ return { @@ -168,13 +169,13 @@ function decodeSystemMessage(text){ let subjectRef = members.has(subjectId) ? members.get(subjectId).nickname : "???"; let objectRef = members.has(objectId) ? members.get(objectId).nickname : "???"; if (verb === "kicked"){ - return subjectRef + " kicked " + objectRef; + return subjectRef + " " + pres.chat.syslog.kicked + " " + objectRef; } else if (verb === "summoned"){ - return subjectRef + " summoned " + objectRef; + return subjectRef + " " + pres.chat.syslog.summoned + " " + objectRef; } else if (verb === "left"){ - return subjectRef + " left chat"; + return subjectRef + " " + pres.chat.syslog.left; } else if (verb === "created"){ - return subjectRef + " created this chat"; + return subjectRef + " " + pres.chat.syslog.created; } return "... Bad log ..."; } @@ -239,7 +240,6 @@ function convertMessageStToSupercontainer(messageSt){ return; let URI = window.location.host + "/chat/" + openedchat.nickname + "/m/" + String(ID); document.getElementById("message-input").innerText += (" " + URI + ""); - console.log("Tried to get link on message " + ID); }; } @@ -389,7 +389,7 @@ function configureMsgDeletionPopupButtons(){ deactivateActivePopup(); let Sent = genSentBase(); Sent.id = storeHiddenMsgIdForDeletionWin; - safeApiRequestWithLocalStUpdate("deleteMessage", Sent, "Failed to delete message"); + safeApiRequestWithLocalStUpdate("deleteMessage", Sent, pres.chat['failed-delete-message']); }; document.getElementById("msg-deletion-no").onclick = function (ev){ @@ -426,7 +426,7 @@ window.onload = function (){ let Sent = genSentBase(); Sent.content = {}; Sent.content.text = text; - safeApiRequestWithLocalStUpdate("sendMessage", Sent, "Failed to send message"); + safeApiRequestWithLocalStUpdate("sendMessage", Sent, pres.chat['failed-send-message']); } }); diff --git a/assets/js/common.js b/assets/js/common.js index 3b48ded..16fb935 100644 --- a/assets/js/common.js +++ b/assets/js/common.js @@ -57,9 +57,6 @@ function roleToColor(role) { return "#286500" // Bug } -// todo: replace it with translation -const msgErased = "[ ERASED ]"; - function hideHTMLElement(el){ el.style.display = "none"; } diff --git a/assets/js/list-rooms.js b/assets/js/list-rooms.js index 7068e4f..a1b0a73 100644 --- a/assets/js/list-rooms.js +++ b/assets/js/list-rooms.js @@ -13,7 +13,8 @@ let chatBoxes = new Map(); /* Generate text that is displayed on the right side of chat intro box */ function youAreXHere(myRoleHere){ - return "You are " + myRoleHere + " here"; + // todo: TRANSLATE IT + return pres['list-rooms']['you-are-X-here'][0] + " " + myRoleHere + " " + pres['list-rooms']['you-are-X-here'][1]; } @@ -67,7 +68,7 @@ function convertMyMembershipStToBox(myMembershipSt){ return; chatRenunciationWinStoredId = ID; document.getElementById("chat-renunciation-win-title").innerText = - "Do you really want to leave chat " + myMembershipSt.chatNickname + "?"; + pres['list-rooms']['reask-leave-chat-X'] + " " + myMembershipSt.chatNickname + "?"; activatePopupWindowById("chat-renunciation-win"); }; box.querySelector(".CL-my-chat-box-leave-btn").style.display = @@ -119,7 +120,7 @@ function configureChatCreationInterface(){ ).then((Recv) => { updateLocalStateFromRecv(Recv); }).catch((e) => { - alert("Failed to create chat"); + alert(pres['list-rooms']["failed-create-chat"]); console.log(e); }); }; @@ -138,7 +139,6 @@ function configureChatCreationInterface(){ chatNicknameInput.value = ""; chatNameInput.value = ""; activatePopupWindowById("chat-creation-win"); - console.log("Tried to show chat creation window"); }; } @@ -156,7 +156,7 @@ function configureChatRenunciationInterfaceWinPart(){ ).then((Recv) => { updateLocalStateFromRecv(Recv); }).catch((e) => { - alert("Failed to leave chat"); + alert(pres['list-rooms']["failed-create-chat"]); console.log(e); }); } diff --git a/assets/lang/en-US.lang.json b/assets/lang/en-US.lang.json index 21fe522..166587f 100644 --- a/assets/lang/en-US.lang.json +++ b/assets/lang/en-US.lang.json @@ -1,11 +1,76 @@ { "lang": "en", - "loginP": { + "login": { "header": "Login", "directive-nickname": "Enter your nickname:", "placeholder-nickname": "Nickname", "directive-password": "Enter password:", "placeholder-password": "Password", - "act": "Login" + "act": "Login", + "incorrect-nickname-or-password": "Incorrect nickname or password" + }, + "view-profile": { + "header-profile-of": "Profile of", + "directive-nickname": "Nickname:" + }, + "edit-profile": { + "header-profile-of": "Profile of", + "change-user-attributes": "Change user attributes", + "directive-nickname": "Nickname:", + "directive-name": "Enter new name:", + "placeholder-name": "New name", + "directive-password": "Enter new password:", + "placeholder-password": "New password", + "directive-bio": "Change description:", + "act-submit": "Submit changes", + "incorrect-profile-data": "Incorrec profile data" + }, + "list-rooms": { + "header": "List of chat rooms", + "new-chat-header": "Input identifying information for your new chat", + "directive-nickname": "Enter nickname for new chat:", + "placeholder-nickname": "Take a nickname", + "directive-name": "Enter name for new chat:", + "placeholder-name": "Come up with name", + "reask-create-new-chat": "Create new chat?", + "yes-create": "Yes, create", + "no-create": "No, cancel", + "reask-leave-chat-X": "Do you really want to leave chat", + "yes-leave": "Yes, leave", + "no-leave": "No, cancel", + "page-description": "List of available rooms", + "you-are-X-here": ["You are", "here"], + + "failed-create-chat": "Failed to create chat", + "failed-to-leave-chat": "Failed to leave chat" + }, + "chat-members": { + "members-of": "Members of", + "summon-label-nickname": "Nickname for summoned user", + "summon-label-ro": "Make read only", + "yes-summon": "Yes, summon", + "no-summon": "No, cancel", + "yes-kick": "Yes, delete", + "no-kick": "No, cancel", + "members-list-of": "Members list of", + "reask-kick-user-X" : "Do you really want to kick user", + + "failed-summon-member": "Failed to add user to chat", + "failed-kick-member": "Failed to kick user from chat" + }, + "chat": { + "header-chat": "Chat", + "reask-delete-message": "Are you sure you want to delete this message?", + "yes-delete": "Yes, delete", + "no-delete": "No, cancel", + "msgErased": "[ ERASED ]", + "syslog": { + "kicked": "kicked", + "summoned": "summoned", + "left": "left chat", + "created": "created this chat" + }, + "failed-delete-message": "Failed to delete message", + "failed-send-message": "Failed to send message" } } diff --git a/assets/lang/ru-RU.lang.json b/assets/lang/ru-RU.lang.json index 2147a5f..57ff3fe 100644 --- a/assets/lang/ru-RU.lang.json +++ b/assets/lang/ru-RU.lang.json @@ -1,11 +1,21 @@ { "lang": "ru", - "loginP": { + "login": { "header": "Вход", "directive-nickname": "Введите свой никнейм:", - "placeholder-nickname": "", + "placeholder-nickname": "Никнейм", "directive-password": "Введите пароль:", - "placeholder-password": "", - "act": "Войти" + "placeholder-password": "Пароль", + "act": "Войти", + "incorrect-nickname-or-password": "Неверный логин или пароль" + }, + "view-profile": { + "header-profile-of": "Профиль", + "directive-nickname": "Никнейм:" + }, + "edit-profile": { + "header-profile-of": "Профиль", + "directive-nickname": "Никнейм:", + "change-user-attributes": "Изменить аттрибуты пользователя" } } \ No newline at end of file diff --git a/src/http_server/misc_tests/HypertextPages/test.nytl.html b/src/http_server/misc_tests/HypertextPages/test.nytl.html index a6f6f60..5614b90 100644 --- a/src/http_server/misc_tests/HypertextPages/test.nytl.html +++ b/src/http_server/misc_tests/HypertextPages/test.nytl.html @@ -1,8 +1,6 @@ -{% ELDEF main JSON cba %} +{% ELDEF main JSON userprofile %} AAA - {% FOR val IN cba.arr %} - --> {% WRITE val %} - {% ENDFOR %} + --> {% WRITE userprofile.name %} AAA {% ENDELDEF %} diff --git a/src/http_server/misc_tests/nytl_test1.cpp b/src/http_server/misc_tests/nytl_test1.cpp index e0937cd..afd4dde 100644 --- a/src/http_server/misc_tests/nytl_test1.cpp +++ b/src/http_server/misc_tests/nytl_test1.cpp @@ -9,15 +9,11 @@ int main(int argc, char** argv) { exit(1); } - std::string dir_path = argv[1]; + // std::string dir_path = "./src/http_server/misc_tests/HypertextPages"; + std::string dir_path = "/home/gregory/cpp_projects/iu9-ca-web-chat/assets/HypertextPages"; nytl::Templater templater(nytl::TemplaterSettings{nytl::TemplaterDetourRules{dir_path}}); templater.update(); - std::string config_file = argv[2]; - std::string config_text; - een9::readFile(config_file, config_text); - const json::JSON config = json::parse_str_flawless(config_text); - json::JSON userprofile; userprofile["uid"].asInteger() = json::Integer(0l); userprofile["name"].asString() = "radasdasdasdadsdasd"; @@ -25,7 +21,7 @@ int main(int argc, char** argv) { userprofile["bio"].asString() = "Your mother"; json::JSON errors; errors = json::JSON(json::array); - std::string answer2 = templater.render("edit-profile", {&config["presentation"], &userprofile, &errors}); + std::string answer2 = templater.render("err-404", {}); printf("%s\n<>\n", answer2.c_str()); return 0; diff --git a/src/http_server/new_york_transit_line/debug_print.cpp b/src/http_server/new_york_transit_line/debug_print.cpp index 063f17d..f4faa3b 100644 --- a/src/http_server/new_york_transit_line/debug_print.cpp +++ b/src/http_server/new_york_transit_line/debug_print.cpp @@ -7,8 +7,13 @@ namespace nytl { void debug_print_templater(const Templater& T) { printf("===== TEMPLATER INTERNAL RESOURCES =====\n"); for (auto& p: T.elements) { + if (!p.second.is_element) { + printf("=== %s is empty =====\n", p.first.c_str()); + continue; + } printf("=== %s element =====\n", p.first.c_str()); - const Element& el = p.second; + assert(p.second.when_element); + const Element& el = *p.second.when_element; printf("%s, %s\n", el.base ? "BASE" : "NOT BASE", el.is_hidden ? "HIDDEN" : "NOT HIDDEN"); if (!el.is_hidden) { std::string signature; diff --git a/src/http_server/new_york_transit_line/parser.cpp b/src/http_server/new_york_transit_line/parser.cpp index 94e447f..d031d89 100644 --- a/src/http_server/new_york_transit_line/parser.cpp +++ b/src/http_server/new_york_transit_line/parser.cpp @@ -150,17 +150,41 @@ namespace nytl { return concatenateLines(lines); } - void parse_bare_file(const std::string& filename, const std::string& content, - global_elem_set_t& result) - { - if (result.count(filename) != 0) - THROW("Repeated element " + filename); + Element& add_hidden_element(const std::string& new_el_name, global_elem_set_t& result) { + if (result.count(new_el_name) != 0) + THROW("Repated element " + new_el_name); + TemplaterRegPref& rp = result[new_el_name]; + rp.is_element = 1; + rp.when_element = std::make_unique(); + rp.when_element->is_hidden = true; + return *rp.when_element; + } + + Element& add_new_element(const std::string& new_el_name, global_elem_set_t& result) { + if (!is_uname_dotted_sequence(new_el_name)) + THROW("Krabovaya oshibka"); + if (result.count(new_el_name) != 0 && result.at(new_el_name).is_element) + THROW("Repated element " + new_el_name); + size_t n = new_el_name.size(); + for (size_t i = 0; i < n; i++) { + if (new_el_name[i] == '.') { + std::string pref = new_el_name.substr(0, i); + result[pref]; + } + } + TemplaterRegPref& rp = result[new_el_name]; + rp.is_element = 1; + rp.when_element = std::make_unique(); + return *rp.when_element; + } + + void parse_bare_file(const std::string& filename, const std::string& content, global_elem_set_t& result) { + Element& el = add_new_element(filename, result); std::string txt = clement_lstrip(content); rstrip(txt); size_t cut = 9999999999999; one_part_update_min_start_wsp_non_empty(txt, 0, 1, cut); txt = one_part_cut_excess_tab(txt, 0, 1, cut); - Element& el = result[filename]; el.parts = {ElementPart{}}; el.parts[0].when_code.lines = mv(txt); } @@ -379,8 +403,7 @@ namespace nytl { skipWhitespace(ctx); P.ref_over = parse_expression(ctx, local_var_names); P.internal_element = el_name + ".~" + std::to_string(free_hidden++); - Element& newborn = elem_ns[P.internal_element]; - newborn.is_hidden = true; + Element& newborn = add_hidden_element(P.internal_element, elem_ns); arg_name_list_t local_var_names_of_nxt = local_var_names; if (V1 != "_") { if (local_var_names_of_nxt.count(V1) != 0) @@ -417,8 +440,7 @@ namespace nytl { skipWhitespace(ctx); P.ref_over = parse_expression(ctx, local_var_names); P.internal_element = el_name + ".~" + std::to_string(free_hidden++); - Element& newborn = elem_ns[P.internal_element]; - newborn.is_hidden = true; + Element& newborn = add_hidden_element(P.internal_element, elem_ns); arg_name_list_t local_var_names_of_nxt = local_var_names; size_t k = local_var_names_of_nxt.size(); local_var_names_of_nxt.emplace(Vn, k); @@ -427,7 +449,7 @@ namespace nytl { return std::make_unique(P.internal_element, gone_for_ref, local_var_names_of_nxt, ret_data_int, newborn); } - if (op == "PUT") { + if (op == "PUT" || op == "P") { result.parts.emplace_back(); result.parts.back().type = ElementPart::p_put; ElementPart::when_put_S& P = result.parts.back().when_put; @@ -549,9 +571,7 @@ namespace nytl { if (elname_postfix == "_") THROW("Can't use _ as element name"); std::string fullname = elname_postfix == "main" ? filename : filename + "." + elname_postfix; - if (result.count(fullname) != 0) - THROW("Element " + fullname + " has been already defined"); - Element& newborn = result[fullname]; + Element& newborn = add_new_element(fullname, result); arg_name_list_t arglist; while (true) { skipWhitespace(ctx); diff --git a/src/http_server/new_york_transit_line/rendering.cpp b/src/http_server/new_york_transit_line/rendering.cpp index c6583a9..50bf47a 100644 --- a/src/http_server/new_york_transit_line/rendering.cpp +++ b/src/http_server/new_york_transit_line/rendering.cpp @@ -23,37 +23,41 @@ namespace nytl { result(result) { } - void descend(const json::JSON& what) { + void descend(const json::JSON& what, const global_elem_set_t& global_elems) { if (result.is_json) { const json::JSON& P = *result.JSON_subval; if (P.isArray() && what.isInteger()) { const std::vector& arr_p = P.asArray(); int64_t ind_w = what.asInteger().get_int(); - ASSERT(ind_w > 0 && ind_w < arr_p.size(), "Expression \"array[integer]\" caused out-of-bound situation"); + if (!(ind_w > 0 && ind_w < arr_p.size())) + THROW("Expression \"array[integer]\" caused out-of-bound situation"); result = LocalVarValue{true, "", &arr_p[ind_w]}; } else if (P.isDictionary() && what.isString()) { const std::map& dict_p = P.asDictionary(); const std::string& key_w = what.asString(); - ASSERT(dict_p.count(key_w) == 1, "No such key exception (" + key_w + ")"); + if (dict_p.count(key_w) != 1) + THROW("No such key exception (" + key_w + ")"); result = LocalVarValue{true, "", &dict_p.at(key_w)}; } else THROW("Incorrect type of \"json[json]\" expression. Unallowed signature of [] operator"); } else { - ASSERT(what.isString(), "Expression \"element[X]\" allowed only if X is string (json object)"); - if (what.asString().empty()) - return; - if (!is_uname_dotted_sequence(what.asString())) - THROW("Incorrect X in \"element[X]\""); + if (!what.isString()) + THROW("Expression \"element[X]\" allowed only if X is string (json object)"); + if (!isUname(what.asString())) + THROW("Expression \"element[str]\" has incorrect str (" + what.asString() + ")"); result.EL_name += ("." + what.asString()); + if (global_elems.count(result.EL_name) != 1) + THROW("Can't descend. No such element (" + result.EL_name + ")"); } } uptr toMe(bool returned, const global_elem_set_t& global_elems, const std::vector& local_vars) { if (returned) { - ASSERT(temp_ret.is_json, "Expression \"X[ element ]\" is not allowed"); + if (!temp_ret.is_json) + THROW("Expression \"X[ element ]\" is not allowed"); assert(temp_ret.JSON_subval); - descend(*(temp_ret.JSON_subval)); + descend(*(temp_ret.JSON_subval), global_elems); } else { assert(expr.isDictionary()); const json::JSON& val = expr["V"]; @@ -63,6 +67,8 @@ namespace nytl { result = local_vars[lv_ind]; } else if (val.isString()) { std::string cur_el_name_str = expr["V"].asString(); + if (global_elems.count(cur_el_name_str) != 1) + THROW("Bad expression, no such element (" + cur_el_name_str + ")"); result = LocalVarValue{false, cur_el_name_str, NULL}; } else assert(false); @@ -74,7 +80,7 @@ namespace nytl { const json::JSON& t = chain[chain_el++]; if (t.isDictionary()) return std::make_unique(t, temp_ret); - descend(t); + descend(t, global_elems); } } }; @@ -84,6 +90,8 @@ namespace nytl { * and dictionaries. They are stored in json in rendering stack */ LocalVarValue rendering_core_execute_expression(const global_elem_set_t& global_elems, const std::vector& local_vars, const json::JSON& expr) { + + // todo: check if root element exists (if root value is not local variable, then it is element of package) bool returned = false; std::vector> stack; LocalVarValue result; @@ -211,9 +219,9 @@ namespace nytl { uptr RFrame_OverParts::toMe(bool returned, const global_elem_set_t &elem_ns, Ditch &result, const std::function &escape) { if (!returned) - if (elem_ns.count(name) != 1) - THROW("No such element (" + name + ")"); - const Element& el = elem_ns.at(name); + if ((elem_ns.count(name) != 1) || (!elem_ns.at(name).is_element)) + THROW("Can't render. No such element (" + name + ")"); + const Element& el = *elem_ns.at(name).when_element; if (!returned) { /* Continue to do checks */ /* hidden elements (internal) do not need any check */ @@ -222,16 +230,17 @@ namespace nytl { ASSERT(n == passed_args.size(), "Argument count mismatch"); for (size_t i = 0; i < n; i++) { if (el.arguments[i].type == json::true_symbol) { - ASSERT(passed_args[i].is_json, "Expected json element argument, got element"); + if (!passed_args[i].is_json) + THROW("Expected json element argument, got element"); } else { // If not json is expected, element must be expected assert(el.arguments[i].isArray()); - ASSERT(!passed_args[i].is_json, "Expected element element arguemnt, got json"); + if (passed_args[i].is_json) + THROW("Expected element element arguemnt, got json"); const std::string& passed_el_as_arg = passed_args[i].EL_name; - if (elem_ns.count(passed_el_as_arg) != 1) + if ((elem_ns.count(passed_el_as_arg) != 1) || !elem_ns.at(passed_el_as_arg).is_element) THROW("No such element, can't compare signatures of argument value (" + passed_el_as_arg + ")"); - const Element& arg_element = elem_ns.at(passed_args[i].EL_name); - // ASSERT(passed_args); + const Element& arg_element = elem_ns.at(passed_el_as_arg).when_element.operator*(); if(el.arguments[i].asArray() != arg_element.arguments) THROW("Signature of argument " + std::to_string(i) + " does not match"); } diff --git a/src/http_server/new_york_transit_line/templater.cpp b/src/http_server/new_york_transit_line/templater.cpp index b20b365..26758ab 100644 --- a/src/http_server/new_york_transit_line/templater.cpp +++ b/src/http_server/new_york_transit_line/templater.cpp @@ -109,16 +109,17 @@ namespace nytl { return result; } + TemplaterRegPref gen_base_element() { + Element* e = new Element{{json::JSON(true)}, true, false, {}}; + return {1, std::unique_ptr(e)}; + } + void Templater::update() { - elements = { - {"jsinsert", Element{{json::JSON(true)}, true}}, - {"jesc", Element{{json::JSON(true)}, true}}, - {"jesccomp", Element{{json::JSON(true)}, true}}, - /* str2text base element has a dedicated operator - WRITE */ - {"str2text", Element{{json::JSON(true)}, true}}, - /* str2code base element has a dedicated operator - ROUGHINSERT */ - {"str2code", Element{{json::JSON(true)}, true}}, - }; + elements[""] = TemplaterRegPref{0, NULL}; + elements["jsinsert"] = gen_base_element(); + elements["jesc"] = gen_base_element(); + elements["str2text"] = gen_base_element(); + elements["str2code"] = gen_base_element(); std::vector intersting_files = indexing_detour(settings.det); for (const InterestingFile& file: intersting_files) { std::string content = readFile(file.path); @@ -132,7 +133,8 @@ namespace nytl { /* Still can throw some stuff derived from std::exception (like bad alloc) */ std::string Templater::render(const std::string& element, const std::vector &arguments) const { - ASSERT(is_uname_dotted_sequence(element), "Incorrect entry element name"); + if (!is_uname_dotted_sequence(element)) + THROW("Incorrect entry element name"); return rendering_core(element, arguments, elements, settings.escape); } } diff --git a/src/http_server/new_york_transit_line/templater.h b/src/http_server/new_york_transit_line/templater.h index 599ae75..b1f235f 100644 --- a/src/http_server/new_york_transit_line/templater.h +++ b/src/http_server/new_york_transit_line/templater.h @@ -6,6 +6,8 @@ #include #include #include "html_case.h" +#include +#include namespace nytl { typedef json::JSON expression_t; @@ -61,7 +63,12 @@ namespace nytl { std::function escape = html_case_espace_string; }; - typedef std::map global_elem_set_t; + struct TemplaterRegPref { + int is_element = 0; + std::unique_ptr when_element = NULL; + }; + + typedef std::map global_elem_set_t; struct Templater { TemplaterSettings settings; diff --git a/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_login.cpp b/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_login.cpp index 3b0749d..b01fc2e 100644 --- a/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_login.cpp +++ b/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_login.cpp @@ -28,7 +28,7 @@ namespace iu9cawebchat { if (uid < 0) { printf("Redirecting back to /login because of incorrect credentials\n"); json::JSON msg_list = jsonify_html_message_list({{"", - config_presentation["phr"]["decl"]["incorrect-nickname-or-password"].asString()}}); + config_presentation["loginP"]["incorrect-nickname-or-password"].asString()}}); return http_R200("login", wgd, {&config_presentation, &userinfo, &msg_list}); } std::vector> response_hlines; diff --git a/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_user.cpp b/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_user.cpp index c659b63..2137387 100644 --- a/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_user.cpp +++ b/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_user.cpp @@ -104,7 +104,7 @@ namespace iu9cawebchat { } catch (const std::exception& e) { printf("Redirecting back to /user/... because of incorrect credentials\n"); json::JSON msg_list = jsonify_html_message_list({{"", - config_presentation["phr"]["decl"]["incorrect-profile-data"].asString()}}); + config_presentation["edit-profile"]["incorrect-profile-data"].asString()}}); json::JSON alien_userprofile = user_row_to_userprofile_obj(conn, alien); return http_R200("edit-profile", wgd, {&config_presentation, &userinfo, &alien_userprofile, &msg_list}); }