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 #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
00126
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
00137
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
00150
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
00164
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
00177
00178
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
00199
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
00211
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
00226
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
00240
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
00252
00253
00254
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
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
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
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
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
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
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
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
00336 else if ( values.size() == 2 )
00337 return checkRange( now->tm_mon, values[ 0 ], values[ 1 ] );
00338
00339
00340 else if ( values.size() == 1 && values[ 0 ] >= 1000 )
00341 return checkRange( now->tm_year + 1900, values[ 0 ], values[ 0 ] );
00342
00343
00344 else if ( values.size() == 1 && args[ 0 ].isA( NumberType ) )
00345 return checkRange( now->tm_mday, values[ 0 ], values[ 0 ] );
00346
00347
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
00356
00357
00358
00359
00360
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
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
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
00388 else if ( values.size() == 2 )
00389 return checkRange( now->tm_hour, values[ 0 ], values[ 1 ] );
00390
00391
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