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