mirror of
https://github.com/znc/znc.git
synced 2026-08-09 18:32:55 +02:00
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:
@@ -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*")
|
||||
|
||||
@@ -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>>
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
SelfName Русский
|
||||
Reference in New Issue
Block a user