master #6
| @ -34,11 +34,11 @@ | |||||||
|             <a href="/list-rooms" id="go-to-chat-list" class="panel-thing"> |             <a href="/list-rooms" id="go-to-chat-list" class="panel-thing"> | ||||||
|                 <img alt="Go to list of chats" src="/assets/img/list-rooms.svg" width="32px"> |                 <img alt="Go to list of chats" src="/assets/img/list-rooms.svg" width="32px"> | ||||||
|             </a> |             </a> | ||||||
|             <a href="/user/{% WRITE 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 {% WRITE openedchat.name %} ({% WRITE openedchat.nickname %})</p> |             <p class="panel-thing panel-header-txt"> Members list of {% W openedchat.name %} ({% W openedchat.nickname %})</p> | ||||||
|             <a href="/chat/{% WRITE 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> | ||||||
|         </div> |         </div> | ||||||
|  | |||||||
| @ -36,11 +36,11 @@ | |||||||
|             <a href="/list-rooms" id="go-to-chat-list" class="panel-thing"> |             <a href="/list-rooms" id="go-to-chat-list" class="panel-thing"> | ||||||
|                 <img alt="Go to list of chats" src="/assets/img/list-rooms.svg" width="32px"> |                 <img alt="Go to list of chats" src="/assets/img/list-rooms.svg" width="32px"> | ||||||
|             </a> |             </a> | ||||||
|             <a href="/user/{% WRITE 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"> {% WRITE openedchat.name %} ({% WRITE openedchat.nickname %})</p> |             <p class="panel-thing panel-header-txt"> {% W openedchat.name %} ({% W openedchat.nickname %})</p> | ||||||
|             <a href="/chat-members/{% WRITE openedchat.nickname %}" id="go-to-chat-settings" class="panel-thing"> |             <a href="/chat-members/{% W openedchat.nickname %}" id="go-to-chat-settings" class="panel-thing"> | ||||||
|                 <img alt="Settings of chat. List of members" src="/assets/img/settings-iron.svg" width="32px"> |                 <img alt="Settings of chat. List of members" src="/assets/img/settings-iron.svg" width="32px"> | ||||||
|             </a> |             </a> | ||||||
|         </div> |         </div> | ||||||
|  | |||||||
| @ -16,28 +16,28 @@ | |||||||
|             <a href="/list-rooms" id="go-to-chat-list" class="panel-thing"> |             <a href="/list-rooms" id="go-to-chat-list" class="panel-thing"> | ||||||
|                 <img alt="Go to list of chats" src="/assets/img/list-rooms.svg" width="32px"> |                 <img alt="Go to list of chats" src="/assets/img/list-rooms.svg" width="32px"> | ||||||
|             </a> |             </a> | ||||||
|             <a href="/user/{% WRITE 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> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         {% FOR error IN errors %} |         {% FOR error IN errors %} | ||||||
|             <div class="server-notif-error-msg-box"> |             <div class="server-notif-error-msg-box"> | ||||||
|                 {% WRITE error.text %} |                 {% W error.text %} | ||||||
|             </div> |             </div> | ||||||
|         {% ENDFOR %} |         {% ENDFOR %} | ||||||
| 
 | 
 | ||||||
|         <div class="profile-container"> |         <div class="profile-container"> | ||||||
|             <h2 class="profile-name-text">{% WRITE alienprofile.name %}</h2> |             <h2 class="profile-name-text">{% W alienprofile.name %}</h2> | ||||||
|             <h3 class="profile-nickname-text">Nickname: {% WRITE alienprofile.nickname %}</h3> |             <h3 class="profile-nickname-text">Nickname: {% W alienprofile.nickname %}</h3> | ||||||
|             <p class="profile-bio-text"> |             <p class="profile-bio-text"> | ||||||
|                 {% WRITE alienprofile.bio %} |                 {% W alienprofile.bio %} | ||||||
|             </p> |             </p> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <div class="profile-container resp-container"> |         <div class="profile-container resp-container"> | ||||||
|             <h1 class="wide-centered-header">Change user attributes</h1> |             <h1 class="wide-centered-header">Change user attributes</h1> | ||||||
|             <form action = "/user/{% WRITE 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"> | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| {% ELDEF main JSON pres JSON userinfo JSON initial_chatListUpdResp %} | {% ELDEF main JSON pres JSON userinfo JSON initial_chatListUpdResp %} | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html lang="{% WRITE pres.lang %}"> | <html lang="{% W pres.lang %}"> | ||||||
| <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"> | ||||||
| @ -51,7 +51,7 @@ | |||||||
| 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/{% WRITE 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"> | ||||||
|  | |||||||
| @ -1,39 +1,41 @@ | |||||||
| {% ELDEF main JSON pres JSON userinfo JSON errors %} | {% ELDEF main JSON pres JSON userinfo JSON errors %} | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html lang="en"> | <html lang="{% W pres.lang %}"> | ||||||
| <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"> | ||||||
|     <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>Login Page</title> |     <title>{% W pres.loginP.header %}</title> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
|     {% FOR error IN errors %} |     {% FOR error IN errors %} | ||||||
|         <div class="server-notif-error-msg-box"> |         <div class="server-notif-error-msg-box"> | ||||||
|             {% WRITE error.text %} |             {% W error.text %} | ||||||
|         </div> |         </div> | ||||||
|     {% ENDFOR %} |     {% ENDFOR %} | ||||||
| 
 | 
 | ||||||
|     <div class="form-container"> |     <div class="form-container"> | ||||||
|         <h1 class="wide-centered-header">Login</h1> |         <h1 class="wide-centered-header">{% W pres.loginP.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">Enter user nickname:</label></td> |                     <td class="logins-input-td1"><label for="input-nickname">{% W pres.loginP.directive-nickname %}</label></td> | ||||||
|                     <td class="logins-input-td2"> |                     <td class="logins-input-td2"> | ||||||
|                         <input name="nickname" id="input-nickname" type="text" placeholder="Nickname" class="one-line-input" required> |                         <input type="text" name="nickname" id="input-nickname" | ||||||
|  |                                placeholder="{% W pres.loginP.placeholder-nickname %}" class="one-line-input" required> | ||||||
|                     </td> |                     </td> | ||||||
|                 </tr> |                 </tr> | ||||||
|                 <tr> |                 <tr> | ||||||
|                     <td class="logins-input-td1"><label for="input-password">Enter password:</label></td> |                     <td class="logins-input-td1"><label for="input-password">{% W pres.loginP.directive-password %}</label></td> | ||||||
|                     <td class="logins-input-td2"> |                     <td class="logins-input-td2"> | ||||||
|                         <input name="password" id="input-password" type="password" placeholder="Password" class="one-line-input" required> |                         <input name="password" id="input-password" type="password" | ||||||
|  |                                placeholder="{% W pres.loginP.placeholder-password %}" class="one-line-input" required> | ||||||
|                     </td> |                     </td> | ||||||
|                 </tr> |                 </tr> | ||||||
|             </table> |             </table> | ||||||
|             <button class="action-button centered-block-el" type="submit">Login</button> |             <button class="action-button centered-block-el" type="submit">{% W pres.loginP.act %}</button> | ||||||
|         </form> |         </form> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -16,16 +16,16 @@ | |||||||
|             <a href="/list-rooms" id="go-to-chat-list" class="panel-thing"> |             <a href="/list-rooms" id="go-to-chat-list" class="panel-thing"> | ||||||
|                 <img alt="Go to list of chats" src="/assets/img/list-rooms.svg" width="32px"> |                 <img alt="Go to list of chats" src="/assets/img/list-rooms.svg" width="32px"> | ||||||
|             </a> |             </a> | ||||||
|             <a href="/user/{% WRITE 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> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <div class="profile-container"> |         <div class="profile-container"> | ||||||
|             <h2 class="profile-name-text">{% WRITE alienprofile.name %}</h2> |             <h2 class="profile-name-text">{% W alienprofile.name %}</h2> | ||||||
|             <h3 class="profile-nickname-text">Nickname: {% WRITE alienprofile.nickname %}</h3> |             <h3 class="profile-nickname-text">Nickname: {% W alienprofile.nickname %}</h3> | ||||||
|             <p class="profile-bio-text"> |             <p class="profile-bio-text"> | ||||||
|                 {% WRITE alienprofile.bio %} |                 {% W alienprofile.bio %} | ||||||
|             </p> |             </p> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								assets/lang/en-US.lang.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								assets/lang/en-US.lang.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | { | ||||||
|  |   "lang": "en", | ||||||
|  |   "loginP": { | ||||||
|  |     "header": "Login", | ||||||
|  |     "directive-nickname": "Enter your nickname:", | ||||||
|  |     "placeholder-nickname": "Nickname", | ||||||
|  |     "directive-password": "Enter password:", | ||||||
|  |     "placeholder-password": "Password", | ||||||
|  |     "act": "Login" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								assets/lang/ru-RU.lang.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								assets/lang/ru-RU.lang.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | { | ||||||
|  |   "lang": "ru", | ||||||
|  |   "loginP": { | ||||||
|  |     "header": "Вход", | ||||||
|  |     "directive-nickname": "Введите свой никнейм:", | ||||||
|  |     "placeholder-nickname": "", | ||||||
|  |     "directive-password": "Введите пароль:", | ||||||
|  |     "placeholder-password": "", | ||||||
|  |     "act": "Войти" | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -78,6 +78,7 @@ struct CAWebChat { | |||||||
|                 "http_structures/client_request_parse.cpp", |                 "http_structures/client_request_parse.cpp", | ||||||
|                 "http_structures/response_gen.cpp", |                 "http_structures/response_gen.cpp", | ||||||
|                 "http_structures/cookies.cpp", |                 "http_structures/cookies.cpp", | ||||||
|  |                 "http_structures/accept_language.cpp", | ||||||
|                 "connecting_assets/static_asset_manager.cpp", |                 "connecting_assets/static_asset_manager.cpp", | ||||||
|                 "running_mainloop.cpp", |                 "running_mainloop.cpp", | ||||||
|                 "form_data_structure/urlencoded_query.cpp", |                 "form_data_structure/urlencoded_query.cpp", | ||||||
| @ -97,6 +98,7 @@ struct CAWebChat { | |||||||
|                 "http_structures/client_request.h", |                 "http_structures/client_request.h", | ||||||
|                 "http_structures/cookies.h", |                 "http_structures/cookies.h", | ||||||
|                 "http_structures/response_gen.h", |                 "http_structures/response_gen.h", | ||||||
|  |                 "http_structures/accept_language.h", | ||||||
|                 "running_mainloop.h", |                 "running_mainloop.h", | ||||||
|                 "form_data_structure/urlencoded_query.h", |                 "form_data_structure/urlencoded_query.h", | ||||||
|                 "socket_address.h", |                 "socket_address.h", | ||||||
| @ -141,6 +143,7 @@ struct CAWebChat { | |||||||
|                 CTargetDependenceOnExternalLibrary{"sqlite3", {true, true}} |                 CTargetDependenceOnExternalLibrary{"sqlite3", {true, true}} | ||||||
|             }; |             }; | ||||||
|             T.units = { |             T.units = { | ||||||
|  |                 "localizator.cpp", | ||||||
|                 "initialize.cpp", |                 "initialize.cpp", | ||||||
|                 "run.cpp", |                 "run.cpp", | ||||||
|                 "str_fields.cpp", |                 "str_fields.cpp", | ||||||
|  | |||||||
| @ -1,33 +1,9 @@ | |||||||
| { | { | ||||||
|   "presentation": { |   "lang": { | ||||||
|     "lang": "ru", |     "whitelist": ["*"], | ||||||
|     "instance-identity": { |     "force-order": [ | ||||||
|       "top-title": "Вэб чат от ИУ9" |       "ru" | ||||||
|     }, |     ] | ||||||
|     "phr": { |  | ||||||
|       "decl": { |  | ||||||
|         "enter": "Вход", |  | ||||||
|         "nickname": "Никнейм", |  | ||||||
|         "password": "Пароль", |  | ||||||
|         "page-login": "Вход", |  | ||||||
|         "list-of-chat-rooms": "Список Чат-Коsмнат", |  | ||||||
|         "name-of-room": "Название комнаты", |  | ||||||
|         "create-room": "Создать комнату", |  | ||||||
| 
 |  | ||||||
|         "incorrect-nickname-or-password": "Неправильный никнейм или пароль", |  | ||||||
| 
 |  | ||||||
|         "incorrect-profile-data": "Неправильно заполнены поля профиля" |  | ||||||
|       }, |  | ||||||
|       "ask" : { |  | ||||||
|         "select-chat-room": "Выберете чат комнату" |  | ||||||
|       }, |  | ||||||
|       "act": { |  | ||||||
|         "enter": "Войти", |  | ||||||
|         "create-room": "Создать комнату", |  | ||||||
|         "confirm": "Подтвердить", |  | ||||||
|         "create": "Создать" |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }, |   }, | ||||||
|   "assets": "./assets", |   "assets": "./assets", | ||||||
|   "database": { |   "database": { | ||||||
| @ -41,7 +17,7 @@ | |||||||
|     "storage-size-limit": 100000000000 |     "storage-size-limit": 100000000000 | ||||||
|   }, |   }, | ||||||
|   "server": { |   "server": { | ||||||
|     "workers": 8, |     "workers": 16, | ||||||
|     "http-listen": ["127.0.0.1:1025"], |     "http-listen": ["127.0.0.1:1025"], | ||||||
|     "admin-command-listen": ["[::1]:1026"] |     "admin-command-listen": ["[::1]:1026"] | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -0,0 +1,72 @@ | |||||||
|  | #include "accept_language.h" | ||||||
|  | #include <algorithm> | ||||||
|  | #include "grammar.h" | ||||||
|  | #include "../baza_inter.h" | ||||||
|  | 
 | ||||||
|  | namespace een9 { | ||||||
|  |     bool AcceptLanguageSpec(char ch) { | ||||||
|  |         return ch == ',' || ch == ';' || ch == '='; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* todo: This is one of many places in een9, where bad alloc does not interrupt request,
 | ||||||
|  |      * todo:  completely changing response instead. (see cookies and login cookies lol) | ||||||
|  |      * todo: I have to do something about it. Maybe add more exception types */ | ||||||
|  |     std::vector<std::string> parse_header_Accept_Language(const std::string &AcceptLanguage) { | ||||||
|  |         size_t n = AcceptLanguage.size(); | ||||||
|  |         struct LR { | ||||||
|  |             std::string lr; | ||||||
|  |             float q = 1; | ||||||
|  |         }; | ||||||
|  |         size_t i = 0; | ||||||
|  |         auto skipOWS = [&]() { | ||||||
|  |             while (i < n && isSPACE(AcceptLanguage[i])) | ||||||
|  |                 i++; | ||||||
|  |         }; | ||||||
|  |         auto isThis = [&](char ch) { | ||||||
|  |             skipOWS(); | ||||||
|  |             return i >= n ? false : AcceptLanguage[i] == ch; | ||||||
|  |         }; | ||||||
|  |         auto readTkn = [&]() -> std::string { | ||||||
|  |             skipOWS(); | ||||||
|  |             if (i >= n) | ||||||
|  |                 return ""; | ||||||
|  |             size_t bg = i; | ||||||
|  |             while (i < n && !AcceptLanguageSpec(AcceptLanguage[i]) && !isSPACE(AcceptLanguage[i])) | ||||||
|  |                 i++; | ||||||
|  |             return AcceptLanguage.substr(bg, i - bg); | ||||||
|  |         }; | ||||||
|  |         std::vector<LR> lrs; | ||||||
|  | #define myMsg "Bad Accept-Language" | ||||||
|  |         while (i < n) { | ||||||
|  |             skipOWS(); | ||||||
|  |             if (i >= n) | ||||||
|  |                 break; | ||||||
|  |             if (!lrs.empty()) { | ||||||
|  |                 if (isThis(',')) | ||||||
|  |                     i++; | ||||||
|  |                 else | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  |             lrs.emplace_back(); | ||||||
|  |             lrs.back().lr = readTkn(); | ||||||
|  |             LR lr{readTkn(), 0}; | ||||||
|  |             if (isThis(';')) { | ||||||
|  |                 i++; | ||||||
|  |                 if (readTkn() != "q") | ||||||
|  |                     THROW(myMsg); | ||||||
|  |                 if (!isThis('=')) | ||||||
|  |                     THROW(myMsg); | ||||||
|  |                 i++; | ||||||
|  |                 lrs.back().q = std::stof(readTkn()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         std::sort(lrs.begin(), lrs.end(), [](const LR& A, const LR& B) { | ||||||
|  |             return A.q > B.q; | ||||||
|  |         }); | ||||||
|  |         std::vector<std::string> result; | ||||||
|  |         result.reserve(lrs.size()); | ||||||
|  |         for (const LR& lr: lrs) | ||||||
|  |             result.push_back(lr.lr == "*" ? "" : lr.lr); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,13 @@ | |||||||
|  | #ifndef ENGINE_ENGINE_NUMBER_9_HTTP_STRUCTURES_ACCEPT_LANGUAGE_H | ||||||
|  | #define ENGINE_ENGINE_NUMBER_9_HTTP_STRUCTURES_ACCEPT_LANGUAGE_H | ||||||
|  | 
 | ||||||
|  | #include <vector> | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | namespace een9 { | ||||||
|  |     /* Returns language ranges, sorted by priority (reverse)
 | ||||||
|  |      * throws std::exception if header is incorrect! But it is not guaranteed. Maybe it won't */ | ||||||
|  |     std::vector<std::string> parse_header_Accept_Language(const std::string& AcceptLanguage); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
| @ -1,14 +1,20 @@ | |||||||
| #include "cookies.h" | #include "cookies.h" | ||||||
| #include "../baza_inter.h" | #include "../baza_inter.h" | ||||||
| 
 | 
 | ||||||
|  | #include "grammar.h" | ||||||
|  | 
 | ||||||
| namespace een9 { | namespace een9 { | ||||||
|     bool isSPACE(char ch) { |     bool isSPACE(char ch) { | ||||||
|         return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'; |         return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     bool isALPHANUM(char ch) { | ||||||
|  |         return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ('0' <= ch && ch <= '9'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     bool isToken(const std::string &str) { |     bool isToken(const std::string &str) { | ||||||
|         for (char ch : str) { |         for (char ch : str) { | ||||||
|             if (!(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ('0' <= ch && ch <= '9') |             if (!(isALPHANUM(ch) | ||||||
|                 || ch == '!' || ch == '#' || ch == '$' || ch == '%' || ch == '&' || ch == '\'' || ch == '*' |                 || ch == '!' || ch == '#' || ch == '$' || ch == '%' || ch == '&' || ch == '\'' || ch == '*' | ||||||
|                 || ch == '+' || ch == '-' || ch == '.' || ch == '^' || ch == '_' || ch == '`' || ch == '|' |                 || ch == '+' || ch == '-' || ch == '.' || ch == '^' || ch == '_' || ch == '`' || ch == '|' | ||||||
|                 || ch == '~' )) |                 || ch == '~' )) | ||||||
|  | |||||||
| @ -0,0 +1,11 @@ | |||||||
|  | #ifndef ENGINE_ENGINE_NUMBER_9_HTTP_STRUCTURES_GRAMMAR_H | ||||||
|  | #define ENGINE_ENGINE_NUMBER_9_HTTP_STRUCTURES_GRAMMAR_H | ||||||
|  | 
 | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | namespace een9 { | ||||||
|  |     bool isSPACE(char ch); | ||||||
|  |     bool isALPHANUM(char ch); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										35
									
								
								src/http_server/misc_tests/accept_language_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/http_server/misc_tests/accept_language_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | |||||||
|  | #include <engine_engine_number_9/baza_inter.h> | ||||||
|  | #include <engine_engine_number_9/http_structures/accept_language.h> | ||||||
|  | 
 | ||||||
|  | using namespace een9; | ||||||
|  | 
 | ||||||
|  | void test(const std::string& al, const std::vector<std::string>& rls) { | ||||||
|  |     std::vector<std::string> got = parse_header_Accept_Language(al); | ||||||
|  |     if (got != rls) { | ||||||
|  |         printf("Test failed: wrong answer\n"); | ||||||
|  |         abort(); | ||||||
|  |     } | ||||||
|  |     printf("Test passed\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void btest(const std::string& al) { | ||||||
|  |     try { | ||||||
|  |         parse_header_Accept_Language(al); | ||||||
|  |     } catch (std::exception& e) {} | ||||||
|  |     printf("...\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int main() { | ||||||
|  |     test("RU-RU, uk-EN; q = 12.22", {"uk-EN", "RU-RU"}); | ||||||
|  |     test("   RU-RU   ,uk-EN; q = 12.22  ", {"uk-EN", "RU-RU"}); | ||||||
|  |     test(" AAA; q=0.1,  BBB-bb ; q=3, *; q=3", {"BBB-bb", "", "AAA"}); | ||||||
|  |     test(" AAA; q=0.1,  BBB-bb ; q=2.5, *; q=4.5", {"", "BBB-bb", "AAA"}); | ||||||
|  |     test("ABB, AAA; q=0.1,AAB,  BBB-bb ; q=2.5, *; q=4.5", {"", "BBB-bb", "ABB", "AAB", "AAA"}); | ||||||
|  |     test("", {}); | ||||||
|  |     test("   ", {}); | ||||||
|  |     btest(";;;;"); | ||||||
|  |     btest(";;==;;"); | ||||||
|  |     btest("-;"); | ||||||
|  |     btest("-=="); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
| @ -453,11 +453,11 @@ namespace nytl { | |||||||
|                 P.passed_arguments = {parse_expression(ctx, local_var_names)}; |                 P.passed_arguments = {parse_expression(ctx, local_var_names)}; | ||||||
|                 skip_magic_block_end(ctx, syntax); |                 skip_magic_block_end(ctx, syntax); | ||||||
|             }; |             }; | ||||||
|             if (op == "WRITE") { |             if (op == "WRITE" || op == "W") { | ||||||
|                 mediocre_operator("str2text"); |                 mediocre_operator("str2text"); | ||||||
|                 goto ya_e_ya_h_i_ya_g_d_o;; |                 goto ya_e_ya_h_i_ya_g_d_o;; | ||||||
|             } |             } | ||||||
|             if (op == "ROUGHINSERT") { |             if (op == "ROUGHINSERT" || op == "RI") { | ||||||
|                 mediocre_operator("str2code"); |                 mediocre_operator("str2code"); | ||||||
|                 goto ya_e_ya_h_i_ya_g_d_o;; |                 goto ya_e_ya_h_i_ya_g_d_o;; | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -11,12 +11,14 @@ | |||||||
| #include <jsonincpp/jsonobj.h> | #include <jsonincpp/jsonobj.h> | ||||||
| #include <new_york_transit_line/templater.h> | #include <new_york_transit_line/templater.h> | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include "../localizator.h" | ||||||
| 
 | 
 | ||||||
| namespace iu9cawebchat { | namespace iu9cawebchat { | ||||||
|     struct WorkerGuestData { |     struct WorkerGuestData { | ||||||
|         /* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */ |         /* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */ | ||||||
|         std::unique_ptr<nytl::Templater> templater; |         std::unique_ptr<nytl::Templater> templater; | ||||||
|         std::unique_ptr<SqliteConnection> db; |         std::unique_ptr<SqliteConnection> db; | ||||||
|  |         std::unique_ptr<Localizator> locales; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     void initial_extraction_of_all_the_useful_info_from_cookies( |     void initial_extraction_of_all_the_useful_info_from_cookies( | ||||||
|  | |||||||
							
								
								
									
										154
									
								
								src/web_chat/iu9_ca_web_chat_lib/localizator.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								src/web_chat/iu9_ca_web_chat_lib/localizator.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,154 @@ | |||||||
|  | #include "localizator.h" | ||||||
|  | 
 | ||||||
|  | #include <jsonincpp/string_representation.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <dirent.h> | ||||||
|  | #include <engine_engine_number_9/os_utils.h> | ||||||
|  | #include <engine_engine_number_9/baza_throw.h> | ||||||
|  | #include <assert.h> | ||||||
|  | 
 | ||||||
|  | namespace iu9cawebchat { | ||||||
|  |     std::string languageRangeSimpler(const std::string& a) { | ||||||
|  |         return a == "*" ? "" : a; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // I won't use iterators. c plus plus IS a scripting language and I do not want to mess with iterators
 | ||||||
|  |     std::vector<std::string> languageRangeGetPrefixes(const std::string& lr) { | ||||||
|  |         if (lr.empty()) | ||||||
|  |             return {""}; | ||||||
|  |         std::vector<std::string> result = {"", ""}; | ||||||
|  |         for (size_t i = 0; i < lr.size(); i++) { | ||||||
|  |             if (lr[i] == '-') | ||||||
|  |                 result.push_back(result.back()); | ||||||
|  |             result.back() += lr[i]; | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool isInWhitelist(const std::string& lr, const std::vector<std::string>& whitelist) { | ||||||
|  |         for (const std::string& prefix : languageRangeGetPrefixes(lr)) | ||||||
|  |             for (const std::string& nicePrefix: whitelist) | ||||||
|  |                 if (prefix == nicePrefix) | ||||||
|  |                     return true; | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::vector<LanguageFile> collect_lang_dir_content(const std::string& lang_dir, | ||||||
|  |         const std::vector<std::string>& whitelist) { | ||||||
|  | 
 | ||||||
|  |         std::vector<LanguageFile> result; | ||||||
|  |         errno = 0; | ||||||
|  |         DIR* D = opendir(lang_dir.c_str()); | ||||||
|  |         struct Guard1{ DIR*& D; ~Guard1(){ closedir(D); } } g1{D}; | ||||||
|  |         if (!D) | ||||||
|  |             een9_THROW_on_errno("opendir (" + lang_dir + ")"); | ||||||
|  |         while (true) { | ||||||
|  |             errno = 0; | ||||||
|  |             struct dirent* Dent = readdir(D); | ||||||
|  |             if (Dent == NULL) { | ||||||
|  |                 if (errno == 0) | ||||||
|  |                     break; | ||||||
|  |                 een9_THROW_on_errno("dirent"); | ||||||
|  |             } | ||||||
|  |             std::string entry = Dent->d_name; | ||||||
|  |             if (entry == "." || entry == "..") | ||||||
|  |                 continue; | ||||||
|  |             std::string filename = lang_dir + "/" + entry; | ||||||
|  |             struct stat info; | ||||||
|  |             int ret = stat(filename.c_str(), &info); | ||||||
|  |             een9_ASSERT_on_iret(ret, "stat(" + filename + ")"); | ||||||
|  |             if (!S_ISREG(info.st_mode)) | ||||||
|  |                 continue; | ||||||
|  |             const std::string postfix = ".lang.json"; | ||||||
|  |             if (!een9::endsWith(entry, postfix)) | ||||||
|  |                 continue; | ||||||
|  |             std::string lang_antirange = entry.substr(0, entry.size() - postfix.size()); | ||||||
|  |             if (!isInWhitelist(lang_antirange, whitelist)) | ||||||
|  |                 continue; | ||||||
|  |             std::string content; | ||||||
|  |             een9::readFile(filename, content); | ||||||
|  | 
 | ||||||
|  |             result.emplace_back(); | ||||||
|  |             result.back().languagerange = languageRangeSimpler(lang_antirange); | ||||||
|  |             result.back().content = json::parse_str_flawless(content); | ||||||
|  |         } | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     Localizator::Localizator(const LocalizatorSettings &settings) : settings(settings) { | ||||||
|  |         /* First - length of the longest prefix that was found so far (in force_order)
 | ||||||
|  |          * Second - index in force_order that was assigned to this thingy | ||||||
|  |          */ | ||||||
|  | 
 | ||||||
|  |         files = collect_lang_dir_content(settings.lang_dir, settings.whitelist); | ||||||
|  |         size_t n = files.size(); | ||||||
|  | #define redundantFileMsg "Redundant localization file" | ||||||
|  |         for (size_t i = 0; i < n; i++) { | ||||||
|  |             for (size_t j = i + 1; j < n; j++) { | ||||||
|  |                 std::string A = files[i].languagerange; | ||||||
|  |                 std::string B = files[j].languagerange; | ||||||
|  |                 for (std::string& pa: languageRangeGetPrefixes(A)) | ||||||
|  |                     if (pa == B) | ||||||
|  |                         een9_THROW(redundantFileMsg); | ||||||
|  |                 for (std::string& pb: languageRangeGetPrefixes(B)) | ||||||
|  |                     if (pb == A) | ||||||
|  |                         een9_THROW(redundantFileMsg); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         std::map<std::string, std::vector<std::size_t>> pref_to_files; | ||||||
|  |         for (size_t k = 0; k < n; k++) { | ||||||
|  |             for (const std::string& prefix: languageRangeGetPrefixes(files[k].languagerange)) { | ||||||
|  |                 pref_to_files[prefix].push_back(k); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         std::vector<std::pair<size_t, size_t>> assignment; | ||||||
|  |         constexpr size_t inf_bad_order = 999999999; | ||||||
|  |         assignment.assign(n, {0, inf_bad_order}); | ||||||
|  |         if (settings.force_order.size() >= inf_bad_order - 2) | ||||||
|  |             een9_THROW("o_O"); | ||||||
|  |         for (ssize_t i = 0; i < settings.force_order.size(); i++) { | ||||||
|  |             const std::string& ip = settings.force_order[i]; | ||||||
|  |             if (pref_to_files.count(ip) != 1) | ||||||
|  |                 een9_THROW("force-order list contains entries that match no files (" + ip + ")"); | ||||||
|  |             for (size_t k: pref_to_files.at(ip)) { | ||||||
|  |                 if (assignment[k].first <= ip.size()) { | ||||||
|  |                     assignment[k].first = ip.size(); | ||||||
|  |                     assignment[k].second = i; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         for (auto& p: pref_to_files) { | ||||||
|  |             const std::vector<size_t>& candidates = p.second; | ||||||
|  |             assert(!candidates.empty()); | ||||||
|  |             size_t bestSoFar = candidates[0]; | ||||||
|  |             size_t f = inf_bad_order; | ||||||
|  |             for (size_t k: candidates) { | ||||||
|  |                 if (assignment[k].second <= f) { | ||||||
|  |                     f = assignment[k].second; | ||||||
|  |                     bestSoFar = k; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             prefix_to_file[p.first] = bestSoFar; | ||||||
|  |         } | ||||||
|  |         if (prefix_to_file.count("") != 1) | ||||||
|  |             een9_THROW("No locales were provided"); | ||||||
|  |         // todo: remove DEBUG
 | ||||||
|  |         // for (size_t k = 0; k < n; k++) {
 | ||||||
|  |             // printf("%s has priority %lu\n", files[k].languagerange.c_str(), assignment[k].second);
 | ||||||
|  |         // }
 | ||||||
|  |         // printf("==============\n");
 | ||||||
|  |         // for (const auto& p : prefix_to_file) {
 | ||||||
|  |             // printf("%s  ->  %s\n", p.first.c_str(), files[p.second].languagerange.c_str());
 | ||||||
|  |         // }
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const LanguageFile& Localizator::get_right_locale(const std::vector<std::string> &preferred_langs) { | ||||||
|  |         for (const std::string& lr: preferred_langs) { | ||||||
|  |             if (prefix_to_file.count(lr) == 1) | ||||||
|  |                 return files[prefix_to_file.at(lr)]; | ||||||
|  |         } | ||||||
|  |         return files[prefix_to_file.at("")]; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								src/web_chat/iu9_ca_web_chat_lib/localizator.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/web_chat/iu9_ca_web_chat_lib/localizator.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | |||||||
|  | #ifndef IU9_CA_WEB_CHAT_LIB_LOCALIZATOR_H | ||||||
|  | #define IU9_CA_WEB_CHAT_LIB_LOCALIZATOR_H | ||||||
|  | 
 | ||||||
|  | #include <jsonincpp/jsonobj.h> | ||||||
|  | 
 | ||||||
|  | namespace iu9cawebchat { | ||||||
|  |     /* '*' -> ''; X -> X */ | ||||||
|  |     std::string languageRangeSimpler(const std::string& a); | ||||||
|  | 
 | ||||||
|  |     struct LocalizatorSettings { | ||||||
|  |         std::string lang_dir; | ||||||
|  |         std::vector<std::string> whitelist; | ||||||
|  |         std::vector<std::string> force_order; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     /* There is no need to put http Content-Language response value into json file. When is is in the name */ | ||||||
|  |     struct LanguageFile { | ||||||
|  |         std::string languagerange; | ||||||
|  |         json::JSON content; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     /* Localizator uses libjsonincpp internally, and thus can't be read by two treads simultaneously */ | ||||||
|  |     struct Localizator { | ||||||
|  |         LocalizatorSettings settings; | ||||||
|  |         std::vector<LanguageFile> files; | ||||||
|  |         std::map<std::string, size_t> prefix_to_file; | ||||||
|  | 
 | ||||||
|  |         /* Throws std::exception if something goes wrong */ | ||||||
|  |         explicit Localizator(const LocalizatorSettings& settings); | ||||||
|  | 
 | ||||||
|  |         /* Returns a reference to object inside Localizator */ | ||||||
|  |         const LanguageFile& get_right_locale(const std::vector<std::string>& preferred_langs); | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
| @ -5,6 +5,7 @@ | |||||||
| #include <engine_engine_number_9/connecting_assets/static_asset_manager.h> | #include <engine_engine_number_9/connecting_assets/static_asset_manager.h> | ||||||
| #include "find_db.h" | #include "find_db.h" | ||||||
| #include <engine_engine_number_9/running_mainloop.h> | #include <engine_engine_number_9/running_mainloop.h> | ||||||
|  | #include <engine_engine_number_9/http_structures/accept_language.h> | ||||||
| #include <signal.h> | #include <signal.h> | ||||||
| #include "str_fields.h" | #include "str_fields.h" | ||||||
| #include "backend_logic/client_server_interact.h" | #include "backend_logic/client_server_interact.h" | ||||||
| @ -32,11 +33,23 @@ namespace iu9cawebchat { | |||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     LocalizatorSettings make_localizator_settings(const std::string& assets_dir, const json::JSON& config) { | ||||||
|  |         std::vector<std::string> whitelist; | ||||||
|  |         for (const json::JSON& entry: config["lang"]["whitelist"].asArray()) | ||||||
|  |             whitelist.push_back(languageRangeSimpler(entry.asString())); | ||||||
|  |         std::vector<std::string> force_order; | ||||||
|  |         for (const json::JSON& entry: config["lang"]["force-order"].asArray()) | ||||||
|  |             force_order.push_back(languageRangeSimpler(entry.asString())); | ||||||
|  |         return LocalizatorSettings{assets_dir + "/lang", whitelist, force_order}; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     void run_website(const json::JSON& config) { |     void run_website(const json::JSON& config) { | ||||||
|         een9_ASSERT(config["assets"].isString(), "config[\"assets\"] is not string"); |         een9_ASSERT(config["assets"].isString(), "config[\"assets\"] is not string"); | ||||||
|         const std::string& assets_dir = config["assets"].asString(); |         const std::string& assets_dir = config["assets"].asString(); | ||||||
|         een9_ASSERT(een9::isDirectory(assets_dir), "\"" + assets_dir + "\" is not a directory"); |         een9_ASSERT(een9::isDirectory(assets_dir), "\"" + assets_dir + "\" is not a directory"); | ||||||
| 
 | 
 | ||||||
|  |         LocalizatorSettings localizator_settings = make_localizator_settings(assets_dir, config); | ||||||
|  | 
 | ||||||
|         een9::StaticAssetManagerSlaveModule samI; |         een9::StaticAssetManagerSlaveModule samI; | ||||||
|         samI.update({ |         samI.update({ | ||||||
|             een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} }, |             een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} }, | ||||||
| @ -47,7 +60,6 @@ namespace iu9cawebchat { | |||||||
|             } }, |             } }, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         const json::JSON& config_presentation = config["presentation"]; |  | ||||||
|         int64_t slave_number = config["server"]["workers"].asInteger().get_int(); |         int64_t slave_number = config["server"]["workers"].asInteger().get_int(); | ||||||
|         een9_ASSERT(slave_number > 0 && slave_number <= 200, "E"); |         een9_ASSERT(slave_number > 0 && slave_number <= 200, "E"); | ||||||
| 
 | 
 | ||||||
| @ -61,15 +73,24 @@ namespace iu9cawebchat { | |||||||
|                 nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}}); |                 nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}}); | ||||||
|             worker_guest_data[i].templater->update(); |             worker_guest_data[i].templater->update(); | ||||||
|             worker_guest_data[i].db = std::make_unique<SqliteConnection>(sqlite_db_path); |             worker_guest_data[i].db = std::make_unique<SqliteConnection>(sqlite_db_path); | ||||||
|  |             worker_guest_data[i].locales = std::make_unique<Localizator>(localizator_settings); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         een9::MainloopParameters params; |         een9::MainloopParameters params; | ||||||
|         params.guest_core = [&samI, &worker_guest_data, config_presentation] |         params.guest_core = [&samI, &worker_guest_data] | ||||||
|         (const een9::SlaveTask& task, const een9::ClientRequest& req, een9::worker_id_t worker_id) -> std::string { |         (const een9::SlaveTask& task, const een9::ClientRequest& req, een9::worker_id_t worker_id) -> std::string { | ||||||
|             een9_ASSERT_pl(0 <= worker_id && worker_id < worker_guest_data.size()); |             een9_ASSERT_pl(0 <= worker_id && worker_id < worker_guest_data.size()); | ||||||
|             WorkerGuestData& wgd = worker_guest_data[worker_id]; |             WorkerGuestData& wgd = worker_guest_data[worker_id]; | ||||||
|             een9::StaticAsset sa; |             een9::StaticAsset sa; | ||||||
|             ONE_SQLITE_TRANSACTION_GUARD conn_guard(*wgd.db); |             ONE_SQLITE_TRANSACTION_GUARD conn_guard(*wgd.db); | ||||||
|  |             std::string AcceptLanguage; | ||||||
|  |             for (const std::pair<std::string, std::string>& p: req.headers) { | ||||||
|  |                 if (p.first == "Accept-Language") | ||||||
|  |                     AcceptLanguage = p.second; | ||||||
|  |             } | ||||||
|  |             std::vector<std::string> AcceptLanguageB = een9::parse_header_Accept_Language(AcceptLanguage); | ||||||
|  |             const LanguageFile& locale = wgd.locales->get_right_locale(AcceptLanguageB); | ||||||
|  |             const json::JSON& pres = locale.content; | ||||||
|             try { |             try { | ||||||
|                 std::vector<std::pair<std::string, std::string>> cookies; |                 std::vector<std::pair<std::string, std::string>> cookies; | ||||||
|                 std::vector<LoginCookie> login_cookies; |                 std::vector<LoginCookie> login_cookies; | ||||||
| @ -78,17 +99,17 @@ namespace iu9cawebchat { | |||||||
|                 initial_extraction_of_all_the_useful_info_from_cookies(*wgd.db, req, cookies, login_cookies, userinfo, logged_in_user); |                 initial_extraction_of_all_the_useful_info_from_cookies(*wgd.db, req, cookies, login_cookies, userinfo, logged_in_user); | ||||||
| 
 | 
 | ||||||
|                 if (req.uri_path == "/" || req.uri_path == "/list-rooms") { |                 if (req.uri_path == "/" || req.uri_path == "/list-rooms") { | ||||||
|                     return when_page_list_rooms(wgd, config_presentation, req, userinfo); |                     return when_page_list_rooms(wgd, pres, req, userinfo); | ||||||
|                 } |                 } | ||||||
|                 if (req.uri_path == "/login") { |                 if (req.uri_path == "/login") { | ||||||
|                     return when_page_login(wgd, config_presentation, req, login_cookies, userinfo); |                     return when_page_login(wgd, pres, req, login_cookies, userinfo); | ||||||
|                 } |                 } | ||||||
|                 // todo: split
 |                 // todo: split
 | ||||||
|                 if (een9::beginsWith(req.uri_path, "/chat/") || een9::beginsWith(req.uri_path, "/chat-members/")) { |                 if (een9::beginsWith(req.uri_path, "/chat/") || een9::beginsWith(req.uri_path, "/chat-members/")) { | ||||||
|                     return when_page_chat(wgd, config_presentation, req, userinfo); |                     return when_page_chat(wgd, pres, req, userinfo); | ||||||
|                 } |                 } | ||||||
|                 if (een9::beginsWith(req.uri_path, "/user/")) { |                 if (een9::beginsWith(req.uri_path, "/user/")) { | ||||||
|                     return when_page_user(wgd, config_presentation, req, login_cookies, userinfo); |                     return when_page_user(wgd, pres, req, login_cookies, userinfo); | ||||||
|                 } |                 } | ||||||
|                 if (req.uri_path == "/api/chatPollEvents") { |                 if (req.uri_path == "/api/chatPollEvents") { | ||||||
|                     return when_internalapi_chatpollevents(wgd, req, logged_in_user); |                     return when_internalapi_chatpollevents(wgd, req, logged_in_user); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user