readd libconfig

correct regex to proof correct api
This commit is contained in:
Lukas Heiligenbrunner 2020-10-12 01:55:58 +02:00
parent e7cc041bc4
commit 41a8e8e7e1
11 changed files with 327 additions and 153 deletions

View File

@ -136,6 +136,7 @@ namespace StaticData {
}"
)
#define libraries with sources here
add_library(api ${LIB_METHOD}
src/api/API.cpp
src/api/TelegramAPI.cpp
@ -147,12 +148,14 @@ add_library(libdynuiprefresher ${LIB_METHOD}
src/IpHelper.cpp
src/FileLogger.cpp
src/Logger.cpp
src/ConfigParser.cpp)
src/Config.cpp)
add_executable(${Application_Name} src/main.cpp)
message(${CONAN_LIBS})
# LINK generated LIBS #
target_link_libraries(${Application_Name} libdynuiprefresher api CONAN_PKG::libcurl)
target_link_libraries(${Application_Name} libdynuiprefresher api CONAN_PKG::libcurl CONAN_PKG::LibConfig)
if (${GUI})
set(QT5_LIBRARIES Qt5::Widgets Qt5::PrintSupport Qt5::Sql)
@ -179,7 +182,7 @@ if (${GUI})
endif ()
# LINK generated LIBS #
target_link_libraries(${Application_Name}-gui -lpthread libdynuiprefresher api CONAN_PKG::libcurl ${QT5_LIBRARIES})
target_link_libraries(${Application_Name}-gui -lpthread libdynuiprefresher api CONAN_PKG::libcurl CONAN_PKG::LibConfig ${QT5_LIBRARIES})
endif ()
# setting install targets

View File

@ -1,5 +1,6 @@
[requires]
libcurl/7.72.0@heili/release
libcurl/7.72.0@prebuiltconanbinaries/stable
LibConfig/1.7.2@prebuiltconanbinaries/stable
[generators]
cmake

113
inc/Config.h Normal file
View File

@ -0,0 +1,113 @@
/**
* A static class to manage the configuration file, read/write parameters to it.
*
* @author Lukas Heiligenbrunner
* @date 11.02.2020
*/
#pragma once
#include <string>
class Config {
public:
/**
* read configuration out of config file
*
* @return success of config read
*/
static bool readConfig();
/**
* save back configuration to file
*
* @return success of config write
*/
static bool saveConfig();
/**
* validate config file
*
* @return validity of config file
*/
static bool validateConfig();
/**
* check if telegram credentials in config are set
* @return is supported?
*/
static bool isTelegramSupported();
/** Getters **/
/**
* encapsulated getter for DynuApiKey
* @return api key
*/
static const std::string &getDynuapikey();
/**
* encapsulated getter for DomainId
* @return DomainId
*/
static const std::string &getDomainid();
/**
* encapsulated getter for Domainname
* @return Domainname
*/
static const std::string &getDomainname();
/**
* encapsulated getter for TelegramApiKey
* @return TelegramApiKey
*/
static const std::string &getTelegramApiKey();
/**
* encapsulated getter for ChatId
* @return ChatId
*/
static const std::string &getChatId();
/**
* set all parameters without telegram support
*
* @param domainname Dynu Domain name
* @param dynuapikey Dynu api key
* @param domainid Dynu domain id
*/
static void setValues(const std::string &domainname, const std::string &dynuapikey, const std::string &domainid);
/**
* set all parameters with telegram support
*
* @param domainname Dynu Domain name
* @param dynuapikey Dynu api key
* @param domainid Dynu domain id
* @param telegramApiKey Telegram api key
* @param chatId Telegram chat id
*/
static void setValues(const std::string &domainname, const std::string &dynuapikey, const std::string &domainid,
const std::string &telegramApiKey, const std::string &chatId);
private:
/**
* private constructor --> don't allow instance of this class
*/
Config() = default;
/**
* helper variable for managing telegram Support
*/
static bool telegramSupport;
/**
* helper variables for storing keys and ids
*/
static std::string dynuapikey;
static std::string domainid; //id of the dynu domain
static std::string domainname;
static std::string telegramApiKey;
static std::string chatId;
};

View File

@ -1,51 +0,0 @@
//
// Created by lukas on 09.10.20.
//
#pragma once
class ConfigParser {
public:
static bool loadConfig();
bool saveConfig();
static bool validateConfig();
/**
* check if telegram credentials in config are set
* @return is supported?
*/
static bool isTelegramSupported();
/** Getters **/
/**
* encapsulated getter for DynuApiKey
* @return api key
*/
static const std::string &getDynuapikey();
/**
* encapsulated getter for DomainId
* @return DomainId
*/
static const std::string &getDomainid();
/**
* encapsulated getter for Domainname
* @return Domainname
*/
static const std::string &getDomainname();
/**
* encapsulated getter for TelegramApiKey
* @return TelegramApiKey
*/
static const std::string &getTelegramApiKey();
/**
* encapsulated getter for ChatId
* @return ChatId
*/
static const std::string &getChatId();
};

View File

@ -16,7 +16,7 @@ public:
* @param ip ip address to test
* @return validity
*/
static bool isIpValid(std::string ip);
static bool isIpValid(const std::string& ip);
private:
};

182
src/Config.cpp Normal file
View File

@ -0,0 +1,182 @@
#include "Config.h"
#include "Logger.h"
#include "StaticData.h"
#include <iostream>
#include <cstring>
#include <fstream>
#include <libconfig.h++>
#include <sys/stat.h>
std::string Config::dynuapikey;
std::string Config::domainid; //id of the dynu domain
std::string Config::domainname;
std::string Config::telegramApiKey;
std::string Config::chatId;
bool Config::telegramSupport;
bool Config::readConfig() {
libconfig::Config cfg;
try {
cfg.readFile(std::string(StaticData::ConfigDir + StaticData::ConfName).c_str());
}
catch (const libconfig::FileIOException &fioex) {
std::cout << "I/O error while reading config file." << std::endl << "creating new config file!" << std::endl;
// check if config folder exists
struct stat info{};
if (stat(StaticData::ConfigDir.c_str(), &info) != 0) {
Logger::warning("The config folder doesn't exist. Trying to create it.");
// mkdir command is different defined for windows
#ifdef __unix
int check = mkdir(StaticData::ConfigDir.c_str(), 777);
#else
int check = mkdir(StaticData::ConfigDir.c_str());
#endif
// check if directory is created or not
if (!check)
Logger::message("config directory successfully created. ");
else
Logger::error("unable to create config directory.");
} else if (info.st_mode & S_IFDIR) {
Logger::debug("config directory exists already");
} else {
Logger::error("A file exists with the same name as the config dir should be");
}
std::ofstream myfile;
myfile.open(StaticData::ConfigDir + StaticData::ConfName);
if (myfile.is_open()) {
myfile << StaticData::SAMPLECONFIG;
myfile.close();
} else {
Logger::error("error creating file");
}
return false;
}
catch (const libconfig::ParseException &pex) {
std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
<< " - " << pex.getError() << std::endl;
return false;
}
try {
// needed parameters
dynuapikey = (std::string) cfg.lookup("dynuapikey");
domainid = (std::string) cfg.lookup("domainid");
domainname = (std::string) cfg.lookup("domainname");
// optional parameters
telegramApiKey = (std::string) cfg.lookup("telegramApiKey");
chatId = (std::string) cfg.lookup("chatId");
telegramSupport = true;
}
catch (const libconfig::SettingNotFoundException &nfex) {
// triggered if setting is missing in config
if (!(std::strcmp("telegramApiKey", nfex.getPath()) == 0 || std::strcmp("chatId", nfex.getPath()) == 0)) {
std::cerr << "No '" << nfex.getPath() << "' setting in configuration file." << std::endl;
} else {
Logger::message("no Telegram support - fields in config not set");
telegramSupport = false;
}
}
// check if needed values aren't empty
return !(Config::dynuapikey.empty() || Config::domainid.empty() || Config::domainname.empty());
}
bool Config::saveConfig() {
// todo save config
return false;
}
bool Config::validateConfig() {
libconfig::Config cfg;
try {
Logger::message("reading config file: " + std::string(StaticData::ConfigDir + StaticData::ConfName));
cfg.readFile(std::string(StaticData::ConfigDir + StaticData::ConfName).c_str());
}
catch (const libconfig::FileIOException &fioex) {
Logger::warning("config file doesn't exist or permission denied!");
return false;
}
catch (const libconfig::ParseException &pex) {
std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
<< " - " << pex.getError() << std::endl;
return false;
}
Logger::message("Syntax and Permission is OK");
try {
// needed parameters
if (((std::string) cfg.lookup("dynuapikey")).empty()) {
Logger::warning("required parameter \"dynuapikey\" seems to be empty.");
return false;
}
if (((std::string) cfg.lookup("domainid")).empty()) {
Logger::warning("required parameter \"domainid\" seems to be empty.");
return false;
}
if (((std::string) cfg.lookup("domainname")).empty()) {
Logger::warning("required parameter \"domainname\" seems to be empty.");
return false;
}
// optional parameters
cfg.lookup("telegramApiKey");
cfg.lookup("chatId");
telegramSupport = true;
}
catch (const libconfig::SettingNotFoundException &nfex) {
// triggered if setting is missing in config
if (!(std::strcmp("telegramApiKey", nfex.getPath()) == 0 || std::strcmp("chatId", nfex.getPath()) == 0)) {
std::cerr << "No '" << nfex.getPath() << "' setting in configuration file." << std::endl;
return false;
} else {
Logger::message("no Telegram support - fields in config not set");
telegramSupport = false;
}
}
return true;
}
bool Config::isTelegramSupported() {
return telegramSupport;
}
const std::string &Config::getDynuapikey() {
return dynuapikey;
}
const std::string &Config::getDomainid() {
return domainid;
}
const std::string &Config::getDomainname() {
return domainname;
}
const std::string &Config::getTelegramApiKey() {
return telegramApiKey;
}
const std::string &Config::getChatId() {
return chatId;
}
void Config::setValues(const std::string &domainname, const std::string &dynuapikey, const std::string &domainid) {
Config::domainname = domainname;
Config::dynuapikey = dynuapikey;
Config::domainid = domainid;
}
void Config::setValues(const std::string &domainname, const std::string &dynuapikey, const std::string &domainid, const std::string &telegramApiKey, const std::string &chatId) {
setValues(domainname, dynuapikey, domainid);
Config::telegramApiKey = telegramApiKey;
Config::chatId = chatId;
}

View File

@ -1,81 +0,0 @@
//
// Created by lukas on 09.10.20.
//
#include <string>
#include <inc/StaticData.h>
#include <fstream>
#include <regex>
#include <iostream>
#include "inc/ConfigParser.h"
bool ConfigParser::loadConfig() {
const std::string config = StaticData::ConfigDir + StaticData::ConfName;
const std::regex matchcomment(R"(^\s*#)"); // match hash to be a comment line
const std::regex matchkey(R"(.+(?=\=.+))");
const std::regex matchvalue(R"((?:=(.+)(?=\s*#*)))");
std::map<std::string, std::string> entries;
std::ifstream myfile(config);
if (myfile.is_open()) {
std::string line;
while (getline(myfile, line)) {
if (std::regex_search(line, matchcomment) || line == "") {
// comment line
continue;
}
// parse a key value pair
std::smatch mk, mv;
std::regex_search(line, mk, matchkey);
std::regex_search(line, mv, matchvalue);
if (!mk.empty() && !mv.empty()){
entries.insert(std::pair<std::string, std::string>(mk[0], mv[0]));
std::cout << mk[0] << "--" << mv[0] << std::endl;
}
}
myfile.close();
} else return false;
return true;
}
bool ConfigParser::saveConfig() {
// todo
return false;
}
bool ConfigParser::validateConfig() {
// todo
return false;
}
bool ConfigParser::isTelegramSupported() {
return false;
}
const std::string &ConfigParser::getDynuapikey() {
return "";
}
const std::string &ConfigParser::getDomainid() {
return "";
}
const std::string &ConfigParser::getDomainname() {
return "";
}
const std::string &ConfigParser::getTelegramApiKey() {
return "";
}
const std::string &ConfigParser::getChatId() {
return "";
}

View File

@ -3,13 +3,13 @@
#include "api/IPAPI.h"
#include "api/DynuAPI.h"
#include "api/TelegramAPI.h"
#include "Config.h"
#include "StaticData.h"
#include "IpHelper.h"
#include <chrono>
#include <thread>
#include <Logger.h>
#include <inc/ConfigParser.h>
bool IPRefresher::checkIPAdress(bool force) {
FileLogger logger;
@ -35,13 +35,13 @@ bool IPRefresher::checkIPAdress(bool force) {
Logger::message("ip changed! -- from :" + oldip + "to: " + ip);
DynuAPI dynu;
dynu.init(ConfigParser::getDynuapikey(), ConfigParser::getDomainid(), ConfigParser::getDomainname());
dynu.init(Config::getDynuapikey(), Config::getDomainid(), Config::getDomainname());
// actual refresh of IP in api - here
bool result = dynu.refreshIp(ip);
if (result && ConfigParser::isTelegramSupported()) {
if (result && Config::isTelegramSupported()) {
TelegramAPI tele;
tele.init(ConfigParser::getTelegramApiKey(), ConfigParser::getChatId());
tele.init(Config::getTelegramApiKey(), Config::getChatId());
tele.sendMessage(oldip + " moved to " + ip);
} else if (!result) {
//error
@ -61,7 +61,7 @@ void IPRefresher::startUpService(int interval) {
while (true) {
Logger::message("starting check");
if (ConfigParser::loadConfig()) {
if (Config::readConfig()) {
checkIPAdress(false);
} else {
std::cout << "incorrect credentials!" << std::endl;

View File

@ -1,5 +1,7 @@
#include <regex>
#include "IpHelper.h"
bool IpHelper::isIpValid(std::string ip) {
return (ip.find('.') != SIZE_MAX);
bool IpHelper::isIpValid(const std::string& ip) {
const std::regex rgx(R"(^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$)");
return (std::regex_match(ip, rgx));
}

View File

@ -1,5 +1,11 @@
#include <inc/IpHelper.h>
#include <inc/Logger.h>
#include "api/IPAPI.h"
std::string IPAPI::getGlobalIp() {
return request("https://api.ipify.org");
const std::string ip = request("https://api.ipify.org");
if(!IpHelper::isIpValid(ip))
Logger::warning("no valid ip returned from ipapi");
return ip;
}

View File

@ -1,8 +1,8 @@
#include "StaticData.h"
#include "IPRefresher.h"
#include "Logger.h"
#include "Config.h"
#include "api/IPAPI.h"
#include "ConfigParser.h"
/**
* application entry point
@ -21,7 +21,7 @@ int main(int argc, char *argv[]) {
} else if (firstarg == "-v" || firstarg == "--version") {
std::cout << "Version " << StaticData::VERSION << std::endl;
} else if (firstarg == "-f" || firstarg == "--force") {
if (ConfigParser::loadConfig()) {
if (Config::readConfig()) {
IPRefresher::checkIPAdress(true);
} else {
std::cout << "incorrect credentials!" << std::endl;
@ -30,7 +30,7 @@ int main(int argc, char *argv[]) {
} else if (firstarg == "-l" || firstarg == "--loop") {
IPRefresher::startUpService(true);
} else if (firstarg == "-c" || firstarg == "--checkconfig") {
if (ConfigParser::validateConfig()) {
if (Config::validateConfig()) {
Logger::message("Config file is OK");
} else {
Logger::error("There are errors in config file!");
@ -38,16 +38,15 @@ int main(int argc, char *argv[]) {
}
} else if (firstarg == "-ip" || firstarg == "--currentip") {
IPAPI ipapi;
std::cout << "Current global IP: " << ipapi.getGlobalIp() << std::endl;
const std::string ip = ipapi.getGlobalIp();
std::cout << "Current global IP: " << ip << std::endl;
} else {
Logger::message("wrong arguments! -h for help");
}
} else {
ConfigParser::loadConfig();
return 0;
Logger::message("starting check");
if (ConfigParser::loadConfig()) {
if (Config::readConfig()) {
IPRefresher::checkIPAdress(false);
} else {
std::cout << "incorrect credentials!" << std::endl;