00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <cstdlib>
00022 #include <vector>
00023 #include <algorithm>
00024 #include <ctime>
00025
00026 #include <netdb.h>
00027 #include <sys/types.h>
00028 #include <netinet/in.h>
00029 #include <arpa/inet.h>
00030 #include <unistd.h>
00031
00032 #include <qregexp.h>
00033 #include <qstring.h>
00034
00035 #include <kextsock.h>
00036 #include <ksockaddr.h>
00037 #include <kurl.h>
00038 #include <kjs/object.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 { return m_address.s_addr; }
00068 operator String() const { return String( inet_ntoa( m_address ) ); }
00069
00070 private:
00071 Address( const QString& host, bool numeric )
00072 {
00073 int flags = KExtendedSocket::ipv4Socket;
00074 if ( numeric ) flags |= KExtendedSocket::noResolve;
00075 QPtrList< KAddressInfo > addresses =
00076 KExtendedSocket::lookup( host, QString::null, flags );
00077 if ( addresses.isEmpty() ) throw Error();
00078 addresses.setAutoDelete( true );
00079 m_address = static_cast< const KInetSocketAddress* >(
00080 addresses.first()->address() )->hostV4();
00081 }
00082
00083 in_addr m_address;
00084 };
00085
00086 struct Function : public ObjectImp
00087 {
00088 struct ResolveError {};
00089
00090 virtual bool implementsCall() const { return true; }
00091
00092 static int findString( const UString& s, const char* const* values )
00093 {
00094 int index = 0;
00095 UString lower = s.toLower();
00096 for ( const char* const* p = values; *p; ++p, ++index )
00097 if ( lower == *p ) return index;
00098 return -1;
00099 }
00100
00101 static const tm* getTime( ExecState* exec, const List& args )
00102 {
00103 time_t now = std::time( 0 );
00104 if ( args[ args.size() - 1 ].toString( exec ).toLower() == "gmt" )
00105 return std::gmtime( &now );
00106 else return std::localtime( &now );
00107 }
00108
00109 Boolean checkRange( int value, int min, int max )
00110 {
00111 return ( min <= max && value >= min && value <= max ) ||
00112 ( min > max && ( value <= min || value >= max ) );
00113 }
00114 };
00115
00116
00117
00118 struct IsPlainHostName : public Function
00119 {
00120 virtual Value call( ExecState* exec, Object&, const List& args )
00121 {
00122 if ( args.size() != 1 ) return Undefined();
00123 return Boolean( args[ 0 ].toString( exec ).find( "." ) == -1 );
00124 }
00125 };
00126
00127
00128
00129 struct DNSDomainIs : public Function
00130 {
00131 virtual Value call( ExecState* exec, Object&, const List& args )
00132 {
00133 if ( args.size() != 2 ) return Undefined();
00134 QString host = args[ 0 ].toString( exec ).qstring().lower();
00135 QString domain = args[ 1 ].toString( exec ).qstring().lower();
00136 return Boolean( host.endsWith( domain ) );
00137 }
00138 };
00139
00140
00141
00142 struct LocalHostOrDomainIs : public Function
00143 {
00144 virtual Value call( ExecState* exec, Object&, const List& args )
00145 {
00146 if ( args.size() != 2 ) return Undefined();
00147 UString host = args[ 0 ].toString( exec ).toLower();
00148 if ( host.find( "." ) == -1 ) return Boolean( true );
00149 UString fqdn = args[ 1 ].toString( exec ).toLower();
00150 return Boolean( host == fqdn );
00151 }
00152 };
00153
00154
00155
00156 struct IsResolvable : public Function
00157 {
00158 virtual Value call( ExecState* exec, Object&, const List& args )
00159 {
00160 if ( args.size() != 1 ) return Undefined();
00161 try { Address::resolve( args[ 0 ].toString( exec ) ); }
00162 catch ( const Address::Error& ) { return Boolean( false ); }
00163 return Boolean( true );
00164 }
00165 };
00166
00167
00168
00169
00170 struct IsInNet : public Function
00171 {
00172 virtual Value call( ExecState* exec, Object&, const List& args )
00173 {
00174 if ( args.size() != 3 ) return Undefined();
00175 try
00176 {
00177 in_addr_t host = Address::resolve( args[ 0 ].toString( exec ) );
00178 in_addr_t subnet = Address::parse( args[ 1 ].toString( exec ) );
00179 in_addr_t mask = Address::parse( args[ 2 ].toString( exec ) );
00180 return Boolean( ( host & mask ) == ( subnet & mask ) );
00181 }
00182 catch ( const Address::Error& )
00183 {
00184 return Undefined();
00185 }
00186 }
00187 };
00188
00189
00190
00191 struct DNSResolve : public Function
00192 {
00193 virtual Value call( ExecState* exec, Object&, const List& args )
00194 {
00195 if ( args.size() != 1 ) return Undefined();
00196 try { return Address::resolve( args[ 0 ].toString( exec ) ); }
00197 catch ( const Address::Error& ) { return Undefined(); }
00198 }
00199 };
00200
00201
00202
00203 struct MyIpAddress : public Function
00204 {
00205 virtual Value call( ExecState*, Object&, const List& args )
00206 {
00207 if ( args.size() ) return Undefined();
00208 char hostname[ 256 ];
00209 gethostname( hostname, 255 );
00210 hostname[ 255 ] = 0;
00211 try { return Address::resolve( hostname ); }
00212 catch ( const Address::Error& ) { return Undefined(); }
00213 }
00214 };
00215
00216
00217
00218 struct DNSDomainLevels : public Function
00219 {
00220 virtual Value call( ExecState* exec, Object&, const List& args )
00221 {
00222 if ( args.size() != 1 ) return Undefined();
00223 UString host = args[ 0 ].toString( exec );
00224 if ( host.isNull() ) return Number( 0 );
00225 return Number( std::count(
00226 host.data(), host.data() + host.size(), '.' ) );
00227 }
00228 };
00229
00230
00231
00232 struct ShExpMatch : public Function
00233 {
00234 virtual Value call( ExecState* exec, Object&, const List& args )
00235 {
00236 if ( args.size() != 2 ) return Undefined();
00237 QRegExp pattern( args[ 1 ].toString( exec ).qstring(), true, true );
00238 return Boolean( pattern.exactMatch(args[ 0 ].toString( exec ).qstring()) );
00239 }
00240 };
00241
00242
00243
00244
00245
00246 struct WeekdayRange : public Function
00247 {
00248 virtual Value call( ExecState* exec, Object&, const List& args )
00249 {
00250 if ( args.size() < 1 || args.size() > 3 ) return Undefined();
00251 static const char* const days[] =
00252 { "sun", "mon", "tue", "wed", "thu", "fri", "sat", 0 };
00253 int d1 = findString( args[ 0 ].toString( exec ), days );
00254 if ( d1 == -1 ) return Undefined();
00255
00256 int d2 = findString( args[ 1 ].toString( exec ), days );
00257 if ( d2 == -1 ) d2 = d1;
00258 return checkRange( getTime( exec, args )->tm_wday, d1, d2 );
00259 }
00260 };
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 struct DateRange : public Function
00274 {
00275 virtual Value call( ExecState* exec, Object&, const List& args )
00276 {
00277 if ( args.size() < 1 || args.size() > 7 ) return Undefined();
00278 static const char* const months[] =
00279 { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "nov", "dec", 0 };
00280
00281 std::vector< int > values;
00282 for ( int i = 0; i < args.size(); ++i )
00283 {
00284 int value = -1;
00285 if ( args[ i ].isA( NumberType ) )
00286 value = args[ i ].toInteger( exec );
00287 else value = findString( args[ i ].toString( exec ), months );
00288 if ( value >= 0 ) values.push_back( value );
00289 else break;
00290 }
00291
00292 const tm* now = getTime( exec, args );
00293
00294
00295 if ( values.size() == 6 )
00296 return checkRange( ( now->tm_year + 1900 ) * 372 + now->tm_mon * 31 + now->tm_mday,
00297 values[ 2 ] * 372 + values[ 1 ] * 31 + values[ 0 ],
00298 values[ 5 ] * 372 + values[ 4 ] * 31 + values[ 3 ] );
00299
00300
00301 else if ( values.size() == 4 &&
00302 values[ 1 ] < 12 &&
00303 values[ 3 ] < 12 )
00304 return checkRange( now->tm_mon * 31 + now->tm_mday,
00305 values[ 1 ] * 31 + values[ 0 ],
00306 values[ 3 ] * 31 + values[ 2 ] );
00307
00308
00309 else if ( values.size() == 4 )
00310 return checkRange( ( now->tm_year + 1900 ) * 12 + now->tm_mon,
00311 values[ 1 ] * 12 + values[ 0 ],
00312 values[ 3 ] * 12 + values[ 2 ] );
00313
00314
00315 else if ( values.size() == 2 &&
00316 values[ 0 ] >= 1000 &&
00317 values[ 1 ] >= 1000 )
00318 return checkRange( now->tm_year + 1900, values[ 0 ], values[ 1 ] );
00319
00320
00321 else if ( values.size() == 2 &&
00322 args[ 0 ].isA( NumberType ) &&
00323 args[ 1 ].isA( NumberType ) )
00324 return checkRange( now->tm_mday, values[ 0 ], values[ 1 ] );
00325
00326
00327 else if ( values.size() == 2 )
00328 return checkRange( now->tm_mon, values[ 0 ], values[ 1 ] );
00329
00330
00331 else if ( values.size() == 1 && values[ 0 ] >= 1000 )
00332 return checkRange( now->tm_year + 1900, values[ 0 ], values[ 0 ] );
00333
00334
00335 else if ( values.size() == 1 && args[ 0 ].isA( NumberType ) )
00336 return checkRange( now->tm_mday, values[ 0 ], values[ 0 ] );
00337
00338
00339 else if ( values.size() == 1 )
00340 return checkRange( now->tm_mon, values[ 0 ], values[ 0 ] );
00341
00342 else return Undefined();
00343 }
00344 };
00345
00346
00347
00348
00349
00350
00351
00352 struct TimeRange : public Function
00353 {
00354 virtual Value call( ExecState* exec, Object&, const List& args )
00355 {
00356 if ( args.size() < 1 || args.size() > 7 ) return Undefined();
00357
00358 std::vector< int > values;
00359 for ( int i = 0; i < args.size(); ++i )
00360 if ( args[ i ].isA( NumberType ) )
00361 values.push_back( args[ i ].toInteger( exec ) );
00362 else break;
00363
00364 const tm* now = getTime( exec, args );
00365
00366
00367 if ( values.size() == 6 )
00368 return checkRange( now->tm_hour * 3600 + now->tm_min * 60 + now->tm_sec,
00369 values[ 0 ] * 3600 + values[ 1 ] * 60 + values[ 2 ],
00370 values[ 3 ] * 3600 + values[ 4 ] * 60 + values[ 5 ] );
00371
00372
00373 else if ( values.size() == 4 )
00374 return checkRange( now->tm_hour * 60 + now->tm_min,
00375 values[ 0 ] * 60 + values[ 1 ],
00376 values[ 2 ] * 60 + values[ 3 ] );
00377
00378
00379 else if ( values.size() == 2 )
00380 return checkRange( now->tm_hour, values[ 0 ], values[ 1 ] );
00381
00382
00383 else if ( values.size() == 1 )
00384 return checkRange( now->tm_hour, values[ 0 ], values[ 0 ] );
00385
00386 else return Undefined();
00387 }
00388 };
00389
00390 void registerFunctions( ExecState* exec, Object& global )
00391 {
00392 global.put( exec, "isPlainHostName",
00393 Object( new IsPlainHostName ) );
00394 global.put( exec, "dnsDomainIs",
00395 Object( new DNSDomainIs ) );
00396 global.put( exec, "localHostOrDomainIs",
00397 Object( new LocalHostOrDomainIs ) );
00398 global.put( exec, "isResolvable",
00399 Object( new IsResolvable ) );
00400 global.put( exec, "isInNet",
00401 Object( new IsInNet ) );
00402 global.put( exec, "dnsResolve",
00403 Object( new DNSResolve ) );
00404 global.put( exec, "myIpAddress",
00405 Object( new MyIpAddress ) );
00406 global.put( exec, "dnsDomainLevels",
00407 Object( new DNSDomainLevels ) );
00408 global.put( exec, "shExpMatch",
00409 Object( new ShExpMatch ) );
00410 global.put( exec, "weekdayRange",
00411 Object( new WeekdayRange ) );
00412 global.put( exec, "dateRange",
00413 Object( new DateRange ) );
00414 global.put( exec, "timeRange",
00415 Object( new TimeRange ) );
00416 }
00417 }
00418
00419 namespace KPAC
00420 {
00421 Script::Script( const QString& code )
00422 {
00423 ExecState* exec = m_interpreter.globalExec();
00424 Object global = m_interpreter.globalObject();
00425 registerFunctions( exec, global );
00426
00427 Completion result = m_interpreter.evaluate( code );
00428 if ( result.complType() == Throw )
00429 throw Error( result.value().toString( exec ).qstring() );
00430 }
00431
00432 QString Script::evaluate( const KURL& url )
00433 {
00434 ExecState *exec = m_interpreter.globalExec();
00435 Value findFunc = m_interpreter.globalObject().get( exec, "FindProxyForURL" );
00436 Object findObj = Object::dynamicCast( findFunc );
00437 if (!findObj.isValid() || !findObj.implementsCall())
00438 throw Error( "No such function FindProxyForURL" );
00439
00440 Object thisObj;
00441 List args;
00442 args.append(String(url.url()));
00443 args.append(String(url.host()));
00444 Value retval = findObj.call( exec, thisObj, args );
00445
00446 if ( exec->hadException() ) {
00447 Value ex = exec->exception();
00448 exec->clearException();
00449 throw Error( ex.toString( exec ).qstring() );
00450 }
00451
00452 return retval.toString( exec ).qstring();
00453 }
00454 }
00455
00456