23#include "config-kpac.h"
36#include <solid/networking.h>
39#include <QtCore/QFileSystemWatcher>
45 registerPlugin<KPAC::ProxyScout>();
58 static ProxyType proxyTypeFor(
const QString& mode)
60 if (mode.compare(QLatin1String(
"PROXY"), Qt::CaseInsensitive) == 0)
63 if (mode.compare(QLatin1String(
"DIRECT"), Qt::CaseInsensitive) == 0)
66 if (mode.compare(QLatin1String(
"SOCKS"), Qt::CaseInsensitive) == 0 ||
67 mode.compare(QLatin1String(
"SOCKS5"), Qt::CaseInsensitive) == 0)
73 ProxyScout::QueuedRequest::QueuedRequest(
const QDBusMessage &reply,
const KUrl& u,
bool sendall )
74 : transaction( reply ), url( u ), sendAll(sendall)
80 m_componentData(
"proxyscout"),
84 m_debugArea (KDebug::registerArea(
"proxyscout")),
88 connect (Solid::Networking::notifier(), SIGNAL(shouldDisconnect()), SLOT(disconnectNetwork()));
92 ProxyScout::~ProxyScout()
97 QStringList ProxyScout::proxiesForUrl(
const QString& checkUrl,
const QDBusMessage &msg )
102 if ( std::time( 0 ) - m_suspendTime < 300 ) {
103 return QStringList (QLatin1String(
"DIRECT"));
110 return QStringList (QLatin1String(
"DIRECT"));
114 return handleRequest(url);
117 if (m_downloader || startDownload()) {
118 msg.setDelayedReply(
true);
119 m_requestQueue.append( QueuedRequest( msg, url,
true ) );
120 return QStringList();
123 return QStringList(QLatin1String(
"DIRECT"));
126 QString ProxyScout::proxyForUrl(
const QString& checkUrl,
const QDBusMessage &msg )
131 if ( std::time( 0 ) - m_suspendTime < 300 ) {
132 return QLatin1String(
"DIRECT");
139 return QLatin1String(
"DIRECT");
143 return handleRequest(url).first();
146 if (m_downloader || startDownload()) {
147 msg.setDelayedReply(
true);
148 m_requestQueue.append( QueuedRequest( msg, url ) );
152 return QLatin1String(
"DIRECT");
155 void ProxyScout::blackListProxy(
const QString& proxy )
157 m_blackList[ proxy ] = std::time( 0 );
160 void ProxyScout::reset()
173 bool ProxyScout::startDownload()
178 if (m_downloader && !qobject_cast<Discovery*>(m_downloader)) {
183 m_downloader =
new Discovery(
this);
184 connect(m_downloader, SIGNAL(result(
bool)),
this, SLOT(downloadResult(
bool)));
188 if (m_downloader && !qobject_cast<Downloader*>(m_downloader)) {
193 m_downloader =
new Downloader(
this);
194 connect(m_downloader, SIGNAL(result(
bool)),
this, SLOT(downloadResult(
bool)));
200 m_watcher =
new QFileSystemWatcher(
this);
201 connect (m_watcher, SIGNAL(fileChanged(QString)), SLOT(proxyScriptFileChanged(QString)));
203 proxyScriptFileChanged(url.
path());
207 m_downloader->download( url );
218 void ProxyScout::disconnectNetwork()
226 void ProxyScout::downloadResult(
bool success )
232 m_script =
new Script(m_downloader->script());
235 catch (
const Script::Error& e )
237 kWarning() <<
"Error:" << e.message();
239 notify->
setText(
i18n(
"The proxy configuration script is invalid:\n%1" , e.message() ) );
246 notify->
setText( m_downloader->error() );
252 for (RequestQueue::Iterator it = m_requestQueue.begin(), itEnd = m_requestQueue.end(); it != itEnd; ++it) {
254 const QVariant result (handleRequest((*it).url));
255 QDBusConnection::sessionBus().send((*it).transaction.createReply(result));
257 const QVariant result (handleRequest((*it).url).first());
258 QDBusConnection::sessionBus().send((*it).transaction.createReply(result));
262 for (RequestQueue::Iterator it = m_requestQueue.begin(), itEnd = m_requestQueue.end(); it != itEnd; ++it) {
263 QDBusConnection::sessionBus().send((*it).transaction.createReply(QString::fromLatin1(
"DIRECT")));
267 m_requestQueue.clear();
271 m_suspendTime = std::time( 0 );
275 void ProxyScout::proxyScriptFileChanged(
const QString& path)
281 if (!m_watcher->files().isEmpty()) {
282 m_watcher->removePaths(m_watcher->files());
287 m_watcher->addPath(path);
293 QStringList ProxyScout::handleRequest(
const KUrl& url )
297 QStringList proxyList;
298 const QString result = m_script->evaluate(url).trimmed();
299 const QStringList proxies = result.split(QLatin1Char(
';'), QString::SkipEmptyParts);
300 const int size = proxies.count();
302 for (
int i = 0; i < size; ++i) {
303 QString mode, address;
304 const QString proxy = proxies.at(i).trimmed();
305 const int index = proxy.indexOf(QLatin1Char(
' '));
310 mode = proxy.left(index);
311 address = proxy.mid(index + 1).trimmed();
314 const ProxyType type = proxyTypeFor(mode);
319 if (type == Proxy || type == Socks) {
320 const int index = address.indexOf(QLatin1Char(
':'));
321 if (index == -1 || !KProtocolInfo::isKnownProtocol(address.left(index))) {
322 const QString protocol ((type == Proxy ? QLatin1String(
"http://") : QLatin1String(
"socks://")));
323 const KUrl url (protocol + address);
332 if (type == Direct || !m_blackList.contains(address)) {
333 proxyList << address;
334 }
else if (std::time(0) - m_blackList[address] > 1800) {
336 m_blackList.remove( address );
337 proxyList << address;
341 if (!proxyList.isEmpty()) {
342 kDebug(m_debugArea) << proxyList;
347 catch (
const Script::Error& e )
349 kError() << e.message();
351 n->
setText(
i18n(
"The proxy configuration script returned an error:\n%1" , e.message() ) );
356 return QStringList (QLatin1String(
"DIRECT"));
360#include "proxyscout.moc"
void setComponentData(const KComponentData &componentData)
void setText(const QString &text)
#define K_EXPORT_PLUGIN(factory)
static QString proxyConfigScript()
Returns the URL of the script for automatic proxy configuration.
static void reparseConfiguration()
Force a reload of the general config file of io-slaves ( kioslaverc).
static ProxyType proxyType()
Returns the type of proxy configuration that is used.
static KUrl fromPath(const QString &text)
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
QString path(AdjustPathOption trailing=LeaveTrailingSlash) const
bool equals(const KUrl &u, const EqualsOptions &options=0) const
CompareWithoutTrailingSlash
QString i18n(const char *text)
K_PLUGIN_FACTORY(ProxyScoutFactory, registerPlugin< KPAC::ProxyScout >();) namespace KPAC