• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KIO

script.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 #include "script.h"
00021 
00022 
00023 #include <cstdlib>
00024 #include <vector>
00025 #include <algorithm>
00026 #include <ctime>
00027 #include <cstring>
00028 
00029 #include <netdb.h>
00030 #include <sys/types.h>
00031 #include <netinet/in.h>
00032 #include <arpa/inet.h>
00033 #include <unistd.h>
00034 
00035 #include <QtCore/QRegExp>
00036 #include <QtCore/QString>
00037 #include <QtNetwork/QHostAddress>
00038 #include <QtNetwork/QHostInfo>
00039 
00040 #include <kurl.h>
00041 #include <kjs/object.h>
00042 
00043 using namespace KJS;
00044 
00045 QString UString::qstring() const
00046 {
00047     return QString( reinterpret_cast< const QChar* >( data() ), size() );
00048 }
00049 
00050 UString::UString( const QString &s )
00051 {
00052     const unsigned int len = s.length();
00053     UChar *data = static_cast<UChar*>( fastMalloc( sizeof(UChar) * len ) );
00054     memcpy( data, s.unicode(), len * sizeof( UChar ) );
00055     m_rep = Rep::create( data, len );
00056 }
00057 
00058 namespace
00059 {
00060     class Address
00061     {
00062     public:
00063         struct Error {};
00064         static Address resolve( const UString& host )
00065             { return Address( host.qstring(), false ); }
00066         static Address parse( const UString& ip )
00067             { return Address( ip.qstring(), true ); }
00068 
00069         operator QHostAddress() const { return m_address; }
00070         operator UString() const { return UString( m_address.toString() ); }
00071 
00072     private:
00073         Address( const QString& host, bool numeric )
00074         {
00075             if ( numeric ) {
00076                 m_address = QHostAddress( host );
00077                 if ( m_address.isNull() )
00078                     throw Error();
00079             } else {
00080                 QHostInfo addresses = QHostInfo::fromName(host);
00081                 if ( addresses.error() || addresses.addresses().isEmpty() )
00082                     throw Error();
00083                 m_address = addresses.addresses().at(0);
00084             }
00085         }
00086 
00087         QHostAddress m_address;
00088     };
00089 
00090     struct Function : public JSObject
00091     {
00092         struct ResolveError {};
00093 
00094         virtual bool implementsCall() const { return true; }
00095 
00096         static int findString( const UString& s, const char* const* values )
00097         {
00098             int index = 0;
00099             UString lower = s.qstring().toLower();
00100             for ( const char* const* p = values; *p; ++p, ++index )
00101                 if ( lower == *p ) return index;
00102             return -1;
00103         }
00104 
00105         static const tm* getTime( ExecState* exec, const List& args )
00106         {
00107             time_t now = std::time( 0 );
00108             if ( args[ args.size() - 1 ]->toString( exec ).qstring().toLower() == "gmt" )
00109                 return std::gmtime( &now );
00110             else return std::localtime( &now );
00111         }
00112 
00113         JSValue *checkRange( double value, double min, double max )
00114         {
00115             return jsBoolean(( min <= max && value >= min && value <= max ) || ( min > max && ( value <= min || value >= max ) ));
00116         }
00117     };
00118 
00119     // isPlainHostName( host )
00120     // @returns true if @p host doesn't contains a domain part
00121     struct IsPlainHostName : public Function
00122     {
00123         virtual JSValue *callAsFunction( ExecState* exec, JSObject*, const List& args )
00124         {
00125             if ( args.size() != 1 ) return jsUndefined();
00126             return jsBoolean( args[ 0 ]->toString( exec ).qstring().indexOf( "." ) == -1 );
00127         }
00128     };
00129 
00130     // dnsDomainIs( host, domain )
00131     // @returns true if the domain part of @p host matches @p domain
00132     struct DNSDomainIs : public Function
00133     {
00134         virtual JSValue *callAsFunction( ExecState* exec, JSObject*, const List& args )
00135         {
00136             if ( args.size() != 2 ) return jsUndefined();
00137             QString host = args[ 0 ]->toString( exec ).qstring().toLower();
00138             QString domain = args[ 1 ]->toString( exec ).qstring().toLower();
00139             return jsBoolean( host.endsWith( domain ) );
00140         }
00141     };
00142 
00143     // localHostOrDomainIs( host, fqdn )
00144     // @returns true if @p host is unqualified or equals @p fqdn
00145     struct LocalHostOrDomainIs : public Function
00146     {
00147         virtual JSValue *callAsFunction( ExecState* exec, JSObject*, const List& args )
00148         {
00149             if ( args.size() != 2 ) return jsUndefined();
00150             UString host = args[ 0 ]->toString( exec ).qstring().toLower();
00151             if ( host.find( "." ) == -1 ) return jsBoolean( true );
00152             UString fqdn = args[ 1 ]->toString( exec ).qstring().toLower();
00153             return jsBoolean( host == fqdn );
00154         }
00155     };
00156 
00157     // isResolvable( host )
00158     // @returns true if host can be resolved via DNS
00159     struct IsResolvable : public Function
00160     {
00161         virtual JSValue *callAsFunction( ExecState* exec, JSObject*, const List& args )
00162         {
00163             if ( args.size() != 1 ) return jsUndefined();
00164             try { Address::resolve( args[ 0 ]->toString( exec ) ); }
00165             catch ( const Address::Error& ) { return jsBoolean( false ); }
00166             return jsBoolean( true );
00167         }
00168     };
00169 
00170     // isInNet( host, subnet, mask )
00171     // @returns true if @p host is within the IP subnet
00172     //          specified via @p subnet and @p mask
00173     struct IsInNet : public Function
00174     {
00175         virtual JSValue *callAsFunction( ExecState* exec, JSObject*, const List& args )
00176         {
00177             if ( args.size() != 3 ) return jsUndefined();
00178             try
00179             {
00180                 QHostAddress host = Address::resolve( args[ 0 ]->toString( exec ) );
00181                 QHostAddress subnet = Address::parse( args[ 1 ]->toString( exec ) );
00182                 QHostAddress mask = Address::parse( args[ 2 ]->toString( exec ) );
00183 
00184                 return jsBoolean( ( host.toIPv4Address() & mask.toIPv4Address() ) ==
00185                                 ( subnet.toIPv4Address() & mask.toIPv4Address() ) );
00186             }
00187             catch ( const Address::Error& )
00188             {
00189                 return jsUndefined();
00190             }
00191         }
00192     };
00193 
00194     // dnsResolve( host )
00195     // @returns the IP address of @p host in dotted quad notation
00196     struct DNSResolve : public Function
00197     {
00198         virtual JSValue *callAsFunction( ExecState* exec, JSObject*, const List& args )
00199         {
00200             if ( args.size() != 1 ) return jsUndefined();
00201             try { return jsString(Address::resolve( args[ 0 ]->toString( exec ) )); }
00202             catch ( const Address::Error& ) { return jsUndefined(); }
00203         }
00204     };
00205 
00206     // myIpAddress()
00207     // @returns the local machine's IP address in dotted quad notation
00208     struct MyIpAddress : public Function
00209     {
00210         virtual JSValue *callAsFunction( ExecState*, JSObject*, const List& args )
00211         {
00212             if ( args.size() ) return jsUndefined();
00213             char hostname[ 256 ];
00214             gethostname( hostname, 255 );
00215             hostname[ 255 ] = 0;
00216             try { return jsString(Address::resolve( hostname )); }
00217             catch ( const Address::Error& ) { return jsUndefined(); }
00218         }
00219     };
00220 
00221     // dnsDomainLevels( host )
00222     // @returns the number of dots ('.') in @p host
00223     struct DNSDomainLevels : public Function
00224     {
00225         virtual JSValue *callAsFunction( ExecState* exec, JSObject*, const List& args )
00226         {
00227             if ( args.size() != 1 ) return jsUndefined();
00228             UString host = args[ 0 ]->toString( exec );
00229             if ( host.isNull() ) return jsNumber( 0 );
00230 #ifdef __SUNPRO_CC
00231             /* 
00232              * Under Solaris, the default STL is the old broken interface 
00233              * to ::count which takes an extra Size& parameter.
00234              */
00235             int c = 0;
00236             std::count( host.data(), host.data() + host.size(), '.', c );
00237             return jsNumber(c);
00238 #else
00239             return jsNumber( std::count(
00240                 host.data(), host.data() + host.size(), '.' ) );
00241 #endif
00242         }
00243     };
00244 
00245     // shExpMatch( str, pattern )
00246     // @returns true if @p str matches the shell @p pattern
00247     struct ShExpMatch : public Function
00248     {
00249         virtual JSValue *callAsFunction( ExecState* exec, JSObject*, const List& args )
00250         {
00251             if ( args.size() != 2 ) return jsUndefined();
00252             QRegExp pattern( args[ 1 ]->toString( exec ).qstring(), Qt::CaseSensitive, QRegExp::Wildcard );
00253             return jsBoolean( pattern.exactMatch(args[ 0 ]->toString( exec ).qstring()) );
00254         }
00255     };
00256 
00257     // weekdayRange( day [, "GMT" ] )
00258     // weekdayRange( day1, day2 [, "GMT" ] )
00259     // @returns true if the current day equals day or between day1 and day2 resp.
00260     // If the last argument is "GMT", GMT timezone is used, otherwise local time
00261     struct WeekdayRange : public Function
00262     {
00263         virtual JSValue *callAsFunction( ExecState* exec, JSObject*, const List& args )
00264         {
00265             if ( args.size() < 1 || args.size() > 3 ) return jsUndefined();
00266             static const char* const days[] =
00267                 { "sun", "mon", "tue", "wed", "thu", "fri", "sat", 0 };
00268             int d1 = findString( args[ 0 ]->toString( exec ), days );
00269             if ( d1 == -1 ) return jsUndefined();
00270 
00271             int d2 = findString( args[ 1 ]->toString( exec ), days );
00272             if ( d2 == -1 ) d2 = d1;
00273             return checkRange( getTime( exec, args )->tm_wday, d1, d2 );
00274         }
00275     };
00276 
00277     // dateRange( day [, "GMT" ] )
00278     // dateRange( day1, day2 [, "GMT" ] )
00279     // dateRange( month [, "GMT" ] )
00280     // dateRange( month1, month2 [, "GMT" ] )
00281     // dateRange( year [, "GMT" ] )
00282     // dateRange( year1, year2 [, "GMT" ] )
00283     // dateRange( day1, month1, day2, month2 [, "GMT" ] )
00284     // dateRange( month1, year1, month2, year2 [, "GMT" ] )
00285     // dateRange( day1, month1, year1, day2, month2, year2 [, "GMT" ] )
00286     // @returns true if the current date (GMT or local time according to
00287     // presence of "GMT" as last argument) is within the given range
00288     struct DateRange : public Function
00289     {
00290         virtual JSValue *callAsFunction( ExecState* exec, JSObject*, const List& args )
00291         {
00292             if ( args.size() < 1 || args.size() > 7 ) return jsUndefined();
00293             static const char* const months[] =
00294                 { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "nov", "dec", 0 };
00295 
00296             std::vector< double > values;
00297             for ( int i = 0; i < args.size(); ++i )
00298             {
00299                 double value = -1;
00300                 if ( args[ i ]->type() == NumberType )
00301                     value = args[ i ]->toInteger( exec );
00302                 else value = findString( args[ i ]->toString( exec ), months );
00303                 if ( value >= 0 ) values.push_back( value );
00304                 else break;
00305             }
00306 
00307             const tm* now = getTime( exec, args );
00308 
00309             // day1, month1, year1, day2, month2, year2
00310             if ( values.size() == 6 )
00311                 return checkRange( ( now->tm_year + 1900 ) * 372 + now->tm_mon * 31 + now->tm_mday,
00312                                    values[ 2 ] * 372 + values[ 1 ] * 31 + values[ 0 ],
00313                                    values[ 5 ] * 372 + values[ 4 ] * 31 + values[ 3 ] );
00314 
00315             // day1, month1, day2, month2
00316             else if ( values.size() == 4 &&
00317                       values[ 1 ] < 12 &&
00318                       values[ 3 ] < 12 )
00319                 return checkRange( now->tm_mon * 31 + now->tm_mday,
00320                                    values[ 1 ] * 31 + values[ 0 ],
00321                                    values[ 3 ] * 31 + values[ 2 ] );
00322 
00323             // month1, year1, month2, year2
00324             else if ( values.size() == 4 )
00325                 return checkRange( ( now->tm_year + 1900 ) * 12 + now->tm_mon,
00326                                    values[ 1 ] * 12 + values[ 0 ],
00327                                    values[ 3 ] * 12 + values[ 2 ] );
00328 
00329             // year1, year2
00330             else if ( values.size() == 2 &&
00331                       values[ 0 ] >= 1000 &&
00332                       values[ 1 ] >= 1000 )
00333                 return checkRange( now->tm_year + 1900, values[ 0 ], values[ 1 ] );
00334 
00335             // day1, day2
00336             else if ( values.size() == 2 &&
00337                       args[ 0 ]->type() == NumberType &&
00338                       args[ 1 ]->type() == NumberType )
00339                 return checkRange( now->tm_mday, values[ 0 ], values[ 1 ] );
00340 
00341             // month1, month2
00342             else if ( values.size() == 2 )
00343                 return checkRange( now->tm_mon, values[ 0 ], values[ 1 ] );
00344 
00345             // year
00346             else if ( values.size() == 1 && values[ 0 ] >= 1000 )
00347                 return checkRange( now->tm_year + 1900, values[ 0 ], values[ 0 ] );
00348 
00349             // day
00350             else if ( values.size() == 1 && args[ 0 ]->type() == NumberType )
00351                 return checkRange( now->tm_mday, values[ 0 ], values[ 0 ] );
00352 
00353             // month
00354             else if ( values.size() == 1 )
00355                 return checkRange( now->tm_mon, values[ 0 ], values[ 0 ] );
00356 
00357             else return jsUndefined();
00358         }
00359     };
00360 
00361     // timeRange( hour [, "GMT" ] )
00362     // timeRange( hour1, hour2 [, "GMT" ] )
00363     // timeRange( hour1, min1, hour2, min2 [, "GMT" ] )
00364     // timeRange( hour1, min1, sec1, hour2, min2, sec2 [, "GMT" ] )
00365     // @returns true if the current time (GMT or local based on presence
00366     // of "GMT" argument) is within the given range
00367     struct TimeRange : public Function
00368     {
00369         virtual JSValue *callAsFunction( ExecState* exec, JSObject*, const List& args )
00370         {
00371             if ( args.size() < 1 || args.size() > 7 ) return jsUndefined();
00372 
00373             std::vector< double > values;
00374             for ( int i = 0; i < args.size(); ++i )
00375                 if ( args[ i ]->type() == NumberType )
00376                     values.push_back( args[ i ]->toInteger( exec ) );
00377                 else break;
00378 
00379             const tm* now = getTime( exec, args );
00380 
00381             // hour1, min1, sec1, hour2, min2, sec2
00382             if ( values.size() == 6 )
00383                 return checkRange( now->tm_hour * 3600 + now->tm_min * 60 + now->tm_sec,
00384                                    values[ 0 ] * 3600 + values[ 1 ] * 60 + values[ 2 ],
00385                                    values[ 3 ] * 3600 + values[ 4 ] * 60 + values[ 5 ] );
00386 
00387             // hour1, min1, hour2, min2
00388             else if ( values.size() == 4 )
00389                 return checkRange( now->tm_hour * 60 + now->tm_min,
00390                                    values[ 0 ] * 60 + values[ 1 ],
00391                                    values[ 2 ] * 60 + values[ 3 ] );
00392 
00393             // hour1, hour2
00394             else if ( values.size() == 2 )
00395                 return checkRange( now->tm_hour, values[ 0 ], values[ 1 ] );
00396 
00397             // hour
00398             else if ( values.size() == 1 )
00399                 return checkRange( now->tm_hour, values[ 0 ], values[ 0 ] );
00400 
00401             else return jsUndefined();
00402         }
00403     };
00404 
00405     void registerFunctions( ExecState* exec, JSObject *global )
00406     {
00407         global->put( exec, "isPlainHostName", new IsPlainHostName );
00408         global->put( exec, "dnsDomainIs", new DNSDomainIs );
00409         global->put( exec, "localHostOrDomainIs", new LocalHostOrDomainIs );
00410         global->put( exec, "isResolvable", new IsResolvable );
00411         global->put( exec, "isInNet", new IsInNet );
00412         global->put( exec, "dnsResolve", new DNSResolve );
00413         global->put( exec, "myIpAddress", new MyIpAddress );
00414         global->put( exec, "dnsDomainLevels", new DNSDomainLevels );
00415         global->put( exec, "shExpMatch", new ShExpMatch );
00416         global->put( exec, "weekdayRange", new WeekdayRange );
00417         global->put( exec, "dateRange", new DateRange );
00418         global->put( exec, "timeRange", new TimeRange );
00419     }
00420 }
00421 
00422 namespace KPAC
00423 {
00424     Script::Script( const QString& code )
00425     {
00426         m_interpreter = new KJS::Interpreter();
00427         m_interpreter->ref();
00428         ExecState* exec  = m_interpreter->globalExec();
00429         JSObject* global = m_interpreter->globalObject();
00430         registerFunctions( exec, global );
00431 
00432         Completion result = m_interpreter->evaluate( "", 0, code );
00433         if ( result.complType() == Throw )
00434             throw Error( result.value()->toString( exec ).qstring() );
00435     }
00436     
00437     Script::~Script()
00438     {
00439         m_interpreter->deref();
00440     }
00441 
00442     QString Script::evaluate( const KUrl& url )
00443     {
00444         ExecState *exec = m_interpreter->globalExec();
00445         JSValue *findFunc = m_interpreter->globalObject()->get( exec, "FindProxyForURL" );
00446         JSObject *findObj = findFunc->getObject();
00447         if (!findObj || !findObj->implementsCall())
00448             throw Error( "No such function FindProxyForURL" );
00449     
00450         List args;
00451         args.append(jsString(url.url()));
00452         args.append(jsString(url.host()));
00453         JSValue *retval = findObj->call( exec, m_interpreter->globalObject(), args );
00454         
00455         if ( exec->hadException() ) {
00456             JSValue *ex = exec->exception();
00457             exec->clearException();
00458             throw Error( ex->toString( exec ).qstring() );
00459         }
00460 
00461         return retval->toString( exec ).qstring();
00462     }
00463 }
00464 
00465 // vim: ts=4 sw=4 et

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal