Make list of languages installed discoverable at runtime.

Stop hardcoding Russian in webadmin.
Limit the setting in controlpanel to the known languages, because
untrusted language code might lead to some interesting vulnerabilities.
This commit is contained in:
Alexey Sokolov
2017-08-19 18:05:47 +01:00
parent 328461faf1
commit f885699d1a
6 changed files with 65 additions and 8 deletions
+2
View File
@@ -247,6 +247,8 @@ endif()
install(DIRECTORY webskins
DESTINATION "${CMAKE_INSTALL_DATADIR}/znc")
install(DIRECTORY translations
DESTINATION "${CMAKE_INSTALL_DATADIR}/znc")
install(DIRECTORY man/
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1"
FILES_MATCHING PATTERN "znc*")
+7
View File
@@ -20,6 +20,12 @@
#include <znc/ZNCString.h>
#include <unordered_map>
struct CTranslationInfo {
static std::map<CString, CTranslationInfo> GetTranslations();
CString sSelfName;
};
// All instances of modules share single message map using this class stored in
// CZNC.
class CTranslation {
@@ -38,6 +44,7 @@ class CTranslation {
void DelReference(const CString& sDomain);
private:
// Domain is either "znc" or "znc-foo" where foo is a module name
const std::locale& LoadTranslation(const CString& sDomain);
std::unordered_map<CString /* domain */,
std::unordered_map<CString /* language */, std::locale>>
+19 -3
View File
@@ -276,7 +276,9 @@ class CAdminMod : public CModule {
PutModule("StatusPrefix = " + pUser->GetStatusPrefix());
#ifdef HAVE_I18N
else if (sVar == "language")
PutModule("Language = " + pUser->GetLanguage());
PutModule("Language = " + (pUser->GetLanguage().empty()
? "en"
: pUser->GetLanguage()));
#endif
#ifdef HAVE_ICU
else if (sVar == "clientencoding")
@@ -453,8 +455,22 @@ class CAdminMod : public CModule {
}
#ifdef HAVE_I18N
else if (sVar == "language") {
pUser->SetLanguage(sValue);
PutModule("Language = " + pUser->GetLanguage());
auto mTranslations = CTranslationInfo::GetTranslations();
// TODO: maybe stop special-casing English
if (sValue == "en") {
pUser->SetLanguage("");
PutModule("Language is set to English");
} else if (mTranslations.count(sValue)) {
pUser->SetLanguage(sValue);
PutModule("Language = " + sValue);
} else {
VCString vsCodes = {"en"};
for (const auto it : mTranslations) {
vsCodes.push_back(it.first);
}
PutModule("Supported languages: " +
CString(", ").Join(vsCodes.begin(), vsCodes.end()));
}
}
#endif
#ifdef HAVE_ICU
+11 -5
View File
@@ -316,7 +316,11 @@ class CWebAdminMod : public CModule {
pNewUser->SetNoTrafficTimeout(uNoTrafficTimeout);
#ifdef HAVE_I18N
pNewUser->SetLanguage(WebSock.GetParam("language"));
CString sLanguage = WebSock.GetParam("language");
if (CTranslationInfo::GetTranslations().count(sLanguage) == 0) {
sLanguage = "";
}
pNewUser->SetLanguage(sLanguage);
#endif
#ifdef HAVE_ICU
CString sEncodingUtf = WebSock.GetParam("encoding_utf");
@@ -1376,13 +1380,15 @@ class CWebAdminMod : public CModule {
#ifdef HAVE_I18N
Tmpl["HaveI18N"] = "true";
// TODO don't have them hardcoded here
// TODO maybe stop hardcoding English here
CTemplate& l_en = Tmpl.AddRow("LanguageLoop");
l_en["Code"] = "";
l_en["Name"] = "English";
CTemplate& l_ru = Tmpl.AddRow("LanguageLoop");
l_ru["Code"] = "ru-RU";
l_ru["Name"] = "Russian";
for (const auto& it : CTranslationInfo::GetTranslations()) {
CTemplate& lang = Tmpl.AddRow("LanguageLoop");
lang["Code"] = it.first;
lang["Name"] = it.second.sSelfName;
}
#else
Tmpl["HaveI18N"] = "false";
#endif
+25
View File
@@ -15,11 +15,36 @@
*/
#include <znc/Translation.h>
#include <znc/FileUtils.h>
#ifdef HAVE_I18N
#include <boost/locale.hpp>
#endif
namespace {
std::map<CString, CTranslationInfo> FillTranslations() {
std::map<CString, CTranslationInfo> mTranslations;
CDir Dir;
Dir.Fill(_DATADIR_ "/translations");
for (CFile* pFile : Dir) {
CString sName = pFile->GetShortName();
CTranslationInfo& translation = mTranslations[sName];
MCString msData;
// TODO: make the file format more sensible than this
msData.ReadFromDisk(pFile->GetLongName());
translation.sSelfName = msData["SelfName"];
// TODO: right-to-left support
}
return mTranslations;
}
} // namespace
std::map<CString, CTranslationInfo> CTranslationInfo::GetTranslations() {
static std::map<CString, CTranslationInfo> mTranslations =
FillTranslations();
return mTranslations;
}
CTranslation& CTranslation::Get() {
static CTranslation translation;
return translation;
+1
View File
@@ -0,0 +1 @@
SelfName Русский