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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
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