aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog47
-rw-r--r--Makefile.am61
-rw-r--r--NEWS1
-rw-r--r--acinclude.m450
-rw-r--r--configure.ac1
-rw-r--r--netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java27
-rw-r--r--netx/net/sourceforge/jnlp/resources/Messages.properties2
-rw-r--r--netx/net/sourceforge/jnlp/runtime/FakePacEvaluator.java54
-rw-r--r--netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java79
-rw-r--r--netx/net/sourceforge/jnlp/runtime/PacEvaluator.java56
-rw-r--r--netx/net/sourceforge/jnlp/runtime/PacEvaluatorFactory.java107
-rw-r--r--netx/net/sourceforge/jnlp/runtime/RhinoBasedPacEvaluator.java255
-rw-r--r--netx/net/sourceforge/jnlp/runtime/pac-funcs.js830
-rw-r--r--tests/netx/pac/pac-funcs-test.js446
14 files changed, 1999 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 861d17a..df05710 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,50 @@
+2011-03-07 Omair Majid <[email protected]>
+
+ * NEWS: Update.
+ * Makefile.am
+ (RHINO_RUNTIME): Define to point to rhino jars, or empty.
+ (RUNTIME, LAUNCHER_BOOTCLASSPATH, PLUGIN_BOOTCLASSPATH): Include
+ RHINO_RUNTIME.
+ (PHONY): Add check-pac-functions, clean-jrunscript and clean-tests.
+ (check-local): New target. Depends on check-pac-functions.
+ (check-pac-functions): New target.
+ (jrunscript): New target.
+ (clean-tests): New target.
+ (clean-jrunscript): New target.
+ (netx-source-files.txt): Remove rhino related files if not building with
+ rhino.
+ (build.properties): New target.
+ (stamps/netx.stamp): Depend on build.properties and copy new files to
+ build location.
+ (clean-netx): Remove build.properties.
+ (stamps/bootstrap-directory.stamp): Add java to bootstrap programs.
+ * acinclude.m4 (IT_FIND_RHINO_JAR): New macro.
+ * configure.ac: Invoke IT_FIND_RHINO_JAR.
+ * netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java: Add
+ browserProxyAutoConfig.
+ (initFromBrowserConfig): Initialize browserProxyAutoConfig if needed.
+ (getFromBrowserPAC): Use browserProxyAutoConfig to find proxies.
+ * netx/net/sourceforge/jnlp/resources/Messages.properties: Replace
+ RPRoxyPacNotImplemented with RPRoxyPacNotSupported.
+ * netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java: Add
+ pacEvaluator.
+ (parseConfiguration): Initialize pacEvaluator if needed.
+ (getFromPAC): Use pacEvaulator to find proxies.
+ (getProxiesFromPacResult): New method. Converts a proxy string to a list
+ or proxies.
+ * netx/net/sourceforge/jnlp/runtime/PacEvaluator.java: New file. Defines a
+ Java interface for a PAC evaluator.
+ * netx/net/sourceforge/jnlp/runtime/FakePacEvaluator.java: New file. Dummy
+ implementation of a PAC evaluator.
+ * netx/net/sourceforge/jnlp/runtime/RhinoBasedPacEvaluator.java: New file.
+ A rhino-based PAC evaluator.
+ * netx/net/sourceforge/jnlp/runtime/PacEvaluatorFactory.java: New file. A
+ factory for creating the right PAC evaulator.
+ * netx/net/sourceforge/jnlp/runtime/pac-funcs.js: New file. Defines helper
+ functions needed while evaluating PAC files.
+ * tests/netx/pac/pac-funcs-test.js: New file. Tests the PAC helper
+ functions.
+
2011-03-07 Denis Lila <[email protected]>
* plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java:
diff --git a/Makefile.am b/Makefile.am
index 7d5c90b..db62df0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,7 +8,14 @@ NETX_EXTRA_DIR=$(abs_top_srcdir)/extra/net/sourceforge/jnlp/about/resources
# Build directories
BOOT_DIR = $(abs_top_builddir)/bootstrap/jdk1.6.0
-RUNTIME = $(BOOT_DIR)/jre/lib/rt.jar:$(BOOT_DIR)/jre/lib/jsse.jar
+
+if WITH_RHINO
+ RHINO_RUNTIME=:$(RHINO_JAR)
+else
+ RHINO_RUNTIME=
+endif
+
+RUNTIME = $(BOOT_DIR)/jre/lib/rt.jar:$(BOOT_DIR)/jre/lib/jsse.jar$(RHINO_RUNTIME)
# Flags
IT_CFLAGS=$(CFLAGS) $(ARCHFLAG)
@@ -18,8 +25,8 @@ IT_CLASS_TARGET_VERSION=6
IT_JAVACFLAGS=$(IT_JAVAC_SETTINGS) -source $(IT_LANGUAGE_SOURCE_VERSION) -target $(IT_CLASS_TARGET_VERSION)
JRE='"$(SYSTEM_JDK_DIR)/jre"'
-LAUNCHER_BOOTCLASSPATH="-J-Xbootclasspath/a:$(DESTDIR)$(datadir)/$(PACKAGE_NAME)/netx.jar"
-PLUGIN_BOOTCLASSPATH='"-Xbootclasspath/a:$(DESTDIR)$(datadir)/$(PACKAGE_NAME)/netx.jar:$(DESTDIR)$(datadir)/$(PACKAGE_NAME)/plugin.jar"'
+LAUNCHER_BOOTCLASSPATH="-J-Xbootclasspath/a:$(DESTDIR)$(datadir)/$(PACKAGE_NAME)/netx.jar$(RHINO_RUNTIME)"
+PLUGIN_BOOTCLASSPATH='"-Xbootclasspath/a:$(DESTDIR)$(datadir)/$(PACKAGE_NAME)/netx.jar:$(DESTDIR)$(datadir)/$(PACKAGE_NAME)/plugin.jar$(RHINO_RUNTIME)"'
# Fake update version to shut up the plugin detector hosted by Oracle.
# If Oracle ever release a JDK update greater than 50, this needs to be increased.
@@ -88,14 +95,17 @@ EXTRA_DIST = $(top_srcdir)/netx $(top_srcdir)/plugin javaws.png javaws.desktop.i
all-local: stamps/netx-dist.stamp extra-lib/about.jar stamps/plugin.stamp $(NETX_DIR)/launcher/javaws \
javaws.desktop stamps/docs.stamp $(NETX_DIR)/launcher/controlpanel/itweb-settings itweb-settings.desktop
+check-local: check-pac-functions
+
clean-local: clean-netx clean-plugin clean-liveconnect clean-extra clean-bootstrap-directory \
- clean-native-ecj clean-desktop-files clean-docs
+ clean-native-ecj clean-desktop-files clean-docs clean-tests
if [ -e stamps ] ; then \
rmdir stamps ; \
fi
.PHONY: clean-IcedTeaPlugin clean-add-netx clean-add-netx-debug clean-add-plugin clean-add-plugin-debug \
- clean-bootstrap-directory clean-native-ecj clean-desktop-files clean-netx-docs clean-docs clean-plugin-docs
+ clean-bootstrap-directory clean-native-ecj clean-desktop-files clean-netx-docs clean-docs clean-plugin-docs \
+ clean-tests clean-jrunscript check-local
install-exec-local:
${mkinstalldirs} $(DESTDIR)$(bindir) $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/ $(DESTDIR)$(libdir)
@@ -241,8 +251,20 @@ clean-liveconnect:
netx-source-files.txt:
find $(NETX_SRCDIR) -name '*.java' | sort > $@
+if !WITH_RHINO
+ sed -i '/RhinoBasedPacEvaluator/ d' $@
+endif
+
+build.properties:
+ echo "# This contains build-time settings " > $@
+if WITH_RHINO
+ echo "rhino.available=true" >> $@
+else
+ echo "rhino.available=false" >> $@
+endif
-stamps/netx.stamp: netx-source-files.txt stamps/bootstrap-directory.stamp
+stamps/netx.stamp: netx-source-files.txt stamps/bootstrap-directory.stamp \
+ build.properties
mkdir -p $(NETX_DIR)
$(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
-d $(NETX_DIR) \
@@ -255,6 +277,9 @@ stamps/netx.stamp: netx-source-files.txt stamps/bootstrap-directory.stamp
${INSTALL_DATA} -D $${files} \
$(NETX_DIR)/net/sourceforge/jnlp/resources/$${files}; \
done)
+ cp -a $(NETX_SRCDIR)/net/sourceforge/jnlp/runtime/pac-funcs.js \
+ $(NETX_DIR)/net/sourceforge/jnlp/runtime
+ cp -a build.properties $(NETX_DIR)/net/sourceforge/jnlp/
mkdir -p stamps
touch $@
@@ -272,6 +297,7 @@ stamps/netx-dist.stamp: stamps/netx.stamp $(abs_top_builddir)/netx.manifest
clean-netx:
rm -rf $(NETX_DIR)
+ rm -f build.properties
rm -f stamps/netx-dist.stamp
rm -f netx-source-files.txt
rm -f stamps/netx.stamp
@@ -376,6 +402,28 @@ clean-plugin-docs:
rm -rf ${abs_top_builddir}/docs/plugin
rm -f stamps/plugin-docs.stamp
+
+# check
+# ==========================
+
+jrunscript:
+if WITH_RHINO
+ echo '$(BOOT_DIR)/bin/java -cp $(RHINO_JAR) org.mozilla.javascript.tools.shell.Main $$@' > jrunscript
+ chmod u+x jrunscript
+else
+ echo "jrunscript requires rhino support"
+ exit 1
+endif
+
+check-pac-functions: stamps/bootstrap-directory.stamp jrunscript
+ ./jrunscript $(abs_top_srcdir)/tests/netx/pac/pac-funcs-test.js \
+ $$(readlink -f $(abs_top_srcdir)/netx/net/sourceforge/jnlp/runtime/pac-funcs.js)
+
+clean-tests: clean-jrunscript
+
+clean-jrunscript:
+ rm -f jrunscript
+
# plugin tests
if ENABLE_PLUGIN
@@ -412,6 +460,7 @@ clean-native-ecj:
# bootstrap
stamps/bootstrap-directory.stamp: stamps/native-ecj.stamp
mkdir -p $(BOOT_DIR)/bin stamps/
+ ln -sf $(JAVA) $(BOOT_DIR)/bin/java
ln -sf $(JAR) $(BOOT_DIR)/bin/jar
ln -sf $(abs_top_builddir)/javac $(BOOT_DIR)/bin/javac
ln -sf $(JAVADOC) $(BOOT_DIR)/bin/javadoc
diff --git a/NEWS b/NEWS
index 9231a97..bc75c92 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,7 @@ New in release 1.1 (2011-XX-XX):
- RH677332, CVE-2011-0706: IcedTea multiple signers privilege escalation
* New Features
- IcedTea-Web now installs to a FHS-compliant location
+ - IcedTea-Web can now handle Proxy Auto Config files
* Common Fixes and Improvements
- PR638: JNLPClassLoader.loadClass(String name) can return null
- RH677772: NoSuchAlgorithmException using SSL/TLS in javaws
diff --git a/acinclude.m4 b/acinclude.m4
index 9d06708..cd80f62 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -250,6 +250,56 @@ AC_DEFUN([FIND_ECJ_JAR],
AC_SUBST(ECJ_JAR)
])
+AC_DEFUN([IT_FIND_RHINO_JAR],
+[
+ AC_MSG_CHECKING([whether to include Javascript support via Rhino])
+ AC_ARG_WITH([rhino],
+ [AS_HELP_STRING(--with-rhino,specify location of the rhino jar)],
+ [
+ case "${withval}" in
+ yes)
+ RHINO_JAR=yes
+ ;;
+ no)
+ RHINO_JAR=no
+ ;;
+ *)
+ if test -f "${withval}"; then
+ RHINO_JAR="${withval}"
+ elif test -z "${withval}"; then
+ RHINO_JAR=yes
+ else
+ AC_MSG_RESULT([not found])
+ AC_MSG_ERROR("The rhino jar ${withval} was not found.")
+ fi
+ ;;
+ esac
+ ],
+ [
+ RHINO_JAR=yes
+ ])
+ if test x"${RHINO_JAR}" = "xyes"; then
+ if test -e "/usr/share/java/rhino.jar"; then
+ RHINO_JAR=/usr/share/java/rhino.jar
+ elif test -e "/usr/share/java/js.jar"; then
+ RHINO_JAR=/usr/share/java/js.jar
+ elif test -e "/usr/share/rhino-1.6/lib/js.jar"; then
+ RHINO_JAR=/usr/share/rhino-1.6/lib/js.jar
+ fi
+ if test x"${RHINO_JAR}" = "xyes"; then
+ AC_MSG_RESULT([not found])
+ AC_MSG_ERROR("A rhino jar was not found in /usr/share/java as either rhino.jar or js.jar.")
+ fi
+ fi
+ AC_MSG_RESULT(${RHINO_JAR})
+ AM_CONDITIONAL(WITH_RHINO, test x"${RHINO_JAR}" != "xno")
+dnl Clear RHINO_JAR if it doesn't contain a valid filename
+ if test x"${RHINO_JAR}" = "xno"; then
+ RHINO_JAR=
+ fi
+ AC_SUBST(RHINO_JAR)
+])
+
AC_DEFUN_ONCE([IT_CHECK_PLUGIN],
[
AC_MSG_CHECKING([whether to build the browser plugin])
diff --git a/configure.ac b/configure.ac
index 38ddd6f..e7a618a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -33,6 +33,7 @@ FIND_JAVAC
FIND_JAR
FIND_ECJ_JAR
IT_FIND_JAVADOC
+IT_FIND_RHINO_JAR
AC_CONFIG_FILES([javac], [chmod +x javac])
IT_SET_VERSION
diff --git a/netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java b/netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java
index fb08325..331b954 100644
--- a/netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java
+++ b/netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java
@@ -54,6 +54,8 @@ import java.util.Map;
import net.sourceforge.jnlp.runtime.JNLPProxySelector;
import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.runtime.PacEvaluator;
+import net.sourceforge.jnlp.runtime.PacEvaluatorFactory;
/**
* A ProxySelector which can read proxy settings from a browser's
@@ -85,6 +87,8 @@ public class BrowserAwareProxySelector extends JNLPProxySelector {
private String browserSocks4ProxyHost;
private int browserSocks4ProxyPort;
+ private PacEvaluator browserProxyAutoConfig = null;
+
/**
* Create a new instance of this class, reading configuration fropm the browser
*/
@@ -128,6 +132,12 @@ public class BrowserAwareProxySelector extends JNLPProxySelector {
e.printStackTrace();
}
+ if (browserProxyType == BROWSER_PROXY_TYPE_PAC) {
+ if (browserAutoConfigUrl != null) {
+ browserProxyAutoConfig = PacEvaluatorFactory.getPacEvaluator(browserAutoConfigUrl);
+ }
+ }
+
browserUseSameProxy = Boolean.valueOf(prefs.get("network.proxy.share_proxy_settings"));
browserHttpProxyHost = prefs.get("network.proxy.http");
@@ -216,8 +226,21 @@ public class BrowserAwareProxySelector extends JNLPProxySelector {
* browser.
*/
private List<Proxy> getFromBrowserPAC(URI uri) {
- System.err.println(R("RPRoxyPacNotImplemented"));
- return Arrays.asList(new Proxy[] { Proxy.NO_PROXY });
+ if (browserAutoConfigUrl == null || uri.getScheme().equals("socket")) {
+ return Arrays.asList(new Proxy[] { Proxy.NO_PROXY });
+ }
+
+ List<Proxy> proxies = new ArrayList<Proxy>();
+
+ try {
+ String proxiesString = browserProxyAutoConfig.getProxies(uri.toURL());
+ proxies.addAll(getProxiesFromPacResult(proxiesString));
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ proxies.add(Proxy.NO_PROXY);
+ }
+
+ return proxies;
}
/**
diff --git a/netx/net/sourceforge/jnlp/resources/Messages.properties b/netx/net/sourceforge/jnlp/resources/Messages.properties
index 204509c..a002bc3 100644
--- a/netx/net/sourceforge/jnlp/resources/Messages.properties
+++ b/netx/net/sourceforge/jnlp/resources/Messages.properties
@@ -144,7 +144,7 @@ RNestedJarExtration=Unable to extract nested jar.
RUnexpected=Unexpected {0} at {1}
RConfigurationError=Fatal error while reading the configuration
RConfigurationFatal=ERROR: a fatal error has occurred while loading configuration. Perhaps a global configuration was required but could not be found
-RPRoxyPacNotImplemented=Using Proxy Auto Config (PAC) files is not supported yet.
+RPRoxyPacNotSupported=Using Proxy Auto Config (PAC) files is not supported.
RProxyFirefoxNotFound=Unable to use Firefox's proxy settings. Using "DIRECT" as proxy type.
RProxyFirefoxOptionNotImplemented=Browser proxy option "{0}" ({1}) not supported yet.
diff --git a/netx/net/sourceforge/jnlp/runtime/FakePacEvaluator.java b/netx/net/sourceforge/jnlp/runtime/FakePacEvaluator.java
new file mode 100644
index 0000000..98ff9d1
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/runtime/FakePacEvaluator.java
@@ -0,0 +1,54 @@
+/* FakePacEvaluator.java
+ Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.runtime;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+import java.net.URL;
+
+/**
+ * A dummy PacEvaluator that always returns "DIRECT"
+ */
+public class FakePacEvaluator implements PacEvaluator {
+ @Override
+ public String getProxies(URL url) {
+ if (JNLPRuntime.isDebug()) {
+ System.err.println(R("RPRoxyPacNotSupported"));
+ }
+ return "DIRECT";
+ }
+}
diff --git a/netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java b/netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java
index cf7d6a8..db5a9b7 100644
--- a/netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java
@@ -16,7 +16,6 @@
package net.sourceforge.jnlp.runtime;
-import static net.sourceforge.jnlp.runtime.Translator.R;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -52,6 +51,8 @@ public abstract class JNLPProxySelector extends ProxySelector {
/** The default port to use as a fallback. Currently squid's default port */
public static final int FALLBACK_PROXY_PORT = 3128;
+ private PacEvaluator pacEvaluator = null;
+
/** The proxy type. See PROXY_TYPE_* constants */
private int proxyType = PROXY_TYPE_UNKNOWN;
@@ -96,8 +97,7 @@ public abstract class JNLPProxySelector extends ProxySelector {
proxyType = Integer.valueOf(config.getProperty(DeploymentConfiguration.KEY_PROXY_TYPE));
- String autoConfigString = config
- .getProperty(DeploymentConfiguration.KEY_PROXY_AUTO_CONFIG_URL);
+ String autoConfigString = config.getProperty(DeploymentConfiguration.KEY_PROXY_AUTO_CONFIG_URL);
if (autoConfigString != null) {
try {
autoConfigUrl = new URL(autoConfigString);
@@ -106,6 +106,10 @@ public abstract class JNLPProxySelector extends ProxySelector {
}
}
+ if (autoConfigUrl != null) {
+ pacEvaluator = PacEvaluatorFactory.getPacEvaluator(autoConfigUrl);
+ }
+
bypassList = new ArrayList<String>();
String proxyBypass = config.getProperty(DeploymentConfiguration.KEY_PROXY_BYPASS_LIST);
if (proxyBypass != null) {
@@ -333,14 +337,22 @@ public abstract class JNLPProxySelector extends ProxySelector {
*
* @return a List of valid Proxy objects
*/
- private List<Proxy> getFromPAC(URI uri) {
- if (autoConfigUrl == null) {
+ protected List<Proxy> getFromPAC(URI uri) {
+ if (autoConfigUrl == null || uri.getScheme().equals("socket")) {
return Arrays.asList(new Proxy[] { Proxy.NO_PROXY });
}
- // TODO implement this by reading and using the PAC file
- System.err.println(R("RPRoxyPacNotImplemented"));
- return Arrays.asList(new Proxy[] { Proxy.NO_PROXY });
+ List<Proxy> proxies = new ArrayList<Proxy>();
+
+ try {
+ String proxiesString = pacEvaluator.getProxies(uri.toURL());
+ proxies.addAll(getProxiesFromPacResult(proxiesString));
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ proxies.add(Proxy.NO_PROXY);
+ }
+
+ return proxies;
}
/**
@@ -351,5 +363,56 @@ public abstract class JNLPProxySelector extends ProxySelector {
*/
protected abstract List<Proxy> getFromBrowser(URI uri);
+ /**
+ * Converts a proxy string from a browser into a List of Proxy objects
+ * suitable for java.
+ * @param pacString a string indicating proxies. For example
+ * "PROXY foo.bar:3128; DIRECT"
+ * @return a list of Proxy objects represeting the parsed string.
+ */
+ public static List<Proxy> getProxiesFromPacResult(String pacString) {
+ List<Proxy> proxies = new ArrayList<Proxy>();
+
+ String[] tokens = pacString.split(";");
+ for (String token: tokens) {
+ if (token.startsWith("PROXY")) {
+ String hostPortPair = token.substring("PROXY".length()).trim();
+ if (!hostPortPair.contains(":")) {
+ continue;
+ }
+ String host = hostPortPair.split(":")[0];
+ int port;
+ try {
+ port = Integer.valueOf(hostPortPair.split(":")[1]);
+ } catch (NumberFormatException nfe) {
+ continue;
+ }
+ SocketAddress sa = new InetSocketAddress(host, port);
+ proxies.add(new Proxy(Type.HTTP, sa));
+ } else if (token.startsWith("SOCKS")) {
+ String hostPortPair = token.substring("SOCKS".length()).trim();
+ if (!hostPortPair.contains(":")) {
+ continue;
+ }
+ String host = hostPortPair.split(":")[0];
+ int port;
+ try {
+ port = Integer.valueOf(hostPortPair.split(":")[1]);
+ } catch (NumberFormatException nfe) {
+ continue;
+ }
+ SocketAddress sa = new InetSocketAddress(host, port);
+ proxies.add(new Proxy(Type.SOCKS, sa));
+ } else if (token.startsWith("DIRECT")) {
+ proxies.add(Proxy.NO_PROXY);
+ } else {
+ if (JNLPRuntime.isDebug()) {
+ System.out.println("Unrecognized proxy token: " + token);
+ }
+ }
+ }
+
+ return proxies;
+ }
}
diff --git a/netx/net/sourceforge/jnlp/runtime/PacEvaluator.java b/netx/net/sourceforge/jnlp/runtime/PacEvaluator.java
new file mode 100644
index 0000000..936602e
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/runtime/PacEvaluator.java
@@ -0,0 +1,56 @@
+/* PacEvaluator.java
+ Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.runtime;
+
+import java.net.URL;
+
+/**
+ * This interface represents an object which can evaluate Proxy Auto Config
+ * files.
+ */
+public interface PacEvaluator {
+ /**
+ * Get the proxies for accessing a given URL. The result is obtained by
+ * evaluating the PAC file with the given url (and the host) as input.
+ *
+ * @param url the url for which a proxy is desired
+ * @return a list of proxies in a string like
+ * <pre>"PROXY foo.example.com:8080; PROXY bar.example.com:8080; DIRECT"</pre>
+ */
+ public String getProxies(URL url);
+}
diff --git a/netx/net/sourceforge/jnlp/runtime/PacEvaluatorFactory.java b/netx/net/sourceforge/jnlp/runtime/PacEvaluatorFactory.java
new file mode 100644
index 0000000..9ed6217
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/runtime/PacEvaluatorFactory.java
@@ -0,0 +1,107 @@
+/* PacEvaluatorFactory.java
+ Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.runtime;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.util.Properties;
+
+
+public class PacEvaluatorFactory {
+
+ public static PacEvaluator getPacEvaluator(URL pacUrl) {
+ boolean useRhino = false;
+
+ ClassLoader cl = PacEvaluatorFactory.class.getClassLoader();
+ if (cl == null) {
+ cl = ClassLoader.getSystemClassLoader();
+ }
+ InputStream in = cl.getResourceAsStream("net/sourceforge/jnlp/build.properties");
+ Properties properties = null;
+ try {
+ properties = new Properties();
+ properties.load(in);
+ } catch (IOException e) {
+ if (JNLPRuntime.isDebug()) {
+ e.printStackTrace();
+ }
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e) {
+ if (JNLPRuntime.isDebug()) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ if (properties == null) {
+ return new FakePacEvaluator();
+ }
+
+ String available = properties.getProperty("rhino.available");
+ useRhino = Boolean.valueOf(available);
+
+ if (useRhino) {
+ try {
+ Class<?> evaluator = Class.forName("net.sourceforge.jnlp.runtime.RhinoBasedPacEvaluator");
+ Constructor<?> constructor = evaluator.getConstructor(URL.class);
+ return (PacEvaluator) constructor.newInstance(pacUrl);
+ } catch (ClassNotFoundException e) {
+ // ignore
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ if (e.getCause() != null) {
+ e.getCause().printStackTrace();
+ }
+ }
+ }
+
+ return new FakePacEvaluator();
+ }
+}
diff --git a/netx/net/sourceforge/jnlp/runtime/RhinoBasedPacEvaluator.java b/netx/net/sourceforge/jnlp/runtime/RhinoBasedPacEvaluator.java
new file mode 100644
index 0000000..d5e4ffb
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/runtime/RhinoBasedPacEvaluator.java
@@ -0,0 +1,255 @@
+/* RhinoBasedPacEvaluator.java
+ Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.runtime;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.SocketPermission;
+import java.net.URL;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+
+import net.sourceforge.jnlp.util.TimedHashMap;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.Scriptable;
+
+/**
+ * Represents a Proxy Auto Config file. This object can be used to evaluate the
+ * proxy file to find the proxy for a given url.
+ *
+ * @see http://en.wikipedia.org/wiki/Proxy_auto-config#The_PAC_file
+ */
+public class RhinoBasedPacEvaluator implements PacEvaluator {
+
+ private final String pacHelperFunctionContents;
+ private final String pacContents;
+ private final URL pacUrl;
+ private final TimedHashMap<String, String> cache;
+
+ /**
+ * Initialize a new object by using the PAC file located at the given URL.
+ *
+ * @param pacUrl the url of the PAC file to use
+ */
+ public RhinoBasedPacEvaluator(URL pacUrl) {
+ if (JNLPRuntime.isDebug()) {
+ System.err.println("Using the Rhino based PAC evaluator for url " + pacUrl);
+ }
+ pacHelperFunctionContents = getHelperFunctionContents();
+ this.pacUrl = pacUrl;
+ pacContents = getPacContents(pacUrl);
+ cache = new TimedHashMap<String, String>();
+ }
+
+ /**
+ * Get the proxies for accessing a given URL. The result is obtained by
+ * evaluating the PAC file with the given url (and the host) as input.
+ *
+ * This method performs caching of the result.
+ *
+ * @param url the url for which a proxy is desired
+ * @return a list of proxies in a string like
+ * <pre>"PROXY foo.example.com:8080; PROXY bar.example.com:8080; DIRECT"</pre>
+ *
+ * @see #getProxiesWithoutCaching(URL)
+ */
+ public String getProxies(URL url) {
+ String cachedResult = getFromCache(url);
+ if (cachedResult != null) {
+ return cachedResult;
+ }
+
+ String result = getProxiesWithoutCaching(url);
+ addToCache(url, cachedResult);
+ return result;
+ }
+
+ /**
+ * Get the proxies for accessing a given URL. The result is obtained by
+ * evaluating the PAC file with the given url (and the host) as input.
+ *
+ * @param url the url for which a proxy is desired
+ * @return a list of proxies in a string like
+ * <pre>"PROXY example.com:3128; DIRECT"</pre>
+ *
+ * @see #getProxies(URL)
+ */
+ private String getProxiesWithoutCaching(URL url) {
+ if (pacHelperFunctionContents == null) {
+ System.err.println("Error loading pac functions");
+ return "DIRECT";
+ }
+
+ EvaluatePacAction evaluatePacAction = new EvaluatePacAction(pacContents, pacUrl.toString(),
+ pacHelperFunctionContents, url);
+ Permissions p = new Permissions();
+ p.add(new RuntimePermission("accessClassInPackage.org.mozilla.javascript"));
+ p.add(new SocketPermission("*", "resolve"));
+ ProtectionDomain pd = new ProtectionDomain(null, p);
+ AccessControlContext context = new AccessControlContext(new ProtectionDomain[] { pd });
+
+ return AccessController.doPrivileged(evaluatePacAction, context);
+ }
+
+ /**
+ * Returns the contents of file at pacUrl as a String.
+ */
+ private String getPacContents(URL pacUrl) {
+ StringBuilder contents = null;
+ try {
+ String line = null;
+ BufferedReader pacReader = new BufferedReader(new InputStreamReader(pacUrl.openStream()));
+ contents = new StringBuilder();
+ while ((line = pacReader.readLine()) != null) {
+ // System.out.println(line);
+ contents = contents.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ contents = null;
+ }
+
+ return (contents != null) ? contents.toString() : null;
+ }
+
+ /**
+ * Returns the pac helper functions as a String. The functions are read
+ * from net/sourceforge/jnlp/resources/pac-funcs.js
+ */
+ private String getHelperFunctionContents() {
+ StringBuilder contents = null;
+ try {
+ String line;
+ ClassLoader cl = this.getClass().getClassLoader();
+ if (cl == null) {
+ cl = ClassLoader.getSystemClassLoader();
+ }
+ InputStream in = cl.getResourceAsStream("net/sourceforge/jnlp/runtime/pac-funcs.js");
+ BufferedReader pacFuncsReader = new BufferedReader(new InputStreamReader(in));
+ contents = new StringBuilder();
+ while ((line = pacFuncsReader.readLine()) != null) {
+ // System.out.println(line);
+ contents = contents.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ contents = null;
+ }
+
+ return (contents != null) ? contents.toString() : null;
+ }
+
+ /**
+ * Gets an entry from the cache
+ */
+ private String getFromCache(URL url) {
+ String lookupString = url.getProtocol() + "://" + url.getHost();
+ String result = cache.get(lookupString);
+ return result;
+ }
+
+ /**
+ * Adds an entry to the cache
+ */
+ private void addToCache(URL url, String proxyResult) {
+ String lookupString = url.getAuthority() + "://" + url.getHost();
+ cache.put(lookupString, proxyResult);
+ }
+
+ /**
+ * Helper classs to run remote javascript code (specified by the user as
+ * PAC URL) inside a sandbox.
+ */
+ private static class EvaluatePacAction implements PrivilegedAction<String> {
+
+ private String pacContents;
+ private String pacUrl;
+ private String pacFuncsContents;
+ private URL url;
+
+ public EvaluatePacAction(String pacContents, String pacUrl, String pacFuncsContents, URL url) {
+ this.pacContents = pacContents;
+ this.pacUrl = pacUrl;
+ this.pacFuncsContents = pacFuncsContents;
+ this.url = url;
+ }
+
+ public String run() {
+ Context cx = Context.enter();
+ try {
+ /*
+ * TODO defense in depth.
+ *
+ * This is already running within a sandbox, but we can (and we
+ * should) lock it down further. Look into ClassShutter.
+ */
+ Scriptable scope = cx.initStandardObjects();
+ // any optimization level greater than -1 will trigger code generation
+ // and this block will then need classloader permissions
+ cx.setOptimizationLevel(-1);
+ Object result = null;
+ result = cx.evaluateString(scope, pacFuncsContents, "internal", 1, null);
+ result = cx.evaluateString(scope, pacContents, pacUrl, 1, null);
+
+ Object functionObj = scope.get("FindProxyForURL", scope);
+ if (!(functionObj instanceof Function)) {
+ System.err.println("FindProxyForURL not found");
+ return null;
+ } else {
+ Function findProxyFunction = (Function) functionObj;
+
+ Object[] args = { url.toString(), url.getHost() };
+ result = findProxyFunction.call(cx, scope, scope, args);
+ return (String) result;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return "DIRECT";
+ } finally {
+ Context.exit();
+ }
+ }
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/runtime/pac-funcs.js b/netx/net/sourceforge/jnlp/runtime/pac-funcs.js
new file mode 100644
index 0000000..716def6
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/runtime/pac-funcs.js
@@ -0,0 +1,830 @@
+/* pac-funcs.js
+ Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+/*
+ * These helper functions are required to be able to parse Proxy Auto Config
+ * (PAC) files. PAC files will use these helper functions to decide the best
+ * proxy for connecting to a host.
+ *
+ * This implementation is based on the description of the functions at:
+ * http://web.archive.org/web/20060424005037/wp.netscape.com/eng/mozilla/2.0/relnotes/demo/proxy-live.html
+ */
+
+/**
+ * Returns true if the host does not contain a domain (there are no dots)
+ */
+function isPlainHostName(host) {
+ if (host.indexOf(".") === -1) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * Returns true if the host is part of the domain (the host ends with domain)
+ */
+function dnsDomainIs(host, domain) {
+ var loc = host.lastIndexOf(domain);
+ if (loc === -1) {
+ return false;
+ }
+ if (loc + domain.length === host.length) {
+ // host ends with domain
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Returns true if the host is an exact match of hostdom or if host is not a
+ * fully qualified name but has the same hostname as hostdom
+ */
+function localHostOrDomainIs(host, hostdom) {
+ if (host === hostdom) {
+ // exact match
+ return true;
+ }
+ var firstdot = hostdom.indexOf(".");
+ if (firstdot === -1) {
+ // hostdom has no dots
+ return false;
+ }
+ if (host === hostdom.substring(0, firstdot)) {
+ // hostname matches
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Returns true if the host name can be resolved.
+ */
+function isResolvable(host) {
+ try {
+ java.net.InetAddress.getByName(host);
+ return true;
+ } catch (e) {
+ //if (e.javaException instanceof java.net.UnknownHostException) {
+ return false;
+ //} else {
+ // throw e;
+ //}
+ }
+}
+
+/**
+ * Return true if the ip address of the host matches the pattern given the mask.
+ */
+function isInNet(host, pattern, mask) {
+ if (!isResolvable(host)) {
+ return false;
+ }
+
+ var hostIp = dnsResolve(host);
+ var hostParts = hostIp.split(".");
+ var patternParts = pattern.split(".");
+ var maskParts = mask.split(".");
+
+ if (hostParts.length !== 4 ||
+ patternParts.length !== hostParts.length ||
+ maskParts.length !== hostParts.length) {
+ return false;
+ }
+
+ var matched = true;
+ for (var i = 0; i < hostParts.length; i++) {
+ var partMatches = (hostParts[i] & maskParts[i]) === (patternParts[i] & maskParts[i]);
+ matched = matched && partMatches;
+ }
+
+ return matched;
+}
+
+/**
+ * Returns the IP address of the host as a string
+ */
+function dnsResolve(host) {
+ return java.net.InetAddress.getByName(host).getHostAddress() + "";
+}
+
+/**
+ * Returns the local IP address
+ */
+function myIpAddress() {
+ return java.net.InetAddress.getLocalHost().getHostAddress() + "";
+}
+
+/**
+ * Returns the number of domains in a hostname
+ */
+function dnsDomainLevels(host) {
+ var levels = 0;
+ for (var i = 0; i < host.length; i++) {
+ if (host[i] === '.') {
+ levels++;
+ }
+ }
+ return levels;
+}
+
+/**
+ * Returns true if the shell expression matches the given input string
+ */
+function shExpMatch(str, shExp) {
+
+ // TODO support all special characters
+ // right now we support only * and ?
+
+
+ try {
+
+ // turn shExp into a regular expression
+
+ var work = "";
+
+ // escape characters
+ for (var i = 0; i < shExp.length; i++) {
+ var ch = shExp[i];
+ switch (ch) {
+ case "\\": work = work + "\\\\"; break;
+ case "^": work = work + "\\^"; break;
+ case "$": work = work + "\\$"; break;
+ case "+": work = work + "\\+"; break;
+ case ".": work = work + "\\."; break;
+ case "(": work = work + "\\("; break;
+ case ")": work = work + "\\)"; break;
+ case "{": work = work + "\\{"; break;
+ case "}": work = work + "\\}"; break;
+ case "[": work = work + "\\["; break;
+ case "]": work = work + "\\]"; break;
+
+ case "?": work = work + ".{1}"; break;
+ case "*": work = work + ".*"; break;
+
+ default:
+ work = work + ch;
+ }
+
+ }
+
+ var regExp = "^" + work + "$";
+
+ // match
+ //java.lang.System.out.println("")
+ //java.lang.System.out.println("Input String : " + str);
+ //java.lang.System.out.println("Input Pattern : " + shExp);
+ //java.lang.System.out.println("RegExp : " + regExp.toString());
+ var match = str.match(regExp);
+
+ if (match === null) {
+ return false;
+ } else {
+ return true;
+ }
+
+
+ } catch (e) {
+ return false;
+ }
+
+}
+
+
+/**
+ * Returns true if the current weekday matches the desired weekday(s)
+ *
+ * Possible ways of calling:
+ * weekdayRange(wd1);
+ * weekdayRange(wd1, "GMT");
+ * weekdayRange(wd1, wd2);
+ * weekdayRange(wd1, wd2, "GMT");
+ *
+ * Where wd1 and wd2 are one of "SUN", "MON", "TUE", "WED", "THU", "FRI" and
+ * "SAT"
+ *
+ * The argument "GMT", if present, is always the last argument
+ */
+function weekdayRange() {
+ var wd1;
+ var wd2;
+ var gmt = false;
+
+ function isWeekDay(day) {
+ if (day === "SUN" || day === "MON" || day === "TUE" || day === "WED" ||
+ day === "THU" || day === "FRI" || day === "SAT") {
+ return true;
+ }
+ return false;
+ }
+
+ function strToWeekDay(str) {
+ switch (str) {
+ case "SUN": return 0;
+ case "MON": return 1;
+ case "TUE": return 2;
+ case "WED": return 3;
+ case "THU": return 4;
+ case "FRI": return 5;
+ case "SAT": return 6;
+ default: return 0;
+ }
+ }
+
+ if (arguments.length > 1) {
+ if (arguments[arguments.length-1] === "GMT") {
+ gmt = true;
+ arguments.splice(0,arguments.length-1);
+ }
+ }
+
+ if (arguments.length === 0) { return false; }
+
+ wd1 = arguments[0];
+
+ if (!isWeekDay(wd1)) { return false; }
+
+ var today = new Date().getDay();
+ if (arguments.length >= 2) {
+ // return true if current weekday is between wd1 and wd2 (inclusive)
+ wd2 = arguments[1];
+ if (!isWeekDay(wd2)) { return false; }
+
+ var day1 = strToWeekDay(wd1);
+ var day2 = strToWeekDay(wd2);
+
+ if (day1 <= day2) {
+ if ( day1 <= today && today <= day2) {
+ return true;
+ }
+ return false;
+ } else {
+ if (day1 <= today || today <= day2) {
+ return true;
+ }
+ return false;
+ }
+ } else {
+ // return true if the current weekday is wd1
+ if (strToWeekDay(wd1) === today) {
+ return true;
+ }
+ return false;
+ }
+}
+
+/**
+ * Returns true if the current date matches the given date(s)
+ *
+ * Possible ways of calling:
+ * dateRange(day)
+ * dateRange(day1, day2)
+ * dateRange(month)
+ * dateRange(month1, month2)
+ * dateRange(year)
+ * dateRange(year1, year2)
+ * dateRange(day1, month1, day2, month2)
+ * dateRange(month1, year1, month2, year2)
+ * dateRange(day1, month1, year1, day2, month2, year2)
+ *
+ * The parameter "GMT" may additionally be passed as the last argument in any
+ * of the above ways of calling.
+ */
+function dateRange() {
+
+ // note: watch out for wrapping around of dates. date ranges, like
+ // month=9 to month=8, wrap around and cover the entire year. this
+ // makes everything more interesting
+
+ var gmt;
+ if (arguments.length > 1) {
+ if (arguments[arguments.length-1] === "GMT") {
+ gmt = true;
+ arguments.splice(0,arguments.length-1);
+ }
+ }
+
+ function isDate(date) {
+ if (typeof(date) === 'number' && (date <= 31 && date >= 1)) {
+ return true;
+ }
+ return false;
+ }
+
+ function strToMonth(month) {
+ switch (month) {
+ case "JAN": return 0;
+ case "FEB": return 1;
+ case "MAR": return 2;
+ case "APR": return 3;
+ case "MAY": return 4;
+ case "JUN": return 5;
+ case "JUL": return 6;
+ case "AUG": return 7;
+ case "SEP": return 8;
+ case "OCT": return 9;
+ case "NOV": return 10;
+ case "DEC": return 11;
+ default: return 0;
+ }
+ }
+
+ function isMonth(month) {
+ if (month === "JAN" || month === "FEB" || month === "MAR" ||
+ month === "APR" || month === "MAY" || month === "JUN" ||
+ month === "JUL" || month === "AUG" || month === "SEP" ||
+ month === "OCT" || month === "NOV" || month === "DEC") {
+ return true;
+ }
+ return false;
+ }
+
+ function isYear(year) {
+ if (typeof(year) === 'number') {
+ return true;
+ }
+ return false;
+ }
+
+ function inDateRange(today, date1, date2) {
+ if (date1 <= date2) {
+ if (date1 <= today.getDate() && today.getDate() <= date2) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (date1 <= today.getDate() || today.getDate() <= date2) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ function inMonthRange(today, month1, month2) {
+ if (month1 <= month2) {
+ if (month1 <= today.getMonth() && today.getMonth() <= month2) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (month1 <= today.getMonth() || today.getMonth() <= month2) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ function inYearRange(today, year1, year2) {
+ if (year1 <= today.getYear() && today.getYear() <= year2) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ function inMonthDateRange(today, date1, month1, date2, month2) {
+ if (month1 === month2) {
+ if (today.getMonth() === month1) {
+ if (date1 <= today.getDate() && today.getDate() <= date2) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (date1 <= date2) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ } else if (month1 < month2) {
+ if (month1 <= today.getMonth() && today.getMonth() <= month2) {
+ if (today.getMonth() === month1) {
+ if (today.getDate() >= date1) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (today.getMonth() === month2) {
+ if (today.getDate() <= date2) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+ } else {
+ if (month1 <= today.getMonth() || today.getMonth() <= month2) {
+ if (today.getMonth() === month1) {
+ if (today.getDate() >= date1) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (today.getMonth() === month2) {
+ if (today.getDate() <= date2) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+
+ function inYearMonthRange(today, month1, year1, month2, year2) {
+ if (year1 === year2) {
+ if (today.getYear() === year1) {
+ if (month1 <= today.getMonth() && today.getMonth() <= month2) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ if (year1 < year2) {
+ if (year1 <= today.getYear() && today.getYear() <= year2) {
+ if (today.getYear() === year1) {
+ if (today.getMonth() >= month1) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (today.getYear() === year2) {
+ if (today.getMonth() <= month2) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ }
+
+ function inYearMonthDateRange(today, date1, month1, year1, date2, month2, year2) {
+ if (year1 === year2) {
+ if (year1 === today.getYear()) {
+ if ((month1 <= today.getMonth()) && (today.getMonth() <= month2)) {
+ if (month1 === month2) {
+ if (date1 <= today.getDate() && today.getDate() <= date2) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (today.getMonth() === month1) {
+ if (today.getDate() >= date1) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (today.getMonth() === month2) {
+ if (today.getDate() <= date2) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ } else if (year1 < year2) {
+ if (year1 <= today.getYear() && today.getYear() <= year2) {
+ if (today.getYear() === year1) {
+ if (today.getMonth() === month1) {
+ if (today.getDate() >= date1) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (today.getMonth() > month1) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (today.getYear() === year2) {
+ if (today.getMonth() <= month2) {
+
+ } else {
+ return true;
+ }
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ // TODO: change date to gmt, whatever
+ var today = new Date();
+
+ var arg1;
+ var arg2;
+ var arg3;
+ var arg4;
+ var arg5;
+ var arg6;
+
+ switch (arguments.length) {
+ case 1:
+ var arg = arguments[0];
+ if (isDate(arg)) {
+ if (today.getDate() === arg) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (isMonth(arg)) {
+ if (strToMonth(arg) === today.getMonth()) {
+ return true;
+ } else {
+ return false;
+ }
+ } else { // year
+ if (today.getYear() === arg) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ case 2:
+ arg1 = arguments[0];
+ arg2 = arguments[1];
+ if (isDate(arg1) && isDate(arg2)) {
+ var date1 = arg1;
+ var date2 = arg2;
+
+ return inDateRange(today, date1, date2);
+
+ } else if (isMonth(arg1) && isMonth(arg2)) {
+ var month1 = strToMonth(arg1);
+ var month2 = strToMonth(arg2);
+
+ return inMonthRange(today, month1, month2);
+
+ } else if (isYear(arg1) && isYear(arg2)) {
+ var year1 = arg1;
+ var year2 = arg2;
+
+ return inYearRange(today, year1, year2);
+ } else {
+ return false;
+ }
+ case 4:
+ arg1 = arguments[0];
+ arg2 = arguments[1];
+ arg3 = arguments[2];
+ arg4 = arguments[3];
+
+ if (isDate(arg1) && isMonth(arg2) && isDate(arg3) && isMonth(arg4)) {
+ var date1 = arg1;
+ var month1 = strToMonth(arg2);
+ var date2 = arg3;
+ var month2 = strToMonth(arg4);
+
+ return inMonthDateRange(today, date1, month1, date2, month2);
+
+ } else if (isMonth(arg1) && isYear(arg2) && isMonth(arg3) && isYear(arg4)) {
+ var month1 = strToMonth(arg1);
+ var year1 = arg2;
+ var month2 = strToMonth(arg3);
+ var year2 = arg4;
+
+ return inYearMonthRange(today, month1, year1, month2, year2);
+ } else {
+ return false;
+ }
+ case 6:
+ arg1 = arguments[0];
+ arg2 = arguments[1];
+ arg3 = arguments[2];
+ arg4 = arguments[3];
+ arg5 = arguments[4];
+ arg6 = arguments[5];
+ if (isDate(arg1) && isMonth(arg2) && isYear(arg3) &&
+ isDate(arg4) && isMonth(arg5) && isYear(arg6)) {
+ var day1 = arg1;
+ var month1 = strToMonth(arg2);
+ var year1 = arg3;
+ var day2 = arg4;
+ var month2 = strToMonth(arg5);
+ var year2 = arg6;
+
+ return inYearMonthDateRange(today, day1, month1, year1, day2, month2, year2);
+ } else {
+ return false;
+ }
+ default:
+ return false;
+ }
+
+}
+
+/**
+ * Returns true if the current time matches the range given
+ *
+ * timeRange(hour)
+ * timeRange(hour1, hour2)
+ * timeRange(hour1, min1, hour2, min2)
+ * timeRange(hour1, min1, sec1, hour2, min2, sec2)
+ *
+ * The string "GMT" can be used as the last additional parameter in addition to
+ * the methods listed above.
+ */
+function timeRange() {
+
+ // watch out for wrap around of times
+
+ var gmt;
+ if (arguments.length > 1) {
+ if (arguments[arguments.length-1] === "GMT") {
+ gmt = true;
+ arguments.splice(0,arguments.length-1);
+ }
+ }
+
+ function isHour(hour) {
+ if (typeof(hour) === "number" && ( 0 <= hour && hour <= 23)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ function isMin(minute) {
+ if (typeof(minute) === "number" && (0 <= minute && minute <= 59)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ function inHourRange(now, hour1, hour2) {
+ if (hour1 === hour2) {
+ if (now.getHours() === hour1) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (hour1 < hour2) {
+ if (hour1 <= now.getHours() && now.getHours() <= hour2) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (hour1 <= now.getHours() || now.getHours() <= hour2) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ function inHourMinuteRange(now, hour1, min1, hour2, min2) {
+ if (hour1 == hour2) {
+ if (now.getHours() == hour1) {
+ if (min1 <= min2) {
+ if (min1 <= now.getMinutes() && now.getMinutes() <= min2) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (min1 <= now.getMinutes() || now.getMinutes() <= min2) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ } else {
+ if (min1 <= min2) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ } else if (hour1 < hour2) {
+ if (hour1 <= now.getHours() && now.getHours() <= hour2) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (hour1 <= now.getHours() || now.getHours() <= hour2) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ var today = new Date();
+
+ switch (arguments.length) {
+ case 1:
+ var hour = arguments[0];
+ if (today.getHours() === hour) {
+ return true;
+ } else {
+ return false;
+ }
+ case 2:
+ var hour1 = arguments[0];
+ var hour2 = arguments[1];
+ if (isHour(hour1) && isHour(hour2)) {
+ return inHourRange(today, hour1, hour2);
+ } else {
+ return false;
+ }
+ case 4:
+ var hour1 = arguments[0];
+ var min1 = arguments[1];
+ var hour2 = arguments[2];
+ var min2 = arguments[3];
+
+ if (isHour(hour1) && isMin(min1) && isHour(hour2) && isMin(min2)) {
+ return inHourMinuteRange(today, hour1, min1, hour2, min2);
+ } else {
+ return false;
+ }
+
+ case 6:
+ var hour1 = arguments[0];
+ var min1 = arguments[1];
+ var sec1 = arguments[2];
+ var hour2 = arguments[3];
+ var min2 = arguments[4];
+ var sec2 = arguments[5];
+
+ // TODO handle seconds properly
+
+ return inHourMinuteRange(today, hour1, min1, hour2, min2);
+ default:
+ return false;
+ }
+}
+
diff --git a/tests/netx/pac/pac-funcs-test.js b/tests/netx/pac/pac-funcs-test.js
new file mode 100644
index 0000000..110b60c
--- /dev/null
+++ b/tests/netx/pac/pac-funcs-test.js
@@ -0,0 +1,446 @@
+
+var ICEDTEA_CLASSPATH_ORG_IP = "208.78.240.231";
+var CLASSPATH_ORG_IP = "199.232.41.10";
+
+var testsFailed = 0;
+var testsPassed = 0;
+
+print("loading needed files\n");
+file = arguments[0] + "";
+load(file)
+print("finished loaded needed files\n");
+
+
+function main() {
+
+ testIsPlainHostName();
+ testDnsDomainIs();
+ testLocalHostOrDomainIs();
+ testIsResolvable();
+ testIsInNet();
+ testDnsResolve();
+ testDnsDomainLevels();
+ testShExpMatch();
+ testWeekdayRange();
+ testDateRange();
+ testTimeRange();
+
+ java.lang.System.out.println(testsFailed + " of " + (testsFailed + testsPassed) + " tests failed");
+}
+
+function runTests(name, tests) {
+ java.lang.System.out.println("Testing: " + name.name);
+
+ var undefined_var;
+
+ for ( var i = 0; i < tests.length; i++) {
+
+ java.lang.System.out.print("Test " + (i + 1) + ": ");
+ var expectedVal = tests[i][0];
+ var args = tests[i].slice(1);
+ var returnVal;
+ try {
+ returnVal = name.apply(null, args);
+ } catch (e) {
+ returnVal = e;
+ }
+ if (returnVal === expectedVal) {
+ java.lang.System.out.println("Passed.");
+ testsPassed++;
+ } else {
+ java.lang.System.out.println("FAILED.");
+ java.lang.System.out.println(name.name + "(" + args.join(", ") + ")");
+ java.lang.System.out.println("Expected '" + expectedVal + "' but got '" + returnVal + "'");
+ testsFailed++;
+ }
+ }
+}
+
+function testIsPlainHostName() {
+ var tests = [
+ [ false, "icedtea.classpath.org" ],
+ [ false, "classpath.org" ],
+ [ true, "org" ],
+ [ true, "icedtea" ],
+ [ false, ".icedtea.classpath.org" ],
+ [ false, "icedtea." ],
+ [ false, "icedtea.classpath." ]
+ ];
+
+ runTests(isPlainHostName, tests);
+}
+
+function testDnsDomainIs() {
+ var tests = [
+ [ true, "icedtea.classpath.org", "icedtea.classpath.org" ],
+ [ true, "icedtea.classpath.org", ".classpath.org" ],
+ [ true, "icedtea.classpath.org", ".org" ],
+ [ false, "icedtea.classpath.org", "icedtea.classpath.com" ],
+ [ false, "icedtea.classpath.org", "icedtea.classpath" ],
+ [ false, "icedtea.classpath", "icedtea.classpath.org" ],
+ [ false, "icedtea", "icedtea.classpath.org" ]
+ ];
+
+ runTests(dnsDomainIs, tests);
+}
+
+function testLocalHostOrDomainIs() {
+
+ var tests = [
+ [ true, "icedtea.classpath.org", "icedtea.classpath.org" ],
+ [ true, "icedtea", "icedtea.classpath.org" ],
+ [ false, "icedtea.classpath.org", "icedtea.classpath.com" ],
+ [ false, "icedtea.classpath", "icedtea.classpath.org" ],
+ [ false, "foo.classpath.org", "icedtea.classpath.org" ],
+ [ false, "foo", "icedtea.classpath.org" ]
+ ];
+
+ runTests(localHostOrDomainIs, tests);
+}
+
+function testIsResolvable() {
+
+ var tests = [
+ [ true, "icedtea.classpath.org", "icedtea.classpath.org" ],
+ [ true, "classpath.org" ],
+ [ false, "icedtea" ],
+ [ false, "foobar.classpath.org" ],
+ [ false, "icedtea.classpath.com" ]
+ ];
+
+ runTests(isResolvable, tests);
+}
+
+function testIsInNet() {
+
+ var parts = ICEDTEA_CLASSPATH_ORG_IP.split("\.");
+
+ var fakeParts = ICEDTEA_CLASSPATH_ORG_IP.split("\.");
+ fakeParts[0] = fakeParts[0] + 1;
+
+ function createIp(array) {
+ return array[0] + "." + array[1] + "." + array[2] + "." + array[3];
+ }
+
+ var tests = [
+ [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "255.255.255.255"],
+ [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "255.255.255.0"],
+ [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "255.255.0.0"],
+ [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "255.0.0.0"],
+ [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "0.0.0.0"],
+ [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "255.255.255.255"],
+ [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "0.0.0.0"],
+ [ true, "icedtea.classpath.org", createIp(parts), "255.255.255.255" ],
+ [ false, "icedtea.classpath.org", createIp(fakeParts), "255.255.255.255"],
+ [ false, "icedtea.classpath.org", createIp(fakeParts), "255.255.255.0"],
+ [ false, "icedtea.classpath.org", createIp(fakeParts), "255.255.0.0"],
+ [ false, "icedtea.classpath.org", createIp(fakeParts), "255.0.0.0"],
+ [ true, "icedtea.classpath.org", createIp(fakeParts), "0.0.0.0"]
+ ];
+
+ runTests(isInNet, tests);
+}
+
+function testDnsResolve() {
+ var tests = [
+ [ ICEDTEA_CLASSPATH_ORG_IP, "icedtea.classpath.org" ],
+ //[ CLASSPATH_ORG_IP, "classpath.org" ],
+ [ "127.0.0.1", "localhost" ]
+ ];
+
+ runTests(dnsResolve, tests);
+}
+
+function testDnsDomainLevels() {
+ var tests = [
+ [ 0, "org" ],
+ [ 1, "classpath.org" ],
+ [ 2, "icedtea.classpath.org" ],
+ [ 3, "foo.icedtea.classpath.org" ]
+ ];
+
+ runTests(dnsDomainLevels, tests);
+
+}
+function testShExpMatch() {
+ var tests = [
+ [ true, "icedtea.classpath.org", "icedtea.classpath.org"],
+ [ false, "icedtea.classpath.org", ".org"],
+ [ false, "icedtea.classpath.org", "icedtea."],
+ [ false, "icedtea", "icedtea.classpath.org"],
+
+ [ true, "icedtea.classpath.org", "*" ],
+ [ true, "icedtea.classpath.org", "*.classpath.org" ],
+ [ true, "http://icedtea.classpath.org", "*.classpath.org" ],
+ [ true, "http://icedtea.classpath.org/foobar/", "*.classpath.org/*" ],
+ [ true, "http://icedtea.classpath.org/foobar/", "*/foobar/*" ],
+ [ true, "http://icedtea.classpath.org/foobar/", "*foobar*" ],
+ [ true, "http://icedtea.classpath.org/foobar/", "*foo*" ],
+ [ false, "http://icedtea.classpath.org/foobar/", "*/foo/*" ],
+ [ false, "http://icedtea.classpath.org/foobar/", "*/foob/*" ],
+ [ false, "http://icedtea.classpath.org/foobar/", "*/fooba/*" ],
+ [ false, "http://icedtea.classpath.org/foo/", "*foobar*" ],
+
+ [ true, "1", "?" ],
+ [ true, "12", "??" ],
+ [ true, "123", "1?3" ],
+ [ true, "123", "?23" ],
+ [ true, "123", "12?" ],
+ [ true, "1234567890", "??????????" ],
+ [ false, "1234567890", "?????????" ],
+ [ false, "123", "1?1" ],
+ [ false, "123", "??" ],
+
+ [ true, "http://icedtea.classpath.org/f1/", "*/f?/*" ],
+ [ true, "http://icedtea1.classpath.org/f1/", "*icedtea?.classpath*/f?/*" ],
+ [ false, "http://icedtea.classpath.org/f1/", "*/f2/*" ],
+ [ true, "http://icedtea.classpath.org/f1/", "*/f?/*" ],
+ [ false, "http://icedtea.classpath.org/f1", "f?*"],
+ [ false, "http://icedtea.classpath.org/f1", "f?*"],
+ [ false, "http://icedtea.classpath.org/f1", "f?*"],
+
+ [ true, "http://icedtea.classpath.org/foobar/", "*.classpath.org/*" ],
+ [ true, "http://icedtea.classpath.org/foobar/", "*.classpath.org/*" ],
+ [ true, "http://icedtea.classpath.org/foobar/", "*.classpath.org/*" ],
+
+ [ true, "http://icedtea.classpath.org/foo.php?id=bah", "*foo.php*" ],
+ [ false, "http://icedtea.classpath.org/foo_php?id=bah", "*foo.php*" ]
+ ];
+
+ runTests(shExpMatch, tests);
+}
+
+function testWeekdayRange() {
+
+ var today = new Date();
+ var day = today.getDay();
+
+ function dayToStr(day) {
+ switch (day) {
+ case -2: return "FRI";
+ case -1: return "SAT";
+ case 0: return "SUN";
+ case 1: return "MON";
+ case 2: return "TUE";
+ case 3: return "WED";
+ case 4: return "THU";
+ case 5: return "FRI";
+ case 6: return "SAT";
+ case 7: return "SUN";
+ case 8: return "MON";
+ default: return "FRI";
+ }
+
+ }
+
+ var tests = [
+ [ true, dayToStr(day) ],
+ [ false, dayToStr(day+1) ],
+ [ false, dayToStr(day-1) ],
+ ];
+}
+
+function testDateRange() {
+
+ function incDate(date) {
+ return (date + 1 - 1) % 31 +1 ;
+ }
+
+ function decDate(date) {
+ return (date - 1 - 1 + 31) % 31 + 1;
+ }
+
+ function monthToStr(month) {
+ switch (month) {
+ case -1: return "DEC";
+ case 0: return "JAN";
+ case 1: return "FEB";
+ case 2: return "MAR";
+ case 3: return "APR";
+ case 4: return "MAY";
+ case 5: return "JUN";
+ case 6: return "JUL";
+ case 7: return "AUG";
+ case 8: return "SEP";
+ case 9: return "OCT";
+ case 10: return "NOV";
+ case 11: return "DEC";
+ case 12: return "JAN";
+ default: throw "Invalid Month";
+ }
+ }
+
+ var today = new Date();
+ var date = today.getDate();
+ var month = today.getMonth();
+ var year = today.getYear();
+
+ var tests = [
+ [ true, date ],
+ [ false, incDate(date) ],
+ [ false, decDate(date) ],
+
+ [ true, monthToStr(month) ],
+ [ false, monthToStr(month+1) ],
+ [ false, monthToStr(month-1) ],
+
+ [ true, year ],
+ [ false, year - 1],
+ [ false, year + 1],
+
+ [ true, date, date ],
+ [ true, date, incDate(date) ],
+ [ true, decDate(date), date ],
+ [ true, decDate(date), incDate(date) ],
+ [ false, incDate(date), decDate(date) ],
+ [ false, decDate(decDate(date)), decDate(date) ],
+ [ false, incDate(date), incDate(incDate(date)) ],
+
+ [ true, monthToStr(month), monthToStr(month) ],
+ [ true, monthToStr(month), monthToStr(month+1) ],
+ [ true, monthToStr(month-1), monthToStr(month) ],
+ [ true, monthToStr(month-1), monthToStr(month+1) ],
+ [ true, "JAN", "DEC" ],
+ [ true, "DEC", "NOV" ],
+ [ true, "JUL", "JUN"],
+ [ false, monthToStr(month+1), monthToStr(month+1) ],
+ [ false, monthToStr(month-1), monthToStr(month-1) ],
+ [ false, monthToStr(month+1), monthToStr(month-1) ],
+
+ [ true, year, year ],
+ [ true, year, year+1 ],
+ [ true, year-1, year ],
+ [ true, year-1, year+1 ],
+ [ false, year-2, year-1 ],
+ [ false, year+1, year+1 ],
+ [ false, year+1, year+2 ],
+ [ false, year+1, year-1 ],
+
+ [ true, date, monthToStr(month) , date, monthToStr(month) ],
+ [ true, decDate(date), monthToStr(month) , date, monthToStr(month) ],
+ [ false, decDate(date), monthToStr(month) , decDate(date), monthToStr(month) ],
+ [ true, date, monthToStr(month) , incDate(date), monthToStr(month) ],
+ [ false, incDate(date), monthToStr(month) , incDate(date), monthToStr(month) ],
+ [ true, decDate(date), monthToStr(month) , incDate(date), monthToStr(month) ],
+ [ false, incDate(date), monthToStr(month) , decDate(date), monthToStr(month) ],
+ [ true, date, monthToStr(month-1) , date, monthToStr(month) ],
+ [ true, date, monthToStr(month) , date, monthToStr(month+1) ],
+ [ true, date, monthToStr(month-1) , date, monthToStr(month+1) ],
+ [ true, incDate(date), monthToStr(month-1) , date, monthToStr(month+1) ],
+ [ true, date, monthToStr(month-1) , decDate(date), monthToStr(month+1) ],
+ [ false, date, monthToStr(month+1) , date, monthToStr(month-1) ],
+ [ false, incDate(date), monthToStr(month+1) , incDate(date), monthToStr(month-1) ],
+ [ false, decDate(date), monthToStr(month+1) , decDate(date), monthToStr(month-1) ],
+ [ true, 1, "JAN", 31, "DEC" ],
+ [ true, 2, "JAN", 1, "JAN" ],
+ [ false, 1, monthToStr(month+1), 31, monthToStr(month+1) ],
+ [ false, 1, monthToStr(month-1), 31, monthToStr(month-1) ],
+
+ [ true, monthToStr(month), year, monthToStr(month), year ],
+ [ true, monthToStr(month-1), year, monthToStr(month), year ],
+ [ true, monthToStr(month), year, monthToStr(month+1), year ],
+ [ true, monthToStr(month-1), year, monthToStr(month+1), year ],
+ [ true, monthToStr(0), year, monthToStr(11), year ],
+ [ false, monthToStr(month+1), year, monthToStr(month-1), year ],
+ [ false, monthToStr(month+1), year, monthToStr(month+1), year ],
+ [ false, monthToStr(month-1), year, monthToStr(month-1), year ],
+ [ false, monthToStr(month), year-1, monthToStr(month-1), year ],
+ [ true, monthToStr(month), year, monthToStr(month), year + 1 ],
+ [ true, monthToStr(month), year-1, monthToStr(month), year ],
+ [ true, monthToStr(month), year-1, monthToStr(month), year+1 ],
+ [ true, monthToStr(0), year, monthToStr(0), year+1 ],
+ [ true, monthToStr(0), year-1, monthToStr(0), year+1 ],
+ [ false, monthToStr(0), year-1, monthToStr(11), year-1 ],
+ [ false, monthToStr(0), year+1, monthToStr(11), year+1 ],
+
+ [ true, date, monthToStr(month), year, date, monthToStr(month), year ],
+ [ true, decDate(date), monthToStr(month), year, incDate(date), monthToStr(month), year ],
+ [ true, decDate(date), monthToStr(month-1), year, incDate(date), monthToStr(month+1), year ],
+ [ true, decDate(date), monthToStr(month-1), year-1, incDate(date), monthToStr(month+1), year+1 ],
+ [ true, incDate(date), monthToStr(month-1), year-1, incDate(date), monthToStr(month+1), year+1 ],
+ [ false, incDate(date), monthToStr(month), year, incDate(date), monthToStr(month+1), year+1 ],
+ [ false, date, monthToStr(month+1), year, incDate(date), monthToStr(month+1), year+1 ],
+ [ true, 1, monthToStr(0), 0, 31, monthToStr(11), 100000 ],
+ [ true, 1, monthToStr(0), year, 31, monthToStr(11), year ],
+ [ true, 1, monthToStr(0), year-1, 31, monthToStr(11), year+1 ],
+ [ false, 1, monthToStr(0), year-1, 31, monthToStr(11), year-1 ],
+ [ false, 1, monthToStr(0), year+1, 31, monthToStr(11), year+1 ],
+
+ ];
+
+ runTests(dateRange, tests);
+
+}
+
+function testTimeRange() {
+ var now = new Date();
+
+ var hour = now.getHours();
+ var min = now.getMinutes();
+ var sec = now.getSeconds();
+
+ function toHour(input) {
+ if (input < 0) {
+ while (input < 0) {
+ input = input + 24;
+ }
+ return (input % 24);
+ } else {
+ return (input % 24);
+ }
+ }
+
+ function toMin(input) {
+ if (input < 0) {
+ while (input < 0) {
+ input = input + 60;
+ }
+ return (input % 60);
+ } else {
+ return (input % 60);
+ }
+ }
+
+ tests = [
+ [ true, hour ],
+ [ false, toHour(hour+1)],
+ [ false, toHour(hour-1)],
+
+ [ true, hour, hour ],
+ [ true, toHour(hour-1), hour ],
+ [ true, hour, toHour(hour+1)],
+ [ true, toHour(hour-1), toHour(hour+1)],
+ [ true, toHour(hour+1), hour ],
+ [ true, hour, toHour(hour-1) ],
+ [ false, toHour(hour-2), toHour(hour-1)],
+ [ false, toHour(hour+1), toHour(hour+2)],
+ [ false, toHour(hour+1), toHour(hour-1) ],
+ [ true, 0, 23 ],
+ [ true, 12, 11 ],
+
+ [ true, hour, min, hour, min ],
+ [ true, hour, min, hour, toMin(min+1) ],
+ [ true, hour, toMin(min-1), hour, min ],
+ [ true, hour, toMin(min-1), hour, toMin(min+1) ],
+ [ true, hour, toMin(min+2), hour, toMin(min+1) ],
+ [ false, hour, toMin(min+1), hour, toMin(min+1) ],
+ [ false, hour, toMin(min-1), hour, toMin(min-1) ],
+ [ false, hour, toMin(min+1), hour, toMin(min-1) ],
+ [ true, toHour(hour-1), min, hour, min ],
+ [ true, hour, min, toHour(hour+1), min ],
+ [ true, toHour(hour-1), min, toHour(hour+1), min ],
+ [ true, 0, 0, 23, 59 ],
+ [ true, 0, 1, 0, 0 ],
+
+ [ true, 0, 1, 0, 0, 0, 0 ],
+ [ true, hour, min, sec, hour, min, sec ],
+ [ true, hour, min, sec, hour, min + 10, sec ],
+ [ true, hour, min, sec - 10, hour, min, sec ],
+ [ true, hour, min, sec, hour, min-1 , sec ],
+
+ ];
+
+ runTests(timeRange, tests);
+}
+
+main();