You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
smart-group-server-xl/SGSXLConfig.cpp

389 lines
11 KiB

/*
* Copyright (C) 2010,2011,2012 by Jonathan Naylor G4KLX
* Copyright (c) 2017 by Thomas A. Early N7TAE
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <string>
#include <sstream>
#include <iostream>
#include <filesystem>
#include "Utils.h"
#include "SGSXLConfig.h"
CSGSXLConfig::CSGSXLConfig(const std::string &pathname)
{
m_hasErrors = false;
if (pathname.size() < 1) {
printf("Configuration filename too short!\n");
m_hasErrors = true;
return;
}
Config cfg;
try {
cfg.readFile(pathname.c_str());
}
catch(const FileIOException &fioex) {
printf("Can't read %s\n", pathname.c_str());
m_hasErrors = true;
return;
}
catch(const ParseException &pex) {
printf("Parse error at %s:%d - %s\n", pex.getFile(), pex.getLine(), pex.getError());
m_hasErrors = true;
return;
}
if (! get_value(cfg, "gateway.callsign", m_callsign, 3, 8, "")
|| 0 == m_callsign.size()) {
m_hasErrors = true;
printf("No Gateway callsign specified");
return;
}
CUtils::ToUpper(m_callsign);
get_value(cfg, "gateway.address", m_address, 0, 20, "");
printf("GATEWAY: callsign='%s' address='%s'\n", m_callsign.c_str(), m_address.c_str());
//ircDDB Networks
for(int i = 0; i < cfg.lookup("ircddb").getLength(); i++) {
SircDDB * ircddb = new SircDDB();
std::stringstream key;
key << "ircddb.[" << i << "].hostname";
if(! get_value(cfg, key.str(), ircddb->hostname, 5, 30, "") || ircddb->hostname == "") {//do not allow hostname to be empty
delete ircddb;
continue;
}
key.str("");key.clear();
key << "ircddb.[" << i << "].username";
if (! get_value(cfg, key.str(), ircddb->username, 3, 8, m_callsign)) {//default user name to callsign
delete ircddb;
continue;
}
CUtils::ToUpper(ircddb->username);
key.str("");key.clear();
key << "ircddb.[" << i << "].password";
if(!get_value(cfg, key.str(), ircddb->password, 0, 30, "")) {
delete ircddb;
continue;
}
this->m_ircDDB.push_back(ircddb);
std::cout << "IRCDDB: host=" << ircddb->hostname << " user=" << ircddb->username << " password=" << ircddb->password << "\n";
}
if(this->m_ircDDB.size() == 0) {//no ircddb network specified? Default to openquad!
SircDDB * ircddb = new SircDDB();
ircddb->hostname = "rr.openquad.net";
ircddb->password = "";
ircddb->username = m_callsign;
this->m_ircDDB.push_back(ircddb);
std::cout << "No ircDDB networks configure'd, defaulting to IRCDDB: host=" << ircddb->hostname << " user=" << ircddb->username << " password=" << ircddb->password << "\n";
}
// module parameters
for (int i=0; i<cfg.lookup("module").getLength(); i++) {
std::stringstream key;
std::string basename, subscribe, unsubscribe, band;
key << "module.[" << i << "].basename";
if (get_value(cfg, key.str(), basename, 1, 7, "")) {
bool isokay = true;
for (std::string::iterator it=basename.begin(); it!=basename.end(); it++) {
if (! isalnum(*it)) {
isokay = false;
break;
}
}
if (isokay)
CUtils::ToUpper(basename);
else {
printf("Malformed basename for module %d: '%s'\n", i, basename.c_str());
basename.clear();
}
}
key.str("");key.clear();
key << "module.[" << i << "].band";
get_value(cfg, key.str(), band, 1, 1, "A");
CUtils::ToUpper(band);
if (! isalpha(band[0])) {
printf("Module %d band is not a letter\n", i);
basename.clear();
}
key.str("");key.clear();
key << "module.[" << i << "].subscribe";
get_value(cfg, key.str(), subscribe, 1, 1, "A");
CUtils::ToUpper(subscribe);
if (subscribe[0] != ' ' && ('A' > subscribe[0] || subscribe[0] > 'Z')) {
printf("subscribe suffix not space or letter\n");
basename.clear();
}
key.str("");key.clear();
key << "module.[" << i << "].unsubscribe";
get_value(cfg, key.str(), unsubscribe, 1, 1, "T");
CUtils::ToUpper(unsubscribe);
if ('A' > unsubscribe[0] || unsubscribe[0] > 'Z') {
printf("unsubscribe suffix not a letter\n");
basename.clear();
}
if (! subscribe.compare(unsubscribe)) {
// subscribe and unsubscribe suffix needs to be different
printf("subscribe and unsubscribe for %s are identical\n", basename.c_str());
basename.clear();
}
// skip to the next module definition
if (0 == basename.size())
continue;
struct Smodule *pmod = new struct Smodule;
// pad basename with spaces
basename.resize(7, ' ');
pmod->callsign = basename + subscribe;
pmod->logoff = basename + unsubscribe;
pmod->band = band;
key.str("");key.clear();
key << "module.[" << i << "].info";
get_value(cfg, key.str(), pmod->info, 0, 20, "Smart Group Server XL");
if (pmod->info.size())
pmod->info.resize(20, ' ');
key.str("");key.clear();
key << "module.[" << i << "].permanent";
get_value(cfg, key.str(), pmod->permanent, 0, 120, "");
CUtils::ToUpper(pmod->permanent);
int ivalue;
key.str("");key.clear();
key << "module.[" << i << "].usertimeout";
get_value(cfg, key.str(), ivalue, 0, 300, 300);
pmod->usertimeout = (unsigned int)ivalue;
bool bvalue;
key.str("");key.clear();
key << "module.[" << i << "].callsignswitch";
get_value(cfg, key.str(), bvalue, false);
pmod->callsignswitch = bvalue ? SCS_GROUP_CALLSIGN : SCS_USER_CALLSIGN;
key.str("");key.clear();
key << "module.[" << i << "].txmsgswitch";
get_value(cfg, key.str(), pmod->txmsgswitch, true);
key.str("");key.clear();
key << "module.[" << i << "].reflector";
if (! get_value(cfg, key.str(), basename, 8, 8, "")) {
printf("reflector %d must be undefined or exactly 8 chars!\n", i);
basename.clear();
}
pmod->reflector.clear();
if (basename.size()) {
CUtils::ToUpper(basename);
if ( (0==basename.compare(0,3,"XRF") || 0==basename.compare(0,3,"DCS")) && isdigit(basename[3]) && isdigit(basename[4]) && isdigit(basename[5]) && ' '==basename[6] && isalpha(basename[7]) )
pmod->reflector = basename;
}
printf("Module %d: callsign='%s' unsubscribe='%s' info='%s' permanent='%s' usertimeout=%d callsignswitch=%s, txmsgswitch=%s reflector='%s'\n",
i, pmod->callsign.c_str(), pmod->logoff.c_str(), pmod->info.c_str(), pmod->permanent.c_str(), pmod->usertimeout,
SCS_GROUP_CALLSIGN==pmod->callsignswitch ? "Group" : "User", pmod->txmsgswitch ? "true" : "false", pmod->reflector.c_str());
m_module.push_back(pmod);
}
// remote control
get_value(cfg, "remote.enabled", m_remoteEnabled, false);
if (m_remoteEnabled) {
get_value(cfg, "remote.password", m_remotePassword, 6, 30, "");
int ivalue;
get_value(cfg, "remote.port", ivalue, 1000, 65000, 39999);
m_remotePort = (unsigned int)ivalue;
printf("Remote enabled: password='%s', port=%d\n", m_remotePassword.c_str(), m_remotePort);
} else {
m_remotePort = 0U;
m_remotePassword.clear();
printf("Remote disabled\n");
}
//audio
get_value(cfg, "audio.enabled", m_audioEnabled, true);
get_value(cfg, "audio.language", m_audioLanguage, TL_ENGLISH_UK);
if(m_audioEnabled) {
printf("Audio enabled\n");
} else {
printf("Audio disabled\n");
}
}
CSGSXLConfig::~CSGSXLConfig()
{
while (m_module.size()) {
delete m_module.back();
m_module.pop_back();
}
while(m_ircDDB.size()) {
delete m_ircDDB.back();
m_ircDDB.pop_back();
}
}
unsigned int CSGSXLConfig::getModCount()
{
return m_module.size();
}
unsigned int CSGSXLConfig::getIrcDDBCount()
{
return m_ircDDB.size();
}
unsigned int CSGSXLConfig::getLinkCount(const char *type)
{
unsigned int count = 0;
for (unsigned int i=0; i<getModCount(); i++)
if (0 == m_module[i]->reflector.compare(0, 3, type))
count++;
return count;
}
void CSGSXLConfig::getAudio(bool & enabled, TEXT_LANG & lang) const
{
enabled = m_audioEnabled;
lang = m_audioLanguage;
}
bool CSGSXLConfig::hasErrors()
{
return m_hasErrors;
}
bool CSGSXLConfig::get_value(const Config &cfg, const std::string &path, int &value, int min, int max, int default_value)
{
if (cfg.lookupValue(path, value)) {
if (value < min || value > max)
value = default_value;
} else
value = default_value;
return true;
}
bool CSGSXLConfig::get_value(const Config &cfg, const std::string &path, TEXT_LANG& lang, TEXT_LANG defaultValue)
{
lang = defaultValue;
std::string value;
if(cfg.lookupValue(path, value)) {
if(value == "de_DE")
{
lang = TL_DEUTSCH;
}
else if(value == "dk_DK")
{
lang = TL_DANSK;
}
else if(value == "it_IT")
{
lang = TL_ITALIANO;
}
else if(value == "fr_FR")
{
lang = TL_FRANCAIS;
}
else if(value == "es_ES")
{
lang = TL_ESPANOL;
}
else if(value == "se_SE")
{
lang = TL_SVENSKA;
}
else if(value == "pl_PL")
{
lang = TL_POLSKI;
}
else if(value == "en_US")
{
lang = TL_ENGLISH_US;
}
else if(value == "en_GB")
{
lang = TL_ENGLISH_UK;
}
else if(value == "no_NO")
{
lang = TL_NORSK;
}
}
return true;
}
bool CSGSXLConfig::get_value(const Config &cfg, const std::string &path, bool &value, bool default_value)
{
if (! cfg.lookupValue(path, value))
value = default_value;
return true;
}
bool CSGSXLConfig::get_value(const Config &cfg, const std::string &path, std::string &value, int min, int max, const std::string &default_value)
{
if (cfg.lookupValue(path, value)) {
int l = value.length();
if (l<min || l>max) {
std::cout << path << "=" << value << " has an inalid length, must be between " << min << " and " << max << " actual " << l << "\n";
return false;
}
} else
value = default_value;
return true;
}
void CSGSXLConfig::getGateway(std::string& callsign, std::string& address) const
{
callsign = m_callsign;
address = m_address;
}
void CSGSXLConfig::getIrcDDB(unsigned int ircddb, std::string& hostname, std::string& username, std::string& password) const
{
hostname = m_ircDDB[ircddb]->hostname;
username = m_ircDDB[ircddb]->username;
password = m_ircDDB[ircddb]->password;
}
void CSGSXLConfig::getGroup(unsigned int mod, std::string& band, std::string& callsign, std::string& logoff, std::string& info, std::string& permanent, unsigned int& userTimeout, CALLSIGN_SWITCH& callsignSwitch, bool& txMsgSwitch, std::string& reflector) const
{
band = m_module[mod]->band;
callsign = m_module[mod]->callsign;
logoff = m_module[mod]->logoff;
info = m_module[mod]->info;
permanent = m_module[mod]->permanent;
userTimeout = m_module[mod]->usertimeout;
callsignSwitch = m_module[mod]->callsignswitch;
txMsgSwitch = m_module[mod]->txmsgswitch;
reflector = m_module[mod]->reflector;
}
void CSGSXLConfig::getRemote(bool& enabled, std::string& password, unsigned int& port) const
{
enabled = m_remoteEnabled;
password = m_remotePassword;
port = m_remotePort;
}

Powered by TurnKey Linux.