master #6
							
								
								
									
										25
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								README.md
									
									
									
									
									
								
							| @ -60,6 +60,31 @@ regexis024_build_system.sh | |||||||
| Утилита `iu9-ca-web-chat-admin-cli` позволяет администратору сервиса контролировать его через сокет | Утилита `iu9-ca-web-chat-admin-cli` позволяет администратору сервиса контролировать его через сокет | ||||||
| (адрес указан в `config["server"]["admin-command-listen"]`). | (адрес указан в `config["server"]["admin-command-listen"]`). | ||||||
| 
 | 
 | ||||||
|  | По адресам `config.server.admin-command-listen` идёт прослушивание так называемых "команд администратора". | ||||||
|  | iu9cawebchat определяет свой простой протокол для передачи этих команд. | ||||||
|  | Утилита iu9-ca-web-chat-admin-cli может отправить текст с некой командой на сервер на этот адрес и получить | ||||||
|  | ответ от сервера. | ||||||
|  | 
 | ||||||
|  | ```shell | ||||||
|  | iu9-ca-web-chat-admin-cli <server admin-control address> <command text> [<command text> ...] | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Дополнительные параметры конкатенируются, разделяясь переводом строки. | ||||||
|  | Команды администратора: | ||||||
|  | 
 | ||||||
|  | `updateroopw <new root password>` - сменить пароль пользователя с номером 0 | ||||||
|  | 
 | ||||||
|  | `adduser <user nickname> <user name> <user password> <user bio>` - зарегистрировать пользователя сайта  | ||||||
|  | 
 | ||||||
|  | Если нужно ввести пробел или символ `\ ` в любое из этих полей, перед ними нужно поставить `\ `; | ||||||
|  | 
 | ||||||
|  | Параметры конфигурации `config.lang.whitelist` и `config.lang.force-order` определяют на | ||||||
|  | какие языки будет локализован сервер, и какие переводы приоритетнее каких. | ||||||
|  | На данный момент поддерживаются | ||||||
|  |  - `ru-RU`  | ||||||
|  |  - `en-US` | ||||||
|  | Все переводы хранятся в папке `assets/lang`. | ||||||
|  | 
 | ||||||
| # Список участников | # Список участников | ||||||
| 
 | 
 | ||||||
| 1. [Китанин Фёдор](https://gitflic.ru/user/fed-kit) | 1. [Китанин Фёдор](https://gitflic.ru/user/fed-kit) | ||||||
|  | |||||||
| @ -8,25 +8,25 @@ | |||||||
|     <link rel="stylesheet" href="/assets/css/common.css"> |     <link rel="stylesheet" href="/assets/css/common.css"> | ||||||
|     <link rel="stylesheet" href="/assets/css/common-popup.css"> |     <link rel="stylesheet" href="/assets/css/common-popup.css"> | ||||||
|     <link rel="stylesheet" href="/assets/css/chat-members.css"> |     <link rel="stylesheet" href="/assets/css/chat-members.css"> | ||||||
|     <title>Chat Members</title> |     <title>{%w pres.chat-members.members-of %} {%w openedchat.name %}</title> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
|     {% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %} |     {% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %} | ||||||
| 
 | 
 | ||||||
|     <div id="user-summoning-win" class="popup-window"> |     <div id="user-summoning-win" class="popup-window"> | ||||||
|         <h1 class="popup-window-msg">Nickname for summoned user</h1> |         <h1 class="popup-window-msg">{%w pres.chat-members.summon-label-nickname %}</h1> | ||||||
|         <input class="one-line-input" id="summoned-user-nickname"> |         <input class="one-line-input" id="summoned-user-nickname"> | ||||||
|         <input type="checkbox" id="summoned-user-is-read-only"> |         <input type="checkbox" id="summoned-user-is-read-only"> | ||||||
|         <label>Make read only</label><br> |         <label>{%w pres.chat-members.summon-label-ro %}</label><br> | ||||||
|         <button class="popup-window-btn-yes" id="user-summoning-yes">Yes, summon</button> |         <button class="popup-window-btn-yes" id="user-summoning-yes">{%w pres.chat-members.yes-summon %}</button> | ||||||
|         <button class="popup-window-btn-no" id="user-summoning-no">No, cancel</button> |         <button class="popup-window-btn-no" id="user-summoning-no">{%w pres.chat-members.no-summon %}</button> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <div id="user-deletion-win" class="popup-window"> |     <div id="user-deletion-win" class="popup-window"> | ||||||
|         <!-- header will actually be rewritten before showing the window to include user nickname --> |         <!-- header will actually be rewritten before showing the window to include user nickname --> | ||||||
|         <h1 id="user-deletion-win-title" class="popup-window-msg">Are you sure you want to ban user?</h1> |         <h1 id="user-deletion-win-title" class="popup-window-msg"> ||||||||| </h1> | ||||||
|         <button class="popup-window-btn-yes" id="user-deletion-yes">Yes, delete</button> |         <button class="popup-window-btn-yes" id="user-deletion-yes">{%w pres.chat-members.yes-kick %}</button> | ||||||
|         <button class="popup-window-btn-no" id="user-deletion-no">No, cancel</button> |         <button class="popup-window-btn-no" id="user-deletion-no">{%w pres.chat-members.no-kick %}</button> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <div class="document-container resp-container"> |     <div class="document-container resp-container"> | ||||||
| @ -37,7 +37,9 @@ | |||||||
|             <a href="/user/{% W userinfo.nickname %}" id="go-to-my-profile" class="panel-thing"> |             <a href="/user/{% W userinfo.nickname %}" id="go-to-my-profile" class="panel-thing"> | ||||||
|                 <img alt="Go to my profile" src="/assets/img/user.svg" width="32px"> |                 <img alt="Go to my profile" src="/assets/img/user.svg" width="32px"> | ||||||
|             </a> |             </a> | ||||||
|             <p class="panel-thing panel-header-txt"> Members list of {% W openedchat.name %} ({% W openedchat.nickname %})</p> |             <p class="panel-thing panel-header-txt"> | ||||||
|  |                 {%w pres.chat-members.members-list-of %} {% W openedchat.name %} ({% W openedchat.nickname %}) | ||||||
|  |             </p> | ||||||
|             <a href="/chat/{% W openedchat.nickname %}" id="go-to-chat-settings" class="panel-thing"> |             <a href="/chat/{% W openedchat.nickname %}" id="go-to-chat-settings" class="panel-thing"> | ||||||
|                 <img alt="Back to chat" src="/assets/img/return.svg" width="32px"> |                 <img alt="Back to chat" src="/assets/img/return.svg" width="32px"> | ||||||
|             </a> |             </a> | ||||||
|  | |||||||
| @ -18,17 +18,17 @@ | |||||||
|     <link rel="stylesheet" href="/assets/css/common.css"> |     <link rel="stylesheet" href="/assets/css/common.css"> | ||||||
|     <link rel="stylesheet" href="/assets/css/common-popup.css"> |     <link rel="stylesheet" href="/assets/css/common-popup.css"> | ||||||
|     <link rel="stylesheet" href="/assets/css/chat.css"> |     <link rel="stylesheet" href="/assets/css/chat.css"> | ||||||
|     <title>Chat</title> |     <title>{%w pres.chat.header-chat %} {%w openedchat.name %}</title> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
|     {% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %} |     {% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %} | ||||||
| 
 | 
 | ||||||
|     <div id="msg-deletion-win" class="popup-window"> |     <div id="msg-deletion-win" class="popup-window"> | ||||||
|         <h1 class="popup-window-msg">Are you sure you want to delete this message?</h1> |         <h1 class="popup-window-msg">{%w pres.chat.reask-delete-message %}</h1> | ||||||
|         <!-- message preview will be actually rewritten before each window activation--> |         <!-- mesage preview will be actually rewritten before each window activation--> | ||||||
|         <p class="message-in-popup-preview" id="win-deletion-msg-preview">Lorem ipsum dolor</p> |         <p class="message-in-popup-preview" id="win-deletion-msg-preview">|||||||||</p> | ||||||
|         <button class="popup-window-btn-yes" id="msg-deletion-yes">Yes, delete</button> |         <button class="popup-window-btn-yes" id="msg-deletion-yes">{%w pres.chat.yes-delete %}</button> | ||||||
|         <button class="popup-window-btn-no" id="msg-deletion-no">No, cancel</button> |         <button class="popup-window-btn-no" id="msg-deletion-no">{%w pres.chat.no-delete %}</button> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <div class="fullscreen-container resp-container"> |     <div class="fullscreen-container resp-container"> | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ | |||||||
|     <link rel="icon" type="image/png" href="/assets/img/favicon.png"> |     <link rel="icon" type="image/png" href="/assets/img/favicon.png"> | ||||||
|     <link rel="stylesheet" href="/assets/css/common.css"> |     <link rel="stylesheet" href="/assets/css/common.css"> | ||||||
|     <link rel="stylesheet" href="/assets/css/edit-profile.css"> |     <link rel="stylesheet" href="/assets/css/edit-profile.css"> | ||||||
|     <title>Edit user Profile</title> |     <title>{%w pres.edit-profile.header-profile-of %} {%w alienprofile.name %}</title> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
| 
 | 
 | ||||||
| @ -29,37 +29,39 @@ | |||||||
| 
 | 
 | ||||||
|         <div class="profile-container"> |         <div class="profile-container"> | ||||||
|             <h2 class="profile-name-text">{% W alienprofile.name %}</h2> |             <h2 class="profile-name-text">{% W alienprofile.name %}</h2> | ||||||
|             <h3 class="profile-nickname-text">Nickname: {% W alienprofile.nickname %}</h3> |             <h3 class="profile-nickname-text">{%w pres.edit-profile.directive-nickname %} {% W alienprofile.nickname %}</h3> | ||||||
|             <p class="profile-bio-text"> |             <p class="profile-bio-text"> | ||||||
|                 {% W alienprofile.bio %} |                 {% W alienprofile.bio %} | ||||||
|             </p> |             </p> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <div class="profile-container resp-container"> |         <div class="profile-container"> | ||||||
|             <h1 class="wide-centered-header">Change user attributes</h1> |             <h1 class="wide-centered-header">{%w pres.edit-profile.change-user-attributes %}</h1> | ||||||
|             <form action = "/user/{% W alienprofile.nickname %}" method="post" enctype="application/x-www-form-urlencoded"> |             <form action = "/user/{% W alienprofile.nickname %}" method="post" enctype="application/x-www-form-urlencoded"> | ||||||
|                 <table class="logins-input-table"> |                 <table class="logins-input-table"> | ||||||
|                     <tr> |                     <tr> | ||||||
|                         <td class="logins-input-td1"> |                         <td class="logins-input-td1"> | ||||||
|                             <label for="new-name-input">Enter new name:</label> |                             <label for="new-name-input">{%w pres.edit-profile.directive-name %}</label> | ||||||
|                         </td> |                         </td> | ||||||
|                         <td class="logins-input-td2"> |                         <td class="logins-input-td2"> | ||||||
|                             <input name="name" id="new-name-input" type="text" placeholder="New name" class="one-line-input"> |                             <input name="name" id="new-name-input" type="text" | ||||||
|  |                                    placeholder="{%w pres.edit-profile.placeholder-name %}" class="one-line-input"> | ||||||
|                         </td> |                         </td> | ||||||
|                     </tr> |                     </tr> | ||||||
|                     <tr> |                     <tr> | ||||||
|                         <td class="logins-input-td1"> |                         <td class="logins-input-td1"> | ||||||
|                             <label for="new-password-input">Enter new password: </label> |                             <label for="new-password-input">{%w pres.edit-profile.directive-password %}</label> | ||||||
|                         </td> |                         </td> | ||||||
|                         <td class="logins-input-td2"> |                         <td class="logins-input-td2"> | ||||||
|                             <input name="password" id="new-password-input" type="password" placeholder="New password" class="one-line-input"> |                             <input name="password" id="new-password-input" type="password" | ||||||
|  |                                    placeholder="{%w pres.edit-profile.placeholder-password %}" class="one-line-input"> | ||||||
|                         </td> |                         </td> | ||||||
|                     </tr> |                     </tr> | ||||||
|                 </table> |                 </table> | ||||||
|                 <label for="input-change-bio">Change description:</label> |                 <label for="input-change-bio">{%w pres.edit-profile.directive-bio %}</label> | ||||||
|                 <br> |                 <br> | ||||||
|                 <textarea name="bio" id="input-change-bio" class="multiline-input"></textarea> |                 <textarea name="bio" id="input-change-bio" class="multiline-input"></textarea> | ||||||
|                 <button class="action-button centered-block-el" type="submit">Submit changes</button> |                 <button class="action-button centered-block-el" type="submit">{%w pres.edit-profile.act-submit %}</button> | ||||||
|             </form> |             </form> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ | |||||||
| <head> | <head> | ||||||
|     <meta charset="UTF-8"> |     <meta charset="UTF-8"> | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> |     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|     <title>List of chat rooms</title> |     <title>{%w pres.list-rooms.header %}</title> | ||||||
|     <link rel="icon" type="image/png" href="/assets/img/favicon.png"> |     <link rel="icon" type="image/png" href="/assets/img/favicon.png"> | ||||||
|     <link rel="stylesheet" href="/assets/css/common.css"> |     <link rel="stylesheet" href="/assets/css/common.css"> | ||||||
|     <link rel="stylesheet" href="/assets/css/common-popup.css"> |     <link rel="stylesheet" href="/assets/css/common-popup.css"> | ||||||
| @ -17,45 +17,47 @@ | |||||||
|         let initial_chatListUpdResp = {% PUT jsinsert initial_chatListUpdResp %}; |         let initial_chatListUpdResp = {% PUT jsinsert initial_chatListUpdResp %}; | ||||||
|     </script> |     </script> | ||||||
|     <div id="chat-creation-win" class="popup-window"> |     <div id="chat-creation-win" class="popup-window"> | ||||||
|         <h1 class="popup-window-msg">Input identifying information for your new chat</h1> |         <h1 class="popup-window-msg">{%w pres.list-rooms.new-chat-header %}</h1> | ||||||
|         <table class="id-str-input-table"> |         <table class="id-str-input-table"> | ||||||
|             <tr> |             <tr> | ||||||
|                 <td class="id-str-input-td1"> |                 <td class="id-str-input-td1"> | ||||||
|                     <label for="chat-nickname-input">Enter nickname for new chat:</label> |                     <label for="chat-nickname-input">{%w pres.list-rooms.directive-nickname %}</label> | ||||||
|                 </td> |                 </td> | ||||||
|                 <td class="id-str-input-td2"> |                 <td class="id-str-input-td2"> | ||||||
|                     <input id="chat-nickname-input" type="text" placeholder="Take a nickname" class="one-line-input" required> |                     <input id="chat-nickname-input" type="text" class="one-line-input" | ||||||
|  |                            placeholder="{%w pres.list-rooms.placeholder-nickname %}" required> | ||||||
|                 </td> |                 </td> | ||||||
|             </tr> |             </tr> | ||||||
|             <tr> |             <tr> | ||||||
|                 <td class="id-str-input-td1"> |                 <td class="id-str-input-td1"> | ||||||
|                     <label for="chat-name-input">Enter name for new chat:</label> |                     <label for="chat-name-input">{%w pres.list-rooms.directive-name %}</label> | ||||||
|                 </td> |                 </td> | ||||||
|                 <td class="id-str-input-td2"> |                 <td class="id-str-input-td2"> | ||||||
|                     <input id="chat-name-input" type="text" placeholder="Come up with name" class="one-line-input" required> |                     <input id="chat-name-input" type="text" class="one-line-input" | ||||||
|  |                            placeholder="{%w pres.list-rooms.placeholder-name %}" required> | ||||||
|                 </td> |                 </td> | ||||||
|             </tr> |             </tr> | ||||||
|         </table> |         </table> | ||||||
|         <h1 class="popup-window-msg">Create new chat?</h1> |         <h1 class="popup-window-msg">{%w pres.list-rooms.reask-create-new-chat %}</h1> | ||||||
|         <button class="popup-window-btn-yes" id="chat-creation-win-yes">Yes, create</button> |         <button class="popup-window-btn-yes" id="chat-creation-win-yes">{%w pres.list-rooms.yes-create %}</button> | ||||||
|         <button class="popup-window-btn-no" id="chat-creation-win-no">No, cancel</button> |         <button class="popup-window-btn-no" id="chat-creation-win-no">{%w pres.list-rooms.no-create %}</button> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <div id="chat-renunciation-win" class="popup-window"> |     <div id="chat-renunciation-win" class="popup-window"> | ||||||
|         <!-- header will actually be rewritten before showing the window to include chat nickname --> |         <!-- header will actually be rewritten before showing the window to include chat nickname --> | ||||||
|         <h1 id="chat-renunciation-win-title" class="popup-window-msg">Are you sure you want to leave chat?</h1> |         <h1 id="chat-renunciation-win-title" class="popup-window-msg">||||||||||</h1> | ||||||
|         <button class="popup-window-btn-yes" id="chat-renunciation-win-yes">Yes, leave</button> |         <button class="popup-window-btn-yes" id="chat-renunciation-win-yes">{%w pres.list-rooms.yes-leave %}</button> | ||||||
|         <button class="popup-window-btn-no" id="chat-renunciation-win-no">No, cancel</button> |         <button class="popup-window-btn-no" id="chat-renunciation-win-no">{%w pres.list-rooms.no-leave %}</button> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
| x | x | ||||||
|     <div class="document-container resp-container"> |     <div class="document-container resp-container"> | ||||||
|         <div id="navigation-panel" class="panel"> |         <div id="navigation-panel" class="panel"> | ||||||
|             <a href="/user/{% W userinfo.nickname %}" id="go-to-my-profile" class="panel-thing"> |             <a href="/user/{%w userinfo.nickname %}" id="go-to-my-profile" class="panel-thing"> | ||||||
|                 <img alt="Go to my profile" src="/assets/img/user.svg" width="32px"> |                 <img alt="Go to my profile" src="/assets/img/user.svg" width="32px"> | ||||||
|             </a> |             </a> | ||||||
|             <p class="panel-thing panel-header-txt"> |             <p class="panel-thing panel-header-txt"> | ||||||
|                 List of available rooms |                 {%w pres.list-rooms.page-description %} | ||||||
|             </p> |             </p> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ | |||||||
|     <link rel="icon" type="image/png" href="/assets/img/favicon.png"> |     <link rel="icon" type="image/png" href="/assets/img/favicon.png"> | ||||||
|     <link rel="stylesheet" href="/assets/css/common.css"> |     <link rel="stylesheet" href="/assets/css/common.css"> | ||||||
|     <link rel="stylesheet" href="/assets/css/login.css"> |     <link rel="stylesheet" href="/assets/css/login.css"> | ||||||
|     <title>{% W pres.loginP.header %}</title> |     <title>{% W pres.login.header %}</title> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
|     {% FOR error IN errors %} |     {% FOR error IN errors %} | ||||||
| @ -17,25 +17,25 @@ | |||||||
|     {% ENDFOR %} |     {% ENDFOR %} | ||||||
| 
 | 
 | ||||||
|     <div class="form-container"> |     <div class="form-container"> | ||||||
|         <h1 class="wide-centered-header">{% W pres.loginP.header %}</h1> |         <h1 class="wide-centered-header">{% W pres.login.header %}</h1> | ||||||
|         <form action="/login" method="post" enctype="application/x-www-form-urlencoded"> |         <form action="/login" method="post" enctype="application/x-www-form-urlencoded"> | ||||||
|             <table class="logins-input-table"> |             <table class="logins-input-table"> | ||||||
|                 <tr> |                 <tr> | ||||||
|                     <td class="logins-input-td1"><label for="input-nickname">{% W pres.loginP.directive-nickname %}</label></td> |                     <td class="logins-input-td1"><label for="input-nickname">{% W pres.login.directive-nickname %}</label></td> | ||||||
|                     <td class="logins-input-td2"> |                     <td class="logins-input-td2"> | ||||||
|                         <input type="text" name="nickname" id="input-nickname" |                         <input type="text" name="nickname" id="input-nickname" | ||||||
|                                placeholder="{% W pres.loginP.placeholder-nickname %}" class="one-line-input" required> |                                placeholder="{% W pres.login.placeholder-nickname %}" class="one-line-input" required> | ||||||
|                     </td> |                     </td> | ||||||
|                 </tr> |                 </tr> | ||||||
|                 <tr> |                 <tr> | ||||||
|                     <td class="logins-input-td1"><label for="input-password">{% W pres.loginP.directive-password %}</label></td> |                     <td class="logins-input-td1"><label for="input-password">{% W pres.login.directive-password %}</label></td> | ||||||
|                     <td class="logins-input-td2"> |                     <td class="logins-input-td2"> | ||||||
|                         <input name="password" id="input-password" type="password" |                         <input name="password" id="input-password" type="password" | ||||||
|                                placeholder="{% W pres.loginP.placeholder-password %}" class="one-line-input" required> |                                placeholder="{% W pres.login.placeholder-password %}" class="one-line-input" required> | ||||||
|                     </td> |                     </td> | ||||||
|                 </tr> |                 </tr> | ||||||
|             </table> |             </table> | ||||||
|             <button class="action-button centered-block-el" type="submit">{% W pres.loginP.act %}</button> |             <button class="action-button centered-block-el" type="submit">{% W pres.login.act %}</button> | ||||||
|         </form> |         </form> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ | |||||||
|     <link rel="icon" type="image/png" href="/assets/img/favicon.png"> |     <link rel="icon" type="image/png" href="/assets/img/favicon.png"> | ||||||
|     <link rel="stylesheet" href="/assets/css/common.css"> |     <link rel="stylesheet" href="/assets/css/common.css"> | ||||||
|     <!-- This page is so simple, that it does not even have it's separate css file --> |     <!-- This page is so simple, that it does not even have it's separate css file --> | ||||||
|     <title>User Profile</title> |     <title>{%w pres.view-profile.header-profile-of %} {%w alienprofile.name %}</title> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
| 
 | 
 | ||||||
| @ -22,10 +22,10 @@ | |||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <div class="profile-container"> |         <div class="profile-container"> | ||||||
|             <h2 class="profile-name-text">{% W alienprofile.name %}</h2> |             <h2 class="profile-name-text">{%w alienprofile.name %}</h2> | ||||||
|             <h3 class="profile-nickname-text">Nickname: {% W alienprofile.nickname %}</h3> |             <h3 class="profile-nickname-text">{%w pres.view-profile.directive-nickname%} {%w alienprofile.nickname %}</h3> | ||||||
|             <p class="profile-bio-text"> |             <p class="profile-bio-text"> | ||||||
|                 {% W alienprofile.bio %} |                 {%w alienprofile.bio %} | ||||||
|             </p> |             </p> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|  | |||||||
| @ -62,7 +62,7 @@ function convertMemberStToBox(memberSt){ | |||||||
|             return; |             return; | ||||||
|         userDeletionWinStoredUId = ID; |         userDeletionWinStoredUId = ID; | ||||||
|         document.getElementById("user-deletion-win-title").innerText = |         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"); |         activatePopupWindowById("user-deletion-win"); | ||||||
|     }; |     }; | ||||||
|     box.querySelector(".CM-member-box-leave-btn").style.display = |     box.querySelector(".CM-member-box-leave-btn").style.display = | ||||||
| @ -124,7 +124,7 @@ function configureSummonUserInterface(){ | |||||||
|             updateLocalStateFromRecv(Recv); |             updateLocalStateFromRecv(Recv); | ||||||
|         }).catch((e) => { |         }).catch((e) => { | ||||||
|            console.log(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); |             updateLocalStateFromRecv(Recv); | ||||||
|         }).catch((e) => { |         }).catch((e) => { | ||||||
|             console.log(e); |             console.log(e); | ||||||
|             alert("Failed to kick user from chat"); |             alert(pres['chat-members']["failed-kick-member"]); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -27,6 +27,7 @@ let storeHiddenMsgIdForDeletionWin = -1; | |||||||
| // Positive in production, negative for debug
 | // Positive in production, negative for debug
 | ||||||
| let softZoneSz = -150; | let softZoneSz = -150; | ||||||
| let chatPadding = 300; | let chatPadding = 300; | ||||||
|  | const msgErased = pres.chat.msgErased; | ||||||
| 
 | 
 | ||||||
| function genSentBase(){ | function genSentBase(){ | ||||||
|     return { |     return { | ||||||
| @ -168,13 +169,13 @@ function decodeSystemMessage(text){ | |||||||
|     let subjectRef = members.has(subjectId) ? members.get(subjectId).nickname : "???"; |     let subjectRef = members.has(subjectId) ? members.get(subjectId).nickname : "???"; | ||||||
|     let objectRef = members.has(objectId) ? members.get(objectId).nickname : "???"; |     let objectRef = members.has(objectId) ? members.get(objectId).nickname : "???"; | ||||||
|     if (verb === "kicked"){ |     if (verb === "kicked"){ | ||||||
|         return subjectRef + " kicked " + objectRef; |         return subjectRef + " " + pres.chat.syslog.kicked + " " + objectRef; | ||||||
|     } else if (verb === "summoned"){ |     } else if (verb === "summoned"){ | ||||||
|         return subjectRef + " summoned " + objectRef; |         return subjectRef + " " + pres.chat.syslog.summoned + " " + objectRef; | ||||||
|     } else if (verb === "left"){ |     } else if (verb === "left"){ | ||||||
|         return subjectRef + " left chat"; |         return subjectRef + " " + pres.chat.syslog.left; | ||||||
|     } else if (verb === "created"){ |     } else if (verb === "created"){ | ||||||
|         return subjectRef + " created this chat"; |         return subjectRef + " " + pres.chat.syslog.created; | ||||||
|     } |     } | ||||||
|     return "... Bad log ..."; |     return "... Bad log ..."; | ||||||
| } | } | ||||||
| @ -239,7 +240,6 @@ function convertMessageStToSupercontainer(messageSt){ | |||||||
|                 return; |                 return; | ||||||
|             let URI = window.location.host + "/chat/" + openedchat.nickname + "/m/" + String(ID); |             let URI = window.location.host + "/chat/" + openedchat.nickname + "/m/" + String(ID); | ||||||
|             document.getElementById("message-input").innerText += (" " + URI + ""); |             document.getElementById("message-input").innerText += (" " + URI + ""); | ||||||
|             console.log("Tried to get link on message " + ID); |  | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -389,7 +389,7 @@ function configureMsgDeletionPopupButtons(){ | |||||||
|         deactivateActivePopup(); |         deactivateActivePopup(); | ||||||
|         let Sent = genSentBase(); |         let Sent = genSentBase(); | ||||||
|         Sent.id = storeHiddenMsgIdForDeletionWin; |         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){ |     document.getElementById("msg-deletion-no").onclick = function (ev){ | ||||||
| @ -426,7 +426,7 @@ window.onload = function (){ | |||||||
|             let Sent = genSentBase(); |             let Sent = genSentBase(); | ||||||
|             Sent.content = {}; |             Sent.content = {}; | ||||||
|             Sent.content.text = text; |             Sent.content.text = text; | ||||||
|             safeApiRequestWithLocalStUpdate("sendMessage", Sent, "Failed to send message"); |             safeApiRequestWithLocalStUpdate("sendMessage", Sent, pres.chat['failed-send-message']); | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -57,9 +57,6 @@ function roleToColor(role) { | |||||||
|     return "#286500"  // Bug
 |     return "#286500"  // Bug
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // todo: replace it with translation
 |  | ||||||
| const msgErased = "[ ERASED ]"; |  | ||||||
| 
 |  | ||||||
| function hideHTMLElement(el){ | function hideHTMLElement(el){ | ||||||
|     el.style.display = "none"; |     el.style.display = "none"; | ||||||
| } | } | ||||||
|  | |||||||
| @ -13,7 +13,8 @@ let chatBoxes = new Map(); | |||||||
| 
 | 
 | ||||||
| /* Generate text that is displayed on the right side of chat intro box */ | /* Generate text that is displayed on the right side of chat intro box */ | ||||||
| function youAreXHere(myRoleHere){ | 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; |             return; | ||||||
|         chatRenunciationWinStoredId = ID; |         chatRenunciationWinStoredId = ID; | ||||||
|         document.getElementById("chat-renunciation-win-title").innerText = |         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"); |         activatePopupWindowById("chat-renunciation-win"); | ||||||
|     }; |     }; | ||||||
|     box.querySelector(".CL-my-chat-box-leave-btn").style.display = |     box.querySelector(".CL-my-chat-box-leave-btn").style.display = | ||||||
| @ -119,7 +120,7 @@ function configureChatCreationInterface(){ | |||||||
|         ).then((Recv) => { |         ).then((Recv) => { | ||||||
|             updateLocalStateFromRecv(Recv); |             updateLocalStateFromRecv(Recv); | ||||||
|         }).catch((e) => { |         }).catch((e) => { | ||||||
|             alert("Failed to create chat"); |             alert(pres['list-rooms']["failed-create-chat"]); | ||||||
|             console.log(e); |             console.log(e); | ||||||
|         }); |         }); | ||||||
|     }; |     }; | ||||||
| @ -138,7 +139,6 @@ function configureChatCreationInterface(){ | |||||||
|         chatNicknameInput.value = ""; |         chatNicknameInput.value = ""; | ||||||
|         chatNameInput.value = ""; |         chatNameInput.value = ""; | ||||||
|         activatePopupWindowById("chat-creation-win"); |         activatePopupWindowById("chat-creation-win"); | ||||||
|         console.log("Tried to show chat creation window"); |  | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -156,7 +156,7 @@ function configureChatRenunciationInterfaceWinPart(){ | |||||||
|         ).then((Recv) => { |         ).then((Recv) => { | ||||||
|             updateLocalStateFromRecv(Recv); |             updateLocalStateFromRecv(Recv); | ||||||
|         }).catch((e) => { |         }).catch((e) => { | ||||||
|             alert("Failed to leave chat"); |             alert(pres['list-rooms']["failed-create-chat"]); | ||||||
|             console.log(e); |             console.log(e); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -1,11 +1,76 @@ | |||||||
| { | { | ||||||
|   "lang": "en", |   "lang": "en", | ||||||
|   "loginP": { |   "login": { | ||||||
|     "header": "Login", |     "header": "Login", | ||||||
|     "directive-nickname": "Enter your nickname:", |     "directive-nickname": "Enter your nickname:", | ||||||
|     "placeholder-nickname": "Nickname", |     "placeholder-nickname": "Nickname", | ||||||
|     "directive-password": "Enter password:", |     "directive-password": "Enter password:", | ||||||
|     "placeholder-password": "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" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,11 +1,21 @@ | |||||||
| { | { | ||||||
|   "lang": "ru", |   "lang": "ru", | ||||||
|   "loginP": { |   "login": { | ||||||
|     "header": "Вход", |     "header": "Вход", | ||||||
|     "directive-nickname": "Введите свой никнейм:", |     "directive-nickname": "Введите свой никнейм:", | ||||||
|     "placeholder-nickname": "", |     "placeholder-nickname": "Никнейм", | ||||||
|     "directive-password": "Введите пароль:", |     "directive-password": "Введите пароль:", | ||||||
|     "placeholder-password": "", |     "placeholder-password": "Пароль", | ||||||
|     "act": "Войти" |     "act": "Войти", | ||||||
|  |     "incorrect-nickname-or-password": "Неверный логин или пароль" | ||||||
|  |   }, | ||||||
|  |   "view-profile": { | ||||||
|  |     "header-profile-of": "Профиль", | ||||||
|  |     "directive-nickname": "Никнейм:" | ||||||
|  |   }, | ||||||
|  |   "edit-profile": { | ||||||
|  |     "header-profile-of": "Профиль", | ||||||
|  |     "directive-nickname": "Никнейм:", | ||||||
|  |     "change-user-attributes": "Изменить аттрибуты пользователя" | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @ -1,8 +1,6 @@ | |||||||
| {% ELDEF main JSON cba %} | {% ELDEF main JSON userprofile %} | ||||||
|     AAA |     AAA | ||||||
|         {% FOR val IN cba.arr %} |     --> {% WRITE userprofile.name %} | ||||||
|             --> {% WRITE val %} |  | ||||||
|         {% ENDFOR %} |  | ||||||
|     AAA |     AAA | ||||||
| 
 | 
 | ||||||
| {% ENDELDEF %} | {% ENDELDEF %} | ||||||
|  | |||||||
| @ -9,15 +9,11 @@ int main(int argc, char** argv) { | |||||||
|         exit(1); |         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}}); |     nytl::Templater templater(nytl::TemplaterSettings{nytl::TemplaterDetourRules{dir_path}}); | ||||||
|     templater.update(); |     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; |     json::JSON userprofile; | ||||||
|     userprofile["uid"].asInteger() = json::Integer(0l); |     userprofile["uid"].asInteger() = json::Integer(0l); | ||||||
|     userprofile["name"].asString() = "radasdasdasdadsdasd"; |     userprofile["name"].asString() = "radasdasdasdadsdasd"; | ||||||
| @ -25,7 +21,7 @@ int main(int argc, char** argv) { | |||||||
|     userprofile["bio"].asString() = "Your mother"; |     userprofile["bio"].asString() = "Your mother"; | ||||||
|     json::JSON errors; |     json::JSON errors; | ||||||
|     errors = json::JSON(json::array); |     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<a><f><t><e><r><><l><f>\n", answer2.c_str()); |     printf("%s\n<a><f><t><e><r><><l><f>\n", answer2.c_str()); | ||||||
| 
 | 
 | ||||||
|     return 0; |     return 0; | ||||||
|  | |||||||
| @ -7,8 +7,13 @@ namespace nytl { | |||||||
|     void debug_print_templater(const Templater& T) { |     void debug_print_templater(const Templater& T) { | ||||||
|         printf("===== TEMPLATER INTERNAL RESOURCES =====\n"); |         printf("===== TEMPLATER INTERNAL RESOURCES =====\n"); | ||||||
|         for (auto& p: T.elements) { |         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()); |             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"); |             printf("%s, %s\n", el.base ? "BASE" : "NOT BASE", el.is_hidden ? "HIDDEN" : "NOT HIDDEN"); | ||||||
|             if (!el.is_hidden) { |             if (!el.is_hidden) { | ||||||
|                 std::string signature; |                 std::string signature; | ||||||
|  | |||||||
| @ -150,17 +150,41 @@ namespace nytl { | |||||||
|         return concatenateLines(lines); |         return concatenateLines(lines); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void parse_bare_file(const std::string& filename, const std::string& content, |     Element& add_hidden_element(const std::string& new_el_name, global_elem_set_t& result) { | ||||||
|                              global_elem_set_t& result) |         if (result.count(new_el_name) != 0) | ||||||
|     { |             THROW("Repated element " + new_el_name); | ||||||
|         if (result.count(filename) != 0) |         TemplaterRegPref& rp = result[new_el_name]; | ||||||
|             THROW("Repeated element " + filename); |         rp.is_element = 1; | ||||||
|  |         rp.when_element = std::make_unique<Element>(); | ||||||
|  |         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<Element>(); | ||||||
|  |         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); |         std::string txt = clement_lstrip(content); | ||||||
|         rstrip(txt); |         rstrip(txt); | ||||||
|         size_t cut = 9999999999999; |         size_t cut = 9999999999999; | ||||||
|         one_part_update_min_start_wsp_non_empty(txt, 0, 1, cut); |         one_part_update_min_start_wsp_non_empty(txt, 0, 1, cut); | ||||||
|         txt = one_part_cut_excess_tab(txt, 0, 1, cut); |         txt = one_part_cut_excess_tab(txt, 0, 1, cut); | ||||||
|         Element& el = result[filename]; |  | ||||||
|         el.parts = {ElementPart{}}; |         el.parts = {ElementPart{}}; | ||||||
|         el.parts[0].when_code.lines = mv(txt); |         el.parts[0].when_code.lines = mv(txt); | ||||||
|     } |     } | ||||||
| @ -379,8 +403,7 @@ namespace nytl { | |||||||
|                 skipWhitespace(ctx); |                 skipWhitespace(ctx); | ||||||
|                 P.ref_over = parse_expression(ctx, local_var_names); |                 P.ref_over = parse_expression(ctx, local_var_names); | ||||||
|                 P.internal_element = el_name + ".~" + std::to_string(free_hidden++); |                 P.internal_element = el_name + ".~" + std::to_string(free_hidden++); | ||||||
|                 Element& newborn = elem_ns[P.internal_element]; |                 Element& newborn = add_hidden_element(P.internal_element, elem_ns); | ||||||
|                 newborn.is_hidden = true; |  | ||||||
|                 arg_name_list_t local_var_names_of_nxt = local_var_names; |                 arg_name_list_t local_var_names_of_nxt = local_var_names; | ||||||
|                 if (V1 != "_") { |                 if (V1 != "_") { | ||||||
|                     if (local_var_names_of_nxt.count(V1) != 0) |                     if (local_var_names_of_nxt.count(V1) != 0) | ||||||
| @ -417,8 +440,7 @@ namespace nytl { | |||||||
|                 skipWhitespace(ctx); |                 skipWhitespace(ctx); | ||||||
|                 P.ref_over = parse_expression(ctx, local_var_names); |                 P.ref_over = parse_expression(ctx, local_var_names); | ||||||
|                 P.internal_element = el_name + ".~" + std::to_string(free_hidden++); |                 P.internal_element = el_name + ".~" + std::to_string(free_hidden++); | ||||||
|                 Element& newborn = elem_ns[P.internal_element]; |                 Element& newborn = add_hidden_element(P.internal_element, elem_ns); | ||||||
|                 newborn.is_hidden = true; |  | ||||||
|                 arg_name_list_t local_var_names_of_nxt = local_var_names; |                 arg_name_list_t local_var_names_of_nxt = local_var_names; | ||||||
|                 size_t k = local_var_names_of_nxt.size(); |                 size_t k = local_var_names_of_nxt.size(); | ||||||
|                 local_var_names_of_nxt.emplace(Vn, k); |                 local_var_names_of_nxt.emplace(Vn, k); | ||||||
| @ -427,7 +449,7 @@ namespace nytl { | |||||||
|                 return std::make_unique<ECPFrame>(P.internal_element, gone_for_ref, local_var_names_of_nxt, |                 return std::make_unique<ECPFrame>(P.internal_element, gone_for_ref, local_var_names_of_nxt, | ||||||
|                     ret_data_int, newborn); |                     ret_data_int, newborn); | ||||||
|             } |             } | ||||||
|             if (op == "PUT") { |             if (op == "PUT" || op == "P") { | ||||||
|                 result.parts.emplace_back(); |                 result.parts.emplace_back(); | ||||||
|                 result.parts.back().type = ElementPart::p_put; |                 result.parts.back().type = ElementPart::p_put; | ||||||
|                 ElementPart::when_put_S& P = result.parts.back().when_put; |                 ElementPart::when_put_S& P = result.parts.back().when_put; | ||||||
| @ -549,9 +571,7 @@ namespace nytl { | |||||||
|             if (elname_postfix == "_") |             if (elname_postfix == "_") | ||||||
|                 THROW("Can't use _ as element name"); |                 THROW("Can't use _ as element name"); | ||||||
|             std::string fullname = elname_postfix == "main" ? filename : filename + "." + elname_postfix; |             std::string fullname = elname_postfix == "main" ? filename : filename + "." + elname_postfix; | ||||||
|             if (result.count(fullname) != 0) |             Element& newborn = add_new_element(fullname, result); | ||||||
|                 THROW("Element " + fullname + " has been already defined"); |  | ||||||
|             Element& newborn = result[fullname]; |  | ||||||
|             arg_name_list_t arglist; |             arg_name_list_t arglist; | ||||||
|             while (true) { |             while (true) { | ||||||
|                 skipWhitespace(ctx); |                 skipWhitespace(ctx); | ||||||
|  | |||||||
| @ -23,37 +23,41 @@ namespace nytl { | |||||||
|               result(result) { |               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) { |             if (result.is_json) { | ||||||
|                 const json::JSON& P = *result.JSON_subval; |                 const json::JSON& P = *result.JSON_subval; | ||||||
|                 if (P.isArray() && what.isInteger()) { |                 if (P.isArray() && what.isInteger()) { | ||||||
|                     const std::vector<json::JSON>& arr_p = P.asArray(); |                     const std::vector<json::JSON>& arr_p = P.asArray(); | ||||||
|                     int64_t ind_w = what.asInteger().get_int(); |                     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]}; |                     result = LocalVarValue{true, "", &arr_p[ind_w]}; | ||||||
|                 } else if (P.isDictionary() && what.isString()) { |                 } else if (P.isDictionary() && what.isString()) { | ||||||
|                     const std::map<std::string, json::JSON>& dict_p = P.asDictionary(); |                     const std::map<std::string, json::JSON>& dict_p = P.asDictionary(); | ||||||
|                     const std::string& key_w = what.asString(); |                     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)}; |                     result = LocalVarValue{true, "", &dict_p.at(key_w)}; | ||||||
|                 } else |                 } else | ||||||
|                     THROW("Incorrect type of \"json[json]\" expression. Unallowed signature of [] operator"); |                     THROW("Incorrect type of \"json[json]\" expression. Unallowed signature of [] operator"); | ||||||
|             } else { |             } else { | ||||||
|                 ASSERT(what.isString(), "Expression \"element[X]\" allowed only if X is string (json object)"); |                 if (!what.isString()) | ||||||
|                 if (what.asString().empty()) |                     THROW("Expression \"element[X]\" allowed only if X is string (json object)"); | ||||||
|                     return; |                 if (!isUname(what.asString())) | ||||||
|                 if (!is_uname_dotted_sequence(what.asString())) |                     THROW("Expression \"element[str]\" has incorrect str (" + what.asString() + ")"); | ||||||
|                     THROW("Incorrect X in \"element[X]\""); |  | ||||||
|                 result.EL_name += ("." + 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<EEFrame> toMe(bool returned, const global_elem_set_t& global_elems, |         uptr<EEFrame> toMe(bool returned, const global_elem_set_t& global_elems, | ||||||
|                 const std::vector<LocalVarValue>& local_vars) { |                 const std::vector<LocalVarValue>& local_vars) { | ||||||
|             if (returned) { |             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); |                 assert(temp_ret.JSON_subval); | ||||||
|                 descend(*(temp_ret.JSON_subval)); |                 descend(*(temp_ret.JSON_subval), global_elems); | ||||||
|             } else { |             } else { | ||||||
|                 assert(expr.isDictionary()); |                 assert(expr.isDictionary()); | ||||||
|                 const json::JSON& val = expr["V"]; |                 const json::JSON& val = expr["V"]; | ||||||
| @ -63,6 +67,8 @@ namespace nytl { | |||||||
|                     result = local_vars[lv_ind]; |                     result = local_vars[lv_ind]; | ||||||
|                 } else if (val.isString()) { |                 } else if (val.isString()) { | ||||||
|                     std::string cur_el_name_str = expr["V"].asString(); |                     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}; |                     result = LocalVarValue{false, cur_el_name_str, NULL}; | ||||||
|                 } else |                 } else | ||||||
|                     assert(false); |                     assert(false); | ||||||
| @ -74,7 +80,7 @@ namespace nytl { | |||||||
|                 const json::JSON& t = chain[chain_el++]; |                 const json::JSON& t = chain[chain_el++]; | ||||||
|                 if (t.isDictionary()) |                 if (t.isDictionary()) | ||||||
|                     return std::make_unique<EEFrame>(t, temp_ret); |                     return std::make_unique<EEFrame>(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 */ |      * and dictionaries. They are stored in json in rendering stack */ | ||||||
|     LocalVarValue rendering_core_execute_expression(const global_elem_set_t& global_elems, |     LocalVarValue rendering_core_execute_expression(const global_elem_set_t& global_elems, | ||||||
|         const std::vector<LocalVarValue>& local_vars, const json::JSON& expr) { |         const std::vector<LocalVarValue>& 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; |         bool returned = false; | ||||||
|         std::vector<uptr<EEFrame>> stack; |         std::vector<uptr<EEFrame>> stack; | ||||||
|         LocalVarValue result; |         LocalVarValue result; | ||||||
| @ -211,9 +219,9 @@ namespace nytl { | |||||||
|     uptr<RFrame> RFrame_OverParts::toMe(bool returned, const global_elem_set_t &elem_ns, Ditch &result, |     uptr<RFrame> RFrame_OverParts::toMe(bool returned, const global_elem_set_t &elem_ns, Ditch &result, | ||||||
|         const std::function<std::string(std::string)> &escape) { |         const std::function<std::string(std::string)> &escape) { | ||||||
|         if (!returned) |         if (!returned) | ||||||
|             if (elem_ns.count(name) != 1) |             if ((elem_ns.count(name) != 1) || (!elem_ns.at(name).is_element)) | ||||||
|                 THROW("No such element (" + name + ")"); |                 THROW("Can't render. No such element (" + name + ")"); | ||||||
|         const Element& el = elem_ns.at(name); |         const Element& el = *elem_ns.at(name).when_element; | ||||||
|         if (!returned) { |         if (!returned) { | ||||||
|             /* Continue to do checks */ |             /* Continue to do checks */ | ||||||
|             /* hidden elements (internal) do not need any check */ |             /* hidden elements (internal) do not need any check */ | ||||||
| @ -222,16 +230,17 @@ namespace nytl { | |||||||
|                 ASSERT(n == passed_args.size(), "Argument count mismatch"); |                 ASSERT(n == passed_args.size(), "Argument count mismatch"); | ||||||
|                 for (size_t i = 0; i < n; i++) { |                 for (size_t i = 0; i < n; i++) { | ||||||
|                     if (el.arguments[i].type == json::true_symbol) { |                     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 { |                     } else { | ||||||
|                         // If not json is expected, element must be expected
 |                         // If not json is expected, element must be expected
 | ||||||
|                         assert(el.arguments[i].isArray()); |                         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; |                         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 + ")"); |                             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); |                         const Element& arg_element = elem_ns.at(passed_el_as_arg).when_element.operator*(); | ||||||
|                         // ASSERT(passed_args);
 |  | ||||||
|                         if(el.arguments[i].asArray() != arg_element.arguments) |                         if(el.arguments[i].asArray() != arg_element.arguments) | ||||||
|                             THROW("Signature of argument " + std::to_string(i) + " does not match"); |                             THROW("Signature of argument " + std::to_string(i) + " does not match"); | ||||||
|                     } |                     } | ||||||
|  | |||||||
| @ -109,16 +109,17 @@ namespace nytl { | |||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     TemplaterRegPref gen_base_element() { | ||||||
|  |         Element* e = new Element{{json::JSON(true)}, true, false, {}}; | ||||||
|  |         return {1, std::unique_ptr<Element>(e)}; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     void Templater::update() { |     void Templater::update() { | ||||||
|         elements = { |         elements[""] = TemplaterRegPref{0, NULL}; | ||||||
|             {"jsinsert", Element{{json::JSON(true)}, true}}, |         elements["jsinsert"] = gen_base_element(); | ||||||
|             {"jesc", Element{{json::JSON(true)}, true}}, |         elements["jesc"] = gen_base_element(); | ||||||
|             {"jesccomp", Element{{json::JSON(true)}, true}}, |         elements["str2text"] = gen_base_element(); | ||||||
|             /* str2text base element has a dedicated operator - WRITE */ |         elements["str2code"] = gen_base_element(); | ||||||
|             {"str2text", Element{{json::JSON(true)}, true}}, |  | ||||||
|             /* str2code base element has a dedicated operator - ROUGHINSERT */ |  | ||||||
|             {"str2code", Element{{json::JSON(true)}, true}}, |  | ||||||
|         }; |  | ||||||
|         std::vector<InterestingFile> intersting_files = indexing_detour(settings.det); |         std::vector<InterestingFile> intersting_files = indexing_detour(settings.det); | ||||||
|         for (const InterestingFile& file: intersting_files) { |         for (const InterestingFile& file: intersting_files) { | ||||||
|             std::string content = readFile(file.path); |             std::string content = readFile(file.path); | ||||||
| @ -132,7 +133,8 @@ namespace nytl { | |||||||
| 
 | 
 | ||||||
|     /* Still can throw some stuff derived from std::exception (like bad alloc) */ |     /* Still can throw some stuff derived from std::exception (like bad alloc) */ | ||||||
|     std::string Templater::render(const std::string& element, const std::vector<const json::JSON*> &arguments) const { |     std::string Templater::render(const std::string& element, const std::vector<const json::JSON*> &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); |         return rendering_core(element, arguments, elements, settings.escape); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,6 +6,8 @@ | |||||||
| #include <jsonincpp/jsonobj.h> | #include <jsonincpp/jsonobj.h> | ||||||
| #include <functional> | #include <functional> | ||||||
| #include "html_case.h" | #include "html_case.h" | ||||||
|  | #include <memory> | ||||||
|  | #include <forward_list> | ||||||
| 
 | 
 | ||||||
| namespace nytl { | namespace nytl { | ||||||
|     typedef json::JSON expression_t; |     typedef json::JSON expression_t; | ||||||
| @ -61,7 +63,12 @@ namespace nytl { | |||||||
|         std::function<std::string(std::string)> escape = html_case_espace_string; |         std::function<std::string(std::string)> escape = html_case_espace_string; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     typedef std::map<std::string, Element> global_elem_set_t; |     struct TemplaterRegPref { | ||||||
|  |         int is_element = 0; | ||||||
|  |         std::unique_ptr<Element> when_element = NULL; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     typedef std::map<std::string, TemplaterRegPref> global_elem_set_t; | ||||||
| 
 | 
 | ||||||
|     struct Templater { |     struct Templater { | ||||||
|         TemplaterSettings settings; |         TemplaterSettings settings; | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ namespace iu9cawebchat { | |||||||
|             if (uid < 0) { |             if (uid < 0) { | ||||||
|                 printf("Redirecting back to /login because of incorrect credentials\n"); |                 printf("Redirecting back to /login because of incorrect credentials\n"); | ||||||
|                 json::JSON msg_list = jsonify_html_message_list({{"", |                 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}); |                 return http_R200("login", wgd, {&config_presentation, &userinfo, &msg_list}); | ||||||
|             } |             } | ||||||
|             std::vector<std::pair<std::string, std::string>> response_hlines; |             std::vector<std::pair<std::string, std::string>> response_hlines; | ||||||
|  | |||||||
| @ -104,7 +104,7 @@ namespace iu9cawebchat { | |||||||
|             } catch (const std::exception& e) { |             } catch (const std::exception& e) { | ||||||
|                 printf("Redirecting back to /user/... because of incorrect credentials\n"); |                 printf("Redirecting back to /user/... because of incorrect credentials\n"); | ||||||
|                 json::JSON msg_list = jsonify_html_message_list({{"", |                 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); |                 json::JSON alien_userprofile = user_row_to_userprofile_obj(conn, alien); | ||||||
|                 return http_R200("edit-profile", wgd, {&config_presentation, &userinfo, &alien_userprofile, &msg_list}); |                 return http_R200("edit-profile", wgd, {&config_presentation, &userinfo, &alien_userprofile, &msg_list}); | ||||||
|             } |             } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user