diff options
Diffstat (limited to 'client')
-rw-r--r-- | client/Config.cpp | 16 | ||||
-rw-r--r-- | client/Config.h | 34 | ||||
-rw-r--r-- | client/Dialog.cpp | 40 | ||||
-rw-r--r-- | client/Dialog.h | 3 | ||||
-rw-r--r-- | client/Proxifier.cpp | 521 | ||||
-rw-r--r-- | client/Proxifier.h | 140 | ||||
-rw-r--r-- | client/UpdatedConfig.cpp | 2 |
7 files changed, 631 insertions, 125 deletions
diff --git a/client/Config.cpp b/client/Config.cpp index 38ff50f..489818e 100644 --- a/client/Config.cpp +++ b/client/Config.cpp @@ -201,6 +201,18 @@ vector<string> Config::GetProxies(string &country, string &state, string &city) return proxies; } +ProxyEntryStatic* Config::GetStaticProxy(string& name) +{ + for (unsigned i = 0; i < staticProxy.size(); i++) + { + if (name.compare(staticProxy[i].name) == 0) + { + return &staticProxy[i]; + } + } + return NULL; +} + vector<ProxyEntryStatic> Config::GetStaticProxyGuiLine(unsigned line) { vector<ProxyEntryStatic> staticProxyLine; @@ -349,7 +361,7 @@ void Config::ParseGenericProxies(string data) } } -void Config::ParseStaticPorxies(string data) +void Config::ParseStaticProxies(string data) { /* clear previous proxies */ staticProxy.clear(); @@ -491,6 +503,6 @@ void Config::ReadStaticProxy() proxyFile.read (buffer, length); proxyFile.close(); string proxies = buffer; - ParseStaticPorxies(proxies); + ParseStaticProxies(proxies); delete[] buffer; } diff --git a/client/Config.h b/client/Config.h index 5254361..f7653e0 100644 --- a/client/Config.h +++ b/client/Config.h @@ -140,7 +140,7 @@ public: * @return Alphabetically sorted vector<string> with unique state names.<br/> * Resultant vector<string> may be empty in case if there are no states in specified country */ - vector<string> GetStates(std::string &country); + vector<string> GetStates(string &country); /** * @brief Get list of cities in particular country without states<br/> @@ -179,12 +179,19 @@ public: vector<string> GetProxies(string &country, string &state, string &city); /** + * @brief Get static proxy entry by name + * @param name static proxy name + * @return ProxyEntryStatic object on success or false otherwise + */ + ProxyEntryStatic* GetStaticProxy(string& name); + + /** * @brief Get list of static proxy entries * @param line number of GUI line proxy list associated with * @return List of static proxy entries sorted by speed in descending order */ vector<ProxyEntryStatic> GetStaticProxyGuiLine(unsigned line); - + /** * @brief Get number of static proxy GUI lines * @return number of static proxy GUI lines or 0 if none @@ -245,53 +252,50 @@ protected: */ unsigned retryTimeout; }; - + + /** + * @brief array of config server entries + */ + vector<ServerEntry> servers; + /** + * @brief time between subsequent config updates + */ + unsigned updateInterval; /** * @brief create new instance (not allowed for use by other classes and functions) */ Config(); - /** * @brief parse client configuration * @param data string containing configuration parameters */ void ParseConfig(string data); - /** * @brief parse list of generic proxies * @param data string containing list of ProxyEntryGeneric records */ void ParseGenericProxies(string data); - /** * @brief parse list of static proxies * @param data string containing list of ProxyEntryStatic records */ - void ParseStaticPorxies(string data); - + void ParseStaticProxies(string data); /** * @brief parse firewall configuration * @param data string containing list of FirewallEntry records */ void ParseFirewalls(string data); - /** * @brief parse list of file to be deleted * @param data string containing path to aforementioned file */ void ParseDeleteList(string data); - /** * @brief parse list of files to be downloaded * @param data string containing path to new file and it's md5 hash */ void ParseDownloadList(string data); - /** - * @brief time between subsequent config updates - */ - unsigned updateInterval; - vector<ServerEntry> servers; private: vector<ProxyEntryGeneric> genericProxy; vector<ProxyEntryStatic> staticProxy; diff --git a/client/Dialog.cpp b/client/Dialog.cpp index 4c92a79..279bfc8 100644 --- a/client/Dialog.cpp +++ b/client/Dialog.cpp @@ -52,7 +52,7 @@ ProxyDialog::ProxyDialog(QWidget *parent): QDialog(parent) genericProxyGroup = new QButtonGroup; staticProxyGroup = new QButtonGroup; - /* static proxy panel */ + // static proxy panel bottomLabel = new QLabel(QString::fromLocal8Bit(cfg->BottomPanelText.c_str())); bottomLabel->setObjectName("bottomLabel"); bottomLabel->setAlignment(Qt::AlignHCenter); @@ -91,7 +91,10 @@ ProxyDialog::ProxyDialog(QWidget *parent): QDialog(parent) QPushButton *btn = new QPushButton(); btn->setObjectName("bottomBtn"); btn->setCheckable(true); + btn->setChecked(proxifier->IsOn(staticProxyLine[j].host, staticProxyLine[j].port)); + btn->setProperty("proxyName", QString::fromLocal8Bit(staticProxyLine[j].name.c_str())); btn->setLayout(btnLayout); + connect(btn, SIGNAL(toggled(bool)), this, SLOT(StaticToggled(bool))); staticProxyGroup->addButton(btn); bottomPanelLayout->addWidget(btn, i, j); } @@ -106,14 +109,35 @@ ProxyDialog::ProxyDialog(QWidget *parent): QDialog(parent) setLayout(mainLayout); } -void ProxyDialog::StaticToggle(bool val) +void ProxyDialog::StaticToggled(bool on) { - Logger::Debug("toggle: %s\n", val ? "true" : "false"); -} - -void ProxyDialog::StaticClick() -{ - Logger::Debug("click\n"); + QPushButton* btn = (QPushButton*) sender(); + QVariant propVal = btn->property("proxyName"); + QString proxyName = propVal.toString(); + Logger::Debug("Static Proxy button toggled\n"); + Logger::Debug("State '%s', associated proxy name: %s\n", on ? "down" : "up", proxyName.toStdString().c_str()); + + UpdatedConfig *cfg = UpdatedConfig::CurrentConfig(); + string name = proxyName.toStdString(); + ProxyEntryStatic* proxy = cfg->GetStaticProxy(name); + if (proxy == NULL) + { + Logger::Error("Static proxy with name '%s' was not found\n", proxyName.toStdString().c_str()); + return; + } + Proxifier *proxifier = Proxifier::GetInstance(); + if (!proxifier->IsValid()) + { + Logger::Fatal("No valid proxifier configuration file found!\n"); + } + if (on) + { + proxifier->TurnProxyOn(*proxy); + } + else + { + proxifier->TurnProxyOff(*proxy); + } } void ProxyDialog::CountryActivated(int index) diff --git a/client/Dialog.h b/client/Dialog.h index e3be343..8fd5aff 100644 --- a/client/Dialog.h +++ b/client/Dialog.h @@ -30,8 +30,7 @@ private slots: void StateActivated(int index); void CityActivated(int index); - void StaticToggle(bool toggle); - void StaticClick(); + void StaticToggled(bool toggle); private: QButtonGroup *genericProxyGroup; QButtonGroup *staticProxyGroup; diff --git a/client/Proxifier.cpp b/client/Proxifier.cpp index 84553f7..c8e7cf8 100644 --- a/client/Proxifier.cpp +++ b/client/Proxifier.cpp @@ -4,11 +4,13 @@ #include "Logger.h" #include "Proxifier.h" +// static field initialization +string Proxifier::defaultChain = "Client"; +string Proxifier::defaultRule = "Default"; +Proxifier* Proxifier::instance = NULL; -Proxifier* Proxifier::instance = NULL; - -Proxifier::Proxy::Proxy(): port(0), id(0), option(0), emptyAuth(true) +Proxifier::ProxifierProxy::ProxifierProxy(): id(0), option(0), emptyAuth(true) { } @@ -46,6 +48,172 @@ bool Proxifier::IsValid() return valid; } +bool Proxifier::IsOn(string& addr, short port) +{ + // at first proxy should be in proxy list + int proxyId = 0; + if (!isProxyExists(addr, port, &proxyId)) + { + return false; + } + // next - check for "Client" chain + int chainId; + if (!isChainExists(defaultChain, &chainId)) + { + return false; + } + // and next - find chain by id + for (unsigned i = 0; chainList.size(); i++) + { + if (chainList[i].id == chainId) + { + map<int, bool>::iterator it = chainList[i].proxies.find(proxyId); + if (it == chainList[i].proxies.end()) + { + return false; + } + return it->second; + } + } + return false; +} + +bool Proxifier::TurnProxyOn(Proxy& proxy) +{ + if (!valid) + { + return false; + } + // if proxy do not exist - add it + int proxyId = 0; + if (!isProxyExists(proxy.host, proxy.port, &proxyId)) + { + ProxifierProxy _proxy; + _proxy.login = proxy.login; + _proxy.password = proxy.password; + _proxy.host = proxy.host; + _proxy.port = proxy.port; + _proxy.type = proxy.type; + // default values for Proxifier Proxy record + _proxy.option = 0; + _proxy.useAuth = !proxy.login.empty(); + _proxy.emptyAuth = false; + if (!AddProxy(_proxy, &proxyId)) + { + return false; + } + } + // if "Client" chain do not exist - add it + int chainId = 0; + if (!isChainExists(defaultChain, &chainId)) + { + if (!AddChain(defaultChain, &chainId)) + { + return false; + } + } + + // try to find proxy in chain + for (unsigned i = 0; i < chainList.size(); i++) + { + if (chainList[i].name.compare(defaultChain) != 0) + { + continue; + } + + map<int, bool>::iterator it = chainList[i].proxies.find(proxyId); + if (it != chainList[i].proxies.end()) + { + if (!it->second) + { + // proxy is not enabled - remove it and add again + RemoveProxyFromChain(proxyId, chainId); + AddProxyToChain(proxyId, chainId); + } + } + else + { + // proxy not found in the target chain - add it + AddProxyToChain(proxyId, chainId); + } + } + + if (isRuleExists(defaultRule)) + { + // the "Default" rule can't be disabled from Proxifier's UI + // so we can skip this check here + string action = "Chain"; + if (!SetRuleAction(defaultRule, action, chainId)) + { + return false; + } + } + else + { + Rule rule; + rule.isEnabled = true; + rule.name = defaultRule; + rule.action = "Chain"; + rule.actId = chainId; + if (!AddRule(rule)) + { + return false; + } + } + return true; +} + +bool Proxifier::TurnProxyOff(Proxy& proxy) +{ + if (!valid) + { + return false; + } + // check if proxy do not exist + int proxyId = 0; + if (!isProxyExists(proxy.host, proxy.port, &proxyId)) + { + return true; + } + int chainId = 0; + if (!isChainExists(defaultChain, &chainId)) + { + return true; + } + // try to find proxy in chain + bool isFound = false; + for (unsigned i = 0; i < chainList.size(); i++) + { + if (chainList[i].name.compare(defaultChain) != 0) + { + continue; + } + + map<int, bool>::iterator it = chainList[i].proxies.find(proxyId); + if (it != chainList[i].proxies.end()) + { + isFound = true; + // if it was the last proxy in chain - change default rule + if (chainList[i].proxies.size() == 1) + { + string action = "Direct"; + SetRuleAction(defaultRule, action); + } + RemoveProxyFromChain(proxyId, chainId); + // update config to reflect last changes + ReadConfig(); + break; + } + } + if (!isFound) + { + return true; + } + + return true; +} + + void Proxifier::ReadConfig() { valid = false; @@ -53,19 +221,19 @@ void Proxifier::ReadConfig() QFile config(filename); if (!config.open(QIODevice::ReadOnly)) { - Logger::Error("Can't open Proxifier configuration file\n"); + Logger::Error("Can't open Proxifier config file\n"); return; } if (!configDom.setContent(&config)) { - Logger::Fatal("Invalid Proxifier configuration file!"); + Logger::Fatal("Invalid Proxifier config file!\n"); return; } QDomElement root = configDom.documentElement(); if (root.tagName() != "ProxifierProfile") { - Logger::Fatal("Invalid Proxifier configuration file!"); + Logger::Fatal("Invalid Proxifier config file!\n"); return; } QDomElement options = root.firstChildElement("Options"); @@ -76,19 +244,19 @@ void Proxifier::ReadConfig() // parse proxy list if (!ReadProxyList(root)) { - Logger::Fatal("Invalid Proxifier configuration file!"); + Logger::Fatal("Invalid Proxifier config file!\n"); return; } // parse chain list if (!ReadChainList(root)) { - Logger::Fatal("Invalid Proxifier configuration file!"); + Logger::Fatal("Invalid Proxifier configfile!\n"); return; } // parse rule list if (!ReadRuleList(root)) { - Logger::Fatal("Invalid Proxifier configuration file!"); + Logger::Fatal("Invalid Proxifier config file!\n"); return; } config.close(); @@ -109,7 +277,7 @@ bool Proxifier::ReadProxyList(QDomElement& root) while (!proxy.isNull()) { bool ok = true; // used when converting values to int - Proxy proxyRecord; + ProxifierProxy proxyRecord; // check whether attributes are present if (! (proxy.hasAttribute("id") && proxy.hasAttribute("type"))) @@ -155,7 +323,7 @@ bool Proxifier::ReadProxyList(QDomElement& root) QDomElement authElem = proxy.firstChildElement("Authentication"); if (!authElem.isNull()) { - if (! authElem.hasChildNodes()) + if (!authElem.hasChildNodes()) { // in case if "NTLM + userLogin" = selfclosing auth tag Logger::Trace("Auth section is empty\n"); @@ -312,6 +480,7 @@ bool Proxifier::ReadRuleList(QDomElement& root) return true; } + int Proxifier::GetNextId() { if (!valid) @@ -333,33 +502,32 @@ int Proxifier::GetNextId() max = chainList[i].id; } } - return max; + return max + 1; } -bool Proxifier::AddProxy(Proxy& proxy, int* id) +bool Proxifier::AddProxy(ProxifierProxy& 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; - } + Logger::Trace("Adding new proxy to Proxifier config\n"); + // read XML DOM structure QDomDocument configDom("config"); - QFile config(filename); - if (!config.open(QIODevice::WriteOnly)) + QFile* config = new QFile(filename); + if (!config->open(QIODevice::ReadOnly)) { - Logger::Error("Can't open Proxifier configuration file\n"); + Logger::Error("Can't open Proxifier config file for reading\n"); return false; } - if (!configDom.setContent(&config)) + if (!configDom.setContent(config)) { - Logger::Fatal("Invalid Proxifier configuration file!"); + Logger::Fatal("Invalid Proxifier config file!\n"); return false; } + config->close(); + delete config; + QDomElement root = configDom.documentElement(); if (root.tagName() != "ProxifierProfile") { - Logger::Error("Invalid Proxifier configuration file!"); + Logger::Error("Invalid Proxifier config file!\n"); return false; } QDomElement proxyListElem = root.firstChildElement("ProxyList"); @@ -367,7 +535,6 @@ bool Proxifier::AddProxy(Proxy& proxy, int* id) { return false; } - // create proxy record // root element QDomElement proxyElem = configDom.createElement("Proxy"); @@ -417,29 +584,45 @@ bool Proxifier::AddProxy(Proxy& proxy, int* id) proxyElem.appendChild(authElem); } proxyListElem.appendChild(proxyElem); - QTextStream(&config) << configDom.toString(indent); - config.close(); + // update state to reflect all the changes + ReadProxyList(root); + + // save new DOM to file + config = new QFile(filename); + if (!config->open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier config file for writing\n"); + return false; + } + QTextStream(config) << configDom.toString(indent); + config->close(); + delete config; return true; } bool Proxifier::AddChain(string& name, int *id) { + Logger::Trace("Adding new chain to Proxifier config\n"); + // read XML DOM structure QDomDocument configDom("config"); - QFile config(filename); - if (!config.open(QIODevice::WriteOnly)) + QFile* config = new QFile(filename); + if (!config->open(QIODevice::ReadOnly)) { - Logger::Error("Can't open Proxifier configuration file\n"); + Logger::Error("Can't open Proxifier config file\n"); return false; } - if (!configDom.setContent(&config)) + if (!configDom.setContent(config)) { - Logger::Fatal("Invalid Proxifier configuration file!"); + Logger::Fatal("Invalid Proxifier config file!\n"); return false; } + config->close(); + delete config; + QDomElement root = configDom.documentElement(); if (root.tagName() != "ProxifierProfile") { - Logger::Error("Invalid Proxifier configuration file!"); + Logger::Error("Invalid Proxifier config file!\n"); return false; } QDomElement chainListElem = root.firstChildElement("ChainList"); @@ -461,30 +644,45 @@ bool Proxifier::AddChain(string& name, int *id) nameElem.appendChild(nameTxt); chainElem.appendChild(nameElem); chainListElem.appendChild(chainElem); + // update state to reflect all the changes + ReadChainList(root); - QTextStream(&config) << configDom.toString(indent); - config.close(); + // save new DOM to file + config = new QFile(filename); + if (!config->open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier config file for writing\n"); + return false; + } + QTextStream(config) << configDom.toString(indent); + config->close(); + delete config; return true; } -bool Proxifier::AddChainProxy(int proxyId, int chainId) +bool Proxifier::AddProxyToChain(int proxyId, int chainId) { + Logger::Trace("Adding proxy to chain in Proxifier config\n"); + // read XML DOM structure QDomDocument configDom("config"); - QFile config(filename); - if (!config.open(QIODevice::WriteOnly)) + QFile* config = new QFile(filename); + if (!config->open(QIODevice::ReadOnly)) { - Logger::Error("Can't open Proxifier configuration file\n"); + Logger::Error("Can't open Proxifier config file\n"); return false; } - if (!configDom.setContent(&config)) + if (!configDom.setContent(config)) { - Logger::Fatal("Invalid Proxifier configuration file!"); + Logger::Fatal("Invalid Proxifier config file!\n"); return false; } + config->close(); + delete config; + QDomElement root = configDom.documentElement(); if (root.tagName() != "ProxifierProfile") { - Logger::Error("Invalid Proxifier configuration file!"); + Logger::Error("Invalid Proxifier config file!\n"); return false; } QDomElement chainListElem = root.firstChildElement("ChainList"); @@ -524,30 +722,45 @@ bool Proxifier::AddChainProxy(int proxyId, int chainId) break; } } + // update state to reflect all the changes + ReadChainList(root); - QTextStream(&config) << configDom.toString(indent); - config.close(); + // save new DOM to file + config = new QFile(filename); + if (!config->open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier config file for writing\n"); + return false; + } + QTextStream(config) << configDom.toString(indent); + config->close(); + delete config; return true; } -bool Proxifier::RemoveChainProxy(int proxyId, int chainId) +bool Proxifier::RemoveProxyFromChain(int proxyId, int chainId) { + Logger::Trace("Removing proxy from chain in Proxifier config\n"); + // read XML DOM structure QDomDocument configDom("config"); - QFile config(filename); - if (!config.open(QIODevice::WriteOnly)) + QFile* config = new QFile(filename); + if (!config->open(QIODevice::ReadOnly)) { Logger::Error("Can't open Proxifier configuration file\n"); return false; } - if (!configDom.setContent(&config)) + if (!configDom.setContent(config)) { - Logger::Fatal("Invalid Proxifier configuration file!"); + Logger::Fatal("Invalid Proxifier configuration file!\n"); return false; } + config->close(); + delete config; + QDomElement root = configDom.documentElement(); if (root.tagName() != "ProxifierProfile") { - Logger::Error("Invalid Proxifier configuration file!"); + Logger::Error("Invalid Proxifier configuration file!\n"); return false; } QDomElement chainListElem = root.firstChildElement("ChainList"); @@ -591,31 +804,46 @@ bool Proxifier::RemoveChainProxy(int proxyId, int chainId) break; } } + // update state to reflect all the changes + ReadChainList(root); - QTextStream(&config) << configDom.toString(indent); - config.close(); + // save new DOM to file + config = new QFile(filename); + if (!config->open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier config file for writing\n"); + return false; + } + QTextStream(config) << configDom.toString(indent); + config->close(); + delete config; return true; } bool Proxifier::AddRule(Rule& rule) { + Logger::Trace("Adding rules to Proxifier config\n"); + // read XML DOM structure QDomDocument configDom("config"); - QFile config(filename); - if (!config.open(QIODevice::WriteOnly)) + QFile* config = new QFile(filename); + if (!config->open(QIODevice::ReadOnly)) { - Logger::Error("Can't open Proxifier configuration file\n"); + Logger::Error("Can't open Proxifier config file\n"); return false; } - if (!configDom.setContent(&config)) + if (!configDom.setContent(config)) { - Logger::Fatal("Invalid Proxifier configuration file!"); + Logger::Fatal("Invalid Proxifier config file!\n"); return false; } + config->close(); + delete config; + QDomElement root = configDom.documentElement(); if (root.tagName() != "ProxifierProfile") { - Logger::Error("Invalid Proxifier configuration file!"); + Logger::Error("Invalid Proxifier config file!\n"); return false; } QDomElement ruleListElem = root.firstChildElement("RuleList"); @@ -678,31 +906,118 @@ bool Proxifier::AddRule(Rule& rule) QDomText portsTxt = configDom.createTextNode(actionId); } ruleElem.appendChild(actionElem); + // update state to reflect all the changes + ReadRuleList(root); - QTextStream(&config) << configDom.toString(indent); - config.close(); + // save new DOM to file + config = new QFile(filename); + if (!config->open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier config file for writing\n"); + return false; + } + QTextStream(config) << configDom.toString(indent); + config->close(); + delete config; return true; } -bool Proxifier::RemoveRule(string name) +bool Proxifier::SetRuleAction(string& name, string& action, int actId) { // !names only compared! + Logger::Trace("Setting rule action in Proxifier config\n"); + // read XML DOM structure QDomDocument configDom("config"); - QFile config(filename); - if (!config.open(QIODevice::WriteOnly)) + QFile* config = new QFile(filename); + if (!config->open(QIODevice::ReadWrite)) { Logger::Error("Can't open Proxifier configuration file\n"); return false; } - if (!configDom.setContent(&config)) + if (!configDom.setContent(config)) + { + Logger::Fatal("Invalid Proxifier configuration file!\n"); + return false; + } + config->close(); + delete config; + + QDomElement root = configDom.documentElement(); + if (root.tagName() != "ProxifierProfile") + { + Logger::Error("Invalid Proxifier configuration file!\n"); + 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())) + { + // remove old + QDomElement oldActionElem = ruleElem.firstChildElement("Action"); + ruleElem.removeChild(oldActionElem); + // add new + QDomElement newActionElem = configDom.createElement("Action"); + QString actionType = QString::fromLocal8Bit(action.c_str()); + newActionElem.setAttribute("type", actionType); + if ((actionType == "Chain") || (actionType == "Proxy")) + { + QString actionId; + actionId.setNum(actId); + QDomText portsTxt = configDom.createTextNode(actionId); + } + ruleElem.appendChild(newActionElem); + break; + } + } + // update state to reflect all the changes + ReadRuleList(root); + + // save new DOM to file + config = new QFile(filename); + if (!config->open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier config file for writing\n"); + return false; + } + QTextStream(config) << configDom.toString(indent); + config->close(); + delete config; + return true; +} + +bool Proxifier::RemoveRule(string& name) +{ + // !names only compared! + Logger::Trace("Removing rule from Proxifier config\n"); + // read XML DOM structure + QDomDocument configDom("config"); + QFile* config = new QFile(filename); + if (!config->open(QIODevice::ReadWrite)) { - Logger::Fatal("Invalid Proxifier configuration file!"); + Logger::Error("Can't open Proxifier configuration file\n"); return false; } + if (!configDom.setContent(config)) + { + Logger::Fatal("Invalid Proxifier configuration file!\n"); + return false; + } + config->close(); + delete config; + QDomElement root = configDom.documentElement(); if (root.tagName() != "ProxifierProfile") { - Logger::Error("Invalid Proxifier configuration file!"); + Logger::Error("Invalid Proxifier configuration file!\n"); return false; } QDomElement ruleListElem = root.firstChildElement("ChainList"); @@ -722,9 +1037,77 @@ bool Proxifier::RemoveRule(string name) break; } } + // update state to reflect all the changes + ReadRuleList(root); - QTextStream(&config) << configDom.toString(indent); - config.close(); + // save new DOM to file + config = new QFile(filename); + if (!config->open(QIODevice::WriteOnly)) + { + Logger::Error("Can't open Proxifier config file for writing\n"); + return false; + } + QTextStream(config) << configDom.toString(indent); + config->close(); + delete config; return true; } +bool Proxifier::isProxyExists(string& addr, short port, int *id) +{ + if (!valid) + { + return false; + } + for (unsigned i = 0; i < proxyList.size(); i++) + { + ProxifierProxy proxy = proxyList[i]; + if ((addr.compare(proxy.host) == 0) && (port == proxy.port)) + { + if (id != NULL) + { + *id = proxy.id; + } + return true; + } + } + return false; +} + +bool Proxifier::isChainExists(string& name, int* id) +{ + if (!valid) + { + return false; + } + for (unsigned i = 0; i < chainList.size(); i++) + { + Chain chain = chainList[i]; + if (name.compare(chain.name) == 0) + { + if (id != NULL) + { + *id = chain.id; + } + return true; + } + } + return false; +} + +bool Proxifier::isRuleExists(string& name) +{ + if (!valid) + { + return false; + } + for (unsigned i = 0; i < ruleList.size(); i++) + { + Rule rule = ruleList[i]; + if (name.compare(rule.name) == 0) + { + return true; + } + } + return false; +} diff --git a/client/Proxifier.h b/client/Proxifier.h index 320ba44..af27b80 100644 --- a/client/Proxifier.h +++ b/client/Proxifier.h @@ -7,33 +7,71 @@ #include <string> #include <QDomElement> #include <QString> +#include "Proxy.h" + using namespace std; class QDomDocument; +class Proxy; +/** + * @brief Special class that represents proxifier's configuration file + * @note All operation that turn on/off and add/remove proxies and chain will apply to "Default" rule + * All proxies are put into "Client" chain event if it's only one proxy + */ class Proxifier { public: /** + * @brief Get application-wide singleton instance of Proxifier class + * @return pointer to Proxifier singleton + */ + 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(); + /** + * @brief Check if certain server is turned on in Proxifier's tules and list + */ + bool IsOn(string& addr, short port); + /** + * @brief turn proxy on, all traffic will go throught this proxy + * @param proxy Proxy class that represents particular proxy + * @return true on success or false otherwise + * @note adds specified proxy to Proxifier's Proxy list and in "Client" chain<br/> + * Also adds "Client" chain to "Default" rule if its not there + */ + bool TurnProxyOn(Proxy& proxy); + /** + * @brief turn proxy off + * @param proxy Proxy class that represents particular proxy + * @return true on success or false otherwise<br/> + * alse true will be returned even if proxy is not exist in config + * @note removes specified proxy from "Client" chain and from Proxy list<br/> + * If its the last proxy in client chain then "Default" rule will be resetted to<br/> + * send all traffic directly to servers + */ + bool TurnProxyOff(Proxy& proxy); + +private: + /** * @brief class representing Proxifier's proxy setting */ - class Proxy + class ProxifierProxy: public Proxy { public: - string login; - string password; - string host; - string type; - short port; - // proxifier-specific fields int id; short option; bool useAuth; // whether to authenticate on server bool emptyAuth; // self-closing auth (for Proxifier it means to use current login+pass) - Proxy(); + ProxifierProxy(); }; /** @@ -92,26 +130,18 @@ public: 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 + * @brief XML indentation level */ - bool IsValid(); + static const int indent = 4; /** - * @brief read Proxifier config from file and parse it - * @note you should check IsValid() method to get to know if the config is valid + * @brief default chain name to add proxies to */ - void ReadConfig(); - -private: + static string defaultChain; /** - * @brief XML indentation level + * @brief default rule name to add proxies to */ - static const int indent = 4; + static string defaultRule; /** * @brief pointer to sigleton instance */ @@ -120,14 +150,37 @@ private: * @brief XML file name to read data from */ QString filename; + /** + * @brief indicates whether config valid or not + */ bool valid; - vector<Proxy> proxyList; + vector<ProxifierProxy> proxyList; vector<Chain> chainList; vector<Rule> ruleList; Proxifier(); + /** + * @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(); + /** + * @brief read ProxyList section in Proxifier's config + * @param root root DOM element + * @return true on success or false otherwise + */ bool ReadProxyList(QDomElement& root); + /** + * @brief read ChainList section in Proxifier's config + * @param root root DOM element + * @return true on success or false otherwise + */ bool ReadChainList(QDomElement& root); + /** + * @brief read RuleList section in Proxifier's config + * @param root root DOM element + * @return true on success or false otherwise + */ bool ReadRuleList(QDomElement& root); /** * @brief gets the next valid ID fo proxy/chain @@ -141,28 +194,28 @@ private: * id new proxy id will be set there * @return true on success or false otherwise */ - bool AddProxy(Proxy& proxy, int* id); + bool AddProxy(ProxifierProxy& 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); + 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); + bool AddProxyToChain(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); + bool RemoveProxyFromChain(int proxyId, int chainId); /** * @brief add new rule to Proxifier config * @param rule rule class representing Proxifier's rule entry @@ -170,11 +223,42 @@ private: */ bool AddRule(Rule& rule); /** + * @brief modify action on existing rule + * @param name name of the rule to modify + * action action name to set to + * actId id of action target (if applicable) + * @return true on success or false otherwise + */ + bool SetRuleAction(string& name, string& action, int actId = -1); + /** * @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); + bool RemoveRule(string& name); + /** + * @brief Check if certain proxy address exists in Proxifier's Proxy list + * @param addr proxy address to check for + * port proxy port to check for + * id if proxy exist then there'll be it's id number otherwise this value is undetermined + * @return true if proxy exist or false otherwise + * @note DNS names are not resolved and not compared to IPs<br/> + * proxies are compared only by checking address and port values + */ + bool isProxyExists(string& addr, short port, int* id = NULL); + /** + * @brief Check if certain chain exisis in Proxifier's Chain list + * @param name chain name to check for + * id if chain exist then there'll be it's id number otherwise this value is undetermined + * @return true if chain exist or false otherwise + */ + bool isChainExists(string& name, int* id = NULL); + /** + * @brief Check if certain rule exists + * @param name rule name to check for + * @return true if rule exist or false otherwise + */ + bool isRuleExists(string& name); }; #endif diff --git a/client/UpdatedConfig.cpp b/client/UpdatedConfig.cpp index 6873d30..0d7703a 100644 --- a/client/UpdatedConfig.cpp +++ b/client/UpdatedConfig.cpp @@ -145,7 +145,7 @@ void UpdatedConfig::gotServerReply(SslClient::RequestType &type, QByteArray &con ParseGenericProxies(confdata.constData()); break; case SslClient::StaticProxyList: - ParseStaticPorxies(confdata.constData()); + ParseStaticProxies(confdata.constData()); break; case SslClient::FirewallList: ParseFirewalls(confdata.constData()); |