kio Library API Documentation

kproxybindings.cpp

00001 /*
00002  *  $Id: kproxybindings.cpp,v 1.15.2.1 2003/04/07 14:32:39 mutz 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                 hostname[0] = '\0';
00152                 if(!gethostname(hostname, sizeof(hostname)))
00153                     hostname[sizeof(hostname)-1] = '\0';
00154                 UString addr = dnsResolve(hostname);
00155                 if (addr.isNull())
00156                     result = Undefined();
00157                 else
00158                     result = String(addr);
00159             }
00160             break;
00161         case DNSDomainLevels:
00162             // dnsDomainLevels(host)
00163             // counts the dots in host
00164             if (args.size() == 1)
00165             {
00166                 UString host = args[0].toString(exec);
00167                 int p = -1, count = 0;
00168                 while ((p = host.find(".", p+1)) != -1)
00169                     count++;
00170                 result = Number(count);
00171             }
00172             break;
00173         case ShExpMatch:
00174             // shExpMatch(string, glob)
00175             // true if string matches the shell-glob-like pattern glob
00176             if (args.size() == 2)
00177             {
00178                 QRegExp rex(args[1].toString(exec).qstring(), true, true);
00179                 result = Boolean(rex.search(args[0].toString(exec).qstring(), 0) != -1);
00180             }
00181             break;
00182         case WeekdayRange:
00183             // weekdayRange(day [, "GMT"])
00184             // weekdayRange(day1, day2 [, "GMT"])
00185             // true if the current day is day or between day1 and day2
00186             // if the additional parameter "GMT" is given, compares
00187             // to the current time in GMT, otherwise to localtime
00188             if (args.size() >= 1 && args.size() <= 3)
00189             {
00190                 static const char *weekdays[] = {"son", "mon", "tue", "wed", "thu", "fri", "sat", 0};
00191                 int day1 = findString(args[0].toString(exec).qstring().lower(), weekdays);
00192                 if (day1 == -1)
00193                     break;
00194                 int day2 = args.size() > 1 ?
00195                     findString(args[1].toString(exec).qstring().lower(), weekdays) : -1;
00196                 if (day2 == -1)
00197                     day2 = day1;
00198                 const struct tm *now = getTime(exec,args);
00199                 result = Boolean(checkRange(now->tm_wday, day1, day2));
00200             }
00201             break;
00202         case DateRange:
00203             // dateRange(day [, "GMT"])
00204             // dateRange(day1, day2 [, "GMT"])
00205             // dateRange(month [, "GMT"])
00206             // dateRange(month1, month2 [, "GMT"])
00207             // dateRange(year [, "GMT"])
00208             // dateRange(year1, year2 [, "GMT"])
00209             // dateRange(day1, month1, day2, month2 [, "GMT"])
00210             // dateRange(month1, year1, month2, year2 [, "GMT"])
00211             // dateRange(day1, month1, year1, day2, month2, year2 [, "GMT"])
00212             // true if the current is day or between day1 and day2
00213             // in the month month or between month1 and month2
00214             // in the year year or between year1 and year2
00215             // days are given as numbers from 1 to 31
00216             // months are given as three-letter-names
00217             // years are given with four digits
00218             if (args.size() >= 1 && args.size() <= 7)
00219             {
00220                 static const char *months[] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "nov", "dec", 0};
00221                 int values[6] = {-1, -1, -1, -1, -1, -1};
00222                 for (int i = 0; i < 6 && i < args.size(); ++i)
00223                 {
00224                     if (args[i].isA(NumberType))
00225                         values[i] = (args[i].toInteger(exec));
00226                     else
00227                         values[i] = findString(args[i].toString(exec).qstring().lower(), months);
00228                 }
00229                 int min, max, current;
00230                 const struct tm *now = getTime(exec,args);
00231                 if (values[5] != -1) // day1, month1, year1, day2, month2, year2
00232                 {
00233                     min = values[2] * 372 + values[1] * 31 + values[0];
00234                     max = values[5] * 372 + values[4] * 31 + values[3];
00235                     current = now->tm_year * 372 + now->tm_mon * 31 + now->tm_mday;
00236                 }
00237                 else if (values[3] != -1 && args[0].isA(NumberType)) // day1, month1, day2, month2
00238                 {
00239                     min = values[1] * 31 + values[0];
00240                     max = values[3] * 31 + values[2];
00241                     current = now->tm_mon * 31 + now->tm_mday;
00242                 }
00243                 else if (values[3] != -1) // month1, year1, month2, year2
00244                 {
00245                     min = values[1] * 12 + values[0];
00246                     max = values[3] * 12 + values[2];
00247                     current = now->tm_year * 12 + now->tm_mon;
00248                 }
00249                 else
00250                 {
00251                     min = values[0];
00252                     max = values[1] != -1 ? values[1] : values[0];
00253                     if (!args[0].isA(NumberType)) // month[1, month2]
00254                         current = now->tm_mon;
00255                     else if (values[0] <= 31) // day[1, day2]
00256                         current = now->tm_mday;
00257                     else // year[1, year2]
00258                         current = now->tm_year;
00259                 }
00260                 result = Boolean(checkRange(current, min, max));
00261             }
00262             break;
00263         case TimeRange:
00264             // timeRange(hour [, "GMT"])
00265             // timeRange(hour1, hour2 [, "GMT"])
00266             // timeRange(hour1, min1, hour2, min2 [, "GMT"])
00267             // timeRange(hour1, min1, sec1, hour2, min2, sec2 [, "GMT"])
00268             // true if the current time is in the given range
00269             if (args.size() >= 1 && args.size() <= 7)
00270             {
00271                 int values[6] = {-1, -1, -1, -1, -1, -1};
00272                 for (int i = 0; i < args.size(); ++i)
00273                 {
00274                     if (!args[i].isA(NumberType))
00275                         break;
00276                     values[i] = (args[i].toInteger(exec));
00277                 }
00278                 if (values[0] == -1)
00279                     break;
00280                 int min, max;
00281                 if (values[5] != -1) // hour1, min1, sec1, hour2, min2, sec2
00282                 {
00283                     min = values[0] * 3600 + values[1] * 60 + values[2];
00284                     max = values[3] * 3600 + values[4] * 60 + values[5];
00285                 }
00286                 else if (values[3] != -1) // hour1, min1, hour2, min2
00287                 {
00288                     min = values[0] * 3600 + values[1] * 60;
00289                     max = values[2] * 3600 + values[3] * 60 + 59;
00290                 }
00291                 else if (values[1] != -1) // hour1, hour2
00292                 {
00293                     min = values[0] * 3600;
00294                     max = values[1] * 3600 + 3559;
00295                 }
00296                 else // hour1
00297                 {
00298                     min = values[0] * 3600;
00299                     max = values[0] * 3600 + 3559;
00300                 }
00301                 const struct tm *now = getTime(exec,args);
00302                 result = Boolean(checkRange(now->tm_hour * 3600 + now->tm_min * 60 + now->tm_sec, min, max));
00303             }
00304             break;
00305     }
00306     return result;
00307 }
00308 
00309 const UString KProxyFunc::dnsResolve(const UString &host) const
00310 {
00311     struct hostent *info = gethostbyname(host.ascii());
00312     if (!info)
00313         return UString();
00314     // FIXME is this cast okay (malte)?
00315     return UString(inet_ntoa(*((struct in_addr *) info->h_addr_list[0])));
00316 }
00317 
00318 const struct tm *KProxyFunc::getTime(ExecState *exec, const List &args) const
00319 {
00320     time_t now = time(0);
00321     return args[args.size() -1].toString(exec).qstring().lower() == "gmt" ?
00322         gmtime(&now) : localtime(&now);
00323 }
00324 
00325 int KProxyFunc::findString(const QString &str, const char **list) const
00326 {
00327     for (int i = 0; list[i]; ++i)
00328     {
00329         if (list[i] == str)
00330             return i;
00331     }
00332     return -1;
00333 }
00334 
00335 bool KProxyFunc::checkRange(int value, int min, int max) const
00336 {
00337     return (min <= max && value >= min && value <= max)
00338         || (min > max && (value >= min || value <= max));
00339 }
00340 
00341 
00342 void KProxyFunc::init(ExecState *exec, Object &global)
00343 {
00344     global.put(exec, "ProxyConfig", global);
00345     global.put(exec, "isPlainHostName", Object(new KProxyFunc(KProxyFunc::IsPlainHostName)));
00346     global.put(exec, "dnsDomainIs", Object(new KProxyFunc(KProxyFunc::DNSDomainIs)));
00347     global.put(exec, "localHostOrDomainIs", Object(new KProxyFunc(KProxyFunc::LocalHostOrDomainIs)));
00348     global.put(exec, "isResolvable", Object(new KProxyFunc(KProxyFunc::IsResolvable)));
00349     global.put(exec, "isInNet", Object(new KProxyFunc(KProxyFunc::IsInNet)));
00350     global.put(exec, "dnsResolve", Object(new KProxyFunc(KProxyFunc::DNSResolve)));
00351     global.put(exec, "myIpAddress", Object(new KProxyFunc(KProxyFunc::MyIPAddress)));
00352     global.put(exec, "dnsDomainLevels", Object(new KProxyFunc(KProxyFunc::DNSDomainLevels)));
00353     global.put(exec, "shExpMatch", Object(new KProxyFunc(KProxyFunc::ShExpMatch)));
00354     global.put(exec, "weekdayRange", Object(new KProxyFunc(KProxyFunc::WeekdayRange)));
00355     global.put(exec, "dateRange", Object(new KProxyFunc(KProxyFunc::DateRange)));
00356     global.put(exec, "timeRange", Object(new KProxyFunc(KProxyFunc::TimeRange)));
00357 }
00358 
00359 // vim: ts=4 sw=4 et
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:14:13 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001