yate/modules/server/accfile.cpp

293 lines
7.2 KiB
C++

/**
* accfile.cpp
* This file is part of the YATE Project http://YATE.null.ro
*
* Account provider for client registrations and settings.
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2004-2017 Null Team
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
*
* 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.
*/
#include <yatephone.h>
using namespace TelEngine;
namespace { // anonymous
class AccFilePlugin : public Plugin
{
public:
AccFilePlugin();
~AccFilePlugin(){}
virtual void initialize();
private:
bool m_first;
};
static Mutex s_mutex(false,"AccFile");
static Configuration s_cfg(Engine::configFile("accfile"));
static char s_helpOpt[] = " accounts [reload|{login|logout|...} [account]]\r\n";
static char s_helpMsg[] = "Controls client accounts (to other servers) operations\r\n";
INIT_PLUGIN(AccFilePlugin);
class AccHandler : public MessageHandler
{
public:
AccHandler()
: MessageHandler("user.account",100,__plugin.name())
{ }
virtual bool received(Message &msg);
};
class CmdHandler : public MessageHandler
{
public:
CmdHandler()
: MessageHandler("engine.command",100,__plugin.name())
{ }
virtual bool received(Message &msg);
};
class HelpHandler : public MessageHandler
{
public:
HelpHandler()
: MessageHandler("engine.help",100,__plugin.name())
{ }
virtual bool received(Message &msg);
};
class StatusHandler : public MessageHandler
{
public:
StatusHandler()
: MessageHandler("engine.status",100,__plugin.name())
{ }
virtual bool received(Message &msg);
};
class StartHandler : public MessageHandler
{
public:
StartHandler()
: MessageHandler("engine.start",150,__plugin.name())
{ }
virtual bool received(Message &msg);
};
static void copyParams(NamedList& dest, const NamedList& src)
{
for (unsigned int i=0;i<src.length();i++) {
const NamedString* par = src.getParam(i);
if (par && par->name() && (par->name() != "operation"))
dest.addParam(par->name(),*par);
}
}
static bool emitAccounts(const char* operation, const String& account = String::empty())
{
bool ok = account.null();
Lock lock(s_mutex);
for (unsigned int i=0;i<s_cfg.sections();i++) {
NamedList* acc = s_cfg.getSection(i);
if (!(acc && acc->getBoolValue("enabled",(acc->getValue("username") != 0))))
continue;
if (account && (account != *acc))
continue;
Message* m = new Message("user.login");
copyParams(*m,*acc);
m->setParam("account",*acc);
if (operation)
m->setParam("operation",operation);
ok = Engine::enqueue(m);
}
return ok;
}
static bool operAccounts(const String& operation, const String& account = String::empty())
{
if (operation == "reload") {
Lock lock(s_mutex);
s_cfg.load();
return true;
}
return emitAccounts(operation,account);
}
// perform command line completion
static void doCompletion(Message &msg, const String& partLine, const String& partWord)
{
if (partLine.null() || (partLine == "help") || (partLine == "status"))
Module::itemComplete(msg.retValue(),"accounts",partWord);
else if (partLine == "accounts") {
Module::itemComplete(msg.retValue(),"reload",partWord);
Module::itemComplete(msg.retValue(),"login",partWord);
Module::itemComplete(msg.retValue(),"logout",partWord);
}
else if ((partLine == "accounts login") || (partLine == "accounts logout")) {
for (unsigned int i=0;i<s_cfg.sections();i++) {
NamedList* acc = s_cfg.getSection(i);
if (acc && acc->getBoolValue("enabled",(acc->getValue("username") != 0)))
Module::itemComplete(msg.retValue(),*acc,partWord);
}
}
}
bool AccHandler::received(Message &msg)
{
String action = msg.getValue("operation");
if (action.null())
return false;
if (action == "list") {
for (unsigned int i=0;i<s_cfg.sections();i++) {
NamedList* acc = s_cfg.getSection(i);
if (!(acc && acc->getBoolValue("enabled",(acc->getValue("username") != 0))))
continue;
msg.retValue().append(*acc,",");
}
return false;
}
String account = msg.getValue("account");
if (account.null())
return false;
Lock lock(s_mutex);
NamedList* acc = s_cfg.getSection(account);
if (acc) {
copyParams(msg,*acc);
return true;
}
return false;
}
bool CmdHandler::received(Message &msg)
{
String line = msg.getValue("line");
if (line.null()) {
doCompletion(msg,msg.getValue("partline"),msg.getValue("partword"));
return false;
}
if (!line.startSkip("accounts"))
return false;
bool ok = false;
int sep = line.find(' ');
if (sep > 0)
ok = operAccounts(line.substr(0,sep).trimBlanks(),line.substr(sep+1).trimBlanks());
else
ok = operAccounts(line);
if (!ok)
msg.retValue() = "Accounts operation failed: " + line + "\r\n";
return true;
}
bool HelpHandler::received(Message &msg)
{
String line = msg.getValue("line");
if (line.null()) {
msg.retValue() << s_helpOpt;
return false;
}
if (line != "accounts")
return false;
msg.retValue() << s_helpOpt << s_helpMsg;
return true;
}
bool StatusHandler::received(Message &msg)
{
String dest(msg.getValue("module"));
bool exact = (dest == "accfile");
if (dest && !exact && (dest != "accounts") && (dest != "misc"))
return false;
Lock lock(s_mutex);
unsigned int n = s_cfg.sections();
if (!s_cfg.getSection(0))
--n;
msg.retValue() << "name=accfile,type=misc;users=" << n;
if (msg.getBoolValue("details",true)) {
msg.retValue() << ";";
bool first = true;
for (unsigned int i=0;i<s_cfg.sections();i++) {
NamedList *acct = s_cfg.getSection(i);
if (!acct)
continue;
const char* user = acct->getValue("username");
if (!acct->getBoolValue(YSTRING("enabled"),(0 != user)))
continue;
if (first)
first = false;
else
msg.retValue() << ",";
msg.retValue() << *acct << "=" << String::uriEscape(user,",;|"," +?&");
}
}
msg.retValue() << "\r\n";
return exact;
}
bool StartHandler::received(Message &msg)
{
emitAccounts("login");
return false;
};
AccFilePlugin::AccFilePlugin()
: Plugin("accfile"),
m_first(true)
{
Output("Loaded module Accounts from file");
}
void AccFilePlugin::initialize()
{
Output("Initializing module Accounts from file");
if (m_first) {
Lock lock(s_mutex);
m_first = false;
s_cfg.load();
Engine::install(new StatusHandler);
Engine::install(new StartHandler);
Engine::install(new CmdHandler);
Engine::install(new HelpHandler);
}
else {
String oper = s_cfg.getValue("general","auto_oper");
if (oper) {
s_mutex.lock();
s_cfg.load();
oper = s_cfg.getValue("general","auto_oper");
s_mutex.unlock();
ObjList* list = oper.split(',',false);
for (ObjList* l = list->skipNull(); l; l = l->skipNext()) {
oper = *static_cast <const String*>(l->get());
if (oper.trimSpaces())
emitAccounts(oper);
}
}
}
}
}; // anonymous namespace
/* vi: set ts=8 sw=4 sts=4 noet: */