works with comol/updater
This commit is contained in:
175
autoproxy.hxx
175
autoproxy.hxx
@@ -8,8 +8,18 @@
|
|||||||
#ifndef PROXYFACE_HXX
|
#ifndef PROXYFACE_HXX
|
||||||
#define PROXYFACE_HXX
|
#define PROXYFACE_HXX
|
||||||
|
|
||||||
|
#ifdef QT_NETWORK_LIB
|
||||||
|
#include <QtNetwork/QNetworkProxy>
|
||||||
|
#include <QtNetwork/QNetworkAccessManager>
|
||||||
|
#include <QtNetwork/QNetworkReply>
|
||||||
|
#include <QtCore/QTimer>
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
#include <map>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
//! auto proxy configuration
|
//! auto proxy configuration
|
||||||
namespace proxy {
|
namespace proxy {
|
||||||
@@ -35,9 +45,20 @@ namespace proxy {
|
|||||||
SOCKS //<SOCKS5 proxy
|
SOCKS //<SOCKS5 proxy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! One proxy
|
||||||
|
struct Proxy {
|
||||||
|
Proxy(): type(DIRECT), port(0) {}
|
||||||
|
Proxy(Type t, std::string h, unsigned int p): type(t), host(h), port(p) {}
|
||||||
|
Proxy(Type t, std::string h, std::string p): type(t), host(h), port(0) {
|
||||||
|
std::stringstream(p)>>port;
|
||||||
|
}
|
||||||
|
Type type;
|
||||||
|
std::string host;
|
||||||
|
unsigned int port;
|
||||||
|
};
|
||||||
|
|
||||||
//! List of proxies, type -> url and port
|
//! List of proxies, type -> url and port
|
||||||
typedef std::list< std::pair<Type, std::pair<std::string, std::string> > >
|
typedef std::list<Proxy> List;
|
||||||
List;
|
|
||||||
|
|
||||||
//! Unified Interface for accessing proxy::Face
|
//! Unified Interface for accessing proxy::Face
|
||||||
/*! Abstract interface, impementation for Unix and Windoze differs.
|
/*! Abstract interface, impementation for Unix and Windoze differs.
|
||||||
@@ -49,15 +70,157 @@ namespace proxy {
|
|||||||
proxy::Auto pf; // keep for program life time (because of caching)
|
proxy::Auto pf; // keep for program life time (because of caching)
|
||||||
proxy::List pf.proxies("http://swisssign.com");
|
proxy::List pf.proxies("http://swisssign.com");
|
||||||
[...] // set proxy, read from http://swisssign.com
|
[...] // set proxy, read from http://swisssign.com
|
||||||
@endcode */
|
@endcode
|
||||||
class Interface {
|
|
||||||
|
@example test.cxx */
|
||||||
|
class Interface
|
||||||
|
#ifdef QT_NETWORK_LIB
|
||||||
|
: public QObject
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef QT_NETWORK_LIB
|
||||||
|
Q_OBJECT;
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
//! Keep your instance as long as possible, because of caching.
|
//! Keep your instance as long as possible, because of caching.
|
||||||
Interface() {}
|
Interface() {
|
||||||
|
#ifdef QT_NETWORK_LIB
|
||||||
|
if (!connect(&_timeout, SIGNAL(timeout()), SLOT(timeout())))
|
||||||
|
qFatal("connect failed");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
virtual ~Interface() {}
|
virtual ~Interface() {}
|
||||||
//! Get list of proxies for a given URL.
|
//! Get list of proxies for a given URL.
|
||||||
/*! @throw a child of std::exception if anything fails */
|
|
||||||
virtual List proxies(const std::string& url) = 0;
|
virtual List proxies(const std::string& url) = 0;
|
||||||
|
#ifdef QT_NETWORK_LIB
|
||||||
|
//! If Qt Network is available you may check the proxies found
|
||||||
|
/*! First checks for direct access to the target. If this is not
|
||||||
|
possible, starts scan for proxies.
|
||||||
|
|
||||||
|
Returns immediately and signals proxyFound() if a valid
|
||||||
|
configuration has been found, or proxyError() in case of
|
||||||
|
timeout. You should wait for either of the signals, before you
|
||||||
|
can call this method again.
|
||||||
|
|
||||||
|
@param url the url to find a proxy for
|
||||||
|
@param timeout [ms] time to give up search */
|
||||||
|
void proxy(const std::string& url, int timeout=2000) {
|
||||||
|
qDebug()<<"Search proxy for URL, direct and default"
|
||||||
|
<<"url="<<url.data()<<"timeout="<<timeout;
|
||||||
|
for (Requests::iterator it(_requests.begin()); it!=_requests.end(); ++it)
|
||||||
|
delete it->second.first;
|
||||||
|
_requests.clear();
|
||||||
|
_direct = true; // first try direct access
|
||||||
|
QNetworkProxy directProxy(QNetworkProxy::NoProxy);
|
||||||
|
setupProxyCheck(directProxy, url);
|
||||||
|
QNetworkProxy defaultProxy;
|
||||||
|
setupProxyCheck(defaultProxy, url);
|
||||||
|
_timeout.setSingleShot(true);
|
||||||
|
_timeout.setInterval(timeout);
|
||||||
|
_timeout.start();
|
||||||
|
}
|
||||||
|
//! If Qt Network is available you may check the proxies found
|
||||||
|
/*! @copydoc proxy(const std::string&, int) */
|
||||||
|
void proxy(const QUrl& url, int timeout=2000) {
|
||||||
|
proxy(url.toString().toStdString(), timeout);
|
||||||
|
}
|
||||||
|
//! If Qt Network is available you may check the proxies found
|
||||||
|
/*! @copydoc proxy(const std::string&, int) */
|
||||||
|
void proxy(const QString& url, int timeout=2000) {
|
||||||
|
proxy(url.toStdString(), timeout);
|
||||||
|
}
|
||||||
|
static QString toString(const QNetworkProxy& p) {
|
||||||
|
switch (p.type()) {
|
||||||
|
case QNetworkProxy::NoProxy:
|
||||||
|
return QString("direct://");
|
||||||
|
case QNetworkProxy::DefaultProxy:
|
||||||
|
if (QNetworkProxy::applicationProxy().type()
|
||||||
|
!=QNetworkProxy::DefaultProxy)
|
||||||
|
return QString("Default Proxy: %1")
|
||||||
|
.arg(toString(QNetworkProxy::applicationProxy()));
|
||||||
|
else
|
||||||
|
return QString("Default Proxy: **ERROR**"
|
||||||
|
" application proxy is configured as"
|
||||||
|
" QNetworkProxy::DefaultProxy");
|
||||||
|
case QNetworkProxy::Socks5Proxy:
|
||||||
|
return QString("socks://%1:%2").arg(p.hostName()).arg(p.port());
|
||||||
|
case QNetworkProxy::HttpProxy:
|
||||||
|
return QString("http://%1:%2").arg(p.hostName()).arg(p.port());
|
||||||
|
case QNetworkProxy::HttpCachingProxy:
|
||||||
|
return QString("http-cache://%1:%2").arg(p.hostName()).arg(p.port());
|
||||||
|
case QNetworkProxy::FtpCachingProxy:
|
||||||
|
return QString("ftp-cache://%1:%2").arg(p.hostName()).arg(p.port());
|
||||||
|
}
|
||||||
|
return QString("**ERROR** illegal proxy type");
|
||||||
|
}
|
||||||
|
Q_SIGNALS:
|
||||||
|
//! Signals a valid proxy for the URL requested earlier.
|
||||||
|
void proxyFound(const QUrl&, const QNetworkProxy&);
|
||||||
|
//! Signals a timeout, and no valid proxy for the URL requested earlier.
|
||||||
|
void proxyError(QNetworkReply::NetworkError);
|
||||||
|
private:
|
||||||
|
void setupProxyCheck(const QNetworkProxy& prxy, const std::string& url) {
|
||||||
|
qDebug()<<"Testing proxy for url:"<<toString(prxy)<<"url="<<url.data();
|
||||||
|
QNetworkAccessManager* manager(new QNetworkAccessManager);
|
||||||
|
manager->setProxy(prxy);
|
||||||
|
if (!connect(manager, SIGNAL(finished(QNetworkReply*)),
|
||||||
|
this, SLOT(replyFinished(QNetworkReply*))))
|
||||||
|
qFatal("connect failed");
|
||||||
|
_requests.insert
|
||||||
|
(std::make_pair(manager->head
|
||||||
|
(QNetworkRequest
|
||||||
|
(QUrl(QString::fromStdString(url)))),
|
||||||
|
std::make_pair(manager, prxy)));
|
||||||
|
}
|
||||||
|
private Q_SLOTS:
|
||||||
|
void timeout() {
|
||||||
|
_timeout.stop();
|
||||||
|
std::string url;
|
||||||
|
for (Requests::iterator it(_requests.begin());
|
||||||
|
it!=_requests.end(); ++it) {
|
||||||
|
url = it->first->url().toString().toStdString();
|
||||||
|
delete it->second.first;
|
||||||
|
}
|
||||||
|
_requests.clear();
|
||||||
|
qDebug()<<"Proxy detection timed out"<<"url="<<url.data();
|
||||||
|
if (_direct && url.size()) {
|
||||||
|
qDebug()<<"Direct or preconfigured proxy not available,"
|
||||||
|
" try autoproxy negotiation";
|
||||||
|
_direct = false;
|
||||||
|
List l(proxies(url));
|
||||||
|
for (List::const_iterator it(l.begin()); it!=l.end(); ++it) {
|
||||||
|
QNetworkProxy prxy((it->type==DEFAULT?QNetworkProxy::DefaultProxy
|
||||||
|
:(it->type==HTTP?QNetworkProxy::HttpProxy
|
||||||
|
:(it->type==SOCKS?QNetworkProxy::Socks5Proxy
|
||||||
|
:QNetworkProxy::NoProxy))),
|
||||||
|
QString::fromStdString(it->host), it->port);
|
||||||
|
setupProxyCheck(prxy, url);
|
||||||
|
}
|
||||||
|
_timeout.start();
|
||||||
|
} else {
|
||||||
|
qDebug()<<"No proxy at all, giving up - offline?";
|
||||||
|
proxyError(QNetworkReply::TimeoutError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void replyFinished(QNetworkReply* reply) {
|
||||||
|
_timeout.stop();
|
||||||
|
QNetworkProxy prxy(_requests[reply].second);
|
||||||
|
QUrl url(reply->url());
|
||||||
|
for (Requests::iterator it(_requests.begin()); it!=_requests.end(); ++it)
|
||||||
|
delete it->second.first;
|
||||||
|
_requests.clear();
|
||||||
|
qDebug()<<"SUCCESS - Valid proxy found for url:"
|
||||||
|
<<"url="<<url<<"proxy="<<toString(prxy);
|
||||||
|
proxyFound(url, prxy);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
typedef std::map
|
||||||
|
<QNetworkReply*, std::pair<QNetworkAccessManager*, QNetworkProxy> >
|
||||||
|
Requests;
|
||||||
|
Requests _requests;
|
||||||
|
bool _direct;
|
||||||
|
QTimer _timeout;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@ extern "C" {
|
|||||||
|
|
||||||
namespace proxy {
|
namespace proxy {
|
||||||
|
|
||||||
class Unix: Interface {
|
class Unix: public Interface {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ namespace proxy {
|
|||||||
std::string host(proxy.substr(0, proxy.rfind(":")));
|
std::string host(proxy.substr(0, proxy.rfind(":")));
|
||||||
std::cout<<"Proxy found: "<<host<<", port="<<port<<", type"<<type
|
std::cout<<"Proxy found: "<<host<<", port="<<port<<", type"<<type
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
res.push_back(std::make_pair(type, std::make_pair(host, port)));
|
res.push_back(Proxy(type, host, port));
|
||||||
}
|
}
|
||||||
for (int i(0); proxies[i]; ++i)
|
for (int i(0); proxies[i]; ++i)
|
||||||
delete proxies[i];
|
delete proxies[i];
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
namespace proxy {
|
namespace proxy {
|
||||||
|
|
||||||
class Windoze: Interface {
|
class Windoze: public Interface {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -64,27 +64,22 @@ namespace proxy {
|
|||||||
case WINHTTP_ACCESS_TYPE_DEFAULT_PROXY: type=DEFAULT; break;
|
case WINHTTP_ACCESS_TYPE_DEFAULT_PROXY: type=DEFAULT; break;
|
||||||
case WINHTTP_ACCESS_TYPE_NAMED_PROXY: type=HTTP; break;
|
case WINHTTP_ACCESS_TYPE_NAMED_PROXY: type=HTTP; break;
|
||||||
}
|
}
|
||||||
res.push_back
|
res.push_back(Proxy(type,
|
||||||
(std::make_pair(type,
|
std::string(host.begin(), host.end()),
|
||||||
std::make_pair
|
std::string(port.begin(), port.end())));
|
||||||
(std::string(host.begin(), host.end()),
|
|
||||||
std::string(port.begin(), port.end()))));
|
|
||||||
}
|
}
|
||||||
if (!res.size())
|
if (!res.size()) res.push_back(Proxy());
|
||||||
res.push_back
|
|
||||||
(std::make_pair(DIRECT,
|
|
||||||
std::make_pair(std::string(), std::string())));
|
|
||||||
|
|
||||||
if (proxyInfo.lpszProxy) GlobalFree(proxyInfo.lpszProxy);
|
if (proxyInfo.lpszProxy) GlobalFree(proxyInfo.lpszProxy);
|
||||||
if (proxyInfo.lpszProxyBypass) GlobalFree(proxyInfo.lpszProxyBypass);
|
if (proxyInfo.lpszProxyBypass) GlobalFree(proxyInfo.lpszProxyBypass);
|
||||||
if (hHttpSession) WinHttpCloseHandle(hHttpSession);
|
if (hHttpSession) WinHttpCloseHandle(hHttpSession);
|
||||||
return res;
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
if (proxyInfo.lpszProxy) GlobalFree(proxyInfo.lpszProxy);
|
if (proxyInfo.lpszProxy) GlobalFree(proxyInfo.lpszProxy);
|
||||||
if (proxyInfo.lpszProxyBypass) GlobalFree(proxyInfo.lpszProxyBypass);
|
if (proxyInfo.lpszProxyBypass) GlobalFree(proxyInfo.lpszProxyBypass);
|
||||||
if (hHttpSession) WinHttpCloseHandle(hHttpSession);
|
if (hHttpSession) WinHttpCloseHandle(hHttpSession);
|
||||||
throw;
|
if (!res.size()) res.push_back(Proxy()); // try direct acces
|
||||||
}
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
14
test.cxx
14
test.cxx
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
@code
|
@code
|
||||||
i586-mingw32msvc-g++ test.cxx \
|
i586-mingw32msvc-g++ test.cxx \
|
||||||
_I . -I ~/.wine/drive_c/MicrosoftSDK/include \
|
-I . -I ~/.wine/drive_c/MicrosoftSDK/include \
|
||||||
winhttp.a
|
winhttp.a
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@@ -40,12 +40,12 @@ int main(int argc, char** argv) try {
|
|||||||
p.size();
|
p.size();
|
||||||
p.pop_front())
|
p.pop_front())
|
||||||
std::cout<<" -> found "
|
std::cout<<" -> found "
|
||||||
<<(p.begin()->first==proxy::DIRECT?"DIRECT"
|
<<(p.begin()->type==proxy::DIRECT?"DIRECT"
|
||||||
:(p.begin()->first==proxy::DEFAULT?"DEFAULT"
|
:(p.begin()->type==proxy::DEFAULT?"DEFAULT"
|
||||||
:(p.begin()->first==proxy::HTTP?"HTTP"
|
:(p.begin()->type==proxy::HTTP?"HTTP"
|
||||||
:(p.begin()->first==proxy::SOCKS?"SOCKS":"**ERROR**"))))
|
:(p.begin()->type==proxy::SOCKS?"SOCKS":"**ERROR**"))))
|
||||||
<<" proxy host: "<<p.begin()->second.first
|
<<" proxy host: "<<p.begin()->host
|
||||||
<<" (Port: "<<p.begin()->second.second<<")"<<std::endl;
|
<<" (Port: "<<p.begin()->port<<")"<<std::endl;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} catch(std::exception& x) {
|
} catch(std::exception& x) {
|
||||||
|
Reference in New Issue
Block a user