works with comol/updater

master
Marc Wäckerlin 15 years ago
parent 9c1e9dfb44
commit 0d00344e30
  1. 175
      autoproxy.hxx
  2. 4
      proxyface/unix.hxx
  3. 19
      proxyface/windoze.hxx
  4. 14
      test.cxx

@ -8,8 +8,18 @@
#ifndef 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 <string>
#include <sstream>
//! auto proxy configuration
namespace proxy {
@ -35,9 +45,20 @@ namespace 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
typedef std::list< std::pair<Type, std::pair<std::string, std::string> > >
List;
typedef std::list<Proxy> List;
//! Unified Interface for accessing proxy::Face
/*! 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::List pf.proxies("http://swisssign.com");
[...] // set proxy, read from http://swisssign.com
@endcode */
class Interface {
@endcode
@example test.cxx */
class Interface
#ifdef QT_NETWORK_LIB
: public QObject
#endif
{
#ifdef QT_NETWORK_LIB
Q_OBJECT;
#endif
public:
//! 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() {}
//! 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;
#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 {
class Unix: Interface {
class Unix: public Interface {
public:
@ -43,7 +43,7 @@ namespace proxy {
std::string host(proxy.substr(0, proxy.rfind(":")));
std::cout<<"Proxy found: "<<host<<", port="<<port<<", type"<<type
<<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)
delete proxies[i];

@ -15,7 +15,7 @@
namespace proxy {
class Windoze: Interface {
class Windoze: public Interface {
public:
@ -64,27 +64,22 @@ namespace proxy {
case WINHTTP_ACCESS_TYPE_DEFAULT_PROXY: type=DEFAULT; break;
case WINHTTP_ACCESS_TYPE_NAMED_PROXY: type=HTTP; break;
}
res.push_back
(std::make_pair(type,
std::make_pair
(std::string(host.begin(), host.end()),
std::string(port.begin(), port.end()))));
res.push_back(Proxy(type,
std::string(host.begin(), host.end()),
std::string(port.begin(), port.end())));
}
if (!res.size())
res.push_back
(std::make_pair(DIRECT,
std::make_pair(std::string(), std::string())));
if (!res.size()) res.push_back(Proxy());
if (proxyInfo.lpszProxy) GlobalFree(proxyInfo.lpszProxy);
if (proxyInfo.lpszProxyBypass) GlobalFree(proxyInfo.lpszProxyBypass);
if (hHttpSession) WinHttpCloseHandle(hHttpSession);
return res;
} catch (...) {
if (proxyInfo.lpszProxy) GlobalFree(proxyInfo.lpszProxy);
if (proxyInfo.lpszProxyBypass) GlobalFree(proxyInfo.lpszProxyBypass);
if (hHttpSession) WinHttpCloseHandle(hHttpSession);
throw;
if (!res.size()) res.push_back(Proxy()); // try direct acces
}
return res;
}
};
}

@ -20,7 +20,7 @@
@code
i586-mingw32msvc-g++ test.cxx \
_I . -I ~/.wine/drive_c/MicrosoftSDK/include \
-I . -I ~/.wine/drive_c/MicrosoftSDK/include \
winhttp.a
@endcode
@ -40,12 +40,12 @@ int main(int argc, char** argv) try {
p.size();
p.pop_front())
std::cout<<" -> found "
<<(p.begin()->first==proxy::DIRECT?"DIRECT"
:(p.begin()->first==proxy::DEFAULT?"DEFAULT"
:(p.begin()->first==proxy::HTTP?"HTTP"
:(p.begin()->first==proxy::SOCKS?"SOCKS":"**ERROR**"))))
<<" proxy host: "<<p.begin()->second.first
<<" (Port: "<<p.begin()->second.second<<")"<<std::endl;
<<(p.begin()->type==proxy::DIRECT?"DIRECT"
:(p.begin()->type==proxy::DEFAULT?"DEFAULT"
:(p.begin()->type==proxy::HTTP?"HTTP"
:(p.begin()->type==proxy::SOCKS?"SOCKS":"**ERROR**"))))
<<" proxy host: "<<p.begin()->host
<<" (Port: "<<p.begin()->port<<")"<<std::endl;
}
return 0;
} catch(std::exception& x) {

Loading…
Cancel
Save