kio Library API Documentation

kproxybindings.cpp

00001 /*
00002  *  $Id: kproxybindings.cpp,v 1.15 2002/08/01 15:24:51 coolo Exp $
00003  *  KJS-Bindings for Proxy Auto Configuration
00004  *
00005  *  Copyright (C) 2000 Malte Starostik <malte@kde.org>
00006  *
00007  *  This library is free software; you can redistribute it and/or
00008  *  modify it under the terms of the GNU Library General Public
00009  *  License as published by the Free Software Foundation; either
00010  *  version 2 of the License, or (at your option) any later version.
00011  *
00012  *  This library is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  *  Library General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU Library General Public License
00018  *  along with this library; see the file COPYING.LIB.  If not, write to
00019  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020  *  Boston, MA 02111-1307, USA.
00021  */
00022 
00023 #include <unistd.h>
00024 #include <sys/types.h>
00025 #include <sys/socket.h>
00026 
00027 #include <netinet/in.h>
00028 #include <arpa/inet.h>
00029 
00030 #include <netdb.h>
00031 #include <time.h>
00032 
00033 #include <qstring.h>
00034 #include <qregexp.h>
00035 
00036 #include "kproxybindings.h"
00037 
00038 // e.g. Solaris doesn't have that, but uses -1 for inet_addr() error-handling
00039 #ifndef INADDR_NONE
00040 #define INADDR_NONE -1
00041 #endif
00042 
00043 using namespace KJS;
00044 
00046 QString UString::qstring() const
00047 {
00048     return QString((QChar*) data(), size());
00049 }
00050 
00051 KProxyFunc::KProxyFunc(int id)
00052 {
00053     m_id = id;
00054 }
00055 
00056 bool KProxyFunc::implementsCall() const
00057 {
00058   return true;
00059 }
00060 
00061 Value KProxyFunc::call(ExecState *exec, Object &/*thisObj*/, const List &args)
00062 {
00063     Value result = Undefined();
00064     switch (m_id)
00065     {
00066         case IsPlainHostName:
00067             // isPlainHostName(host)
00068             // true if host does not contain a domain.
00069             if (args.size() == 1)
00070                 result = Boolean(args[0].toString(exec).find(".") == -1);
00071             break;
00072         case DNSDomainIs:
00073             // dnsDomainIs(host, domain)
00074             // true is host ends in domain
00075             if (args.size() == 2)
00076             {
00077                 QString host = args[0].toString(exec).qstring().lower();
00078                 QString domain = args[1].toString(exec).qstring().lower();
00079                 int p = host.find(domain);
00080                 if (p >= 0)
00081                     result = Boolean(host.mid(p) == domain);
00082                 else
00083                     result = Boolean(false);
00084             }
00085             break;
00086         case LocalHostOrDomainIs:
00087             // localHostOrDomainIs(host, domain)
00088             // true if host ends in domain or does not contain any dots.
00089             if (args.size() == 2)
00090             {
00091                 QString host = args[0].toString(exec).qstring().lower();
00092                 if (host.find(".") == -1)
00093                     result = Boolean(true);
00094                 else
00095                 {
00096                     QString domain = args[1].toString(exec).qstring().lower();
00097                     int p = host.find(domain);
00098                     if (p >= 0)
00099                         result = Boolean(host.mid(p) == domain);
00100                     else
00101                         result = Boolean(false);
00102                 }
00103             }
00104             break;
00105         case IsResolvable:
00106             // isResolvable(host)
00107             // true if host can be resolved to an IP
00108             if (args.size() == 1)
00109                 result = Boolean(!dnsResolve(args[0].toString(exec)).isNull());
00110             break;
00111         case IsInNet:
00112             // isInNet(host, pattern, mask)
00113             // true if host (after DNS lookup) is inside the subnet
00114             // given by pattern/mask, both dotted quads
00115             if (args.size() == 3)
00116             {
00117                 UString host = dnsResolve(args[0].toString(exec));
00118                 if (host.isNull())
00119                     result = Boolean(false);
00120                 else
00121                 {
00122                     unsigned long ip, pattern = 0, mask = 0;
00123                     // unfortunately inet_aton is not available on Solaris (malte)
00124                     if ((ip = inet_addr(host.ascii())) == INADDR_NONE
00125                         || (pattern = inet_addr(args[1].toString(exec).ascii())) == INADDR_NONE
00126                         || (mask = inet_addr(args[2].toString(exec).ascii())) == INADDR_NONE)
00127                         result = Boolean(false);
00128                     else
00129                         result = Boolean((ip & mask) == (pattern & mask));
00130                 }
00131             }
00132             break;
00133         case DNSResolve:
00134             // dnsResolve(host)
00135             // returns the IP of host
00136             if (args.size() == 1)
00137             {
00138                 UString addr = dnsResolve(args[0].toString(exec));
00139                 if (addr.isNull())
00140                     result = Undefined();
00141                 else
00142                     result = String(addr);
00143             }
00144             break;
00145         case MyIPAddress:
00146             // myIpAddress()
00147             // returns the IP of the client
00148             if (args.size() == 0)
00149             {
00150                 char hostname[256];
00151                 gethostname(hostname, 255);
00152                 UString addr = dnsResolve(hostname);
00153                 if (addr.isNull())
00154                     result = Undefined();
00155                 else
00156                     result = String(addr);
00157             }
00158             break;
00159         case DNSDomainLevels:
00160             // dnsDomainLevels(host)
00161             // counts the dots in host
00162             if (args.size() == 1)
00163             {
00164                 UString host = args[0].toString(exec);
00165                 int p = -1, count = 0;
00166                 while ((p = host.find(".", p+1)) != -1)
00167                     count++;
00168                 result = Number(count);
00169             }
00170             break;
00171         case ShExpMatch:
00172             // shExpMatch(string, glob)
00173             // true if string matches the shell-glob-like pattern glob
00174             if (args.size() == 2)
00175             {
00176                 QRegExp rex(args[1].toString(exec).qstring(), true, true);
00177                 result = Boolean(rex.search(args[0].toString(exec).qstring(), 0) != -1);
00178             }
00179             break;
00180         case WeekdayRange:
00181             // weekdayRange(day [, "GMT"])
00182             // weekdayRange(day1, day2 [, "GMT"])
00183             // true if the current day is day or between day1 and day2
00184             // if the additional parameter "GMT" is given, compares
00185             // to the current time in GMT, otherwise to localtime
00186             if (args.size() >= 1 && args.size() <= 3)
00187             {
00188                 static const char *weekdays[] = {"son", "mon", "tue", "wed", "thu", "fri", "sat", 0};
00189                 int day1 = findString(args[0].toString(exec).qstring().lower(), weekdays);
00190                 if (day1 == -1)
00191                     break;
00192                 int day2 = args.size() > 1 ?
00193                     findString(args[1].toString(exec).qstring().lower(), weekdays) : -1;
00194                 if (day2 == -1)
00195                     day2 = day1;
00196                 const struct tm *now = getTime(exec,args);
00197                 result = Boolean(checkRange(now->tm_wday, day1, day2));
00198             }
00199             break;
00200         case DateRange:
00201             // dateRange(day [, "GMT"])
00202             // dateRange(day1, day2 [, "GMT"])
00203             // dateRange(month [, "GMT"])
00204             // dateRange(month1, month2 [, "GMT"])
00205             // dateRange(year [, "GMT"])
00206             // dateRange(year1, year2 [, "GMT"])
00207             // dateRange(day1, month1, day2, month2 [, "GMT"])
00208             // dateRange(month1, year1, month2, year2 [, "GMT"])
00209             // dateRange(day1, month1, year1, day2, month2, year2 [, "GMT"])
00210             // true if the current is day or between day1 and day2
00211             // in the month month or between month1 and month2
00212             // in the year year or between year1 and year2
00213             // days are given as numbers from 1 to 31
00214             // months are given as three-letter-names
00215             // years are given with four digits
00216             if (args.size() >= 1 && args.size() <= 7)
00217             {
00218                 static const char *months[] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "nov", "dec", 0};
00219                 int values[6] = {-1, -1, -1, -1, -1, -1};
00220                 for (int i = 0; i < 6 && i < args.size(); ++i)
00221                 {
00222                     if (args[i].isA(NumberType))
00223                         values[i] = (args[i].toInteger(exec));
00224                     else
00225                         values[i] = findString(args[i].toString(exec).qstring().lower(), months);
00226                 }
00227                 int min, max, current;
00228                 const struct tm *now = getTime(exec,args);
00229                 if (values[5] != -1) // day1, month1, year1, day2, month2, year2
00230                 {
00231                     min = values[2] * 372 + values[1] * 31 + values[0];
00232                     max = values[5] * 372 + values[4] * 31 + values[3];
00233                     current = now->tm_year * 372 + now->tm_mon * 31 + now->tm_mday;
00234                 }
00235                 else if (values[3] != -1 && args[0].isA(NumberType)) // day1, month1, day2, month2
00236                 {
00237                     min = values[1] * 31 + values[0];
00238                     max = values[3] * 31 + values[2];
00239                     current = now->tm_mon * 31 + now->tm_mday;
00240                 }
00241                 else if (values[3] != -1) // month1, year1, month2, year2
00242                 {
00243                     min = values[1] * 12 + values[0];
00244                     max = values[3] * 12 + values[2];
00245                     current = now->tm_year * 12 + now->tm_mon;
00246                 }
00247                 else
00248                 {
00249                     min = values[0];
00250                     max = values[1] != -1 ? values[1] : values[0];
00251                     if (!args[0].isA(NumberType)) // month[1, month2]
00252                         current = now->tm_mon;
00253                     else if (values[0] <= 31) // day[1, day2]
00254                         current = now->tm_mday;
00255                     else // year[1, year2]
00256                         current = now->tm_year;
00257                 }
00258                 result = Boolean(checkRange(current, min, max));
00259             }
00260             break;
00261         case TimeRange:
00262             // timeRange(hour [, "GMT"])
00263             // timeRange(hour1, hour2 [, "GMT"])
00264             // timeRange(hour1, min1, hour2, min2 [, "GMT"])
00265             // timeRange(hour1, min1, sec1, hour2, min2, sec2 [, "GMT"])
00266             // true if the current time is in the given range
00267             if (args.size() >= 1 && args.size() <= 7)
00268             {
00269                 int values[6] = {-1, -1, -1, -1, -1, -1};
00270                 for (int i = 0; i < args.size(); ++i)
00271                 {
00272                     if (!args[i].isA(NumberType))
00273                         break;
00274                     values[i] = (args[i].toInteger(exec));
00275                 }
00276                 if (values[0] == -1)
00277                     break;
00278                 int min, max;
00279                 if (values[5] != -1) // hour1, min1, sec1, hour2, min2, sec2
00280                 {
00281                     min = values[0] * 3600 + values[1] * 60 + values[2];
00282                     max = values[3] * 3600 + values[4] * 60 + values[5];
00283                 }
00284                 else if (values[3] != -1) // hour1, min1, hour2, min2
00285                 {
00286                     min = values[0] * 3600 + values[1] * 60;
00287                     max = values[2] * 3600 + values[3] * 60 + 59;
00288                 }
00289                 else if (values[1] != -1) // hour1, hour2
00290                 {
00291                     min = values[0] * 3600;
00292                     max = values[1] * 3600 + 3559;
00293                 }
00294                 else // hour1
00295                 {
00296                     min = values[0] * 3600;
00297                     max = values[0] * 3600 + 3559;
00298                 }
00299                 const struct tm *now = getTime(exec,args);
00300                 result = Boolean(checkRange(now->tm_hour * 3600 + now->tm_min * 60 + now->tm_sec, min, max));
00301             }
00302             break;
00303     }
00304     return result;
00305 }
00306 
00307 const UString KProxyFunc::dnsResolve(const UString &host) const
00308 {
00309     struct hostent *info = gethostbyname(host.ascii());
00310     if (!info)
00311         return UString();
00312     // FIXME is this cast okay (malte)?
00313     return UString(inet_ntoa(*((struct in_addr *) info->h_addr_list[0])));
00314 }
00315 
00316 const struct tm *KProxyFunc::getTime(ExecState *exec, const List &args) const
00317 {
00318     time_t now = time(0);
00319     return args[args.size() -1].toString(exec).qstring().lower() == "gmt" ?
00320         gmtime(&now) : localtime(&now);
00321 }
00322 
00323 int KProxyFunc::findString(const QString &str, const char **list) const
00324 {
00325     for (int i = 0; list[i]; ++i)
00326     {
00327         if (list[i] == str)
00328             return i;
00329     }
00330     return -1;
00331 }
00332 
00333 bool KProxyFunc::checkRange(int value, int min, int max) const
00334 {
00335     return (min <= max && value >= min && value <= max)
00336         || (min > max && (value >= min || value <= max));
00337 }
00338 
00339 
00340 void KProxyFunc::init(ExecState *exec, Object &global)
00341 {
00342     global.put(exec, "ProxyConfig", global);
00343     global.put(exec, "isPlainHostName", Object(new KProxyFunc(KProxyFunc::IsPlainHostName)));
00344     global.put(exec, "dnsDomainIs", Object(new KProxyFunc(KProxyFunc::DNSDomainIs)));
00345     global.put(exec, "localHostOrDomainIs", Object(new KProxyFunc(KProxyFunc::LocalHostOrDomainIs)));
00346     global.put(exec, "isResolvable", Object(new KProxyFunc(KProxyFunc::IsResolvable)));
00347     global.put(exec, "isInNet", Object(new KProxyFunc(KProxyFunc::IsInNet)));
00348     global.put(exec, "dnsResolve", Object(new KProxyFunc(KProxyFunc::DNSResolve)));
00349     global.put(exec, "myIpAddress", Object(new KProxyFunc(KProxyFunc::MyIPAddress)));
00350     global.put(exec, "dnsDomainLevels", Object(new KProxyFunc(KProxyFunc::DNSDomainLevels)));
00351     global.put(exec, "shExpMatch", Object(new KProxyFunc(KProxyFunc::ShExpMatch)));
00352     global.put(exec, "weekdayRange", Object(new KProxyFunc(KProxyFunc::WeekdayRange)));
00353     global.put(exec, "dateRange", Object(new KProxyFunc(KProxyFunc::DateRange)));
00354     global.put(exec, "timeRange", Object(new KProxyFunc(KProxyFunc::TimeRange)));
00355 }
00356 
00357 // vim: ts=4 sw=4 et
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:21:31 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001