diff options
author | Alex Borisov <borisov.alexandr@rambler.ru> | 2011-12-16 02:48:44 +0200 |
---|---|---|
committer | Alex Borisov <borisov.alexandr@rambler.ru> | 2011-12-16 02:48:44 +0200 |
commit | 897b78bc5000b7ae7a4a56d4072ef02b6bcec222 (patch) | |
tree | 2fb8c65c5112a2ab4261623c869ea08d30d69512 /client | |
parent | f77a7f9a1e282dba6e39f6b7f0685971cfac7747 (diff) |
XML reading/writing
Diffstat (limited to 'client')
-rw-r--r-- | client/Dialog.cpp | 3 | ||||
-rw-r--r-- | client/Proxifier.cpp | 454 | ||||
-rw-r--r-- | client/Proxifier.h | 90 |
3 files changed, 517 insertions, 30 deletions
diff --git a/client/Dialog.cpp b/client/Dialog.cpp index dfb280d..4c92a79 100644 --- a/client/Dialog.cpp +++ b/client/Dialog.cpp @@ -13,12 +13,13 @@ using namespace std; ProxyDialog::ProxyDialog(QWidget *parent): QDialog(parent) { UpdatedConfig *cfg = UpdatedConfig::CurrentConfig(); + Proxifier *proxifier = Proxifier::GetInstance(); if (!proxifier->IsValid()) { Logger::Fatal("No valid proxifier configuration file found!\n"); } - + /* generic proxy panel */ topLabel = new QLabel(QString::fromLocal8Bit(cfg->TopPanelText.c_str())); topLabel->setObjectName("topLabel"); diff --git a/client/Proxifier.cpp b/client/Proxifier.cpp index 5ef213d..84553f7 100644 --- a/client/Proxifier.cpp +++ b/client/Proxifier.cpp @@ -18,7 +18,7 @@ Proxifier::Chain::Chain(): id(0) } -Proxifier::Rule::Rule(): isEnabled(false), id(0) +Proxifier::Rule::Rule(): isEnabled(false), actId(0) { } @@ -37,7 +37,8 @@ Proxifier* Proxifier::GetInstance() Proxifier::Proxifier(): valid(false) { - Update(); + filename = "Default.ppx"; + ReadConfig(); } bool Proxifier::IsValid() @@ -45,23 +46,23 @@ bool Proxifier::IsValid() return valid; } -void Proxifier::Update() +void Proxifier::ReadConfig() { valid = false; - configDom = new QDomDocument("config"); - QFile config("Default.ppx"); + QDomDocument configDom("config"); + QFile config(filename); if (!config.open(QIODevice::ReadOnly)) { Logger::Error("Can't open Proxifier configuration file\n"); return; } - if (!configDom->setContent(&config)) + if (!configDom.setContent(&config)) { Logger::Fatal("Invalid Proxifier configuration file!"); return; } - QDomElement root = configDom->documentElement(); + QDomElement root = configDom.documentElement(); if (root.tagName() != "ProxifierProfile") { Logger::Fatal("Invalid Proxifier configuration file!"); @@ -73,28 +74,28 @@ void Proxifier::Update() */ // parse proxy list - if (!UpdateProxyList(root)) + if (!ReadProxyList(root)) { Logger::Fatal("Invalid Proxifier configuration file!"); return; } // parse chain list - if (!UpdateChainList(root)) + if (!ReadChainList(root)) { Logger::Fatal("Invalid Proxifier configuration file!"); return; } // parse rule list - if (!UpdateRuleList(root)) + if (!ReadRuleList(root)) { Logger::Fatal("Invalid Proxifier configuration file!"); return; } - + config.close(); valid = true; } -bool Proxifier::UpdateProxyList(QDomElement& root) +bool Proxifier::ReadProxyList(QDomElement& root) { Logger::Trace("Processing Proxifier proxy list\n"); QDomElement proxyListElem = root.firstChildElement("ProxyList"); @@ -157,6 +158,7 @@ bool Proxifier::UpdateProxyList(QDomElement& root) if (! authElem.hasChildNodes()) { // in case if "NTLM + userLogin" = selfclosing auth tag + Logger::Trace("Auth section is empty\n"); proxyRecord.emptyAuth = true; } else @@ -171,7 +173,8 @@ bool Proxifier::UpdateProxyList(QDomElement& root) } else { - Logger::Trace("Auth section is empty\n"); + Logger::Trace("Auth section is not present\n"); + proxyRecord.useAuth = false; } Logger::Trace("Found proxy in proxifier config: id=%d\n", proxyRecord.id); proxyList.push_back(proxyRecord); @@ -182,7 +185,7 @@ bool Proxifier::UpdateProxyList(QDomElement& root) return true; } -bool Proxifier::UpdateChainList(QDomElement& root) +bool Proxifier::ReadChainList(QDomElement& root) { Logger::Trace("Processing Proxifier chain list\n"); QDomElement chainListElem = root.firstChildElement("ChainList"); @@ -242,7 +245,7 @@ bool Proxifier::UpdateChainList(QDomElement& root) return true; } -bool Proxifier::UpdateRuleList(QDomElement& root) +bool Proxifier::ReadRuleList(QDomElement& root) { Logger::Trace("Processing Proxifier rule list\n"); QDomElement ruleListElem = root.firstChildElement("RuleList"); @@ -295,8 +298,8 @@ bool Proxifier::UpdateRuleList(QDomElement& root) QString actionTxt = actionElem.attribute("type"); if ((actionTxt == "Chain") || (actionTxt == "Proxy")) { - QString idTxt = actionElem.text(); - ruleRecord.id = idTxt.toInt(); + QString actIdTxt = actionElem.text(); + ruleRecord.actId = actIdTxt.toInt(); } ruleRecord.action = actionTxt.toStdString(); Logger::Trace("Found rule in proxifier config: name=%s\n", ruleRecord.name.c_str()); @@ -308,3 +311,420 @@ bool Proxifier::UpdateRuleList(QDomElement& root) return true; } + +int Proxifier::GetNextId() +{ + if (!valid) + { + return -1; + } + int max = 100; // first default proxifier ID + for (unsigned i = 0; i < proxyList.size(); i++) + { + if (proxyList[i].id > max) + { + max = proxyList[i].id; + } + } + for (unsigned i = 0; i < chainList.size(); i++) + { + if (chainList[i].id > max) + { + max = chainList[i].id; + } + } + return max; +} + +bool Proxifier::AddProxy(Proxy& proxy, int* id) +{ + Logger::Trace("Adding new proxy to Proxifier configuration\n"); + if (!valid) + { + Logger::Error("Current Proxifier configuration is not valid. Update first!\n"); + return false; + } + QDomDocument configDom("config"); + QFile config(filename); + if (!config.open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier configuration file\n"); + return false; + } + if (!configDom.setContent(&config)) + { + Logger::Fatal("Invalid Proxifier configuration file!"); + return false; + } + QDomElement root = configDom.documentElement(); + if (root.tagName() != "ProxifierProfile") + { + Logger::Error("Invalid Proxifier configuration file!"); + return false; + } + QDomElement proxyListElem = root.firstChildElement("ProxyList"); + if (proxyListElem.isNull()) + { + return false; + } + + // create proxy record + // root element + QDomElement proxyElem = configDom.createElement("Proxy"); + *id = GetNextId(); + if (*id == -1) + { + Logger::Error("Can't get valid ID number!\n"); + return false; + } + proxyElem.setAttribute("id", *id); + proxyElem.setAttribute("type", QString::fromLocal8Bit(proxy.type.c_str())); + // address element + QDomElement addrElem = configDom.createElement("Address"); + QDomText addrTxt = configDom.createTextNode(QString::fromLocal8Bit(proxy.host.c_str())); + addrElem.appendChild(addrTxt); + proxyElem.appendChild(addrElem); + // port element + QDomElement portElem = configDom.createElement("Port"); + QString portStr; + QDomText portTxt = configDom.createTextNode(portStr.setNum(proxy.port)); + portElem.appendChild(portTxt); + proxyElem.appendChild(portElem); + // option element + QDomElement optsElem = configDom.createElement("Options"); + QString optsStr; + QDomText optsTxt = configDom.createTextNode(optsStr.setNum(proxy.option)); + optsElem.appendChild(optsTxt); + proxyElem.appendChild(optsElem); + // auth element + if (proxy.useAuth) + { + QDomElement authElem = configDom.createElement("Authentication"); + authElem.setAttribute("enabled", "true"); + if (!proxy.emptyAuth) + { + // username + QDomElement userElem = configDom.createElement("Username"); + QDomText userTxt = configDom.createTextNode(QString::fromLocal8Bit(proxy.login.c_str())); + userElem.appendChild(userTxt); + authElem.appendChild(userElem); + // password + QDomElement passElem = configDom.createElement("Password"); + QDomText passTxt = configDom.createTextNode(QString::fromLocal8Bit(proxy.password.c_str())); + passElem.appendChild(passTxt); + authElem.appendChild(passElem); + } + proxyElem.appendChild(authElem); + } + proxyListElem.appendChild(proxyElem); + QTextStream(&config) << configDom.toString(indent); + config.close(); + return true; +} + +bool Proxifier::AddChain(string& name, int *id) +{ + QDomDocument configDom("config"); + QFile config(filename); + if (!config.open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier configuration file\n"); + return false; + } + if (!configDom.setContent(&config)) + { + Logger::Fatal("Invalid Proxifier configuration file!"); + return false; + } + QDomElement root = configDom.documentElement(); + if (root.tagName() != "ProxifierProfile") + { + Logger::Error("Invalid Proxifier configuration file!"); + return false; + } + QDomElement chainListElem = root.firstChildElement("ChainList"); + if (chainListElem.isNull()) + { + return false; + } + + QDomElement chainElem = configDom.createElement("Chain"); + *id = GetNextId(); + if (*id == -1) + { + Logger::Error("Can't get valid ID number!\n"); + return false; + } + chainElem.setAttribute("id", *id); + QDomElement nameElem = configDom.createElement("Name"); + QDomText nameTxt = configDom.createTextNode(QString::fromLocal8Bit(name.c_str())); + nameElem.appendChild(nameTxt); + chainElem.appendChild(nameElem); + chainListElem.appendChild(chainElem); + + QTextStream(&config) << configDom.toString(indent); + config.close(); + return true; +} + +bool Proxifier::AddChainProxy(int proxyId, int chainId) +{ + QDomDocument configDom("config"); + QFile config(filename); + if (!config.open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier configuration file\n"); + return false; + } + if (!configDom.setContent(&config)) + { + Logger::Fatal("Invalid Proxifier configuration file!"); + return false; + } + QDomElement root = configDom.documentElement(); + if (root.tagName() != "ProxifierProfile") + { + Logger::Error("Invalid Proxifier configuration file!"); + return false; + } + QDomElement chainListElem = root.firstChildElement("ChainList"); + if (chainListElem.isNull()) + { + return false; + } + + QDomElement chainElem = chainListElem.firstChildElement("Chain"); + while (!chainElem.isNull()) + { + bool ok; + if (!chainElem.hasAttribute("id")) + { + Logger::Error("Invalid Chain entry\n"); + chainElem = chainElem.nextSiblingElement("Chain"); + continue; + } + QString idStr = chainElem.attribute("id"); + int id = idStr.toInt(&ok); + if (!ok) + { + Logger::Error("Invalid Chain id\n"); + chainElem = chainElem.nextSiblingElement("Chain"); + continue; + } + if (id == chainId) + { + // chain found => add proxy + QDomElement proxyElem = configDom.createElement("Proxy"); + proxyElem.setAttribute("enabled", "true"); + QString idTxt; + idTxt.setNum(proxyId); + QDomText nameTxt = configDom.createTextNode(idTxt); + proxyElem.appendChild(nameTxt); + chainElem.appendChild(proxyElem); + break; + } + } + + QTextStream(&config) << configDom.toString(indent); + config.close(); + return true; +} + +bool Proxifier::RemoveChainProxy(int proxyId, int chainId) +{ + QDomDocument configDom("config"); + QFile config(filename); + if (!config.open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier configuration file\n"); + return false; + } + if (!configDom.setContent(&config)) + { + Logger::Fatal("Invalid Proxifier configuration file!"); + return false; + } + QDomElement root = configDom.documentElement(); + if (root.tagName() != "ProxifierProfile") + { + Logger::Error("Invalid Proxifier configuration file!"); + return false; + } + QDomElement chainListElem = root.firstChildElement("ChainList"); + if (chainListElem.isNull()) + { + return false; + } + + QDomElement chainElem = chainListElem.firstChildElement("Chain"); + while (!chainElem.isNull()) + { + bool ok; + if (!chainElem.hasAttribute("id")) + { + Logger::Error("Invalid Chain entry\n"); + chainElem = chainElem.nextSiblingElement("Chain"); + continue; + } + QString idStr = chainElem.attribute("id"); + int id = idStr.toInt(&ok); + if (!ok) + { + Logger::Error("Invalid Chain id\n"); + chainElem = chainElem.nextSiblingElement("Chain"); + continue; + } + if (id == chainId) + { + // chain found => find proxy + QDomElement proxyElem = chainElem.firstChildElement("Proxy"); + while (!proxyElem.isNull()) + { + QString idTxt = proxyElem.text(); + int id = idTxt.toInt(); + if (id == proxyId) + { + chainElem.removeChild(proxyElem); + break; + } + } + break; + } + } + + QTextStream(&config) << configDom.toString(indent); + config.close(); + return true; +} + + +bool Proxifier::AddRule(Rule& rule) +{ + QDomDocument configDom("config"); + QFile config(filename); + if (!config.open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier configuration file\n"); + return false; + } + if (!configDom.setContent(&config)) + { + Logger::Fatal("Invalid Proxifier configuration file!"); + return false; + } + QDomElement root = configDom.documentElement(); + if (root.tagName() != "ProxifierProfile") + { + Logger::Error("Invalid Proxifier configuration file!"); + return false; + } + QDomElement ruleListElem = root.firstChildElement("RuleList"); + if (ruleListElem.isNull()) + { + return false; + } + + QDomElement ruleElem = configDom.createElement("Rule"); + if (rule.isEnabled) + { + ruleElem.setAttribute("enabled", "true"); + } + else + { + ruleElem.setAttribute("enabled", "false"); + } + // name element + QDomElement nameElem = configDom.createElement("Name"); + QDomText nameTxt = configDom.createTextNode(QString::fromLocal8Bit(rule.name.c_str())); + nameElem.appendChild(nameTxt); + ruleElem.appendChild(nameElem); + // applications element + if (! rule.apps.empty()) + { + QDomElement appsElem = configDom.createElement("Applications"); + QDomText appsTxt = configDom.createTextNode(QString::fromLocal8Bit(rule.apps.c_str())); + appsElem.appendChild(appsTxt); + ruleElem.appendChild(appsElem); + } + // targets element + if (! rule.targets.empty()) + { + QDomElement targetsElem = configDom.createElement("Applications"); + QDomText targetsTxt = configDom.createTextNode(QString::fromLocal8Bit(rule.targets.c_str())); + targetsElem.appendChild(targetsTxt); + ruleElem.appendChild(targetsElem); + } + // ports element + if (! rule.targets.empty()) + { + QDomElement portsElem = configDom.createElement("Ports"); + QDomText portsTxt = configDom.createTextNode(QString::fromLocal8Bit(rule.ports.c_str())); + portsElem.appendChild(portsTxt); + ruleElem.appendChild(portsElem); + } + // action element + if (rule.action.empty()) + { + Logger::Error("Invalid action value: %s\n", rule.action.c_str()); + return false; + } + QDomElement actionElem = configDom.createElement("Action"); + QString actionType = QString::fromLocal8Bit(rule.action.c_str()); + actionElem.setAttribute("type", actionType); + if ((actionType == "Chain") || (actionType == "Proxy")) + { + QString actionId; + actionId.setNum(rule.actId); + QDomText portsTxt = configDom.createTextNode(actionId); + } + ruleElem.appendChild(actionElem); + + QTextStream(&config) << configDom.toString(indent); + config.close(); + return true; +} + +bool Proxifier::RemoveRule(string name) +{ + // !names only compared! + QDomDocument configDom("config"); + QFile config(filename); + if (!config.open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier configuration file\n"); + return false; + } + if (!configDom.setContent(&config)) + { + Logger::Fatal("Invalid Proxifier configuration file!"); + return false; + } + QDomElement root = configDom.documentElement(); + if (root.tagName() != "ProxifierProfile") + { + Logger::Error("Invalid Proxifier configuration file!"); + return false; + } + QDomElement ruleListElem = root.firstChildElement("ChainList"); + if (ruleListElem.isNull()) + { + return false; + } + + QDomElement ruleElem = ruleListElem.firstChildElement("Rule"); + while (!ruleElem.isNull()) + { + QDomElement nameElem = ruleElem.firstChildElement("Name"); + QString nameStr = nameElem.text(); + if (nameStr == QString::fromLocal8Bit(name.c_str())) + { + ruleListElem.removeChild(ruleElem); + break; + } + } + + QTextStream(&config) << configDom.toString(indent); + config.close(); + return true; +} + diff --git a/client/Proxifier.h b/client/Proxifier.h index 37ea3fd..320ba44 100644 --- a/client/Proxifier.h +++ b/client/Proxifier.h @@ -6,6 +6,7 @@ #include <vector> #include <string> #include <QDomElement> +#include <QString> using namespace std; @@ -29,8 +30,9 @@ public: // proxifier-specific fields int id; short option; - bool emptyAuth; - + bool useAuth; // whether to authenticate on server + bool emptyAuth; // self-closing auth (for Proxifier it means to use current login+pass) + Proxy(); }; @@ -86,29 +88,93 @@ public: /** * @brief action parameter (applicable only to 'Chain' and 'Proxy' actions) */ - int id; + int actId; Rule(); }; - static Proxifier* GetInstance(); + + /** + * @brief Chack if the current config is valid + * @return true if the config is valid or false otherwise + * @note you may wish to try ReadConfig() before but if it doesn't help + */ bool IsValid(); - void Update(); - + /** + * @brief read Proxifier config from file and parse it + * @note you should check IsValid() method to get to know if the config is valid + */ + void ReadConfig(); + private: + /** + * @brief XML indentation level + */ + static const int indent = 4; + /** + * @brief pointer to sigleton instance + */ static Proxifier *instance; - + /** + * @brief XML file name to read data from + */ + QString filename; bool valid; - QDomDocument *configDom; vector<Proxy> proxyList; vector<Chain> chainList; vector<Rule> ruleList; - + Proxifier(); - bool UpdateProxyList(QDomElement& root); - bool UpdateChainList(QDomElement& root); - bool UpdateRuleList(QDomElement& root); + bool ReadProxyList(QDomElement& root); + bool ReadChainList(QDomElement& root); + bool ReadRuleList(QDomElement& root); + /** + * @brief gets the next valid ID fo proxy/chain + * @note this ID numbers are shared among chains and proxies + * @return next valid ID number + */ + int GetNextId(); + /** + * @brief add new proxy record to Proxifier config + * @param proxy proxy class representing Proxifier's proxy entry + * id new proxy id will be set there + * @return true on success or false otherwise + */ + bool AddProxy(Proxy& proxy, int* id); + /** + * @brief add new chain to proxifier config + * @param name the name of the chain + * id new chain id + * @return true on success or false otherwise + */ + bool AddChain(string& name, int *id); + /** + * @brief add proxy to proxy chain + * @param proxyId proxy ID to add to proxy chain + * chainId chain ID to add proxy to + * @return true on success or false otherwise + */ + bool AddChainProxy(int proxyId, int chainId); + /** + * @brief remove proxy from proxy chain + * @param proxyId proxy ID to remove to proxy chain + * chainId chain ID to remove proxy from + * @return true on success or false otherwise + */ + bool RemoveChainProxy(int proxyId, int chainId); + /** + * @brief add new rule to Proxifier config + * @param rule rule class representing Proxifier's rule entry + * @return true on success or false otherwise + */ + bool AddRule(Rule& rule); + /** + * @brief remove rule to Proxifier config + * @param name name of the rule to remove from Rule list + * @return true on success or false otherwise + */ + bool RemoveRule(string name); }; #endif |