From fcf1581cf1474793631123b82a818f5dd5d386a3 Mon Sep 17 00:00:00 2001 From: Mark Calderbank Date: Thu, 6 Dec 2007 13:58:34 +0000 Subject: [PATCH] New I18n system: server code --- Makefile | 2 +- i18n.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++ i18n.h | 49 +++++++++++++++++++ mvpclient.c | 49 ++++++++++++++++++- mvpclient.h | 4 ++ 5 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 i18n.c create mode 100644 i18n.h diff --git a/Makefile b/Makefile index 659d4e9..fda7d9e 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' ### The object files (add further files here): -OBJS = $(PLUGIN).o dsock.o mvpserver.o udpreplier.o bootpd.o tftpd.o mvpclient.o tcp.o \ +OBJS = $(PLUGIN).o dsock.o mvpserver.o udpreplier.o bootpd.o tftpd.o i18n.o mvpclient.o tcp.o \ ringbuffer.o mvprelay.o \ recplayer.o config.o log.o thread.o mvpreceiver.o tftpclient.o \ media.o responsepacket.o diff --git a/i18n.c b/i18n.c new file mode 100644 index 0000000..7621b40 --- /dev/null +++ b/i18n.c @@ -0,0 +1,134 @@ +/* + Copyright 2007 Mark Calderbank + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "i18n.h" + +#include +#include +#include + +using namespace std; + +I18n::I18n(char* tconfigDir) +{ + configDir = tconfigDir; +} + +void I18n::findLanguages(void) +{ + glob_t globbuf; + char line[1000]; + + CodeList.clear(); + FileList.clear(); + + string l10nGlob = configDir; + l10nGlob += "/l10n/*"; + glob(l10nGlob.c_str(), 0, NULL, &globbuf); + for (unsigned int i=0; i < globbuf.gl_pathc; i++) + { + FILE *f = fopen(globbuf.gl_pathv[i], "r"); + if (f) + { + while (fgets(line, 1000, f) && strncmp(line, "l10n-vomp:", 10) == 0) + { + string langline = line; + string code, name; + + string::size_type pos_start, pos_end; + pos_start = langline.find_first_not_of(" \t\r\n", 10); + if (pos_start == string::npos) break; + pos_end = langline.find_first_of(" \t", pos_start); + if (pos_end == string::npos) break; + code = langline.substr(pos_start, pos_end - pos_start); + pos_start = langline.find_first_not_of(" \t\r\n", pos_end); + if (pos_start == string::npos) break; + pos_end = langline.find_last_not_of(" \t\r\n"); + name = langline.substr(pos_start, pos_end + 1 - pos_start); + CodeList[code] = name; + FileList.insert(lang_file(code, globbuf.gl_pathv[i])); + } + fclose(f); + } + } + globfree(&globbuf); +} + +I18n::trans_table I18n::getLanguageContent(const string code) +{ + trans_table Translations; + if (CodeList.count(code) == 0) return Translations; + LanguageCode = code; + + pair range; + range = FileList.equal_range(code); + lang_file_list::const_iterator iter; + for (iter = range.first; iter != range.second; ++iter) + { + FILE *f; + char line[1000]; + string key; + f = fopen((*iter).second.c_str(), "r"); + if (f) + { + while (fgets(line, 1000, f)) + { + int linetype = 0; + string::size_type offset = 0; + string fileline = line; + if (fileline.compare(0, 2, "x:") == 0) + { // New key to be translated + linetype = 1; offset = 2; + } + if (fileline.compare(0, code.size() + 1, code + ":") == 0) + { // Translation for previous key + if (key.empty()) continue; // Translation without preceding key + linetype = 2; offset = code.size() + 1; + } + if (linetype != 0) + { + string::size_type start, end; + start = fileline.find_first_not_of(" \t\r\n",offset); + if (start == string::npos) + { + if (linetype == 2) Translations[key].clear(); + continue; + } + end = fileline.find_last_not_of(" \t\r\n"); + string text = fileline.substr(start, end + 1 - start); + if (text.length() > 1) // Strip quotes if at both ends + { + if (text[0] == '"' && text[text.length()-1] == '"') + text = text.substr(1, text.length()-2); + } + if (linetype == 1) key = text; + if (linetype == 2) Translations[key] = text; + } + } + fclose(f); + } + } + return Translations; +} + +const I18n::lang_code_list& I18n::getLanguageList(void) +{ + return CodeList; +} diff --git a/i18n.h b/i18n.h new file mode 100644 index 0000000..109c336 --- /dev/null +++ b/i18n.h @@ -0,0 +1,49 @@ +/* + Copyright 2007 Mark Calderbank + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef I18N_H +#define I18N_H + +#include +#include + +class I18n +{ + public: + I18n(char* tconfigDir); + typedef std::map lang_code_list; + typedef std::pair lang_code; + typedef std::map trans_table; + typedef std::pair trans_entry; + + void findLanguages(void); + trans_table getLanguageContent(const std::string code); + const lang_code_list& getLanguageList(void); + + private: + char* configDir; + std::string LanguageCode; + lang_code_list CodeList; + + typedef std::multimap lang_file_list; + typedef std::pair lang_file; + lang_file_list FileList; +}; +#endif diff --git a/mvpclient.c b/mvpclient.c index d366e51..17fced9 100644 --- a/mvpclient.c +++ b/mvpclient.c @@ -30,7 +30,7 @@ int MVPClient::nr_clients = 0; MVPClient::MVPClient(Config* cfgBase, char* tconfigDir, int tsocket) - : tcp(tsocket) + : tcp(tsocket), i18n(tconfigDir) { #ifndef VOMPSTANDALONE lp = NULL; @@ -41,6 +41,7 @@ MVPClient::MVPClient(Config* cfgBase, char* tconfigDir, int tsocket) log = Log::getInstance(); loggedIn = false; configDir = tconfigDir; + log->log("Client", Log::DEBUG, "Config dir: %s", configDir); baseConfig = cfgBase; incClients(); } @@ -383,6 +384,12 @@ void MVPClient::run2() case 32: result = processGetImageBlock(data, extraDataLength, rp); break; + case 33: + result = processGetLanguageList(data, extraDataLength, rp); + break; + case 34: + result = processGetLanguageContent(data, extraDataLength, rp); + break; } if (data) free(data); @@ -1836,6 +1843,46 @@ int MVPClient::processGetImageBlock(UCHAR* data, int length, ResponsePacket* rp) } +int MVPClient::processGetLanguageList(UCHAR* data, int length, ResponsePacket* rp) +{ + i18n.findLanguages(); + const I18n::lang_code_list& languages = i18n.getLanguageList(); + std::string result; + I18n::lang_code_list::const_iterator iter; + for (iter = languages.begin(); iter != languages.end(); ++iter) + { + rp->addString(iter->first.c_str()); + rp->addString(iter->second.c_str()); + } + rp->finalise(); + tcp.sendPacket(rp->getPtr(), rp->getLen()); + delete rp; + return 1; +} + +int MVPClient::processGetLanguageContent(UCHAR* data, int length, ResponsePacket* rp) +{ + if (length <= 0) return 0; + std::string code, result; + code.assign((char*)data, length - 1); + i18n.findLanguages(); + I18n::trans_table texts = i18n.getLanguageContent(code); + I18n::trans_table::const_iterator iter; + for (iter = texts.begin(); iter != texts.end(); ++iter) + { + rp->addString(iter->first.c_str()); + rp->addString(iter->second.c_str()); + } + rp->finalise(); + tcp.sendPacket(rp->getPtr(), rp->getLen()); + delete rp; + return 1; +} + + + + + diff --git a/mvpclient.h b/mvpclient.h index 8afdf4f..9ef5c84 100644 --- a/mvpclient.h +++ b/mvpclient.h @@ -43,6 +43,7 @@ #include "tcp.h" #include "config.h" #include "media.h" +#include "i18n.h" class ResponsePacket; @@ -65,6 +66,7 @@ class MVPClient TCP tcp; Config config; Config* baseConfig; + I18n i18n; bool loggedIn; char* configDir; FILE* imageFile; @@ -103,6 +105,8 @@ class MVPClient int processGetMediaList(UCHAR* data, int length, ResponsePacket* rp); int processGetPicture(UCHAR* data, int length, ResponsePacket* rp); int processGetImageBlock(UCHAR* data, int length, ResponsePacket* rp); + int processGetLanguageList(UCHAR* data, int length, ResponsePacket* rp); + int processGetLanguageContent(UCHAR* data, int length, ResponsePacket* rp); void incClients(); void decClients(); -- 2.39.2