kio Library API Documentation

script.cpp

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., 59 Temple Place - Suite 330, 00017 Boston, MA 02111-1307, USA. 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 // isPlainHostName( host ) 00117 // @returns true if @p host doesn't contains a domain part 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 // dnsDomainIs( host, domain ) 00128 // @returns true if the domain part of @p host matches @p domain 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 // localHostOrDomainIs( host, fqdn ) 00141 // @returns true if @p host is unqualified or equals @p fqdn 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 // isResolvable( host ) 00155 // @returns true if host can be resolved via DNS 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 // isInNet( host, subnet, mask ) 00168 // @returns true if @p host is within the IP subnet 00169 // specified via @p subnet and @p mask 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 // dnsResolve( host ) 00190 // @returns the IP address of @p host in dotted quad notation 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 // myIpAddress() 00202 // @returns the local machine's IP address in dotted quad notation 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 // dnsDomainLevels( host ) 00217 // @returns the number of dots ('.') in @p host 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 // shExpMatch( str, pattern ) 00231 // @returns true if @p str matches the shell @p pattern 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 // weekdayRange( day [, "GMT" ] ) 00243 // weekdayRange( day1, day2 [, "GMT" ] ) 00244 // @returns true if the current day equals day or between day1 and day2 resp. 00245 // If the last argument is "GMT", GMT timezone is used, otherwise local time 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 // dateRange( day [, "GMT" ] ) 00263 // dateRange( day1, day2 [, "GMT" ] ) 00264 // dateRange( month [, "GMT" ] ) 00265 // dateRange( month1, month2 [, "GMT" ] ) 00266 // dateRange( year [, "GMT" ] ) 00267 // dateRange( year1, year2 [, "GMT" ] ) 00268 // dateRange( day1, month1, day2, month2 [, "GMT" ] ) 00269 // dateRange( month1, year1, month2, year2 [, "GMT" ] ) 00270 // dateRange( day1, month1, year1, day2, month2, year2 [, "GMT" ] ) 00271 // @returns true if the current date (GMT or local time according to 00272 // presence of "GMT" as last argument) is within the given range 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 // day1, month1, year1, day2, month2, year2 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 // day1, month1, day2, month2 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 // month1, year1, month2, year2 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 // year1, year2 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 // day1, day2 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 // month1, month2 00327 else if ( values.size() == 2 ) 00328 return checkRange( now->tm_mon, values[ 0 ], values[ 1 ] ); 00329 00330 // year 00331 else if ( values.size() == 1 && values[ 0 ] >= 1000 ) 00332 return checkRange( now->tm_year + 1900, values[ 0 ], values[ 0 ] ); 00333 00334 // day 00335 else if ( values.size() == 1 && args[ 0 ].isA( NumberType ) ) 00336 return checkRange( now->tm_mday, values[ 0 ], values[ 0 ] ); 00337 00338 // month 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 // timeRange( hour [, "GMT" ] ) 00347 // timeRange( hour1, hour2 [, "GMT" ] ) 00348 // timeRange( hour1, min1, hour2, min2 [, "GMT" ] ) 00349 // timeRange( hour1, min1, sec1, hour2, min2, sec2 [, "GMT" ] ) 00350 // @returns true if the current time (GMT or local based on presence 00351 // of "GMT" argument) is within the given range 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 // hour1, min1, sec1, hour2, min2, sec2 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 // hour1, min1, hour2, min2 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 // hour1, hour2 00379 else if ( values.size() == 2 ) 00380 return checkRange( now->tm_hour, values[ 0 ], values[ 1 ] ); 00381 00382 // hour 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 // vim: ts=4 sw=4 et
KDE Logo
This file is part of the documentation for kio Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 23:09:32 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003