KIO
proxyscout.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (c) 2003 Malte Starostik <malte@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 00021 #include <cstdlib> 00022 #include <ctime> 00023 00024 #include <klocale.h> 00025 #include <knotification.h> 00026 #include <kprotocolmanager.h> 00027 #include <kpluginfactory.h> 00028 #include <kpluginloader.h> 00029 #include <QtDBus/QtDBus> 00030 00031 #include "proxyscout.moc" 00032 #include "discovery.h" 00033 #include "script.h" 00034 00035 K_PLUGIN_FACTORY(ProxyScoutFactory, 00036 registerPlugin<KPAC::ProxyScout>(); 00037 ) 00038 K_EXPORT_PLUGIN(ProxyScoutFactory("KProxyScoutd")) 00039 00040 00041 namespace KPAC 00042 { 00043 ProxyScout::QueuedRequest::QueuedRequest( const QDBusMessage &reply, const KUrl& u ) 00044 : transaction( reply ), url( u ) 00045 { 00046 } 00047 00048 ProxyScout::ProxyScout(QObject* parent, const QList<QVariant>&) 00049 : KDEDModule(parent), 00050 m_componentData("proxyscout"), 00051 m_downloader( 0 ), 00052 m_script( 0 ), 00053 m_suspendTime( 0 ) 00054 { 00055 } 00056 00057 ProxyScout::~ProxyScout() 00058 { 00059 delete m_script; 00060 } 00061 00062 QString ProxyScout::proxyForUrl( const QString& checkUrl, const QDBusMessage &msg ) 00063 { 00064 KUrl url( checkUrl ); 00065 00066 if ( m_suspendTime ) 00067 { 00068 if ( std::time( 0 ) - m_suspendTime < 300 ) return "DIRECT"; 00069 m_suspendTime = 0; 00070 } 00071 00072 // Never use a proxy for the script itself 00073 if ( m_downloader && url.equals( m_downloader->scriptUrl(), KUrl::CompareWithoutTrailingSlash ) ) return "DIRECT"; 00074 00075 if ( m_script ) return handleRequest( url ); 00076 00077 if ( m_downloader || startDownload() ) 00078 { 00079 msg.setDelayedReply(true); 00080 m_requestQueue.append( QueuedRequest( msg, url ) ); 00081 return QString(); // return value will be ignored 00082 } 00083 else return "DIRECT"; 00084 } 00085 00086 void ProxyScout::blackListProxy( const QString& proxy ) 00087 { 00088 m_blackList[ proxy ] = std::time( 0 ); 00089 } 00090 00091 void ProxyScout::reset() 00092 { 00093 delete m_script; 00094 m_script = 0; 00095 delete m_downloader; 00096 m_downloader = 0; 00097 m_blackList.clear(); 00098 m_suspendTime = 0; 00099 KProtocolManager::reparseConfiguration(); 00100 } 00101 00102 bool ProxyScout::startDownload() 00103 { 00104 switch ( KProtocolManager::proxyType() ) 00105 { 00106 case KProtocolManager::WPADProxy: 00107 m_downloader = new Discovery( this ); 00108 break; 00109 case KProtocolManager::PACProxy: 00110 m_downloader = new Downloader( this ); 00111 m_downloader->download( KUrl( KProtocolManager::proxyConfigScript() ) ); 00112 break; 00113 default: 00114 return false; 00115 } 00116 connect( m_downloader, SIGNAL( result( bool ) ), 00117 SLOT( downloadResult( bool ) ) ); 00118 return true; 00119 } 00120 00121 void ProxyScout::downloadResult( bool success ) 00122 { 00123 if ( success ) 00124 try 00125 { 00126 m_script = new Script( m_downloader->script() ); 00127 } 00128 catch ( const Script::Error& e ) 00129 { 00130 KNotification *notify= new KNotification ( "script-error" ); 00131 notify->setText( i18n("The proxy configuration script is invalid:\n%1" , e.message() ) ); 00132 notify->setComponentData(m_componentData); 00133 notify->sendEvent(); 00134 success = false; 00135 } 00136 else 00137 { 00138 KNotification *notify = new KNotification ("download-error"); 00139 notify->setText( m_downloader->error() ); 00140 notify->setComponentData(m_componentData); 00141 notify->sendEvent(); 00142 } 00143 00144 for ( RequestQueue::Iterator it = m_requestQueue.begin(); 00145 it != m_requestQueue.end(); ++it ) 00146 { 00147 if ( success ) 00148 QDBusConnection::sessionBus().send( ( *it ).transaction.createReply( handleRequest( ( *it ).url ) ) ); 00149 else 00150 QDBusConnection::sessionBus().send( ( *it ).transaction.createReply( QString( "DIRECT" ) ) ); 00151 } 00152 m_requestQueue.clear(); 00153 m_downloader->deleteLater(); 00154 m_downloader = 0; 00155 // Suppress further attempts for 5 minutes 00156 if ( !success ) m_suspendTime = std::time( 0 ); 00157 } 00158 00159 QString ProxyScout::handleRequest( const KUrl& url ) 00160 { 00161 try 00162 { 00163 QString result = m_script->evaluate( url ); 00164 const QStringList proxies = result.split( ';', QString::SkipEmptyParts ); 00165 for ( QStringList::ConstIterator it = proxies.begin(); 00166 it != proxies.end(); ++it ) 00167 { 00168 QString proxy = ( *it ).trimmed(); 00169 if ( proxy.startsWith( QLatin1String( "PROXY" ) ) ) 00170 { 00171 KUrl proxyURL( proxy = proxy.mid( 5 ).trimmed() ); 00172 // If the URL is invalid or the URL is valid but in opaque 00173 // format which indicates a port number being present in 00174 // this particular case, simply calling setProtocol() on 00175 // it trashes the whole URL. 00176 int len = proxyURL.protocol().length(); 00177 if ( !proxyURL.isValid() || proxy.indexOf( ":/", len ) != len ) 00178 proxy.prepend("http://"); 00179 if ( !m_blackList.contains( proxy ) ) 00180 return proxy; 00181 if ( std::time( 0 ) - m_blackList[ proxy ] > 1800 ) // 30 minutes 00182 { 00183 // black listing expired 00184 m_blackList.remove( proxy ); 00185 return proxy; 00186 } 00187 } 00188 else return "DIRECT"; 00189 } 00190 // FIXME: blacklist 00191 } 00192 catch ( const Script::Error& e ) 00193 { 00194 KNotification *n=new KNotification( "evaluation-error" ); 00195 n->setText( i18n( "The proxy configuration script returned an error:\n%1" , e.message() ) ); 00196 n->setComponentData(m_componentData); 00197 n->sendEvent(); 00198 } 00199 return "DIRECT"; 00200 } 00201 } 00202 00203 // vim: ts=4 sw=4 et
KDE 4.6 API Reference