repoindex/alpm/config.cpp

232 lines
8.7 KiB
C++
Raw Normal View History

2015-08-10 22:46:01 +02:00
#include "config.h"
#include <c++utilities/conversion/stringconversion.h>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <iostream>
using namespace std;
using namespace ApplicationUtilities;
using namespace ConversionUtilities;
namespace PackageManagement {
/*!
* \class Alpm::Config
* \brief The ConfigArgs class bundles the command line arguments for the application.
*/
/*!
* \brief Initializes the command line arguments for the configuration of the application.
*/
ConfigArgs::ConfigArgs(ArgumentParser &parser) :
helpArg(parser),
serverArg("server", "s", "runs a websocket server providing the web interface with information"),
repoindexConfArg("repoindex-conf", "c", "specifies the path of the repo index config file (default is /etc/repoindex.conf"),
rootdirArg("root-dir", "r", "specifies the root directory (default is /)"),
dbpathArg("db-path", "d", "specifies the pacman database path (default is /var/lib/pacman)"),
pacmanConfArg("pacman-conf", "p", "specifies the path of the pacman config file (default is /etc/pacman.conf"),
websocketAddrArg("addr", "a", "specifies the listening address for the websocket server, default is 127.0.0.1"),
websocketPortArg("port", "p", "specifies the listening port for the websocket server, default is 1234"),
certFileArg("cert-file", string(), "specifies the SSL certificate"),
keyFileArg("key-file", string(), "specifies the private SSL key"),
insecureArg("insecure", string(), "forces the server to run in insecure mode")
{
initializer_list<string> pathValueName = {"path"};
serverArg.setDenotesOperation(true);
repoindexConfArg.setCombinable(true);
repoindexConfArg.setValueNames(pathValueName);
repoindexConfArg.setRequiredValueCount(1);
rootdirArg.setCombinable(true);
rootdirArg.setValueNames({"directory"});
rootdirArg.setRequiredValueCount(1);
dbpathArg.setCombinable(true);
dbpathArg.setValueNames(pathValueName);
dbpathArg.setRequiredValueCount(1);
pacmanConfArg.setCombinable(true);
pacmanConfArg.setValueNames(pathValueName);
pacmanConfArg.setRequiredValueCount(1);
websocketAddrArg.setCombinable(true);
websocketAddrArg.setValueNames({"IP address"});
websocketAddrArg.setRequiredValueCount(1);
websocketPortArg.setCombinable(true);
websocketPortArg.setValueNames({"port number"});
websocketPortArg.setRequiredValueCount(1);
certFileArg.setCombinable(true);
certFileArg.setValueNames(pathValueName);
certFileArg.setRequiredValueCount(1);
keyFileArg.setCombinable(true);
keyFileArg.setValueNames(pathValueName);
keyFileArg.setRequiredValueCount(1);
insecureArg.setCombinable(true);
serverArg.setSecondaryArguments({&rootdirArg, &dbpathArg, &pacmanConfArg, &certFileArg, &keyFileArg, &insecureArg});
parser.setMainArguments({&serverArg, &repoindexConfArg, &helpArg});
}
/*!
* \class Alpm::Config
* \brief The Config class represents the configuration for the application.
*/
/*!
* \brief Creates the default configuration for the application.
*/
Config::Config() :
m_alpmRootDir(QStringLiteral("/")),
m_alpmDbPath(QStringLiteral("/var/lib/pacman/")),
m_pacmanConfFile(QStringLiteral("/etc/pacman.conf")),
m_websocketServerListeningAddr(QHostAddress::LocalHost),
m_websocketServerListeningPort(1234),
m_serverInsecure(false),
m_reposFromPacmanConf(false)
{}
/*!
* \cond
*/
inline void assign(quint16 &num, const QJsonValue &val)
{
if(!val.isUndefined()) {
auto n = val.toInt(-1);
if(n > 0 && n <= static_cast<quint16>(-1)) {
num = static_cast<quint16>(n);
} else {
cerr << "Error: The specified value \"" << n << "\" is not a number." << endl;
}
}
}
inline void assign(QHostAddress &addr, const QString &val)
{
if(!val.isEmpty() && !addr.setAddress(val)) {
cerr << "Error: Unable to parse the specified host address \"" << val.toStdString() << "\"." << endl;
}
}
inline void assign(QString &str, const Argument &arg)
{
if(arg.isPresent()) {
str = QString::fromLocal8Bit(arg.values().front().data(), arg.values().front().size());
}
}
inline void assign(quint16 &num, const Argument &arg)
{
if(arg.isPresent()) {
try {
num = stringToNumber<quint16>(arg.values().front());
} catch(const ConversionException &) {
cerr << "Error: The specified argument value \"" << arg.values().front() << "\" is not a number." << endl;
}
}
}
inline void assign(bool &num, const Argument &arg)
{
num |= arg.isPresent();
}
/*!
* \endcond
*/
/*!
* \brief Loads the configuration from the specified configuration file.
*/
void Config::loadFromConfigFile(const QString &configFilePath)
{
QFile file(configFilePath);
if(file.open(QFile::ReadOnly)) {
QJsonParseError error;
auto doc = QJsonDocument::fromJson(file.readAll(), &error);
if(error.error == QJsonParseError::NoError) {
auto mainObj = doc.object();
auto alpmObj = mainObj.value(QStringLiteral("alpm")).toObject();
m_alpmRootDir = alpmObj.value(QStringLiteral("rootDir")).toString(m_alpmRootDir);
m_alpmDbPath = alpmObj.value(QStringLiteral("dbPath")).toString(m_alpmDbPath);
m_pacmanConfFile = alpmObj.value(QStringLiteral("pacmanConfigFile")).toString(m_pacmanConfFile);
auto serverObj = mainObj.value(QStringLiteral("server")).toObject();
assign(m_websocketServerListeningAddr, serverObj.value(QStringLiteral("websocketListeningAddr")).toString());
assign(m_websocketServerListeningPort, serverObj.value(QStringLiteral("websocketListeningPort")));
m_serverCertFile = serverObj.value(QStringLiteral("certFile")).toString(m_serverCertFile);
m_serverKeyFile = serverObj.value(QStringLiteral("keyFile")).toString(m_serverKeyFile);
m_serverInsecure = serverObj.value(QStringLiteral("insecure")).toBool(m_serverInsecure);
auto reposObj = mainObj.value(QStringLiteral("repos")).toObject();
m_reposFromPacmanConf = serverObj.value(QStringLiteral("fromPacmanConfig")).toBool(m_reposFromPacmanConf);
for(const auto &repo : reposObj.value(QStringLiteral("add")).toArray()) {
m_repoEntries << RepoEntry();
m_repoEntries.back().load(repo);
}
} else {
cerr << "Error: Unable to parse config file \"" << configFilePath.toLocal8Bit().data() << "\": "
<< error.errorString().toLocal8Bit().data() << endl;
}
} else {
cerr << "Error: Unable to open config file \"" << configFilePath.toLocal8Bit().data() << "\"." << endl;
}
}
/*!
* \brief Loads the configuration from the configuration file.
*
* The config file is obtained from the specified config args. If no such argument is present,
* some default locations are checked.
*/
void Config::loadFromConfigFile(const ConfigArgs &args)
{
if(args.repoindexConfArg.isPresent()) {
loadFromConfigFile(QString::fromLocal8Bit(args.repoindexConfArg.values().front().data()));
return;
} else {
for(const auto &defaultPath : {QStringLiteral("./repoindex.conf"), QStringLiteral("/etc/repoindex.conf")}) {
if(QFile::exists(defaultPath)) {
loadFromConfigFile(defaultPath);
return;
}
}
}
}
/*!
* \brief Loads the config from the specified configuration arguments.
*/
void Config::loadFromArgs(const ConfigArgs &args)
{
assign(m_alpmRootDir, args.rootdirArg);
assign(m_alpmDbPath, args.dbpathArg);
assign(m_pacmanConfFile, args.pacmanConfArg);
assign(m_websocketServerListeningPort, args.websocketPortArg);
assign(m_serverCertFile, args.certFileArg);
assign(m_serverKeyFile, args.keyFileArg);
assign(m_serverInsecure, args.insecureArg);
if(args.websocketAddrArg.isPresent()) {
assign(m_websocketServerListeningAddr, QString::fromLocal8Bit(args.websocketAddrArg.values().front().data(), args.websocketAddrArg.values().front().size()));
}
}
/*!
* \brief Loads the values from the specified JSON value.
*/
void RepoEntry::load(const QJsonValue &jsonValue)
{
auto obj = jsonValue.toObject();
m_name = obj.value(QStringLiteral("name")).toString(m_name);
m_dbPath = obj.value(QStringLiteral("dbpath")).toString(m_dbPath);
m_srcPath = obj.value(QStringLiteral("srcpath")).toString(m_srcPath);
m_pkgPath = obj.value(QStringLiteral("pkgpath")).toString(m_pkgPath);
for(const auto &server : obj.value(QStringLiteral("servers")).toArray()) {
auto str = server.toString();
if(!str.isEmpty()) {
m_servers << str;
}
}
}
} // namespace Alpm