diff options
Diffstat (limited to 'kio/misc/kpac/proxyscout.cpp')
-rw-r--r-- | kio/misc/kpac/proxyscout.cpp | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/kio/misc/kpac/proxyscout.cpp b/kio/misc/kpac/proxyscout.cpp new file mode 100644 index 000000000..06d860615 --- /dev/null +++ b/kio/misc/kpac/proxyscout.cpp @@ -0,0 +1,196 @@ +/* + Copyright (c) 2003 Malte Starostik <malte@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#include <cstdlib> +#include <ctime> + +#include <dcopclient.h> +#include <kapplication.h> +#include <klocale.h> +#include <knotifyclient.h> +#include <kprotocolmanager.h> + +#include "proxyscout.moc" +#include "discovery.h" +#include "script.h" + +namespace KPAC +{ + ProxyScout::QueuedRequest::QueuedRequest( const KURL& u ) + : transaction( kapp->dcopClient()->beginTransaction() ), + url( u ) + { + } + + ProxyScout::ProxyScout( const QCString& name ) + : KDEDModule( name ), + m_instance( new KInstance( "proxyscout" ) ), + m_downloader( 0 ), + m_script( 0 ), + m_suspendTime( 0 ) + { + } + + ProxyScout::~ProxyScout() + { + delete m_script; + delete m_instance; + } + + QString ProxyScout::proxyForURL( const KURL& url ) + { + if ( m_suspendTime ) + { + if ( std::time( 0 ) - m_suspendTime < 300 ) return "DIRECT"; + m_suspendTime = 0; + } + + // Never use a proxy for the script itself + if ( m_downloader && url.equals( m_downloader->scriptURL(), true ) ) return "DIRECT"; + + if ( m_script ) return handleRequest( url ); + + if ( m_downloader || startDownload() ) + { + m_requestQueue.append( url ); + return QString::null; + } + else return "DIRECT"; + } + + ASYNC ProxyScout::blackListProxy( const QString& proxy ) + { + m_blackList[ proxy ] = std::time( 0 ); + } + + ASYNC ProxyScout::reset() + { + delete m_script; + m_script = 0; + delete m_downloader; + m_downloader = 0; + m_blackList.clear(); + m_suspendTime = 0; + KProtocolManager::reparseConfiguration(); + } + + bool ProxyScout::startDownload() + { + switch ( KProtocolManager::proxyType() ) + { + case KProtocolManager::WPADProxy: + m_downloader = new Discovery( this ); + break; + case KProtocolManager::PACProxy: + m_downloader = new Downloader( this ); + m_downloader->download( KURL( KProtocolManager::proxyConfigScript() ) ); + break; + default: + return false; + } + connect( m_downloader, SIGNAL( result( bool ) ), + SLOT( downloadResult( bool ) ) ); + return true; + } + + void ProxyScout::downloadResult( bool success ) + { + KNotifyClient::Instance notifyInstance( m_instance ); + if ( success ) + try + { + m_script = new Script( m_downloader->script() ); + } + catch ( const Script::Error& e ) + { + KNotifyClient::event( "script-error", i18n( + "The proxy configuration script is invalid:\n%1" ) + .arg( e.message() ) ); + success = false; + } + else KNotifyClient::event( "download-error", m_downloader->error() ); + + for ( RequestQueue::ConstIterator it = m_requestQueue.begin(); + it != m_requestQueue.end(); ++it ) + { + QCString type = "QString"; + QByteArray data; + QDataStream ds( data, IO_WriteOnly ); + if ( success ) ds << handleRequest( ( *it ).url ); + else ds << QString( "DIRECT" ); + kapp->dcopClient()->endTransaction( ( *it ).transaction, type, data ); + } + m_requestQueue.clear(); + m_downloader->deleteLater(); + m_downloader = 0; + // Suppress further attempts for 5 minutes + if ( !success ) m_suspendTime = std::time( 0 ); + } + + QString ProxyScout::handleRequest( const KURL& url ) + { + try + { + QString result = m_script->evaluate( url ); + QStringList proxies = QStringList::split( ';', result ); + for ( QStringList::ConstIterator it = proxies.begin(); + it != proxies.end(); ++it ) + { + QString proxy = ( *it ).stripWhiteSpace(); + if ( proxy.left( 5 ) == "PROXY" ) + { + KURL proxyURL( proxy = proxy.mid( 5 ).stripWhiteSpace() ); + // If the URL is invalid or the URL is valid but in opaque + // format which indicates a port number being present in + // this particular case, simply calling setProtocol() on + // it trashes the whole URL. + int len = proxyURL.protocol().length(); + if ( !proxyURL.isValid() || proxy.find( ":/", len ) != len ) + proxy.prepend("http://"); + BlackList::Iterator it = m_blackList.find( proxy ); + if ( it == m_blackList.end() ) return proxy; + else if ( std::time( 0 ) - *it > 1800 ) // 30 minutes + { + // black listing expired + m_blackList.remove( it ); + return proxy; + } + } + else return "DIRECT"; + } + // FIXME: blacklist + } + catch ( const Script::Error& e ) + { + KNotifyClient::Instance notifyInstance( m_instance ); + KNotifyClient::event( "evaluation-error", i18n( + "The proxy configuration script returned an error:\n%1" ) + .arg( e.message() ) ); + } + return "DIRECT"; + } + + extern "C" KDE_EXPORT KDEDModule* create_proxyscout( const QCString& name ) + { + return new ProxyScout( name ); + } +} + +// vim: ts=4 sw=4 et |