aboutsummaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
Diffstat (limited to 'config')
-rw-r--r--config/open-vm-tools_2/open-vm-tools.inc156
-rw-r--r--config/open-vm-tools_2/open-vm-tools.xml69
-rw-r--r--config/openospfd/openospfd.inc25
-rwxr-xr-xconfig/openvpn-client-export/openvpn-client-export.inc53
-rwxr-xr-xconfig/openvpn-client-export/vpn_openvpn_export.php36
-rw-r--r--config/snort-dev/NOTES.txt18
-rwxr-xr-xconfig/snort-dev/bin/8.0.x86/barnyard2bin0 -> 849388 bytes
-rw-r--r--config/snort-dev/bin/8.0.x86/md5_files9
-rw-r--r--config/snort-dev/bin/8.0.x86/md5_files~9
-rw-r--r--config/snort-dev/css/style2.css220
-rw-r--r--config/snort-dev/help_and_info.php390
-rw-r--r--config/snort-dev/images/footer.jpgbin57412 -> 57411 bytes
-rw-r--r--config/snort-dev/images/footer2.jpgbin31879 -> 31878 bytes
-rw-r--r--config/snort-dev/images/icon-table-sort-asc.pngbin2907 -> 2906 bytes
-rw-r--r--config/snort-dev/images/icon-table-sort-desc.pngbin2914 -> 2913 bytes
-rw-r--r--config/snort-dev/images/icon-table-sort.pngbin3026 -> 3025 bytes
-rw-r--r--config/snort-dev/images/icon_excli.pngbin0 -> 5280 bytes
-rw-r--r--config/snort-dev/images/logo.jpgbin74307 -> 74306 bytes
-rw-r--r--config/snort-dev/javascript/jquery-1.3.2.js8752
-rw-r--r--config/snort-dev/javascript/jquery.blockUI.js926
-rw-r--r--config/snort-dev/javascript/sortableTable.js576
-rw-r--r--config/snort-dev/javascript/tabs.js244
-rw-r--r--config/snort-dev/snort.inc264
-rw-r--r--[-rwxr-xr-x]config/snort-dev/snort.sh0
-rw-r--r--config/snort-dev/snort.xml6
-rw-r--r--config/snort-dev/snort_alerts.php8
-rw-r--r--config/snort-dev/snort_barnyard.php77
-rw-r--r--config/snort-dev/snort_blocked.php7
-rw-r--r--config/snort-dev/snort_check_for_rule_updates.php5
-rw-r--r--config/snort-dev/snort_define_servers.php82
-rw-r--r--config/snort-dev/snort_download_rules.php42
-rw-r--r--config/snort-dev/snort_fbegin.inc288
-rw-r--r--config/snort-dev/snort_gui.inc4
-rw-r--r--config/snort-dev/snort_help_info.php298
-rw-r--r--config/snort-dev/snort_interfaces.php348
-rw-r--r--config/snort-dev/snort_interfaces_edit.php225
-rw-r--r--config/snort-dev/snort_interfaces_global.php178
-rw-r--r--config/snort-dev/snort_preprocessors.php86
-rw-r--r--config/snort-dev/snort_rules.php21
-rw-r--r--config/snort-dev/snort_rules_edit.php486
-rw-r--r--config/snort-dev/snort_rulesets.php92
-rw-r--r--config/squid-8/proxy_monitor.sh72
-rw-r--r--config/squid-8/squid.inc1319
-rw-r--r--config/squid-8/squid.xml334
-rw-r--r--config/squid-8/squid_auth.inc446
-rw-r--r--config/squid-8/squid_auth.xml225
-rw-r--r--config/squid-8/squid_cache.xml224
-rw-r--r--config/squid-8/squid_extauth.xml106
-rw-r--r--config/squid-8/squid_nac.xml143
-rw-r--r--config/squid-8/squid_ng.inc1070
-rw-r--r--config/squid-8/squid_ng.xml267
-rw-r--r--config/squid-8/squid_traffic.xml177
-rw-r--r--config/squid-8/squid_upstream.xml133
-rw-r--r--config/squid-8/squid_users.xml120
-rw-r--r--config/tinydns/tinydns.inc172
-rw-r--r--config/tinydns/tinydns.xml8
56 files changed, 12318 insertions, 6498 deletions
diff --git a/config/open-vm-tools_2/open-vm-tools.inc b/config/open-vm-tools_2/open-vm-tools.inc
new file mode 100644
index 00000000..f1dc17fb
--- /dev/null
+++ b/config/open-vm-tools_2/open-vm-tools.inc
@@ -0,0 +1,156 @@
+<?php
+
+function open_vm_tools_deinstall() {
+ exec("rm /usr/local/etc/rc.d/vmware*");
+}
+
+function open_vm_tools_install() {
+
+ $vmware_guestd = <<<EOF
+#!/bin/sh
+#
+# This file was automatically generated
+# by the pfSense package manager.
+#
+# Do not edit this file. Edit
+# /usr/local/pkg/open-vm-tools.inc instead.
+#
+# PROVIDE: vmware-guestd
+# REQUIRE: DAEMON
+# BEFORE: LOGIN
+
+. /etc/rc.subr
+
+# Global
+checkvm_cmd="/usr/local/bin/vmware-checkvm > /dev/null"
+
+# VMware guest daemon
+name="vmware_guestd"
+rcvar=`set_rcvar`
+start_precmd="\${checkvm_cmd}"
+unset start_cmd
+stop_precmd="\${checkvm_cmd}"
+unset stop_cmd
+command="/usr/local/bin/vmtoolsd"
+command_args="-c /usr/local/share/vmware-tools/tools.conf -p /usr/local/lib/open-vm-tools/plugins/vmsvc"
+pidfile="/var/run/\${name}.pid"
+
+load_rc_config \$name
+vmware_guestd_enable="YES"
+vmware_guestd_flags="--background \${pidfile}"
+run_rc_command "\$1"
+
+EOF;
+
+ $vmware_kmod = <<<EOF
+#!/bin/sh
+#
+# This file was automatically generated
+# by the pfSense package manager.
+#
+# Do not edit this file. Edit
+# /usr/local/pkg/open-vm-tools.inc instead.
+#
+# PROVIDE: vmware-kmod
+# REQUIRE: FILESYSTEMS
+# BEFORE: netif
+
+. /etc/rc.subr
+
+# Global
+checkvm_cmd="/usr/local/bin/vmware-checkvm > /dev/null"
+
+# Functions
+vmware_guest_vmmemctl_start()
+{
+ echo 'Loading vmmemctl kernel module.'
+ kldload /usr/local/lib/vmware-tools/modules/drivers/vmmemctl.ko >/dev/null 2>&1
+}
+vmware_guest_vmxnet_start()
+{
+ echo 'Loading vmxnet kernel module.'
+ kldload /usr/local/lib/vmware-tools/modules/drivers/vmxnet.ko >/dev/null 2>&1
+}
+vmware_guest_vmblock_start()
+{
+ echo 'Loading vmblock kernel module.'
+ kldload /usr/local/lib/vmware-tools/modules/drivers/vmblock.ko >/dev/null 2>&1
+}
+vmware_guest_vmhgfs_start()
+{
+ echo 'Loading vmhgfs kernel module.'
+ kldload /usr/local/lib/vmware-tools/modules/drivers/vmhgfs.ko >/dev/null 2>&1
+}
+
+# VMware kernel module: vmmemctl
+name="vmware_guest_vmmemctl"
+rcvar=`set_rcvar`
+start_precmd="\${checkvm_cmd}"
+start_cmd="vmware_guest_vmmemctl_start"
+stop_precmd="\${checkvm_cmd}"
+stop_cmd=":"
+
+load_rc_config \$name
+vmware_guest_vmmemctl_enable="YES"
+run_rc_command "\$1"
+
+# VMware kernel module: vmxnet
+name="vmware_guest_vmxnet"
+rcvar=`set_rcvar`
+start_precmd="\${checkvm_cmd}"
+start_cmd="vmware_guest_vmxnet_start"
+stop_precmd="\${checkvm_cmd}"
+stop_cmd=":"
+
+load_rc_config \$name
+vmware_guest_vmxnet_enable="YES"
+run_rc_command "\$1"
+
+# VMware kernel module: vmblock
+name="vmware_guest_vmblock"
+rcvar=`set_rcvar`
+start_precmd="\${checkvm_cmd}"
+start_cmd="vmware_guest_vmblock_start"
+stop_precmd="\${checkvm_cmd}"
+stop_cmd=":"
+
+load_rc_config \$name
+vmware_guest_vmblock_enable="YES"
+run_rc_command "\$1"
+
+# VMware kernel module: vmhgfs
+name="vmware_guest_vmhgfs"
+rcvar=`set_rcvar`
+start_precmd="\${checkvm_cmd}"
+start_cmd="vmware_guest_vmhgfs_start"
+stop_precmd="\${checkvm_cmd}"
+stop_cmd=":"
+
+load_rc_config \$name
+vmware_guest_vmhgfs_enable="YES"
+run_rc_command "\$1"
+
+EOF;
+
+ // Write out conf files.
+ $fd = fopen("/usr/local/etc/rc.d/vmware-guestd.sh", "w");
+ if(!$fd)
+ die("Could not open /usr/local/etc/rc.d/vmware-guestd.sh for writing");
+ fwrite($fd, $vmware_guestd);
+ fclose($fd);
+ $fd = fopen("/usr/local/etc/rc.d/vmware-kmod.sh", "w");
+ if(!$fd)
+ die("Could not open /usr/local/etc/rc.d/vmware-kmod.sh for writing");
+ fwrite($fd, $vmware_kmod);
+ fclose($fd);
+
+ // Remove non used files
+ unlink_if_exists("/usr/local/etc/rc.d/vmware-kmod");
+ unlink_if_exists("/usr/local/etc/rc.d/vmware-guestd");
+
+ // Make sure files are executable.
+ exec("chmod a+rx /usr/local/etc/rc.d/*.sh");
+
+}
+
+?> \ No newline at end of file
diff --git a/config/open-vm-tools_2/open-vm-tools.xml b/config/open-vm-tools_2/open-vm-tools.xml
new file mode 100644
index 00000000..c2a74f16
--- /dev/null
+++ b/config/open-vm-tools_2/open-vm-tools.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+ /* ========================================================================== */
+ /*
+ open-vm-tools.xml
+ part of pfSense (http://www.pfSense.org)
+ Copyright (C) 2008 BSD Perimeter LLC
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2008 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+ /* ========================================================================== */
+ /*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <name>open-vm-tools</name>
+ <version>217847</version>
+ <title>Open VM Tools</title>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0644</chmod>
+ <item>http://www.pfsense.com/packages/config/open-vm-tools_2/open-vm-tools.inc</item>
+ </additional_files_needed>
+ <custom_add_php_command>
+ </custom_add_php_command>
+ <custom_php_install_command>
+ conf_mount_rw();
+ open_vm_tools_install();
+ exec("/usr/local/etc/rc.d/vmware-guestd.sh start");
+ exec("/usr/local/etc/rc.d/vmware-kmod.sh start");
+ conf_mount_ro();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ conf_mount_rw();
+ exec("/usr/local/etc/rc.d/vmware-guestd.sh stop");
+ exec("/usr/local/etc/rc.d/vmware-kmod.sh stop");
+ open_vm_tools_deinstall();
+ conf_mount_ro();
+ </custom_php_deinstall_command>
+ <include_file>/usr/local/pkg/open-vm-tools.inc</include_file>
+</packagegui> \ No newline at end of file
diff --git a/config/openospfd/openospfd.inc b/config/openospfd/openospfd.inc
index d6a3e67d..0a5ef351 100644
--- a/config/openospfd/openospfd.inc
+++ b/config/openospfd/openospfd.inc
@@ -176,10 +176,18 @@ function ospfd_install_conf() {
exec("chmod u+rw /usr/local/etc/ospfd.conf");
// ospfd process running? if so reload, elsewise start.
- if(is_ospfd_running() == true) {
- exec("/usr/local/sbin/ospfctl reload");
- } else {
- exec("/usr/local/sbin/ospfd");
+ $oarray = array();
+ $rval = 0;
+ exec("/usr/local/sbin/ospfctl reload", $oarray, $rval);
+ if ($rval != 0) {
+ /*
+ * ospfd isnt actually running as nothing accepted a connection
+ * on the /var/run/ospfd.sock unix socket by ospfctl, this is
+ * just to ensure a clean state. Killing a live ospfd would be bad.
+ */
+ exec("/bin/pkill -x ospfd");
+ // start ospfd
+ exec("/usr/local/sbin/ospfd -f /usr/local/etc/ospfd.conf");
}
conf_mount_ro();
@@ -231,13 +239,4 @@ function ospfd_put_raw_config($conffile) {
$config['installedpackages']['ospfd']['rawconfig'] = $conffile;
}
}
-
-function is_ospfd_running() {
- $status = `ps awux | grep ospfd | grep "parent" | grep -v grep | wc -l | awk '{ print \$1 }'`;
- if(intval($status) > 0)
- return true;
- else
- return false;
-}
-
?>
diff --git a/config/openvpn-client-export/openvpn-client-export.inc b/config/openvpn-client-export/openvpn-client-export.inc
index aabb32eb..ddc97025 100755
--- a/config/openvpn-client-export/openvpn-client-export.inc
+++ b/config/openvpn-client-export/openvpn-client-export.inc
@@ -90,8 +90,8 @@ function openvpn_client_pem_to_pk12($outpath, $outpass, $crtpath, $keypath, $cap
unlink($capath);
}
-function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $usetoken, $nokeys = false, $proxy) {
- global $config, $input_errors;
+function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $usetoken, $nokeys = false, $proxy, $zipconf = false, $outpass = "") {
+ global $config, $input_errors, $g;
// lookup server settings
$settings = $config['openvpn']['openvpn-server'][$srvid];
@@ -195,7 +195,41 @@ function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $usetoke
if ($settings['passtos'])
$conf .= "passtos\n";
- return $conf;
+ if ($zipconf == true) {
+ // create template directory
+ $tempdir = "{$g['tmp_path']}/{$prefix}";
+ mkdir($tempdir, 0700, true);
+
+ file_put_contents("{$tempdir}/{$prefix}-ovpn.conf", $conf);
+
+ file_put_contents("{$tempdir}/{$prefix}-ca.crt", base64_decode($server_ca['crt']));
+ if ($settings['tls']) {
+ $tlsfile = "{$tempdir}/{$prefix}-tls.key";
+ file_put_contents($tlsfile, base64_decode($settings['tls']));
+ }
+
+ // write key files
+ if ($settings['mode'] != "server_user") {
+ $crtfile = "{$tempdir}/{$prefix}-cert.crt";
+ file_put_contents($crtfile, base64_decode($cert['crt']));
+ $keyfile = "{$tempdir}/{$prefix}.key";
+ file_put_contents($keyfile, base64_decode($cert['prv']));
+
+ // convert to pkcs12 format
+ $p12file = "{$tempdir}/{$prefix}.p12";
+ if ($usetoken)
+ openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile);
+ else
+ openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile, $cafile);
+
+ exec("cd {$tempdir}/.. && /usr/local/bin/zip -r {$g['tmp_path']}/{$prefix}-config.zip {$prefix}");
+
+ // Remove temporary directory
+ exec("rm -rf {$tempdir}");
+ return "{$prefix}-config.zip";
+ }
+ } else
+ return $conf;
}
function openvpn_client_export_installer($srvid, $usrid, $crtid, $useaddr, $usetoken, $outpass, $proxy) {
@@ -284,13 +318,12 @@ function openvpn_client_export_installer($srvid, $usrid, $crtid, $useaddr, $uset
file_put_contents($crtfile, base64_decode($cert['crt']));
$keyfile = "{$tempdir}/config/{$prefix}-{$user['name']}.key";
file_put_contents($keyfile, base64_decode($cert['prv']));
-
- // convert to pkcs12 format
- $p12file = "{$tempdir}/config/{$prefix}.p12";
- if ($usetoken)
- openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile);
- else
- openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile, $cafile);
+ // convert to pkcs12 format
+ $p12file = "{$tempdir}/{$prefix}.p12";
+ if ($usetoken)
+ openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile);
+ else
+ openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile, $cafile);
}
// 7zip the configuration data
diff --git a/config/openvpn-client-export/vpn_openvpn_export.php b/config/openvpn-client-export/vpn_openvpn_export.php
index 05d108a6..861dda89 100755
--- a/config/openvpn-client-export/vpn_openvpn_export.php
+++ b/config/openvpn-client-export/vpn_openvpn_export.php
@@ -90,7 +90,7 @@ if (isset($_POST['act']))
$act = $_POST['act'];
$error = false;
-if($act == "conf") {
+if($act == "conf" || $act == "confall") {
$srvid = $_GET['srvid'];
$usrid = $_GET['usrid'];
$crtid = $_GET['crtid'];
@@ -115,6 +115,9 @@ if($act == "conf") {
$useaddr = $_GET['useaddr'];
$usetoken = $_GET['usetoken'];
+ $password = "";
+ if ($_GET['password'])
+ $password = $_GET['password'];
$proxy = "";
if (!empty($_GET['proxy_addr']) || !empty($_GET['proxy_port'])) {
@@ -145,20 +148,31 @@ if($act == "conf") {
}
$exp_name = openvpn_client_export_prefix($srvid);
- $exp_data = openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $usetoken, $nokeys, $proxy);
+ if ($act == "confall")
+ $zipconf = true;
+ $exp_data = openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $usetoken, $nokeys, $proxy, $zipconf, $password);
if (!$exp_data) {
$input_errors[] = "Failed to export config files!";
$error = true;
}
if (!$error) {
- $exp_name = urlencode($exp_name."-config.ovpn");
- $exp_size = strlen($exp_data);
+ if ($act == "confall") {
+ $exp_name = urlencode($exp_data);
+ $exp_size = filesize("{$g['tmp_path']}/{$exp_data}");
+ } else {
+ $exp_name = urlencode($exp_name."-config.ovpn");
+ $exp_size = strlen($exp_data);
+ }
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename={$exp_name}");
header("Content-Length: $exp_size");
- echo $exp_data;
+ if ($act == "confall")
+ readfile("{$g['tmp_path']}/{$exp_data}");
+ else
+ echo $exp_data;
+ @unlink($exp_data);
exit;
}
}
@@ -184,7 +198,7 @@ if($act == "visc") {
$usetoken = $_GET['usetoken'];
$password = "";
if ($_GET['password'])
- $password = $_GET['password']; ;
+ $password = $_GET['password'];
$proxy = "";
if (!empty($_GET['proxy_addr']) || !empty($_GET['proxy_port'])) {
@@ -441,7 +455,9 @@ function server_changed() {
cell1.className = "listr";
cell1.innerHTML = users[i][3];
cell2.className = "listr";
- cell2.innerHTML = "<a href='javascript:download_begin(\"conf\"," + i + ")'>Configuration</a>";
+ cell2.innerHTML = "<a href='javascript:download_begin(\"conf\"," + i + ")'>Configuration</a>";
+ cell2.innerHTML += "&nbsp;/&nbsp;";
+ cell2.innerHTML += "<a href='javascript:download_begin(\"confall\"," + i + ")'>Configuration archive</a>";
cell2.innerHTML += "&nbsp;/&nbsp;";
cell2.innerHTML += "<a href='javascript:download_begin(\"inst\"," + i + ")'>Windows Installer</a>";
cell2.innerHTML += "&nbsp;/&nbsp;";
@@ -457,8 +473,10 @@ function server_changed() {
cell1.className = "listr";
cell1.innerHTML = "none";
cell2.className = "listr";
- cell2.innerHTML = "<a href='javascript:download_begin(\"conf\"," + i + ")'>Configuration</a>";
+ cell2.innerHTML = "<a href='javascript:download_begin(\"conf\"," + i + ")'>Configuration</a>";
cell2.innerHTML += "&nbsp;/&nbsp;";
+ cell2.innerHTML += "<a href='javascript:download_begin(\"confall\"," + i + ")'>Configuration archive</a>";
+ cell2.innerHTML += "&nbsp;/&nbsp;";
cell2.innerHTML += "<a href='javascript:download_begin(\"inst\"," + i + ")'>Windows Installer</a>";
cell2.innerHTML += "&nbsp;/&nbsp;";
cell2.innerHTML += "<a href='javascript:download_begin(\"visc\"," + i + ")'>Viscosity Bundle</a>";
@@ -485,7 +503,7 @@ function usepass_changed() {
function useproxy_changed(obj) {
if ((obj.id == "useproxy" && obj.checked) ||
- $(obj.id).value != 'none') {
+ $(obj.id + 'pass').value != 'none') {
$(obj.id + '_opts').show();
} else {
$(obj.id + '_opts').hide();
diff --git a/config/snort-dev/NOTES.txt b/config/snort-dev/NOTES.txt
index 88c80cb2..b8c61c39 100644
--- a/config/snort-dev/NOTES.txt
+++ b/config/snort-dev/NOTES.txt
@@ -1,19 +1,17 @@
-March 16 2019
-Snort-dev 2.8.5.3 pk v. 12 Beta
+March 26 2019
+Snort-dev 2.8.5.3 pk v. 18 final
-Snort is Stoping/Starting with new UUID. Files are independent of rule order now. Ya me.......
+Final day.
-TODO:
-The snort.sh code needs to be looked at and made sure there is a new file at every enabe/disbale save,
-reboot, rule delete.
+Odds and ends left.
-The snort_interfaces.php needs speed inprovments. !inportant.
-
-Make sure I ad a reset button someware the removes all of snort-devs addd to config.xml
+2.0 group snort gets lost on reboot.
Pierre POMES code needs to be added.
+Threshold tab needs to be added.
+
-Done. \ No newline at end of file
+Done.
diff --git a/config/snort-dev/bin/8.0.x86/barnyard2 b/config/snort-dev/bin/8.0.x86/barnyard2
new file mode 100755
index 00000000..43476338
--- /dev/null
+++ b/config/snort-dev/bin/8.0.x86/barnyard2
Binary files differ
diff --git a/config/snort-dev/bin/8.0.x86/md5_files b/config/snort-dev/bin/8.0.x86/md5_files
new file mode 100644
index 00000000..3b283d80
--- /dev/null
+++ b/config/snort-dev/bin/8.0.x86/md5_files
@@ -0,0 +1,9 @@
+#For Freebsd 8.0
+
+
+MD5 (pcre-8.00.tbz) = 8a1ac82500efccefc6418856e27b6cc1
+MD5 (snort-2.8.5.3.tbz) = 826c15872c6d19bcbe2408fb34d165b9
+MD5 (perl-5.10.1.tbz) = f71020a8bd0f197c9bf70eb6d03b92af
+MD5 (mysql-client-5.1.45.tbz) = 9cb5878ae922c3d4d0e31efe5712a90a
+MD5 (barnyard2) = 4dbff13291a2b8c5018b7ab62f574bc8
+
diff --git a/config/snort-dev/bin/8.0.x86/md5_files~ b/config/snort-dev/bin/8.0.x86/md5_files~
new file mode 100644
index 00000000..3b283d80
--- /dev/null
+++ b/config/snort-dev/bin/8.0.x86/md5_files~
@@ -0,0 +1,9 @@
+#For Freebsd 8.0
+
+
+MD5 (pcre-8.00.tbz) = 8a1ac82500efccefc6418856e27b6cc1
+MD5 (snort-2.8.5.3.tbz) = 826c15872c6d19bcbe2408fb34d165b9
+MD5 (perl-5.10.1.tbz) = f71020a8bd0f197c9bf70eb6d03b92af
+MD5 (mysql-client-5.1.45.tbz) = 9cb5878ae922c3d4d0e31efe5712a90a
+MD5 (barnyard2) = 4dbff13291a2b8c5018b7ab62f574bc8
+
diff --git a/config/snort-dev/css/style2.css b/config/snort-dev/css/style2.css
index cd253de1..d7a1616c 100644
--- a/config/snort-dev/css/style2.css
+++ b/config/snort-dev/css/style2.css
@@ -1,111 +1,111 @@
-/* -----------------------------------
-general
------------------------------------ */
-
-body
-{
- margin: 0px;
- padding: 0px;
- font: 100%/1.4 helvetica, arial, sans-serif;
- color: #444;
- background: #fff;
-}
-
-h1, h2, h3, h4, h5, h6
-{
- margin: 0 0 1em;
- line-height: 1.1;
-}
-
-h2, h3 { color: #003d5d; }
-h2 { font-size: 218.75%; }
-
-
-p
-{
-margin-top: 35pt;
-margin-right: 0pt;
-margin-bottom: -25px;
-margin-left: 0pt;
-text-indent: 25px;
-}
-
-img { border: none; }
-a:link { color: #035389; }
-a:visited { color: #09619C; }
-
-/* -----------------------------------
-Play Hide the tab
------------------------------------ */
-
-div.items p:not(:target) {display: none}
-div.items p:target {display: block}
-
-
-/* -----------------------------------
-layout
------------------------------------ */
-
-#container
-{
- margin: 0 0px;
- background: #fff;
-}
-
-#header
-{
- background: #fff;
-}
-
-#header h1 { margin: 0; }
-
-#navigation
-{
- float: left;
- width: 100%;
- background: #333;
-}
-
-#navigation ul
-{
- margin: 0;
- padding: 0;
-}
-
-#navigation ul li
-{
- list-style-type: none;
- display: inline;
-}
-
-#navigation li a
-{
- display: block;
- float: left;
- padding: 5px 10px;
- color: #fff;
- text-decoration: none;
- border-right: 1px solid #fff;
-}
-
-#navigation li a:hover
-{
- background-color: #3366cc;
- background-image: none;
- background-repeat: repeat;
- background-attachment: scroll;
- background-position: 0% 0%;
-}
-
-#content
-{
- clear: left;
- padding: 20px;
-}
-
-#content h2
-{
- color: #000;
- font-size: 160%;
- margin: 0 0 .5em;
+/* -----------------------------------
+general
+----------------------------------- */
+
+body
+{
+ margin: 0px;
+ padding: 0px;
+ font: 100%/1.4 helvetica, arial, sans-serif;
+ color: #444;
+ background: #fff;
+}
+
+h1, h2, h3, h4, h5, h6
+{
+ margin: 0 0 1em;
+ line-height: 1.1;
+}
+
+h2, h3 { color: #003d5d; }
+h2 { font-size: 218.75%; }
+
+
+p
+{
+margin-top: 35pt;
+margin-right: 0pt;
+margin-bottom: -25px;
+margin-left: 0pt;
+text-indent: 25px;
+}
+
+img { border: none; }
+a:link { color: #035389; }
+a:visited { color: #09619C; }
+
+/* -----------------------------------
+Play Hide the tab
+----------------------------------- */
+
+div.items p:not(:target) {display: none}
+div.items p:target {display: block}
+
+
+/* -----------------------------------
+layout
+----------------------------------- */
+
+#container
+{
+ margin: 0 0px;
+ background: #fff;
+}
+
+#header
+{
+ background: #fff;
+}
+
+#header h1 { margin: 0; }
+
+#navigation
+{
+ float: left;
+ width: 100%;
+ background: #333;
+}
+
+#navigation ul
+{
+ margin: 0;
+ padding: 0;
+}
+
+#navigation ul li
+{
+ list-style-type: none;
+ display: inline;
+}
+
+#navigation li a
+{
+ display: block;
+ float: left;
+ padding: 5px 10px;
+ color: #fff;
+ text-decoration: none;
+ border-right: 1px solid #fff;
+}
+
+#navigation li a:hover
+{
+ background-color: #3366cc;
+ background-image: none;
+ background-repeat: repeat;
+ background-attachment: scroll;
+ background-position: 0% 0%;
+}
+
+#content
+{
+ clear: left;
+ padding: 20px;
+}
+
+#content h2
+{
+ color: #000;
+ font-size: 160%;
+ margin: 0 0 .5em;
} \ No newline at end of file
diff --git a/config/snort-dev/help_and_info.php b/config/snort-dev/help_and_info.php
index ff31d6d0..0f4a0c9f 100644
--- a/config/snort-dev/help_and_info.php
+++ b/config/snort-dev/help_and_info.php
@@ -1,196 +1,196 @@
-<?php
-
- require_once("guiconfig.inc");
-
-echo '
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>Help & Info</title>
-<base target="main">
-<script src="./javascript/tabs.js" type="text/javascript"></script>
-<link href="./css/style2.css" rel="stylesheet" type="text/css" />
-</head>
-
-<body>
-
-<style type="text/css">
-</style>
-
-<div id="container">
- <div id="header">
- <IMG SRC="./images/logo.jpg" width="780px" height="76" ALT="Snort Package">
- </div>
- <div class="navigation" id="navigation">
- <ul>
- <li><a href="#item1" target="_self">Home</a></li>
- <li><a href="#item2" target="_self">About Me</a></li>
- <li><a href="#item3" target="_self">Services</a></li>
- <li><a href="#item4" target="_self">Change Log</a></li>
- <li><a href="#item7" target="_self">Faq</a></li>
- <li><a href="#item6" target="_self">Heros</a></li>
- <li><a href="#item5" target="_self">Developers</a></li>
- </ul>
- </div>
- <br>
-<div class="content" id="item1">
- <p>
- <font size="5"><strong>Snort Package</strong></font> is a GUI based front-end for Sourcefire\'s Snort ® IDS/IPS software. The Snort Package goal is to be
- the best open-source GUI to manage multiple snort sensors and multiple rule snapshots. The project other goal is to be a highly competitive GUI for
- network monitoring for both private and enterprise use. Lastly, this project software development should bring programmers and users together to create
- software.
- </p>
- <p>
- <font size="5"><strong>What is Snort ?</strong></font> Used by fortune 500 companies and goverments Snort is the most widely deployed IDS/IPS technology worldwide. It features rules based logging and
- can perform content searching/matching in addition to being used to detect a variety of other attacks and probes, such as buffer overflows, stealth port
- scans, CGI attacks, SMB probes, and much more.
- </p>
- <p>
- <font size="5"><strong>Requirements :</strong></font><br>
- Minimum requirement 256 mb ram, 500 MHz CPU.<br>
- Recommended 500 mb ram, 1 Ghz CPU.<br>
- The more rules you run the more memory you need.<br>
- The more interfaces you select the more memory you need.<br><br>
- Development is done on a Alix 2D3 system (500 MHz AMD Geode LX800 CPU 256MB DDR DRAM).
- </p>
-</div>
-<div class="content" id="item2">
- <p>
-About Me<br><br>
-Coming soon............
-
-</p>
-</div>
-<div class="content" id="item3">
- <p>
-Services<br><br>
-Coming soon............
-</p>
-</div>
-<div class="content" id="item4">
-<p>
-Change Log<br><br>
-Coming soon............
-</p>
-</div>
-<div class="content" id="item5">
-<p>
-<font size="5"><strong>PfSense</strong></font> is brought to you by a dedicated group of developers who are security and network professionals by trade. The following people are active developers of the pfSense project.
-Username is listed in parenthesis (generally also the person\'s forum username, IRC nickname, etc.).<br><br>
-
-<font size="5"><strong>Main Snort-dev Package Developer</strong></font><br>
-Robert Zelaya<br><br>
-
-<font size="5"><strong>Founders</strong></font><br>
-In alphabetical order<br><br>
-
-Chris Buechler (cmb)<br>
-Scott Ullrich (sullrich)<br><br>
-
-<font size="5"><strong>Active Developers</strong></font><br>
-Listed in order of seniority along with date of first contribution.<br><br>
-
-Bill Marquette (billm) - February 2005<br>
-Holger Bauer (hoba) - May 2005<br>
-Erik Kristensen (ekristen) - August 2005<br>
-Seth Mos (smos) - November 2005<br>
-Scott Dale (sdale) - December 2006<br>
-Martin Fuchs (mfuchs) - June 2007<br>
-Ermal Luçi (ermal) - January 2008<br>
-Matthew Grooms (mgrooms) - July 2008<br>
-Mark Crane (mcrane) - October 2008<br>
-Jim Pingle (jim-p) - February 2009<br>
-Rob Zelaya (robiscool) - March 2009<br>
-Renato Botelho (rbgarga) - May 2009<br><br>
-
-<font size="5"><strong>FreeBSD Developer Assistance</strong></font><br>
-We would like to thank the following FreeBSD developers for their assistance.<br><br>
-
-Max Laier (mlaier)<br>
-Christian S.J. Peron (csjp)<br>
-Andrew Thompson (thompsa)<br>
-Bjoern A. Zeeb (bz)<br><br>
-
-among many others who help us directly, and everyone who contributes to FreeBSD.<br><br>
-
-<font size="5"><strong>Inactive Developers</strong></font><br>
-The following individuals are no longer active contributors, having moved on because of other commitments, or employers forbidding contributions. We thank them for their past contributions.<br><br>
-
-Daniel Berlin (dberlin)<br>
-Daniel Haischt (dsh)<br>
-Espen Johansen (lsf)<br>
-Scott Kamp (dingo)<br>
-Bachman Kharazmi (bkw)<br>
-Fernando Tarlá Cardoso Lemos (fernando)<br>
-Kyle Mott (kyle)<br>
-Colin Smith (colin)<br>
-</p>
-</div>
-<div class="content" id="item6">
-<p>
-Heros<br><br>
-Coming soon............
-</p>
-</div>
-<div class="content" id="item7">
-<p>
-=========================<br>
-
-Q: Do you have a quick install tutorial and tabs explanation.<br>
-
-A: Yes.<br>
-
- http://doc.pfsense.org/index.php/Setup_Snort_Package<br>
-
-=========================<br>
-
-Q: What interfaces can snort listen on ?<br>
-
-A: Right now all WAN interfaces and LAN interfaces. But if you select a LAN interface you may need to adjust the snort rules to use the LAN interface.<br>
-
-==========================<br>
-
-Q: What logs does the snort package keep. ?<br>
-
-A: Most of the snort logs are keept in the /var/log/snort.<br>
- Snorts syslogs\' are saved to the /var/log/snort/snort_sys_0ng0.<br>
-
-==========================<br>
-
-Q: What is the best Performance setting ? or Snort is using 90% cpu and all my memory.<br>
-
-A: Depends how much memory you have and how many rules you want to run.; lowmem for systems with less than 256 mb memory, ac-bnfa for systems<br>
- with over 256 mb of memory. The other options are; ac high memory, best performance, ac-std moderate memory, high performance,acs small<br>
- memory, moderate performance,ac-banded small memory,moderate performance,ac-sparsebands small memory, high performance.<br>
-
- Short version: For most people ac-bnfa is the best setting.<br>
-
-=========================<br>
-
-Q: What is the Oinkmaster code ? How do I get the code ?<br>
-
-A: The Oinkmaster code is your personal password in order to download snort rules.<br>
- You get a Oinkmaster code when you register with snort.org. It is free to register.<br>
- Goto https://www.snort.org/signup to get your personal code.<br>
-
-=========================<br>
-
-Q: What is the Snort.org subscriber option? How do I become a Snort.org subscriber?<br>
-
-A: Snort.org subscribers get the the latest rule updates 30 days faster than registered users.<br>
- Goto http://www.snort.org/vrt/buy-a-subscription/.
- It is highly suggested that you get a paid subscription so that you can always have the latest rules.<br>
-
-=========================<br>
-
-Q: When did you start working on the snort package.<br>
-
-A: I started working on the snort package in May 2009.<br>
-</p>
-</div>
-</div>
-</body>
-</html>
-';
+<?php
+
+ require_once("guiconfig.inc");
+
+echo '
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>Help & Info</title>
+<base target="main">
+<script src="./javascript/tabs.js" type="text/javascript"></script>
+<link href="./css/style2.css" rel="stylesheet" type="text/css" />
+</head>
+
+<body>
+
+<style type="text/css">
+</style>
+
+<div id="container">
+ <div id="header">
+ <IMG SRC="./images/logo.jpg" width="780px" height="76" ALT="Snort Package">
+ </div>
+ <div class="navigation" id="navigation">
+ <ul>
+ <li><a href="#item1" target="_self">Home</a></li>
+ <li><a href="#item2" target="_self">About Me</a></li>
+ <li><a href="#item3" target="_self">Services</a></li>
+ <li><a href="#item4" target="_self">Change Log</a></li>
+ <li><a href="#item7" target="_self">Faq</a></li>
+ <li><a href="#item6" target="_self">Heros</a></li>
+ <li><a href="#item5" target="_self">Developers</a></li>
+ </ul>
+ </div>
+ <br>
+<div class="content" id="item1">
+ <p>
+ <font size="5"><strong>Snort Package</strong></font> is a GUI based front-end for Sourcefire\'s Snort ® IDS/IPS software. The Snort Package goal is to be
+ the best open-source GUI to manage multiple snort sensors and multiple rule snapshots. The project other goal is to be a highly competitive GUI for
+ network monitoring for both private and enterprise use. Lastly, this project software development should bring programmers and users together to create
+ software.
+ </p>
+ <p>
+ <font size="5"><strong>What is Snort ?</strong></font> Used by fortune 500 companies and goverments Snort is the most widely deployed IDS/IPS technology worldwide. It features rules based logging and
+ can perform content searching/matching in addition to being used to detect a variety of other attacks and probes, such as buffer overflows, stealth port
+ scans, CGI attacks, SMB probes, and much more.
+ </p>
+ <p>
+ <font size="5"><strong>Requirements :</strong></font><br>
+ Minimum requirement 256 mb ram, 500 MHz CPU.<br>
+ Recommended 500 mb ram, 1 Ghz CPU.<br>
+ The more rules you run the more memory you need.<br>
+ The more interfaces you select the more memory you need.<br><br>
+ Development is done on a Alix 2D3 system (500 MHz AMD Geode LX800 CPU 256MB DDR DRAM).
+ </p>
+</div>
+<div class="content" id="item2">
+ <p>
+About Me<br><br>
+Coming soon............
+
+</p>
+</div>
+<div class="content" id="item3">
+ <p>
+Services<br><br>
+Coming soon............
+</p>
+</div>
+<div class="content" id="item4">
+<p>
+Change Log<br><br>
+Coming soon............
+</p>
+</div>
+<div class="content" id="item5">
+<p>
+<font size="5"><strong>PfSense</strong></font> is brought to you by a dedicated group of developers who are security and network professionals by trade. The following people are active developers of the pfSense project.
+Username is listed in parenthesis (generally also the person\'s forum username, IRC nickname, etc.).<br><br>
+
+<font size="5"><strong>Main Snort-dev Package Developer</strong></font><br>
+Robert Zelaya<br><br>
+
+<font size="5"><strong>Founders</strong></font><br>
+In alphabetical order<br><br>
+
+Chris Buechler (cmb)<br>
+Scott Ullrich (sullrich)<br><br>
+
+<font size="5"><strong>Active Developers</strong></font><br>
+Listed in order of seniority along with date of first contribution.<br><br>
+
+Bill Marquette (billm) - February 2005<br>
+Holger Bauer (hoba) - May 2005<br>
+Erik Kristensen (ekristen) - August 2005<br>
+Seth Mos (smos) - November 2005<br>
+Scott Dale (sdale) - December 2006<br>
+Martin Fuchs (mfuchs) - June 2007<br>
+Ermal Luçi (ermal) - January 2008<br>
+Matthew Grooms (mgrooms) - July 2008<br>
+Mark Crane (mcrane) - October 2008<br>
+Jim Pingle (jim-p) - February 2009<br>
+Rob Zelaya (robiscool) - March 2009<br>
+Renato Botelho (rbgarga) - May 2009<br><br>
+
+<font size="5"><strong>FreeBSD Developer Assistance</strong></font><br>
+We would like to thank the following FreeBSD developers for their assistance.<br><br>
+
+Max Laier (mlaier)<br>
+Christian S.J. Peron (csjp)<br>
+Andrew Thompson (thompsa)<br>
+Bjoern A. Zeeb (bz)<br><br>
+
+among many others who help us directly, and everyone who contributes to FreeBSD.<br><br>
+
+<font size="5"><strong>Inactive Developers</strong></font><br>
+The following individuals are no longer active contributors, having moved on because of other commitments, or employers forbidding contributions. We thank them for their past contributions.<br><br>
+
+Daniel Berlin (dberlin)<br>
+Daniel Haischt (dsh)<br>
+Espen Johansen (lsf)<br>
+Scott Kamp (dingo)<br>
+Bachman Kharazmi (bkw)<br>
+Fernando Tarlá Cardoso Lemos (fernando)<br>
+Kyle Mott (kyle)<br>
+Colin Smith (colin)<br>
+</p>
+</div>
+<div class="content" id="item6">
+<p>
+Heros<br><br>
+Coming soon............
+</p>
+</div>
+<div class="content" id="item7">
+<p>
+=========================<br>
+
+Q: Do you have a quick install tutorial and tabs explanation.<br>
+
+A: Yes.<br>
+
+ http://doc.pfsense.org/index.php/Setup_Snort_Package<br>
+
+=========================<br>
+
+Q: What interfaces can snort listen on ?<br>
+
+A: Right now all WAN interfaces and LAN interfaces. But if you select a LAN interface you may need to adjust the snort rules to use the LAN interface.<br>
+
+==========================<br>
+
+Q: What logs does the snort package keep. ?<br>
+
+A: Most of the snort logs are keept in the /var/log/snort.<br>
+ Snorts syslogs\' are saved to the /var/log/snort/snort_sys_0ng0.<br>
+
+==========================<br>
+
+Q: What is the best Performance setting ? or Snort is using 90% cpu and all my memory.<br>
+
+A: Depends how much memory you have and how many rules you want to run.; lowmem for systems with less than 256 mb memory, ac-bnfa for systems<br>
+ with over 256 mb of memory. The other options are; ac high memory, best performance, ac-std moderate memory, high performance,acs small<br>
+ memory, moderate performance,ac-banded small memory,moderate performance,ac-sparsebands small memory, high performance.<br>
+
+ Short version: For most people ac-bnfa is the best setting.<br>
+
+=========================<br>
+
+Q: What is the Oinkmaster code ? How do I get the code ?<br>
+
+A: The Oinkmaster code is your personal password in order to download snort rules.<br>
+ You get a Oinkmaster code when you register with snort.org. It is free to register.<br>
+ Goto https://www.snort.org/signup to get your personal code.<br>
+
+=========================<br>
+
+Q: What is the Snort.org subscriber option? How do I become a Snort.org subscriber?<br>
+
+A: Snort.org subscribers get the the latest rule updates 30 days faster than registered users.<br>
+ Goto http://www.snort.org/vrt/buy-a-subscription/.
+ It is highly suggested that you get a paid subscription so that you can always have the latest rules.<br>
+
+=========================<br>
+
+Q: When did you start working on the snort package.<br>
+
+A: I started working on the snort package in May 2009.<br>
+</p>
+</div>
+</div>
+</body>
+</html>
+';
?> \ No newline at end of file
diff --git a/config/snort-dev/images/footer.jpg b/config/snort-dev/images/footer.jpg
index 0cf9675a..4af05707 100644
--- a/config/snort-dev/images/footer.jpg
+++ b/config/snort-dev/images/footer.jpg
Binary files differ
diff --git a/config/snort-dev/images/footer2.jpg b/config/snort-dev/images/footer2.jpg
index 37bdb18e..3332e085 100644
--- a/config/snort-dev/images/footer2.jpg
+++ b/config/snort-dev/images/footer2.jpg
Binary files differ
diff --git a/config/snort-dev/images/icon-table-sort-asc.png b/config/snort-dev/images/icon-table-sort-asc.png
index 330b3c1f..0c127919 100644
--- a/config/snort-dev/images/icon-table-sort-asc.png
+++ b/config/snort-dev/images/icon-table-sort-asc.png
Binary files differ
diff --git a/config/snort-dev/images/icon-table-sort-desc.png b/config/snort-dev/images/icon-table-sort-desc.png
index dc8a92bb..5c52f2d0 100644
--- a/config/snort-dev/images/icon-table-sort-desc.png
+++ b/config/snort-dev/images/icon-table-sort-desc.png
Binary files differ
diff --git a/config/snort-dev/images/icon-table-sort.png b/config/snort-dev/images/icon-table-sort.png
index 389169ab..3cae604b 100644
--- a/config/snort-dev/images/icon-table-sort.png
+++ b/config/snort-dev/images/icon-table-sort.png
Binary files differ
diff --git a/config/snort-dev/images/icon_excli.png b/config/snort-dev/images/icon_excli.png
new file mode 100644
index 00000000..4b54fa31
--- /dev/null
+++ b/config/snort-dev/images/icon_excli.png
Binary files differ
diff --git a/config/snort-dev/images/logo.jpg b/config/snort-dev/images/logo.jpg
index 75abf478..fa01d818 100644
--- a/config/snort-dev/images/logo.jpg
+++ b/config/snort-dev/images/logo.jpg
Binary files differ
diff --git a/config/snort-dev/javascript/jquery-1.3.2.js b/config/snort-dev/javascript/jquery-1.3.2.js
index ac191058..59b71d25 100644
--- a/config/snort-dev/javascript/jquery-1.3.2.js
+++ b/config/snort-dev/javascript/jquery-1.3.2.js
@@ -1,4376 +1,4376 @@
-/*!
- * jQuery JavaScript Library v1.3.2
- * http://jquery.com/
- *
- * Copyright (c) 2009 John Resig
- * Dual licensed under the MIT and GPL licenses.
- * http://docs.jquery.com/License
- *
- * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
- * Revision: 6246
- */
-(function(){
-
-var
- // Will speed up references to window, and allows munging its name.
- window = this,
- // Will speed up references to undefined, and allows munging its name.
- undefined,
- // Map over jQuery in case of overwrite
- _jQuery = window.jQuery,
- // Map over the $ in case of overwrite
- _$ = window.$,
-
- jQuery = window.jQuery = window.$ = function( selector, context ) {
- // The jQuery object is actually just the init constructor 'enhanced'
- return new jQuery.fn.init( selector, context );
- },
-
- // A simple way to check for HTML strings or ID strings
- // (both of which we optimize for)
- quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
- // Is it a simple selector
- isSimple = /^.[^:#\[\.,]*$/;
-
-jQuery.fn = jQuery.prototype = {
- init: function( selector, context ) {
- // Make sure that a selection was provided
- selector = selector || document;
-
- // Handle $(DOMElement)
- if ( selector.nodeType ) {
- this[0] = selector;
- this.length = 1;
- this.context = selector;
- return this;
- }
- // Handle HTML strings
- if ( typeof selector === "string" ) {
- // Are we dealing with HTML string or an ID?
- var match = quickExpr.exec( selector );
-
- // Verify a match, and that no context was specified for #id
- if ( match && (match[1] || !context) ) {
-
- // HANDLE: $(html) -> $(array)
- if ( match[1] )
- selector = jQuery.clean( [ match[1] ], context );
-
- // HANDLE: $("#id")
- else {
- var elem = document.getElementById( match[3] );
-
- // Handle the case where IE and Opera return items
- // by name instead of ID
- if ( elem && elem.id != match[3] )
- return jQuery().find( selector );
-
- // Otherwise, we inject the element directly into the jQuery object
- var ret = jQuery( elem || [] );
- ret.context = document;
- ret.selector = selector;
- return ret;
- }
-
- // HANDLE: $(expr, [context])
- // (which is just equivalent to: $(content).find(expr)
- } else
- return jQuery( context ).find( selector );
-
- // HANDLE: $(function)
- // Shortcut for document ready
- } else if ( jQuery.isFunction( selector ) )
- return jQuery( document ).ready( selector );
-
- // Make sure that old selector state is passed along
- if ( selector.selector && selector.context ) {
- this.selector = selector.selector;
- this.context = selector.context;
- }
-
- return this.setArray(jQuery.isArray( selector ) ?
- selector :
- jQuery.makeArray(selector));
- },
-
- // Start with an empty selector
- selector: "",
-
- // The current version of jQuery being used
- jquery: "1.3.2",
-
- // The number of elements contained in the matched element set
- size: function() {
- return this.length;
- },
-
- // Get the Nth element in the matched element set OR
- // Get the whole matched element set as a clean array
- get: function( num ) {
- return num === undefined ?
-
- // Return a 'clean' array
- Array.prototype.slice.call( this ) :
-
- // Return just the object
- this[ num ];
- },
-
- // Take an array of elements and push it onto the stack
- // (returning the new matched element set)
- pushStack: function( elems, name, selector ) {
- // Build a new jQuery matched element set
- var ret = jQuery( elems );
-
- // Add the old object onto the stack (as a reference)
- ret.prevObject = this;
-
- ret.context = this.context;
-
- if ( name === "find" )
- ret.selector = this.selector + (this.selector ? " " : "") + selector;
- else if ( name )
- ret.selector = this.selector + "." + name + "(" + selector + ")";
-
- // Return the newly-formed element set
- return ret;
- },
-
- // Force the current matched set of elements to become
- // the specified array of elements (destroying the stack in the process)
- // You should use pushStack() in order to do this, but maintain the stack
- setArray: function( elems ) {
- // Resetting the length to 0, then using the native Array push
- // is a super-fast way to populate an object with array-like properties
- this.length = 0;
- Array.prototype.push.apply( this, elems );
-
- return this;
- },
-
- // Execute a callback for every element in the matched set.
- // (You can seed the arguments with an array of args, but this is
- // only used internally.)
- each: function( callback, args ) {
- return jQuery.each( this, callback, args );
- },
-
- // Determine the position of an element within
- // the matched set of elements
- index: function( elem ) {
- // Locate the position of the desired element
- return jQuery.inArray(
- // If it receives a jQuery object, the first element is used
- elem && elem.jquery ? elem[0] : elem
- , this );
- },
-
- attr: function( name, value, type ) {
- var options = name;
-
- // Look for the case where we're accessing a style value
- if ( typeof name === "string" )
- if ( value === undefined )
- return this[0] && jQuery[ type || "attr" ]( this[0], name );
-
- else {
- options = {};
- options[ name ] = value;
- }
-
- // Check to see if we're setting style values
- return this.each(function(i){
- // Set all the styles
- for ( name in options )
- jQuery.attr(
- type ?
- this.style :
- this,
- name, jQuery.prop( this, options[ name ], type, i, name )
- );
- });
- },
-
- css: function( key, value ) {
- // ignore negative width and height values
- if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
- value = undefined;
- return this.attr( key, value, "curCSS" );
- },
-
- text: function( text ) {
- if ( typeof text !== "object" && text != null )
- return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
-
- var ret = "";
-
- jQuery.each( text || this, function(){
- jQuery.each( this.childNodes, function(){
- if ( this.nodeType != 8 )
- ret += this.nodeType != 1 ?
- this.nodeValue :
- jQuery.fn.text( [ this ] );
- });
- });
-
- return ret;
- },
-
- wrapAll: function( html ) {
- if ( this[0] ) {
- // The elements to wrap the target around
- var wrap = jQuery( html, this[0].ownerDocument ).clone();
-
- if ( this[0].parentNode )
- wrap.insertBefore( this[0] );
-
- wrap.map(function(){
- var elem = this;
-
- while ( elem.firstChild )
- elem = elem.firstChild;
-
- return elem;
- }).append(this);
- }
-
- return this;
- },
-
- wrapInner: function( html ) {
- return this.each(function(){
- jQuery( this ).contents().wrapAll( html );
- });
- },
-
- wrap: function( html ) {
- return this.each(function(){
- jQuery( this ).wrapAll( html );
- });
- },
-
- append: function() {
- return this.domManip(arguments, true, function(elem){
- if (this.nodeType == 1)
- this.appendChild( elem );
- });
- },
-
- prepend: function() {
- return this.domManip(arguments, true, function(elem){
- if (this.nodeType == 1)
- this.insertBefore( elem, this.firstChild );
- });
- },
-
- before: function() {
- return this.domManip(arguments, false, function(elem){
- this.parentNode.insertBefore( elem, this );
- });
- },
-
- after: function() {
- return this.domManip(arguments, false, function(elem){
- this.parentNode.insertBefore( elem, this.nextSibling );
- });
- },
-
- end: function() {
- return this.prevObject || jQuery( [] );
- },
-
- // For internal use only.
- // Behaves like an Array's method, not like a jQuery method.
- push: [].push,
- sort: [].sort,
- splice: [].splice,
-
- find: function( selector ) {
- if ( this.length === 1 ) {
- var ret = this.pushStack( [], "find", selector );
- ret.length = 0;
- jQuery.find( selector, this[0], ret );
- return ret;
- } else {
- return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
- return jQuery.find( selector, elem );
- })), "find", selector );
- }
- },
-
- clone: function( events ) {
- // Do the clone
- var ret = this.map(function(){
- if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
- // IE copies events bound via attachEvent when
- // using cloneNode. Calling detachEvent on the
- // clone will also remove the events from the orignal
- // In order to get around this, we use innerHTML.
- // Unfortunately, this means some modifications to
- // attributes in IE that are actually only stored
- // as properties will not be copied (such as the
- // the name attribute on an input).
- var html = this.outerHTML;
- if ( !html ) {
- var div = this.ownerDocument.createElement("div");
- div.appendChild( this.cloneNode(true) );
- html = div.innerHTML;
- }
-
- return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
- } else
- return this.cloneNode(true);
- });
-
- // Copy the events from the original to the clone
- if ( events === true ) {
- var orig = this.find("*").andSelf(), i = 0;
-
- ret.find("*").andSelf().each(function(){
- if ( this.nodeName !== orig[i].nodeName )
- return;
-
- var events = jQuery.data( orig[i], "events" );
-
- for ( var type in events ) {
- for ( var handler in events[ type ] ) {
- jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
- }
- }
-
- i++;
- });
- }
-
- // Return the cloned set
- return ret;
- },
-
- filter: function( selector ) {
- return this.pushStack(
- jQuery.isFunction( selector ) &&
- jQuery.grep(this, function(elem, i){
- return selector.call( elem, i );
- }) ||
-
- jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
- return elem.nodeType === 1;
- }) ), "filter", selector );
- },
-
- closest: function( selector ) {
- var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
- closer = 0;
-
- return this.map(function(){
- var cur = this;
- while ( cur && cur.ownerDocument ) {
- if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
- jQuery.data(cur, "closest", closer);
- return cur;
- }
- cur = cur.parentNode;
- closer++;
- }
- });
- },
-
- not: function( selector ) {
- if ( typeof selector === "string" )
- // test special case where just one selector is passed in
- if ( isSimple.test( selector ) )
- return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
- else
- selector = jQuery.multiFilter( selector, this );
-
- var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
- return this.filter(function() {
- return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
- });
- },
-
- add: function( selector ) {
- return this.pushStack( jQuery.unique( jQuery.merge(
- this.get(),
- typeof selector === "string" ?
- jQuery( selector ) :
- jQuery.makeArray( selector )
- )));
- },
-
- is: function( selector ) {
- return !!selector && jQuery.multiFilter( selector, this ).length > 0;
- },
-
- hasClass: function( selector ) {
- return !!selector && this.is( "." + selector );
- },
-
- val: function( value ) {
- if ( value === undefined ) {
- var elem = this[0];
-
- if ( elem ) {
- if( jQuery.nodeName( elem, 'option' ) )
- return (elem.attributes.value || {}).specified ? elem.value : elem.text;
-
- // We need to handle select boxes special
- if ( jQuery.nodeName( elem, "select" ) ) {
- var index = elem.selectedIndex,
- values = [],
- options = elem.options,
- one = elem.type == "select-one";
-
- // Nothing was selected
- if ( index < 0 )
- return null;
-
- // Loop through all the selected options
- for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
- var option = options[ i ];
-
- if ( option.selected ) {
- // Get the specifc value for the option
- value = jQuery(option).val();
-
- // We don't need an array for one selects
- if ( one )
- return value;
-
- // Multi-Selects return an array
- values.push( value );
- }
- }
-
- return values;
- }
-
- // Everything else, we just grab the value
- return (elem.value || "").replace(/\r/g, "");
-
- }
-
- return undefined;
- }
-
- if ( typeof value === "number" )
- value += '';
-
- return this.each(function(){
- if ( this.nodeType != 1 )
- return;
-
- if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
- this.checked = (jQuery.inArray(this.value, value) >= 0 ||
- jQuery.inArray(this.name, value) >= 0);
-
- else if ( jQuery.nodeName( this, "select" ) ) {
- var values = jQuery.makeArray(value);
-
- jQuery( "option", this ).each(function(){
- this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
- jQuery.inArray( this.text, values ) >= 0);
- });
-
- if ( !values.length )
- this.selectedIndex = -1;
-
- } else
- this.value = value;
- });
- },
-
- html: function( value ) {
- return value === undefined ?
- (this[0] ?
- this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
- null) :
- this.empty().append( value );
- },
-
- replaceWith: function( value ) {
- return this.after( value ).remove();
- },
-
- eq: function( i ) {
- return this.slice( i, +i + 1 );
- },
-
- slice: function() {
- return this.pushStack( Array.prototype.slice.apply( this, arguments ),
- "slice", Array.prototype.slice.call(arguments).join(",") );
- },
-
- map: function( callback ) {
- return this.pushStack( jQuery.map(this, function(elem, i){
- return callback.call( elem, i, elem );
- }));
- },
-
- andSelf: function() {
- return this.add( this.prevObject );
- },
-
- domManip: function( args, table, callback ) {
- if ( this[0] ) {
- var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
- scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
- first = fragment.firstChild;
-
- if ( first )
- for ( var i = 0, l = this.length; i < l; i++ )
- callback.call( root(this[i], first), this.length > 1 || i > 0 ?
- fragment.cloneNode(true) : fragment );
-
- if ( scripts )
- jQuery.each( scripts, evalScript );
- }
-
- return this;
-
- function root( elem, cur ) {
- return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
- (elem.getElementsByTagName("tbody")[0] ||
- elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
- elem;
- }
- }
-};
-
-// Give the init function the jQuery prototype for later instantiation
-jQuery.fn.init.prototype = jQuery.fn;
-
-function evalScript( i, elem ) {
- if ( elem.src )
- jQuery.ajax({
- url: elem.src,
- async: false,
- dataType: "script"
- });
-
- else
- jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
-
- if ( elem.parentNode )
- elem.parentNode.removeChild( elem );
-}
-
-function now(){
- return +new Date;
-}
-
-jQuery.extend = jQuery.fn.extend = function() {
- // copy reference to target object
- var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
-
- // Handle a deep copy situation
- if ( typeof target === "boolean" ) {
- deep = target;
- target = arguments[1] || {};
- // skip the boolean and the target
- i = 2;
- }
-
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !jQuery.isFunction(target) )
- target = {};
-
- // extend jQuery itself if only one argument is passed
- if ( length == i ) {
- target = this;
- --i;
- }
-
- for ( ; i < length; i++ )
- // Only deal with non-null/undefined values
- if ( (options = arguments[ i ]) != null )
- // Extend the base object
- for ( var name in options ) {
- var src = target[ name ], copy = options[ name ];
-
- // Prevent never-ending loop
- if ( target === copy )
- continue;
-
- // Recurse if we're merging object values
- if ( deep && copy && typeof copy === "object" && !copy.nodeType )
- target[ name ] = jQuery.extend( deep,
- // Never move original objects, clone them
- src || ( copy.length != null ? [ ] : { } )
- , copy );
-
- // Don't bring in undefined values
- else if ( copy !== undefined )
- target[ name ] = copy;
-
- }
-
- // Return the modified object
- return target;
-};
-
-// exclude the following css properties to add px
-var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
- // cache defaultView
- defaultView = document.defaultView || {},
- toString = Object.prototype.toString;
-
-jQuery.extend({
- noConflict: function( deep ) {
- window.$ = _$;
-
- if ( deep )
- window.jQuery = _jQuery;
-
- return jQuery;
- },
-
- // See test/unit/core.js for details concerning isFunction.
- // Since version 1.3, DOM methods and functions like alert
- // aren't supported. They return false on IE (#2968).
- isFunction: function( obj ) {
- return toString.call(obj) === "[object Function]";
- },
-
- isArray: function( obj ) {
- return toString.call(obj) === "[object Array]";
- },
-
- // check if an element is in a (or is an) XML document
- isXMLDoc: function( elem ) {
- return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
- !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
- },
-
- // Evalulates a script in a global context
- globalEval: function( data ) {
- if ( data && /\S/.test(data) ) {
- // Inspired by code by Andrea Giammarchi
- // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
- var head = document.getElementsByTagName("head")[0] || document.documentElement,
- script = document.createElement("script");
-
- script.type = "text/javascript";
- if ( jQuery.support.scriptEval )
- script.appendChild( document.createTextNode( data ) );
- else
- script.text = data;
-
- // Use insertBefore instead of appendChild to circumvent an IE6 bug.
- // This arises when a base node is used (#2709).
- head.insertBefore( script, head.firstChild );
- head.removeChild( script );
- }
- },
-
- nodeName: function( elem, name ) {
- return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
- },
-
- // args is for internal usage only
- each: function( object, callback, args ) {
- var name, i = 0, length = object.length;
-
- if ( args ) {
- if ( length === undefined ) {
- for ( name in object )
- if ( callback.apply( object[ name ], args ) === false )
- break;
- } else
- for ( ; i < length; )
- if ( callback.apply( object[ i++ ], args ) === false )
- break;
-
- // A special, fast, case for the most common use of each
- } else {
- if ( length === undefined ) {
- for ( name in object )
- if ( callback.call( object[ name ], name, object[ name ] ) === false )
- break;
- } else
- for ( var value = object[0];
- i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
- }
-
- return object;
- },
-
- prop: function( elem, value, type, i, name ) {
- // Handle executable functions
- if ( jQuery.isFunction( value ) )
- value = value.call( elem, i );
-
- // Handle passing in a number to a CSS property
- return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
- value + "px" :
- value;
- },
-
- className: {
- // internal only, use addClass("class")
- add: function( elem, classNames ) {
- jQuery.each((classNames || "").split(/\s+/), function(i, className){
- if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
- elem.className += (elem.className ? " " : "") + className;
- });
- },
-
- // internal only, use removeClass("class")
- remove: function( elem, classNames ) {
- if (elem.nodeType == 1)
- elem.className = classNames !== undefined ?
- jQuery.grep(elem.className.split(/\s+/), function(className){
- return !jQuery.className.has( classNames, className );
- }).join(" ") :
- "";
- },
-
- // internal only, use hasClass("class")
- has: function( elem, className ) {
- return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
- }
- },
-
- // A method for quickly swapping in/out CSS properties to get correct calculations
- swap: function( elem, options, callback ) {
- var old = {};
- // Remember the old values, and insert the new ones
- for ( var name in options ) {
- old[ name ] = elem.style[ name ];
- elem.style[ name ] = options[ name ];
- }
-
- callback.call( elem );
-
- // Revert the old values
- for ( var name in options )
- elem.style[ name ] = old[ name ];
- },
-
- css: function( elem, name, force, extra ) {
- if ( name == "width" || name == "height" ) {
- var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
-
- function getWH() {
- val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
-
- if ( extra === "border" )
- return;
-
- jQuery.each( which, function() {
- if ( !extra )
- val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
- if ( extra === "margin" )
- val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
- else
- val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
- });
- }
-
- if ( elem.offsetWidth !== 0 )
- getWH();
- else
- jQuery.swap( elem, props, getWH );
-
- return Math.max(0, Math.round(val));
- }
-
- return jQuery.curCSS( elem, name, force );
- },
-
- curCSS: function( elem, name, force ) {
- var ret, style = elem.style;
-
- // We need to handle opacity special in IE
- if ( name == "opacity" && !jQuery.support.opacity ) {
- ret = jQuery.attr( style, "opacity" );
-
- return ret == "" ?
- "1" :
- ret;
- }
-
- // Make sure we're using the right name for getting the float value
- if ( name.match( /float/i ) )
- name = styleFloat;
-
- if ( !force && style && style[ name ] )
- ret = style[ name ];
-
- else if ( defaultView.getComputedStyle ) {
-
- // Only "float" is needed here
- if ( name.match( /float/i ) )
- name = "float";
-
- name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
-
- var computedStyle = defaultView.getComputedStyle( elem, null );
-
- if ( computedStyle )
- ret = computedStyle.getPropertyValue( name );
-
- // We should always get a number back from opacity
- if ( name == "opacity" && ret == "" )
- ret = "1";
-
- } else if ( elem.currentStyle ) {
- var camelCase = name.replace(/\-(\w)/g, function(all, letter){
- return letter.toUpperCase();
- });
-
- ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
-
- // From the awesome hack by Dean Edwards
- // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
-
- // If we're not dealing with a regular pixel number
- // but a number that has a weird ending, we need to convert it to pixels
- if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
- // Remember the original values
- var left = style.left, rsLeft = elem.runtimeStyle.left;
-
- // Put in the new values to get a computed value out
- elem.runtimeStyle.left = elem.currentStyle.left;
- style.left = ret || 0;
- ret = style.pixelLeft + "px";
-
- // Revert the changed values
- style.left = left;
- elem.runtimeStyle.left = rsLeft;
- }
- }
-
- return ret;
- },
-
- clean: function( elems, context, fragment ) {
- context = context || document;
-
- // !context.createElement fails in IE with an error but returns typeof 'object'
- if ( typeof context.createElement === "undefined" )
- context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
-
- // If a single string is passed in and it's a single tag
- // just do a createElement and skip the rest
- if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
- var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
- if ( match )
- return [ context.createElement( match[1] ) ];
- }
-
- var ret = [], scripts = [], div = context.createElement("div");
-
- jQuery.each(elems, function(i, elem){
- if ( typeof elem === "number" )
- elem += '';
-
- if ( !elem )
- return;
-
- // Convert html string into DOM nodes
- if ( typeof elem === "string" ) {
- // Fix "XHTML"-style tags in all browsers
- elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
- return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
- all :
- front + "></" + tag + ">";
- });
-
- // Trim whitespace, otherwise indexOf won't work as expected
- var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
-
- var wrap =
- // option or optgroup
- !tags.indexOf("<opt") &&
- [ 1, "<select multiple='multiple'>", "</select>" ] ||
-
- !tags.indexOf("<leg") &&
- [ 1, "<fieldset>", "</fieldset>" ] ||
-
- tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
- [ 1, "<table>", "</table>" ] ||
-
- !tags.indexOf("<tr") &&
- [ 2, "<table><tbody>", "</tbody></table>" ] ||
-
- // <thead> matched above
- (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
- [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
-
- !tags.indexOf("<col") &&
- [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
-
- // IE can't serialize <link> and <script> tags normally
- !jQuery.support.htmlSerialize &&
- [ 1, "div<div>", "</div>" ] ||
-
- [ 0, "", "" ];
-
- // Go to html and back, then peel off extra wrappers
- div.innerHTML = wrap[1] + elem + wrap[2];
-
- // Move to the right depth
- while ( wrap[0]-- )
- div = div.lastChild;
-
- // Remove IE's autoinserted <tbody> from table fragments
- if ( !jQuery.support.tbody ) {
-
- // String was a <table>, *may* have spurious <tbody>
- var hasBody = /<tbody/i.test(elem),
- tbody = !tags.indexOf("<table") && !hasBody ?
- div.firstChild && div.firstChild.childNodes :
-
- // String was a bare <thead> or <tfoot>
- wrap[1] == "<table>" && !hasBody ?
- div.childNodes :
- [];
-
- for ( var j = tbody.length - 1; j >= 0 ; --j )
- if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
- tbody[ j ].parentNode.removeChild( tbody[ j ] );
-
- }
-
- // IE completely kills leading whitespace when innerHTML is used
- if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
- div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
-
- elem = jQuery.makeArray( div.childNodes );
- }
-
- if ( elem.nodeType )
- ret.push( elem );
- else
- ret = jQuery.merge( ret, elem );
-
- });
-
- if ( fragment ) {
- for ( var i = 0; ret[i]; i++ ) {
- if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
- scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
- } else {
- if ( ret[i].nodeType === 1 )
- ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
- fragment.appendChild( ret[i] );
- }
- }
-
- return scripts;
- }
-
- return ret;
- },
-
- attr: function( elem, name, value ) {
- // don't set attributes on text and comment nodes
- if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
- return undefined;
-
- var notxml = !jQuery.isXMLDoc( elem ),
- // Whether we are setting (or getting)
- set = value !== undefined;
-
- // Try to normalize/fix the name
- name = notxml && jQuery.props[ name ] || name;
-
- // Only do all the following if this is a node (faster for style)
- // IE elem.getAttribute passes even for style
- if ( elem.tagName ) {
-
- // These attributes require special treatment
- var special = /href|src|style/.test( name );
-
- // Safari mis-reports the default selected property of a hidden option
- // Accessing the parent's selectedIndex property fixes it
- if ( name == "selected" && elem.parentNode )
- elem.parentNode.selectedIndex;
-
- // If applicable, access the attribute via the DOM 0 way
- if ( name in elem && notxml && !special ) {
- if ( set ){
- // We can't allow the type property to be changed (since it causes problems in IE)
- if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
- throw "type property can't be changed";
-
- elem[ name ] = value;
- }
-
- // browsers index elements by id/name on forms, give priority to attributes.
- if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
- return elem.getAttributeNode( name ).nodeValue;
-
- // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
- // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
- if ( name == "tabIndex" ) {
- var attributeNode = elem.getAttributeNode( "tabIndex" );
- return attributeNode && attributeNode.specified
- ? attributeNode.value
- : elem.nodeName.match(/(button|input|object|select|textarea)/i)
- ? 0
- : elem.nodeName.match(/^(a|area)$/i) && elem.href
- ? 0
- : undefined;
- }
-
- return elem[ name ];
- }
-
- if ( !jQuery.support.style && notxml && name == "style" )
- return jQuery.attr( elem.style, "cssText", value );
-
- if ( set )
- // convert the value to a string (all browsers do this but IE) see #1070
- elem.setAttribute( name, "" + value );
-
- var attr = !jQuery.support.hrefNormalized && notxml && special
- // Some attributes require a special call on IE
- ? elem.getAttribute( name, 2 )
- : elem.getAttribute( name );
-
- // Non-existent attributes return null, we normalize to undefined
- return attr === null ? undefined : attr;
- }
-
- // elem is actually elem.style ... set the style
-
- // IE uses filters for opacity
- if ( !jQuery.support.opacity && name == "opacity" ) {
- if ( set ) {
- // IE has trouble with opacity if it does not have layout
- // Force it by setting the zoom level
- elem.zoom = 1;
-
- // Set the alpha filter to set the opacity
- elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
- (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
- }
-
- return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
- (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
- "";
- }
-
- name = name.replace(/-([a-z])/ig, function(all, letter){
- return letter.toUpperCase();
- });
-
- if ( set )
- elem[ name ] = value;
-
- return elem[ name ];
- },
-
- trim: function( text ) {
- return (text || "").replace( /^\s+|\s+$/g, "" );
- },
-
- makeArray: function( array ) {
- var ret = [];
-
- if( array != null ){
- var i = array.length;
- // The window, strings (and functions) also have 'length'
- if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
- ret[0] = array;
- else
- while( i )
- ret[--i] = array[i];
- }
-
- return ret;
- },
-
- inArray: function( elem, array ) {
- for ( var i = 0, length = array.length; i < length; i++ )
- // Use === because on IE, window == document
- if ( array[ i ] === elem )
- return i;
-
- return -1;
- },
-
- merge: function( first, second ) {
- // We have to loop this way because IE & Opera overwrite the length
- // expando of getElementsByTagName
- var i = 0, elem, pos = first.length;
- // Also, we need to make sure that the correct elements are being returned
- // (IE returns comment nodes in a '*' query)
- if ( !jQuery.support.getAll ) {
- while ( (elem = second[ i++ ]) != null )
- if ( elem.nodeType != 8 )
- first[ pos++ ] = elem;
-
- } else
- while ( (elem = second[ i++ ]) != null )
- first[ pos++ ] = elem;
-
- return first;
- },
-
- unique: function( array ) {
- var ret = [], done = {};
-
- try {
-
- for ( var i = 0, length = array.length; i < length; i++ ) {
- var id = jQuery.data( array[ i ] );
-
- if ( !done[ id ] ) {
- done[ id ] = true;
- ret.push( array[ i ] );
- }
- }
-
- } catch( e ) {
- ret = array;
- }
-
- return ret;
- },
-
- grep: function( elems, callback, inv ) {
- var ret = [];
-
- // Go through the array, only saving the items
- // that pass the validator function
- for ( var i = 0, length = elems.length; i < length; i++ )
- if ( !inv != !callback( elems[ i ], i ) )
- ret.push( elems[ i ] );
-
- return ret;
- },
-
- map: function( elems, callback ) {
- var ret = [];
-
- // Go through the array, translating each of the items to their
- // new value (or values).
- for ( var i = 0, length = elems.length; i < length; i++ ) {
- var value = callback( elems[ i ], i );
-
- if ( value != null )
- ret[ ret.length ] = value;
- }
-
- return ret.concat.apply( [], ret );
- }
-});
-
-// Use of jQuery.browser is deprecated.
-// It's included for backwards compatibility and plugins,
-// although they should work to migrate away.
-
-var userAgent = navigator.userAgent.toLowerCase();
-
-// Figure out what browser is being used
-jQuery.browser = {
- version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
- safari: /webkit/.test( userAgent ),
- opera: /opera/.test( userAgent ),
- msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
- mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
-};
-
-jQuery.each({
- parent: function(elem){return elem.parentNode;},
- parents: function(elem){return jQuery.dir(elem,"parentNode");},
- next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
- prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
- nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
- prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
- siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
- children: function(elem){return jQuery.sibling(elem.firstChild);},
- contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
-}, function(name, fn){
- jQuery.fn[ name ] = function( selector ) {
- var ret = jQuery.map( this, fn );
-
- if ( selector && typeof selector == "string" )
- ret = jQuery.multiFilter( selector, ret );
-
- return this.pushStack( jQuery.unique( ret ), name, selector );
- };
-});
-
-jQuery.each({
- appendTo: "append",
- prependTo: "prepend",
- insertBefore: "before",
- insertAfter: "after",
- replaceAll: "replaceWith"
-}, function(name, original){
- jQuery.fn[ name ] = function( selector ) {
- var ret = [], insert = jQuery( selector );
-
- for ( var i = 0, l = insert.length; i < l; i++ ) {
- var elems = (i > 0 ? this.clone(true) : this).get();
- jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
- ret = ret.concat( elems );
- }
-
- return this.pushStack( ret, name, selector );
- };
-});
-
-jQuery.each({
- removeAttr: function( name ) {
- jQuery.attr( this, name, "" );
- if (this.nodeType == 1)
- this.removeAttribute( name );
- },
-
- addClass: function( classNames ) {
- jQuery.className.add( this, classNames );
- },
-
- removeClass: function( classNames ) {
- jQuery.className.remove( this, classNames );
- },
-
- toggleClass: function( classNames, state ) {
- if( typeof state !== "boolean" )
- state = !jQuery.className.has( this, classNames );
- jQuery.className[ state ? "add" : "remove" ]( this, classNames );
- },
-
- remove: function( selector ) {
- if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
- // Prevent memory leaks
- jQuery( "*", this ).add([this]).each(function(){
- jQuery.event.remove(this);
- jQuery.removeData(this);
- });
- if (this.parentNode)
- this.parentNode.removeChild( this );
- }
- },
-
- empty: function() {
- // Remove element nodes and prevent memory leaks
- jQuery(this).children().remove();
-
- // Remove any remaining nodes
- while ( this.firstChild )
- this.removeChild( this.firstChild );
- }
-}, function(name, fn){
- jQuery.fn[ name ] = function(){
- return this.each( fn, arguments );
- };
-});
-
-// Helper function used by the dimensions and offset modules
-function num(elem, prop) {
- return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
-}
-var expando = "jQuery" + now(), uuid = 0, windowData = {};
-
-jQuery.extend({
- cache: {},
-
- data: function( elem, name, data ) {
- elem = elem == window ?
- windowData :
- elem;
-
- var id = elem[ expando ];
-
- // Compute a unique ID for the element
- if ( !id )
- id = elem[ expando ] = ++uuid;
-
- // Only generate the data cache if we're
- // trying to access or manipulate it
- if ( name && !jQuery.cache[ id ] )
- jQuery.cache[ id ] = {};
-
- // Prevent overriding the named cache with undefined values
- if ( data !== undefined )
- jQuery.cache[ id ][ name ] = data;
-
- // Return the named cache data, or the ID for the element
- return name ?
- jQuery.cache[ id ][ name ] :
- id;
- },
-
- removeData: function( elem, name ) {
- elem = elem == window ?
- windowData :
- elem;
-
- var id = elem[ expando ];
-
- // If we want to remove a specific section of the element's data
- if ( name ) {
- if ( jQuery.cache[ id ] ) {
- // Remove the section of cache data
- delete jQuery.cache[ id ][ name ];
-
- // If we've removed all the data, remove the element's cache
- name = "";
-
- for ( name in jQuery.cache[ id ] )
- break;
-
- if ( !name )
- jQuery.removeData( elem );
- }
-
- // Otherwise, we want to remove all of the element's data
- } else {
- // Clean up the element expando
- try {
- delete elem[ expando ];
- } catch(e){
- // IE has trouble directly removing the expando
- // but it's ok with using removeAttribute
- if ( elem.removeAttribute )
- elem.removeAttribute( expando );
- }
-
- // Completely remove the data cache
- delete jQuery.cache[ id ];
- }
- },
- queue: function( elem, type, data ) {
- if ( elem ){
-
- type = (type || "fx") + "queue";
-
- var q = jQuery.data( elem, type );
-
- if ( !q || jQuery.isArray(data) )
- q = jQuery.data( elem, type, jQuery.makeArray(data) );
- else if( data )
- q.push( data );
-
- }
- return q;
- },
-
- dequeue: function( elem, type ){
- var queue = jQuery.queue( elem, type ),
- fn = queue.shift();
-
- if( !type || type === "fx" )
- fn = queue[0];
-
- if( fn !== undefined )
- fn.call(elem);
- }
-});
-
-jQuery.fn.extend({
- data: function( key, value ){
- var parts = key.split(".");
- parts[1] = parts[1] ? "." + parts[1] : "";
-
- if ( value === undefined ) {
- var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
-
- if ( data === undefined && this.length )
- data = jQuery.data( this[0], key );
-
- return data === undefined && parts[1] ?
- this.data( parts[0] ) :
- data;
- } else
- return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
- jQuery.data( this, key, value );
- });
- },
-
- removeData: function( key ){
- return this.each(function(){
- jQuery.removeData( this, key );
- });
- },
- queue: function(type, data){
- if ( typeof type !== "string" ) {
- data = type;
- type = "fx";
- }
-
- if ( data === undefined )
- return jQuery.queue( this[0], type );
-
- return this.each(function(){
- var queue = jQuery.queue( this, type, data );
-
- if( type == "fx" && queue.length == 1 )
- queue[0].call(this);
- });
- },
- dequeue: function(type){
- return this.each(function(){
- jQuery.dequeue( this, type );
- });
- }
-});/*!
- * Sizzle CSS Selector Engine - v0.9.3
- * Copyright 2009, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- * More information: http://sizzlejs.com/
- */
-(function(){
-
-var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
- done = 0,
- toString = Object.prototype.toString;
-
-var Sizzle = function(selector, context, results, seed) {
- results = results || [];
- context = context || document;
-
- if ( context.nodeType !== 1 && context.nodeType !== 9 )
- return [];
-
- if ( !selector || typeof selector !== "string" ) {
- return results;
- }
-
- var parts = [], m, set, checkSet, check, mode, extra, prune = true;
-
- // Reset the position of the chunker regexp (start from head)
- chunker.lastIndex = 0;
-
- while ( (m = chunker.exec(selector)) !== null ) {
- parts.push( m[1] );
-
- if ( m[2] ) {
- extra = RegExp.rightContext;
- break;
- }
- }
-
- if ( parts.length > 1 && origPOS.exec( selector ) ) {
- if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
- set = posProcess( parts[0] + parts[1], context );
- } else {
- set = Expr.relative[ parts[0] ] ?
- [ context ] :
- Sizzle( parts.shift(), context );
-
- while ( parts.length ) {
- selector = parts.shift();
-
- if ( Expr.relative[ selector ] )
- selector += parts.shift();
-
- set = posProcess( selector, set );
- }
- }
- } else {
- var ret = seed ?
- { expr: parts.pop(), set: makeArray(seed) } :
- Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
- set = Sizzle.filter( ret.expr, ret.set );
-
- if ( parts.length > 0 ) {
- checkSet = makeArray(set);
- } else {
- prune = false;
- }
-
- while ( parts.length ) {
- var cur = parts.pop(), pop = cur;
-
- if ( !Expr.relative[ cur ] ) {
- cur = "";
- } else {
- pop = parts.pop();
- }
-
- if ( pop == null ) {
- pop = context;
- }
-
- Expr.relative[ cur ]( checkSet, pop, isXML(context) );
- }
- }
-
- if ( !checkSet ) {
- checkSet = set;
- }
-
- if ( !checkSet ) {
- throw "Syntax error, unrecognized expression: " + (cur || selector);
- }
-
- if ( toString.call(checkSet) === "[object Array]" ) {
- if ( !prune ) {
- results.push.apply( results, checkSet );
- } else if ( context.nodeType === 1 ) {
- for ( var i = 0; checkSet[i] != null; i++ ) {
- if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
- results.push( set[i] );
- }
- }
- } else {
- for ( var i = 0; checkSet[i] != null; i++ ) {
- if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
- results.push( set[i] );
- }
- }
- }
- } else {
- makeArray( checkSet, results );
- }
-
- if ( extra ) {
- Sizzle( extra, context, results, seed );
-
- if ( sortOrder ) {
- hasDuplicate = false;
- results.sort(sortOrder);
-
- if ( hasDuplicate ) {
- for ( var i = 1; i < results.length; i++ ) {
- if ( results[i] === results[i-1] ) {
- results.splice(i--, 1);
- }
- }
- }
- }
- }
-
- return results;
-};
-
-Sizzle.matches = function(expr, set){
- return Sizzle(expr, null, null, set);
-};
-
-Sizzle.find = function(expr, context, isXML){
- var set, match;
-
- if ( !expr ) {
- return [];
- }
-
- for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
- var type = Expr.order[i], match;
-
- if ( (match = Expr.match[ type ].exec( expr )) ) {
- var left = RegExp.leftContext;
-
- if ( left.substr( left.length - 1 ) !== "\\" ) {
- match[1] = (match[1] || "").replace(/\\/g, "");
- set = Expr.find[ type ]( match, context, isXML );
- if ( set != null ) {
- expr = expr.replace( Expr.match[ type ], "" );
- break;
- }
- }
- }
- }
-
- if ( !set ) {
- set = context.getElementsByTagName("*");
- }
-
- return {set: set, expr: expr};
-};
-
-Sizzle.filter = function(expr, set, inplace, not){
- var old = expr, result = [], curLoop = set, match, anyFound,
- isXMLFilter = set && set[0] && isXML(set[0]);
-
- while ( expr && set.length ) {
- for ( var type in Expr.filter ) {
- if ( (match = Expr.match[ type ].exec( expr )) != null ) {
- var filter = Expr.filter[ type ], found, item;
- anyFound = false;
-
- if ( curLoop == result ) {
- result = [];
- }
-
- if ( Expr.preFilter[ type ] ) {
- match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
-
- if ( !match ) {
- anyFound = found = true;
- } else if ( match === true ) {
- continue;
- }
- }
-
- if ( match ) {
- for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
- if ( item ) {
- found = filter( item, match, i, curLoop );
- var pass = not ^ !!found;
-
- if ( inplace && found != null ) {
- if ( pass ) {
- anyFound = true;
- } else {
- curLoop[i] = false;
- }
- } else if ( pass ) {
- result.push( item );
- anyFound = true;
- }
- }
- }
- }
-
- if ( found !== undefined ) {
- if ( !inplace ) {
- curLoop = result;
- }
-
- expr = expr.replace( Expr.match[ type ], "" );
-
- if ( !anyFound ) {
- return [];
- }
-
- break;
- }
- }
- }
-
- // Improper expression
- if ( expr == old ) {
- if ( anyFound == null ) {
- throw "Syntax error, unrecognized expression: " + expr;
- } else {
- break;
- }
- }
-
- old = expr;
- }
-
- return curLoop;
-};
-
-var Expr = Sizzle.selectors = {
- order: [ "ID", "NAME", "TAG" ],
- match: {
- ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
- CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
- NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
- ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
- TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
- CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
- POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
- PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
- },
- attrMap: {
- "class": "className",
- "for": "htmlFor"
- },
- attrHandle: {
- href: function(elem){
- return elem.getAttribute("href");
- }
- },
- relative: {
- "+": function(checkSet, part, isXML){
- var isPartStr = typeof part === "string",
- isTag = isPartStr && !/\W/.test(part),
- isPartStrNotTag = isPartStr && !isTag;
-
- if ( isTag && !isXML ) {
- part = part.toUpperCase();
- }
-
- for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
- if ( (elem = checkSet[i]) ) {
- while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
-
- checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
- elem || false :
- elem === part;
- }
- }
-
- if ( isPartStrNotTag ) {
- Sizzle.filter( part, checkSet, true );
- }
- },
- ">": function(checkSet, part, isXML){
- var isPartStr = typeof part === "string";
-
- if ( isPartStr && !/\W/.test(part) ) {
- part = isXML ? part : part.toUpperCase();
-
- for ( var i = 0, l = checkSet.length; i < l; i++ ) {
- var elem = checkSet[i];
- if ( elem ) {
- var parent = elem.parentNode;
- checkSet[i] = parent.nodeName === part ? parent : false;
- }
- }
- } else {
- for ( var i = 0, l = checkSet.length; i < l; i++ ) {
- var elem = checkSet[i];
- if ( elem ) {
- checkSet[i] = isPartStr ?
- elem.parentNode :
- elem.parentNode === part;
- }
- }
-
- if ( isPartStr ) {
- Sizzle.filter( part, checkSet, true );
- }
- }
- },
- "": function(checkSet, part, isXML){
- var doneName = done++, checkFn = dirCheck;
-
- if ( !part.match(/\W/) ) {
- var nodeCheck = part = isXML ? part : part.toUpperCase();
- checkFn = dirNodeCheck;
- }
-
- checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
- },
- "~": function(checkSet, part, isXML){
- var doneName = done++, checkFn = dirCheck;
-
- if ( typeof part === "string" && !part.match(/\W/) ) {
- var nodeCheck = part = isXML ? part : part.toUpperCase();
- checkFn = dirNodeCheck;
- }
-
- checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
- }
- },
- find: {
- ID: function(match, context, isXML){
- if ( typeof context.getElementById !== "undefined" && !isXML ) {
- var m = context.getElementById(match[1]);
- return m ? [m] : [];
- }
- },
- NAME: function(match, context, isXML){
- if ( typeof context.getElementsByName !== "undefined" ) {
- var ret = [], results = context.getElementsByName(match[1]);
-
- for ( var i = 0, l = results.length; i < l; i++ ) {
- if ( results[i].getAttribute("name") === match[1] ) {
- ret.push( results[i] );
- }
- }
-
- return ret.length === 0 ? null : ret;
- }
- },
- TAG: function(match, context){
- return context.getElementsByTagName(match[1]);
- }
- },
- preFilter: {
- CLASS: function(match, curLoop, inplace, result, not, isXML){
- match = " " + match[1].replace(/\\/g, "") + " ";
-
- if ( isXML ) {
- return match;
- }
-
- for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
- if ( elem ) {
- if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
- if ( !inplace )
- result.push( elem );
- } else if ( inplace ) {
- curLoop[i] = false;
- }
- }
- }
-
- return false;
- },
- ID: function(match){
- return match[1].replace(/\\/g, "");
- },
- TAG: function(match, curLoop){
- for ( var i = 0; curLoop[i] === false; i++ ){}
- return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
- },
- CHILD: function(match){
- if ( match[1] == "nth" ) {
- // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
- var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
- match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
- !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
-
- // calculate the numbers (first)n+(last) including if they are negative
- match[2] = (test[1] + (test[2] || 1)) - 0;
- match[3] = test[3] - 0;
- }
-
- // TODO: Move to normal caching system
- match[0] = done++;
-
- return match;
- },
- ATTR: function(match, curLoop, inplace, result, not, isXML){
- var name = match[1].replace(/\\/g, "");
-
- if ( !isXML && Expr.attrMap[name] ) {
- match[1] = Expr.attrMap[name];
- }
-
- if ( match[2] === "~=" ) {
- match[4] = " " + match[4] + " ";
- }
-
- return match;
- },
- PSEUDO: function(match, curLoop, inplace, result, not){
- if ( match[1] === "not" ) {
- // If we're dealing with a complex expression, or a simple one
- if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
- match[3] = Sizzle(match[3], null, null, curLoop);
- } else {
- var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
- if ( !inplace ) {
- result.push.apply( result, ret );
- }
- return false;
- }
- } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
- return true;
- }
-
- return match;
- },
- POS: function(match){
- match.unshift( true );
- return match;
- }
- },
- filters: {
- enabled: function(elem){
- return elem.disabled === false && elem.type !== "hidden";
- },
- disabled: function(elem){
- return elem.disabled === true;
- },
- checked: function(elem){
- return elem.checked === true;
- },
- selected: function(elem){
- // Accessing this property makes selected-by-default
- // options in Safari work properly
- elem.parentNode.selectedIndex;
- return elem.selected === true;
- },
- parent: function(elem){
- return !!elem.firstChild;
- },
- empty: function(elem){
- return !elem.firstChild;
- },
- has: function(elem, i, match){
- return !!Sizzle( match[3], elem ).length;
- },
- header: function(elem){
- return /h\d/i.test( elem.nodeName );
- },
- text: function(elem){
- return "text" === elem.type;
- },
- radio: function(elem){
- return "radio" === elem.type;
- },
- checkbox: function(elem){
- return "checkbox" === elem.type;
- },
- file: function(elem){
- return "file" === elem.type;
- },
- password: function(elem){
- return "password" === elem.type;
- },
- submit: function(elem){
- return "submit" === elem.type;
- },
- image: function(elem){
- return "image" === elem.type;
- },
- reset: function(elem){
- return "reset" === elem.type;
- },
- button: function(elem){
- return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
- },
- input: function(elem){
- return /input|select|textarea|button/i.test(elem.nodeName);
- }
- },
- setFilters: {
- first: function(elem, i){
- return i === 0;
- },
- last: function(elem, i, match, array){
- return i === array.length - 1;
- },
- even: function(elem, i){
- return i % 2 === 0;
- },
- odd: function(elem, i){
- return i % 2 === 1;
- },
- lt: function(elem, i, match){
- return i < match[3] - 0;
- },
- gt: function(elem, i, match){
- return i > match[3] - 0;
- },
- nth: function(elem, i, match){
- return match[3] - 0 == i;
- },
- eq: function(elem, i, match){
- return match[3] - 0 == i;
- }
- },
- filter: {
- PSEUDO: function(elem, match, i, array){
- var name = match[1], filter = Expr.filters[ name ];
-
- if ( filter ) {
- return filter( elem, i, match, array );
- } else if ( name === "contains" ) {
- return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
- } else if ( name === "not" ) {
- var not = match[3];
-
- for ( var i = 0, l = not.length; i < l; i++ ) {
- if ( not[i] === elem ) {
- return false;
- }
- }
-
- return true;
- }
- },
- CHILD: function(elem, match){
- var type = match[1], node = elem;
- switch (type) {
- case 'only':
- case 'first':
- while (node = node.previousSibling) {
- if ( node.nodeType === 1 ) return false;
- }
- if ( type == 'first') return true;
- node = elem;
- case 'last':
- while (node = node.nextSibling) {
- if ( node.nodeType === 1 ) return false;
- }
- return true;
- case 'nth':
- var first = match[2], last = match[3];
-
- if ( first == 1 && last == 0 ) {
- return true;
- }
-
- var doneName = match[0],
- parent = elem.parentNode;
-
- if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
- var count = 0;
- for ( node = parent.firstChild; node; node = node.nextSibling ) {
- if ( node.nodeType === 1 ) {
- node.nodeIndex = ++count;
- }
- }
- parent.sizcache = doneName;
- }
-
- var diff = elem.nodeIndex - last;
- if ( first == 0 ) {
- return diff == 0;
- } else {
- return ( diff % first == 0 && diff / first >= 0 );
- }
- }
- },
- ID: function(elem, match){
- return elem.nodeType === 1 && elem.getAttribute("id") === match;
- },
- TAG: function(elem, match){
- return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
- },
- CLASS: function(elem, match){
- return (" " + (elem.className || elem.getAttribute("class")) + " ")
- .indexOf( match ) > -1;
- },
- ATTR: function(elem, match){
- var name = match[1],
- result = Expr.attrHandle[ name ] ?
- Expr.attrHandle[ name ]( elem ) :
- elem[ name ] != null ?
- elem[ name ] :
- elem.getAttribute( name ),
- value = result + "",
- type = match[2],
- check = match[4];
-
- return result == null ?
- type === "!=" :
- type === "=" ?
- value === check :
- type === "*=" ?
- value.indexOf(check) >= 0 :
- type === "~=" ?
- (" " + value + " ").indexOf(check) >= 0 :
- !check ?
- value && result !== false :
- type === "!=" ?
- value != check :
- type === "^=" ?
- value.indexOf(check) === 0 :
- type === "$=" ?
- value.substr(value.length - check.length) === check :
- type === "|=" ?
- value === check || value.substr(0, check.length + 1) === check + "-" :
- false;
- },
- POS: function(elem, match, i, array){
- var name = match[2], filter = Expr.setFilters[ name ];
-
- if ( filter ) {
- return filter( elem, i, match, array );
- }
- }
- }
-};
-
-var origPOS = Expr.match.POS;
-
-for ( var type in Expr.match ) {
- Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
-}
-
-var makeArray = function(array, results) {
- array = Array.prototype.slice.call( array );
-
- if ( results ) {
- results.push.apply( results, array );
- return results;
- }
-
- return array;
-};
-
-// Perform a simple check to determine if the browser is capable of
-// converting a NodeList to an array using builtin methods.
-try {
- Array.prototype.slice.call( document.documentElement.childNodes );
-
-// Provide a fallback method if it does not work
-} catch(e){
- makeArray = function(array, results) {
- var ret = results || [];
-
- if ( toString.call(array) === "[object Array]" ) {
- Array.prototype.push.apply( ret, array );
- } else {
- if ( typeof array.length === "number" ) {
- for ( var i = 0, l = array.length; i < l; i++ ) {
- ret.push( array[i] );
- }
- } else {
- for ( var i = 0; array[i]; i++ ) {
- ret.push( array[i] );
- }
- }
- }
-
- return ret;
- };
-}
-
-var sortOrder;
-
-if ( document.documentElement.compareDocumentPosition ) {
- sortOrder = function( a, b ) {
- var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
- if ( ret === 0 ) {
- hasDuplicate = true;
- }
- return ret;
- };
-} else if ( "sourceIndex" in document.documentElement ) {
- sortOrder = function( a, b ) {
- var ret = a.sourceIndex - b.sourceIndex;
- if ( ret === 0 ) {
- hasDuplicate = true;
- }
- return ret;
- };
-} else if ( document.createRange ) {
- sortOrder = function( a, b ) {
- var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
- aRange.selectNode(a);
- aRange.collapse(true);
- bRange.selectNode(b);
- bRange.collapse(true);
- var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
- if ( ret === 0 ) {
- hasDuplicate = true;
- }
- return ret;
- };
-}
-
-// Check to see if the browser returns elements by name when
-// querying by getElementById (and provide a workaround)
-(function(){
- // We're going to inject a fake input element with a specified name
- var form = document.createElement("form"),
- id = "script" + (new Date).getTime();
- form.innerHTML = "<input name='" + id + "'/>";
-
- // Inject it into the root element, check its status, and remove it quickly
- var root = document.documentElement;
- root.insertBefore( form, root.firstChild );
-
- // The workaround has to do additional checks after a getElementById
- // Which slows things down for other browsers (hence the branching)
- if ( !!document.getElementById( id ) ) {
- Expr.find.ID = function(match, context, isXML){
- if ( typeof context.getElementById !== "undefined" && !isXML ) {
- var m = context.getElementById(match[1]);
- return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
- }
- };
-
- Expr.filter.ID = function(elem, match){
- var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
- return elem.nodeType === 1 && node && node.nodeValue === match;
- };
- }
-
- root.removeChild( form );
-})();
-
-(function(){
- // Check to see if the browser returns only elements
- // when doing getElementsByTagName("*")
-
- // Create a fake element
- var div = document.createElement("div");
- div.appendChild( document.createComment("") );
-
- // Make sure no comments are found
- if ( div.getElementsByTagName("*").length > 0 ) {
- Expr.find.TAG = function(match, context){
- var results = context.getElementsByTagName(match[1]);
-
- // Filter out possible comments
- if ( match[1] === "*" ) {
- var tmp = [];
-
- for ( var i = 0; results[i]; i++ ) {
- if ( results[i].nodeType === 1 ) {
- tmp.push( results[i] );
- }
- }
-
- results = tmp;
- }
-
- return results;
- };
- }
-
- // Check to see if an attribute returns normalized href attributes
- div.innerHTML = "<a href='#'></a>";
- if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
- div.firstChild.getAttribute("href") !== "#" ) {
- Expr.attrHandle.href = function(elem){
- return elem.getAttribute("href", 2);
- };
- }
-})();
-
-if ( document.querySelectorAll ) (function(){
- var oldSizzle = Sizzle, div = document.createElement("div");
- div.innerHTML = "<p class='TEST'></p>";
-
- // Safari can't handle uppercase or unicode characters when
- // in quirks mode.
- if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
- return;
- }
-
- Sizzle = function(query, context, extra, seed){
- context = context || document;
-
- // Only use querySelectorAll on non-XML documents
- // (ID selectors don't work in non-HTML documents)
- if ( !seed && context.nodeType === 9 && !isXML(context) ) {
- try {
- return makeArray( context.querySelectorAll(query), extra );
- } catch(e){}
- }
-
- return oldSizzle(query, context, extra, seed);
- };
-
- Sizzle.find = oldSizzle.find;
- Sizzle.filter = oldSizzle.filter;
- Sizzle.selectors = oldSizzle.selectors;
- Sizzle.matches = oldSizzle.matches;
-})();
-
-if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
- var div = document.createElement("div");
- div.innerHTML = "<div class='test e'></div><div class='test'></div>";
-
- // Opera can't find a second classname (in 9.6)
- if ( div.getElementsByClassName("e").length === 0 )
- return;
-
- // Safari caches class attributes, doesn't catch changes (in 3.2)
- div.lastChild.className = "e";
-
- if ( div.getElementsByClassName("e").length === 1 )
- return;
-
- Expr.order.splice(1, 0, "CLASS");
- Expr.find.CLASS = function(match, context, isXML) {
- if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
- return context.getElementsByClassName(match[1]);
- }
- };
-})();
-
-function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
- var sibDir = dir == "previousSibling" && !isXML;
- for ( var i = 0, l = checkSet.length; i < l; i++ ) {
- var elem = checkSet[i];
- if ( elem ) {
- if ( sibDir && elem.nodeType === 1 ){
- elem.sizcache = doneName;
- elem.sizset = i;
- }
- elem = elem[dir];
- var match = false;
-
- while ( elem ) {
- if ( elem.sizcache === doneName ) {
- match = checkSet[elem.sizset];
- break;
- }
-
- if ( elem.nodeType === 1 && !isXML ){
- elem.sizcache = doneName;
- elem.sizset = i;
- }
-
- if ( elem.nodeName === cur ) {
- match = elem;
- break;
- }
-
- elem = elem[dir];
- }
-
- checkSet[i] = match;
- }
- }
-}
-
-function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
- var sibDir = dir == "previousSibling" && !isXML;
- for ( var i = 0, l = checkSet.length; i < l; i++ ) {
- var elem = checkSet[i];
- if ( elem ) {
- if ( sibDir && elem.nodeType === 1 ) {
- elem.sizcache = doneName;
- elem.sizset = i;
- }
- elem = elem[dir];
- var match = false;
-
- while ( elem ) {
- if ( elem.sizcache === doneName ) {
- match = checkSet[elem.sizset];
- break;
- }
-
- if ( elem.nodeType === 1 ) {
- if ( !isXML ) {
- elem.sizcache = doneName;
- elem.sizset = i;
- }
- if ( typeof cur !== "string" ) {
- if ( elem === cur ) {
- match = true;
- break;
- }
-
- } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
- match = elem;
- break;
- }
- }
-
- elem = elem[dir];
- }
-
- checkSet[i] = match;
- }
- }
-}
-
-var contains = document.compareDocumentPosition ? function(a, b){
- return a.compareDocumentPosition(b) & 16;
-} : function(a, b){
- return a !== b && (a.contains ? a.contains(b) : true);
-};
-
-var isXML = function(elem){
- return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
- !!elem.ownerDocument && isXML( elem.ownerDocument );
-};
-
-var posProcess = function(selector, context){
- var tmpSet = [], later = "", match,
- root = context.nodeType ? [context] : context;
-
- // Position selectors must be done after the filter
- // And so must :not(positional) so we move all PSEUDOs to the end
- while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
- later += match[0];
- selector = selector.replace( Expr.match.PSEUDO, "" );
- }
-
- selector = Expr.relative[selector] ? selector + "*" : selector;
-
- for ( var i = 0, l = root.length; i < l; i++ ) {
- Sizzle( selector, root[i], tmpSet );
- }
-
- return Sizzle.filter( later, tmpSet );
-};
-
-// EXPOSE
-jQuery.find = Sizzle;
-jQuery.filter = Sizzle.filter;
-jQuery.expr = Sizzle.selectors;
-jQuery.expr[":"] = jQuery.expr.filters;
-
-Sizzle.selectors.filters.hidden = function(elem){
- return elem.offsetWidth === 0 || elem.offsetHeight === 0;
-};
-
-Sizzle.selectors.filters.visible = function(elem){
- return elem.offsetWidth > 0 || elem.offsetHeight > 0;
-};
-
-Sizzle.selectors.filters.animated = function(elem){
- return jQuery.grep(jQuery.timers, function(fn){
- return elem === fn.elem;
- }).length;
-};
-
-jQuery.multiFilter = function( expr, elems, not ) {
- if ( not ) {
- expr = ":not(" + expr + ")";
- }
-
- return Sizzle.matches(expr, elems);
-};
-
-jQuery.dir = function( elem, dir ){
- var matched = [], cur = elem[dir];
- while ( cur && cur != document ) {
- if ( cur.nodeType == 1 )
- matched.push( cur );
- cur = cur[dir];
- }
- return matched;
-};
-
-jQuery.nth = function(cur, result, dir, elem){
- result = result || 1;
- var num = 0;
-
- for ( ; cur; cur = cur[dir] )
- if ( cur.nodeType == 1 && ++num == result )
- break;
-
- return cur;
-};
-
-jQuery.sibling = function(n, elem){
- var r = [];
-
- for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType == 1 && n != elem )
- r.push( n );
- }
-
- return r;
-};
-
-return;
-
-window.Sizzle = Sizzle;
-
-})();
-/*
- * A number of helper functions used for managing events.
- * Many of the ideas behind this code originated from
- * Dean Edwards' addEvent library.
- */
-jQuery.event = {
-
- // Bind an event to an element
- // Original by Dean Edwards
- add: function(elem, types, handler, data) {
- if ( elem.nodeType == 3 || elem.nodeType == 8 )
- return;
-
- // For whatever reason, IE has trouble passing the window object
- // around, causing it to be cloned in the process
- if ( elem.setInterval && elem != window )
- elem = window;
-
- // Make sure that the function being executed has a unique ID
- if ( !handler.guid )
- handler.guid = this.guid++;
-
- // if data is passed, bind to handler
- if ( data !== undefined ) {
- // Create temporary function pointer to original handler
- var fn = handler;
-
- // Create unique handler function, wrapped around original handler
- handler = this.proxy( fn );
-
- // Store data in unique handler
- handler.data = data;
- }
-
- // Init the element's event structure
- var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
- handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
- // Handle the second event of a trigger and when
- // an event is called after a page has unloaded
- return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
- jQuery.event.handle.apply(arguments.callee.elem, arguments) :
- undefined;
- });
- // Add elem as a property of the handle function
- // This is to prevent a memory leak with non-native
- // event in IE.
- handle.elem = elem;
-
- // Handle multiple events separated by a space
- // jQuery(...).bind("mouseover mouseout", fn);
- jQuery.each(types.split(/\s+/), function(index, type) {
- // Namespaced event handlers
- var namespaces = type.split(".");
- type = namespaces.shift();
- handler.type = namespaces.slice().sort().join(".");
-
- // Get the current list of functions bound to this event
- var handlers = events[type];
-
- if ( jQuery.event.specialAll[type] )
- jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
-
- // Init the event handler queue
- if (!handlers) {
- handlers = events[type] = {};
-
- // Check for a special event handler
- // Only use addEventListener/attachEvent if the special
- // events handler returns false
- if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
- // Bind the global event handler to the element
- if (elem.addEventListener)
- elem.addEventListener(type, handle, false);
- else if (elem.attachEvent)
- elem.attachEvent("on" + type, handle);
- }
- }
-
- // Add the function to the element's handler list
- handlers[handler.guid] = handler;
-
- // Keep track of which events have been used, for global triggering
- jQuery.event.global[type] = true;
- });
-
- // Nullify elem to prevent memory leaks in IE
- elem = null;
- },
-
- guid: 1,
- global: {},
-
- // Detach an event or set of events from an element
- remove: function(elem, types, handler) {
- // don't do events on text and comment nodes
- if ( elem.nodeType == 3 || elem.nodeType == 8 )
- return;
-
- var events = jQuery.data(elem, "events"), ret, index;
-
- if ( events ) {
- // Unbind all events for the element
- if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
- for ( var type in events )
- this.remove( elem, type + (types || "") );
- else {
- // types is actually an event object here
- if ( types.type ) {
- handler = types.handler;
- types = types.type;
- }
-
- // Handle multiple events seperated by a space
- // jQuery(...).unbind("mouseover mouseout", fn);
- jQuery.each(types.split(/\s+/), function(index, type){
- // Namespaced event handlers
- var namespaces = type.split(".");
- type = namespaces.shift();
- var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
-
- if ( events[type] ) {
- // remove the given handler for the given type
- if ( handler )
- delete events[type][handler.guid];
-
- // remove all handlers for the given type
- else
- for ( var handle in events[type] )
- // Handle the removal of namespaced events
- if ( namespace.test(events[type][handle].type) )
- delete events[type][handle];
-
- if ( jQuery.event.specialAll[type] )
- jQuery.event.specialAll[type].teardown.call(elem, namespaces);
-
- // remove generic event handler if no more handlers exist
- for ( ret in events[type] ) break;
- if ( !ret ) {
- if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
- if (elem.removeEventListener)
- elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
- else if (elem.detachEvent)
- elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
- }
- ret = null;
- delete events[type];
- }
- }
- });
- }
-
- // Remove the expando if it's no longer used
- for ( ret in events ) break;
- if ( !ret ) {
- var handle = jQuery.data( elem, "handle" );
- if ( handle ) handle.elem = null;
- jQuery.removeData( elem, "events" );
- jQuery.removeData( elem, "handle" );
- }
- }
- },
-
- // bubbling is internal
- trigger: function( event, data, elem, bubbling ) {
- // Event object or event type
- var type = event.type || event;
-
- if( !bubbling ){
- event = typeof event === "object" ?
- // jQuery.Event object
- event[expando] ? event :
- // Object literal
- jQuery.extend( jQuery.Event(type), event ) :
- // Just the event type (string)
- jQuery.Event(type);
-
- if ( type.indexOf("!") >= 0 ) {
- event.type = type = type.slice(0, -1);
- event.exclusive = true;
- }
-
- // Handle a global trigger
- if ( !elem ) {
- // Don't bubble custom events when global (to avoid too much overhead)
- event.stopPropagation();
- // Only trigger if we've ever bound an event for it
- if ( this.global[type] )
- jQuery.each( jQuery.cache, function(){
- if ( this.events && this.events[type] )
- jQuery.event.trigger( event, data, this.handle.elem );
- });
- }
-
- // Handle triggering a single element
-
- // don't do events on text and comment nodes
- if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
- return undefined;
-
- // Clean up in case it is reused
- event.result = undefined;
- event.target = elem;
-
- // Clone the incoming data, if any
- data = jQuery.makeArray(data);
- data.unshift( event );
- }
-
- event.currentTarget = elem;
-
- // Trigger the event, it is assumed that "handle" is a function
- var handle = jQuery.data(elem, "handle");
- if ( handle )
- handle.apply( elem, data );
-
- // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
- if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
- event.result = false;
-
- // Trigger the native events (except for clicks on links)
- if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
- this.triggered = true;
- try {
- elem[ type ]();
- // prevent IE from throwing an error for some hidden elements
- } catch (e) {}
- }
-
- this.triggered = false;
-
- if ( !event.isPropagationStopped() ) {
- var parent = elem.parentNode || elem.ownerDocument;
- if ( parent )
- jQuery.event.trigger(event, data, parent, true);
- }
- },
-
- handle: function(event) {
- // returned undefined or false
- var all, handlers;
-
- event = arguments[0] = jQuery.event.fix( event || window.event );
- event.currentTarget = this;
-
- // Namespaced event handlers
- var namespaces = event.type.split(".");
- event.type = namespaces.shift();
-
- // Cache this now, all = true means, any handler
- all = !namespaces.length && !event.exclusive;
-
- var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
-
- handlers = ( jQuery.data(this, "events") || {} )[event.type];
-
- for ( var j in handlers ) {
- var handler = handlers[j];
-
- // Filter the functions by class
- if ( all || namespace.test(handler.type) ) {
- // Pass in a reference to the handler function itself
- // So that we can later remove it
- event.handler = handler;
- event.data = handler.data;
-
- var ret = handler.apply(this, arguments);
-
- if( ret !== undefined ){
- event.result = ret;
- if ( ret === false ) {
- event.preventDefault();
- event.stopPropagation();
- }
- }
-
- if( event.isImmediatePropagationStopped() )
- break;
-
- }
- }
- },
-
- props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
-
- fix: function(event) {
- if ( event[expando] )
- return event;
-
- // store a copy of the original event object
- // and "clone" to set read-only properties
- var originalEvent = event;
- event = jQuery.Event( originalEvent );
-
- for ( var i = this.props.length, prop; i; ){
- prop = this.props[ --i ];
- event[ prop ] = originalEvent[ prop ];
- }
-
- // Fix target property, if necessary
- if ( !event.target )
- event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
-
- // check if target is a textnode (safari)
- if ( event.target.nodeType == 3 )
- event.target = event.target.parentNode;
-
- // Add relatedTarget, if necessary
- if ( !event.relatedTarget && event.fromElement )
- event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
-
- // Calculate pageX/Y if missing and clientX/Y available
- if ( event.pageX == null && event.clientX != null ) {
- var doc = document.documentElement, body = document.body;
- event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
- event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
- }
-
- // Add which for key events
- if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
- event.which = event.charCode || event.keyCode;
-
- // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
- if ( !event.metaKey && event.ctrlKey )
- event.metaKey = event.ctrlKey;
-
- // Add which for click: 1 == left; 2 == middle; 3 == right
- // Note: button is not normalized, so don't use it
- if ( !event.which && event.button )
- event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
-
- return event;
- },
-
- proxy: function( fn, proxy ){
- proxy = proxy || function(){ return fn.apply(this, arguments); };
- // Set the guid of unique handler to the same of original handler, so it can be removed
- proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
- // So proxy can be declared as an argument
- return proxy;
- },
-
- special: {
- ready: {
- // Make sure the ready event is setup
- setup: bindReady,
- teardown: function() {}
- }
- },
-
- specialAll: {
- live: {
- setup: function( selector, namespaces ){
- jQuery.event.add( this, namespaces[0], liveHandler );
- },
- teardown: function( namespaces ){
- if ( namespaces.length ) {
- var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
-
- jQuery.each( (jQuery.data(this, "events").live || {}), function(){
- if ( name.test(this.type) )
- remove++;
- });
-
- if ( remove < 1 )
- jQuery.event.remove( this, namespaces[0], liveHandler );
- }
- }
- }
- }
-};
-
-jQuery.Event = function( src ){
- // Allow instantiation without the 'new' keyword
- if( !this.preventDefault )
- return new jQuery.Event(src);
-
- // Event object
- if( src && src.type ){
- this.originalEvent = src;
- this.type = src.type;
- // Event type
- }else
- this.type = src;
-
- // timeStamp is buggy for some events on Firefox(#3843)
- // So we won't rely on the native value
- this.timeStamp = now();
-
- // Mark it as fixed
- this[expando] = true;
-};
-
-function returnFalse(){
- return false;
-}
-function returnTrue(){
- return true;
-}
-
-// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
-// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
-jQuery.Event.prototype = {
- preventDefault: function() {
- this.isDefaultPrevented = returnTrue;
-
- var e = this.originalEvent;
- if( !e )
- return;
- // if preventDefault exists run it on the original event
- if (e.preventDefault)
- e.preventDefault();
- // otherwise set the returnValue property of the original event to false (IE)
- e.returnValue = false;
- },
- stopPropagation: function() {
- this.isPropagationStopped = returnTrue;
-
- var e = this.originalEvent;
- if( !e )
- return;
- // if stopPropagation exists run it on the original event
- if (e.stopPropagation)
- e.stopPropagation();
- // otherwise set the cancelBubble property of the original event to true (IE)
- e.cancelBubble = true;
- },
- stopImmediatePropagation:function(){
- this.isImmediatePropagationStopped = returnTrue;
- this.stopPropagation();
- },
- isDefaultPrevented: returnFalse,
- isPropagationStopped: returnFalse,
- isImmediatePropagationStopped: returnFalse
-};
-// Checks if an event happened on an element within another element
-// Used in jQuery.event.special.mouseenter and mouseleave handlers
-var withinElement = function(event) {
- // Check if mouse(over|out) are still within the same parent element
- var parent = event.relatedTarget;
- // Traverse up the tree
- while ( parent && parent != this )
- try { parent = parent.parentNode; }
- catch(e) { parent = this; }
-
- if( parent != this ){
- // set the correct event type
- event.type = event.data;
- // handle event if we actually just moused on to a non sub-element
- jQuery.event.handle.apply( this, arguments );
- }
-};
-
-jQuery.each({
- mouseover: 'mouseenter',
- mouseout: 'mouseleave'
-}, function( orig, fix ){
- jQuery.event.special[ fix ] = {
- setup: function(){
- jQuery.event.add( this, orig, withinElement, fix );
- },
- teardown: function(){
- jQuery.event.remove( this, orig, withinElement );
- }
- };
-});
-
-jQuery.fn.extend({
- bind: function( type, data, fn ) {
- return type == "unload" ? this.one(type, data, fn) : this.each(function(){
- jQuery.event.add( this, type, fn || data, fn && data );
- });
- },
-
- one: function( type, data, fn ) {
- var one = jQuery.event.proxy( fn || data, function(event) {
- jQuery(this).unbind(event, one);
- return (fn || data).apply( this, arguments );
- });
- return this.each(function(){
- jQuery.event.add( this, type, one, fn && data);
- });
- },
-
- unbind: function( type, fn ) {
- return this.each(function(){
- jQuery.event.remove( this, type, fn );
- });
- },
-
- trigger: function( type, data ) {
- return this.each(function(){
- jQuery.event.trigger( type, data, this );
- });
- },
-
- triggerHandler: function( type, data ) {
- if( this[0] ){
- var event = jQuery.Event(type);
- event.preventDefault();
- event.stopPropagation();
- jQuery.event.trigger( event, data, this[0] );
- return event.result;
- }
- },
-
- toggle: function( fn ) {
- // Save reference to arguments for access in closure
- var args = arguments, i = 1;
-
- // link all the functions, so any of them can unbind this click handler
- while( i < args.length )
- jQuery.event.proxy( fn, args[i++] );
-
- return this.click( jQuery.event.proxy( fn, function(event) {
- // Figure out which function to execute
- this.lastToggle = ( this.lastToggle || 0 ) % i;
-
- // Make sure that clicks stop
- event.preventDefault();
-
- // and execute the function
- return args[ this.lastToggle++ ].apply( this, arguments ) || false;
- }));
- },
-
- hover: function(fnOver, fnOut) {
- return this.mouseenter(fnOver).mouseleave(fnOut);
- },
-
- ready: function(fn) {
- // Attach the listeners
- bindReady();
-
- // If the DOM is already ready
- if ( jQuery.isReady )
- // Execute the function immediately
- fn.call( document, jQuery );
-
- // Otherwise, remember the function for later
- else
- // Add the function to the wait list
- jQuery.readyList.push( fn );
-
- return this;
- },
-
- live: function( type, fn ){
- var proxy = jQuery.event.proxy( fn );
- proxy.guid += this.selector + type;
-
- jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
-
- return this;
- },
-
- die: function( type, fn ){
- jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
- return this;
- }
-});
-
-function liveHandler( event ){
- var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
- stop = true,
- elems = [];
-
- jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
- if ( check.test(fn.type) ) {
- var elem = jQuery(event.target).closest(fn.data)[0];
- if ( elem )
- elems.push({ elem: elem, fn: fn });
- }
- });
-
- elems.sort(function(a,b) {
- return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
- });
-
- jQuery.each(elems, function(){
- if ( this.fn.call(this.elem, event, this.fn.data) === false )
- return (stop = false);
- });
-
- return stop;
-}
-
-function liveConvert(type, selector){
- return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
-}
-
-jQuery.extend({
- isReady: false,
- readyList: [],
- // Handle when the DOM is ready
- ready: function() {
- // Make sure that the DOM is not already loaded
- if ( !jQuery.isReady ) {
- // Remember that the DOM is ready
- jQuery.isReady = true;
-
- // If there are functions bound, to execute
- if ( jQuery.readyList ) {
- // Execute all of them
- jQuery.each( jQuery.readyList, function(){
- this.call( document, jQuery );
- });
-
- // Reset the list of functions
- jQuery.readyList = null;
- }
-
- // Trigger any bound ready events
- jQuery(document).triggerHandler("ready");
- }
- }
-});
-
-var readyBound = false;
-
-function bindReady(){
- if ( readyBound ) return;
- readyBound = true;
-
- // Mozilla, Opera and webkit nightlies currently support this event
- if ( document.addEventListener ) {
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", function(){
- document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
- jQuery.ready();
- }, false );
-
- // If IE event model is used
- } else if ( document.attachEvent ) {
- // ensure firing before onload,
- // maybe late but safe also for iframes
- document.attachEvent("onreadystatechange", function(){
- if ( document.readyState === "complete" ) {
- document.detachEvent( "onreadystatechange", arguments.callee );
- jQuery.ready();
- }
- });
-
- // If IE and not an iframe
- // continually check to see if the document is ready
- if ( document.documentElement.doScroll && window == window.top ) (function(){
- if ( jQuery.isReady ) return;
-
- try {
- // If IE is used, use the trick by Diego Perini
- // http://javascript.nwbox.com/IEContentLoaded/
- document.documentElement.doScroll("left");
- } catch( error ) {
- setTimeout( arguments.callee, 0 );
- return;
- }
-
- // and execute any waiting functions
- jQuery.ready();
- })();
- }
-
- // A fallback to window.onload, that will always work
- jQuery.event.add( window, "load", jQuery.ready );
-}
-
-jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
- "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
- "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
-
- // Handle event binding
- jQuery.fn[name] = function(fn){
- return fn ? this.bind(name, fn) : this.trigger(name);
- };
-});
-
-// Prevent memory leaks in IE
-// And prevent errors on refresh with events like mouseover in other browsers
-// Window isn't included so as not to unbind existing unload events
-jQuery( window ).bind( 'unload', function(){
- for ( var id in jQuery.cache )
- // Skip the window
- if ( id != 1 && jQuery.cache[ id ].handle )
- jQuery.event.remove( jQuery.cache[ id ].handle.elem );
-});
-(function(){
-
- jQuery.support = {};
-
- var root = document.documentElement,
- script = document.createElement("script"),
- div = document.createElement("div"),
- id = "script" + (new Date).getTime();
-
- div.style.display = "none";
- div.innerHTML = ' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
-
- var all = div.getElementsByTagName("*"),
- a = div.getElementsByTagName("a")[0];
-
- // Can't get basic test support
- if ( !all || !all.length || !a ) {
- return;
- }
-
- jQuery.support = {
- // IE strips leading whitespace when .innerHTML is used
- leadingWhitespace: div.firstChild.nodeType == 3,
-
- // Make sure that tbody elements aren't automatically inserted
- // IE will insert them into empty tables
- tbody: !div.getElementsByTagName("tbody").length,
-
- // Make sure that you can get all elements in an <object> element
- // IE 7 always returns no results
- objectAll: !!div.getElementsByTagName("object")[0]
- .getElementsByTagName("*").length,
-
- // Make sure that link elements get serialized correctly by innerHTML
- // This requires a wrapper element in IE
- htmlSerialize: !!div.getElementsByTagName("link").length,
-
- // Get the style information from getAttribute
- // (IE uses .cssText insted)
- style: /red/.test( a.getAttribute("style") ),
-
- // Make sure that URLs aren't manipulated
- // (IE normalizes it by default)
- hrefNormalized: a.getAttribute("href") === "/a",
-
- // Make sure that element opacity exists
- // (IE uses filter instead)
- opacity: a.style.opacity === "0.5",
-
- // Verify style float existence
- // (IE uses styleFloat instead of cssFloat)
- cssFloat: !!a.style.cssFloat,
-
- // Will be defined later
- scriptEval: false,
- noCloneEvent: true,
- boxModel: null
- };
-
- script.type = "text/javascript";
- try {
- script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
- } catch(e){}
-
- root.insertBefore( script, root.firstChild );
-
- // Make sure that the execution of code works by injecting a script
- // tag with appendChild/createTextNode
- // (IE doesn't support this, fails, and uses .text instead)
- if ( window[ id ] ) {
- jQuery.support.scriptEval = true;
- delete window[ id ];
- }
-
- root.removeChild( script );
-
- if ( div.attachEvent && div.fireEvent ) {
- div.attachEvent("onclick", function(){
- // Cloning a node shouldn't copy over any
- // bound event handlers (IE does this)
- jQuery.support.noCloneEvent = false;
- div.detachEvent("onclick", arguments.callee);
- });
- div.cloneNode(true).fireEvent("onclick");
- }
-
- // Figure out if the W3C box model works as expected
- // document.body must exist before we can do this
- jQuery(function(){
- var div = document.createElement("div");
- div.style.width = div.style.paddingLeft = "1px";
-
- document.body.appendChild( div );
- jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
- document.body.removeChild( div ).style.display = 'none';
- });
-})();
-
-var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
-
-jQuery.props = {
- "for": "htmlFor",
- "class": "className",
- "float": styleFloat,
- cssFloat: styleFloat,
- styleFloat: styleFloat,
- readonly: "readOnly",
- maxlength: "maxLength",
- cellspacing: "cellSpacing",
- rowspan: "rowSpan",
- tabindex: "tabIndex"
-};
-jQuery.fn.extend({
- // Keep a copy of the old load
- _load: jQuery.fn.load,
-
- load: function( url, params, callback ) {
- if ( typeof url !== "string" )
- return this._load( url );
-
- var off = url.indexOf(" ");
- if ( off >= 0 ) {
- var selector = url.slice(off, url.length);
- url = url.slice(0, off);
- }
-
- // Default to a GET request
- var type = "GET";
-
- // If the second parameter was provided
- if ( params )
- // If it's a function
- if ( jQuery.isFunction( params ) ) {
- // We assume that it's the callback
- callback = params;
- params = null;
-
- // Otherwise, build a param string
- } else if( typeof params === "object" ) {
- params = jQuery.param( params );
- type = "POST";
- }
-
- var self = this;
-
- // Request the remote document
- jQuery.ajax({
- url: url,
- type: type,
- dataType: "html",
- data: params,
- complete: function(res, status){
- // If successful, inject the HTML into all the matched elements
- if ( status == "success" || status == "notmodified" )
- // See if a selector was specified
- self.html( selector ?
- // Create a dummy div to hold the results
- jQuery("<div/>")
- // inject the contents of the document in, removing the scripts
- // to avoid any 'Permission Denied' errors in IE
- .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
-
- // Locate the specified elements
- .find(selector) :
-
- // If not, just inject the full result
- res.responseText );
-
- if( callback )
- self.each( callback, [res.responseText, status, res] );
- }
- });
- return this;
- },
-
- serialize: function() {
- return jQuery.param(this.serializeArray());
- },
- serializeArray: function() {
- return this.map(function(){
- return this.elements ? jQuery.makeArray(this.elements) : this;
- })
- .filter(function(){
- return this.name && !this.disabled &&
- (this.checked || /select|textarea/i.test(this.nodeName) ||
- /text|hidden|password|search/i.test(this.type));
- })
- .map(function(i, elem){
- var val = jQuery(this).val();
- return val == null ? null :
- jQuery.isArray(val) ?
- jQuery.map( val, function(val, i){
- return {name: elem.name, value: val};
- }) :
- {name: elem.name, value: val};
- }).get();
- }
-});
-
-// Attach a bunch of functions for handling common AJAX events
-jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
- jQuery.fn[o] = function(f){
- return this.bind(o, f);
- };
-});
-
-var jsc = now();
-
-jQuery.extend({
-
- get: function( url, data, callback, type ) {
- // shift arguments if data argument was ommited
- if ( jQuery.isFunction( data ) ) {
- callback = data;
- data = null;
- }
-
- return jQuery.ajax({
- type: "GET",
- url: url,
- data: data,
- success: callback,
- dataType: type
- });
- },
-
- getScript: function( url, callback ) {
- return jQuery.get(url, null, callback, "script");
- },
-
- getJSON: function( url, data, callback ) {
- return jQuery.get(url, data, callback, "json");
- },
-
- post: function( url, data, callback, type ) {
- if ( jQuery.isFunction( data ) ) {
- callback = data;
- data = {};
- }
-
- return jQuery.ajax({
- type: "POST",
- url: url,
- data: data,
- success: callback,
- dataType: type
- });
- },
-
- ajaxSetup: function( settings ) {
- jQuery.extend( jQuery.ajaxSettings, settings );
- },
-
- ajaxSettings: {
- url: location.href,
- global: true,
- type: "GET",
- contentType: "application/x-www-form-urlencoded",
- processData: true,
- async: true,
- /*
- timeout: 0,
- data: null,
- username: null,
- password: null,
- */
- // Create the request object; Microsoft failed to properly
- // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
- // This function can be overriden by calling jQuery.ajaxSetup
- xhr:function(){
- return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
- },
- accepts: {
- xml: "application/xml, text/xml",
- html: "text/html",
- script: "text/javascript, application/javascript",
- json: "application/json, text/javascript",
- text: "text/plain",
- _default: "*/*"
- }
- },
-
- // Last-Modified header cache for next request
- lastModified: {},
-
- ajax: function( s ) {
- // Extend the settings, but re-extend 's' so that it can be
- // checked again later (in the test suite, specifically)
- s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
-
- var jsonp, jsre = /=\?(&|$)/g, status, data,
- type = s.type.toUpperCase();
-
- // convert data if not already a string
- if ( s.data && s.processData && typeof s.data !== "string" )
- s.data = jQuery.param(s.data);
-
- // Handle JSONP Parameter Callbacks
- if ( s.dataType == "jsonp" ) {
- if ( type == "GET" ) {
- if ( !s.url.match(jsre) )
- s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
- } else if ( !s.data || !s.data.match(jsre) )
- s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
- s.dataType = "json";
- }
-
- // Build temporary JSONP function
- if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
- jsonp = "jsonp" + jsc++;
-
- // Replace the =? sequence both in the query string and the data
- if ( s.data )
- s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
- s.url = s.url.replace(jsre, "=" + jsonp + "$1");
-
- // We need to make sure
- // that a JSONP style response is executed properly
- s.dataType = "script";
-
- // Handle JSONP-style loading
- window[ jsonp ] = function(tmp){
- data = tmp;
- success();
- complete();
- // Garbage collect
- window[ jsonp ] = undefined;
- try{ delete window[ jsonp ]; } catch(e){}
- if ( head )
- head.removeChild( script );
- };
- }
-
- if ( s.dataType == "script" && s.cache == null )
- s.cache = false;
-
- if ( s.cache === false && type == "GET" ) {
- var ts = now();
- // try replacing _= if it is there
- var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
- // if nothing was replaced, add timestamp to the end
- s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
- }
-
- // If data is available, append data to url for get requests
- if ( s.data && type == "GET" ) {
- s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
-
- // IE likes to send both get and post data, prevent this
- s.data = null;
- }
-
- // Watch for a new set of requests
- if ( s.global && ! jQuery.active++ )
- jQuery.event.trigger( "ajaxStart" );
-
- // Matches an absolute URL, and saves the domain
- var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
-
- // If we're requesting a remote document
- // and trying to load JSON or Script with a GET
- if ( s.dataType == "script" && type == "GET" && parts
- && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
-
- var head = document.getElementsByTagName("head")[0];
- var script = document.createElement("script");
- script.src = s.url;
- if (s.scriptCharset)
- script.charset = s.scriptCharset;
-
- // Handle Script loading
- if ( !jsonp ) {
- var done = false;
-
- // Attach handlers for all browsers
- script.onload = script.onreadystatechange = function(){
- if ( !done && (!this.readyState ||
- this.readyState == "loaded" || this.readyState == "complete") ) {
- done = true;
- success();
- complete();
-
- // Handle memory leak in IE
- script.onload = script.onreadystatechange = null;
- head.removeChild( script );
- }
- };
- }
-
- head.appendChild(script);
-
- // We handle everything using the script element injection
- return undefined;
- }
-
- var requestDone = false;
-
- // Create the request object
- var xhr = s.xhr();
-
- // Open the socket
- // Passing null username, generates a login popup on Opera (#2865)
- if( s.username )
- xhr.open(type, s.url, s.async, s.username, s.password);
- else
- xhr.open(type, s.url, s.async);
-
- // Need an extra try/catch for cross domain requests in Firefox 3
- try {
- // Set the correct header, if data is being sent
- if ( s.data )
- xhr.setRequestHeader("Content-Type", s.contentType);
-
- // Set the If-Modified-Since header, if ifModified mode.
- if ( s.ifModified )
- xhr.setRequestHeader("If-Modified-Since",
- jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
-
- // Set header so the called script knows that it's an XMLHttpRequest
- xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
-
- // Set the Accepts header for the server, depending on the dataType
- xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
- s.accepts[ s.dataType ] + ", */*" :
- s.accepts._default );
- } catch(e){}
-
- // Allow custom headers/mimetypes and early abort
- if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
- // Handle the global AJAX counter
- if ( s.global && ! --jQuery.active )
- jQuery.event.trigger( "ajaxStop" );
- // close opended socket
- xhr.abort();
- return false;
- }
-
- if ( s.global )
- jQuery.event.trigger("ajaxSend", [xhr, s]);
-
- // Wait for a response to come back
- var onreadystatechange = function(isTimeout){
- // The request was aborted, clear the interval and decrement jQuery.active
- if (xhr.readyState == 0) {
- if (ival) {
- // clear poll interval
- clearInterval(ival);
- ival = null;
- // Handle the global AJAX counter
- if ( s.global && ! --jQuery.active )
- jQuery.event.trigger( "ajaxStop" );
- }
- // The transfer is complete and the data is available, or the request timed out
- } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
- requestDone = true;
-
- // clear poll interval
- if (ival) {
- clearInterval(ival);
- ival = null;
- }
-
- status = isTimeout == "timeout" ? "timeout" :
- !jQuery.httpSuccess( xhr ) ? "error" :
- s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
- "success";
-
- if ( status == "success" ) {
- // Watch for, and catch, XML document parse errors
- try {
- // process the data (runs the xml through httpData regardless of callback)
- data = jQuery.httpData( xhr, s.dataType, s );
- } catch(e) {
- status = "parsererror";
- }
- }
-
- // Make sure that the request was successful or notmodified
- if ( status == "success" ) {
- // Cache Last-Modified header, if ifModified mode.
- var modRes;
- try {
- modRes = xhr.getResponseHeader("Last-Modified");
- } catch(e) {} // swallow exception thrown by FF if header is not available
-
- if ( s.ifModified && modRes )
- jQuery.lastModified[s.url] = modRes;
-
- // JSONP handles its own success callback
- if ( !jsonp )
- success();
- } else
- jQuery.handleError(s, xhr, status);
-
- // Fire the complete handlers
- complete();
-
- if ( isTimeout )
- xhr.abort();
-
- // Stop memory leaks
- if ( s.async )
- xhr = null;
- }
- };
-
- if ( s.async ) {
- // don't attach the handler to the request, just poll it instead
- var ival = setInterval(onreadystatechange, 13);
-
- // Timeout checker
- if ( s.timeout > 0 )
- setTimeout(function(){
- // Check to see if the request is still happening
- if ( xhr && !requestDone )
- onreadystatechange( "timeout" );
- }, s.timeout);
- }
-
- // Send the data
- try {
- xhr.send(s.data);
- } catch(e) {
- jQuery.handleError(s, xhr, null, e);
- }
-
- // firefox 1.5 doesn't fire statechange for sync requests
- if ( !s.async )
- onreadystatechange();
-
- function success(){
- // If a local callback was specified, fire it and pass it the data
- if ( s.success )
- s.success( data, status );
-
- // Fire the global callback
- if ( s.global )
- jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
- }
-
- function complete(){
- // Process result
- if ( s.complete )
- s.complete(xhr, status);
-
- // The request was completed
- if ( s.global )
- jQuery.event.trigger( "ajaxComplete", [xhr, s] );
-
- // Handle the global AJAX counter
- if ( s.global && ! --jQuery.active )
- jQuery.event.trigger( "ajaxStop" );
- }
-
- // return XMLHttpRequest to allow aborting the request etc.
- return xhr;
- },
-
- handleError: function( s, xhr, status, e ) {
- // If a local callback was specified, fire it
- if ( s.error ) s.error( xhr, status, e );
-
- // Fire the global callback
- if ( s.global )
- jQuery.event.trigger( "ajaxError", [xhr, s, e] );
- },
-
- // Counter for holding the number of active queries
- active: 0,
-
- // Determines if an XMLHttpRequest was successful or not
- httpSuccess: function( xhr ) {
- try {
- // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
- return !xhr.status && location.protocol == "file:" ||
- ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
- } catch(e){}
- return false;
- },
-
- // Determines if an XMLHttpRequest returns NotModified
- httpNotModified: function( xhr, url ) {
- try {
- var xhrRes = xhr.getResponseHeader("Last-Modified");
-
- // Firefox always returns 200. check Last-Modified date
- return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
- } catch(e){}
- return false;
- },
-
- httpData: function( xhr, type, s ) {
- var ct = xhr.getResponseHeader("content-type"),
- xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
- data = xml ? xhr.responseXML : xhr.responseText;
-
- if ( xml && data.documentElement.tagName == "parsererror" )
- throw "parsererror";
-
- // Allow a pre-filtering function to sanitize the response
- // s != null is checked to keep backwards compatibility
- if( s && s.dataFilter )
- data = s.dataFilter( data, type );
-
- // The filter can actually parse the response
- if( typeof data === "string" ){
-
- // If the type is "script", eval it in global context
- if ( type == "script" )
- jQuery.globalEval( data );
-
- // Get the JavaScript object, if JSON is used.
- if ( type == "json" )
- data = window["eval"]("(" + data + ")");
- }
-
- return data;
- },
-
- // Serialize an array of form elements or a set of
- // key/values into a query string
- param: function( a ) {
- var s = [ ];
-
- function add( key, value ){
- s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
- };
-
- // If an array was passed in, assume that it is an array
- // of form elements
- if ( jQuery.isArray(a) || a.jquery )
- // Serialize the form elements
- jQuery.each( a, function(){
- add( this.name, this.value );
- });
-
- // Otherwise, assume that it's an object of key/value pairs
- else
- // Serialize the key/values
- for ( var j in a )
- // If the value is an array then the key names need to be repeated
- if ( jQuery.isArray(a[j]) )
- jQuery.each( a[j], function(){
- add( j, this );
- });
- else
- add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
-
- // Return the resulting serialization
- return s.join("&").replace(/%20/g, "+");
- }
-
-});
-var elemdisplay = {},
- timerId,
- fxAttrs = [
- // height animations
- [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
- // width animations
- [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
- // opacity animations
- [ "opacity" ]
- ];
-
-function genFx( type, num ){
- var obj = {};
- jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
- obj[ this ] = type;
- });
- return obj;
-}
-
-jQuery.fn.extend({
- show: function(speed,callback){
- if ( speed ) {
- return this.animate( genFx("show", 3), speed, callback);
- } else {
- for ( var i = 0, l = this.length; i < l; i++ ){
- var old = jQuery.data(this[i], "olddisplay");
-
- this[i].style.display = old || "";
-
- if ( jQuery.css(this[i], "display") === "none" ) {
- var tagName = this[i].tagName, display;
-
- if ( elemdisplay[ tagName ] ) {
- display = elemdisplay[ tagName ];
- } else {
- var elem = jQuery("<" + tagName + " />").appendTo("body");
-
- display = elem.css("display");
- if ( display === "none" )
- display = "block";
-
- elem.remove();
-
- elemdisplay[ tagName ] = display;
- }
-
- jQuery.data(this[i], "olddisplay", display);
- }
- }
-
- // Set the display of the elements in a second loop
- // to avoid the constant reflow
- for ( var i = 0, l = this.length; i < l; i++ ){
- this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
- }
-
- return this;
- }
- },
-
- hide: function(speed,callback){
- if ( speed ) {
- return this.animate( genFx("hide", 3), speed, callback);
- } else {
- for ( var i = 0, l = this.length; i < l; i++ ){
- var old = jQuery.data(this[i], "olddisplay");
- if ( !old && old !== "none" )
- jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
- }
-
- // Set the display of the elements in a second loop
- // to avoid the constant reflow
- for ( var i = 0, l = this.length; i < l; i++ ){
- this[i].style.display = "none";
- }
-
- return this;
- }
- },
-
- // Save the old toggle function
- _toggle: jQuery.fn.toggle,
-
- toggle: function( fn, fn2 ){
- var bool = typeof fn === "boolean";
-
- return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
- this._toggle.apply( this, arguments ) :
- fn == null || bool ?
- this.each(function(){
- var state = bool ? fn : jQuery(this).is(":hidden");
- jQuery(this)[ state ? "show" : "hide" ]();
- }) :
- this.animate(genFx("toggle", 3), fn, fn2);
- },
-
- fadeTo: function(speed,to,callback){
- return this.animate({opacity: to}, speed, callback);
- },
-
- animate: function( prop, speed, easing, callback ) {
- var optall = jQuery.speed(speed, easing, callback);
-
- return this[ optall.queue === false ? "each" : "queue" ](function(){
-
- var opt = jQuery.extend({}, optall), p,
- hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
- self = this;
-
- for ( p in prop ) {
- if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
- return opt.complete.call(this);
-
- if ( ( p == "height" || p == "width" ) && this.style ) {
- // Store display property
- opt.display = jQuery.css(this, "display");
-
- // Make sure that nothing sneaks out
- opt.overflow = this.style.overflow;
- }
- }
-
- if ( opt.overflow != null )
- this.style.overflow = "hidden";
-
- opt.curAnim = jQuery.extend({}, prop);
-
- jQuery.each( prop, function(name, val){
- var e = new jQuery.fx( self, opt, name );
-
- if ( /toggle|show|hide/.test(val) )
- e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
- else {
- var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
- start = e.cur(true) || 0;
-
- if ( parts ) {
- var end = parseFloat(parts[2]),
- unit = parts[3] || "px";
-
- // We need to compute starting value
- if ( unit != "px" ) {
- self.style[ name ] = (end || 1) + unit;
- start = ((end || 1) / e.cur(true)) * start;
- self.style[ name ] = start + unit;
- }
-
- // If a +=/-= token was provided, we're doing a relative animation
- if ( parts[1] )
- end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
-
- e.custom( start, end, unit );
- } else
- e.custom( start, val, "" );
- }
- });
-
- // For JS strict compliance
- return true;
- });
- },
-
- stop: function(clearQueue, gotoEnd){
- var timers = jQuery.timers;
-
- if (clearQueue)
- this.queue([]);
-
- this.each(function(){
- // go in reverse order so anything added to the queue during the loop is ignored
- for ( var i = timers.length - 1; i >= 0; i-- )
- if ( timers[i].elem == this ) {
- if (gotoEnd)
- // force the next step to be the last
- timers[i](true);
- timers.splice(i, 1);
- }
- });
-
- // start the next in the queue if the last step wasn't forced
- if (!gotoEnd)
- this.dequeue();
-
- return this;
- }
-
-});
-
-// Generate shortcuts for custom animations
-jQuery.each({
- slideDown: genFx("show", 1),
- slideUp: genFx("hide", 1),
- slideToggle: genFx("toggle", 1),
- fadeIn: { opacity: "show" },
- fadeOut: { opacity: "hide" }
-}, function( name, props ){
- jQuery.fn[ name ] = function( speed, callback ){
- return this.animate( props, speed, callback );
- };
-});
-
-jQuery.extend({
-
- speed: function(speed, easing, fn) {
- var opt = typeof speed === "object" ? speed : {
- complete: fn || !fn && easing ||
- jQuery.isFunction( speed ) && speed,
- duration: speed,
- easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
- };
-
- opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
- jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
-
- // Queueing
- opt.old = opt.complete;
- opt.complete = function(){
- if ( opt.queue !== false )
- jQuery(this).dequeue();
- if ( jQuery.isFunction( opt.old ) )
- opt.old.call( this );
- };
-
- return opt;
- },
-
- easing: {
- linear: function( p, n, firstNum, diff ) {
- return firstNum + diff * p;
- },
- swing: function( p, n, firstNum, diff ) {
- return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
- }
- },
-
- timers: [],
-
- fx: function( elem, options, prop ){
- this.options = options;
- this.elem = elem;
- this.prop = prop;
-
- if ( !options.orig )
- options.orig = {};
- }
-
-});
-
-jQuery.fx.prototype = {
-
- // Simple function for setting a style value
- update: function(){
- if ( this.options.step )
- this.options.step.call( this.elem, this.now, this );
-
- (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
-
- // Set display property to block for height/width animations
- if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
- this.elem.style.display = "block";
- },
-
- // Get the current size
- cur: function(force){
- if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
- return this.elem[ this.prop ];
-
- var r = parseFloat(jQuery.css(this.elem, this.prop, force));
- return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
- },
-
- // Start an animation from one number to another
- custom: function(from, to, unit){
- this.startTime = now();
- this.start = from;
- this.end = to;
- this.unit = unit || this.unit || "px";
- this.now = this.start;
- this.pos = this.state = 0;
-
- var self = this;
- function t(gotoEnd){
- return self.step(gotoEnd);
- }
-
- t.elem = this.elem;
-
- if ( t() && jQuery.timers.push(t) && !timerId ) {
- timerId = setInterval(function(){
- var timers = jQuery.timers;
-
- for ( var i = 0; i < timers.length; i++ )
- if ( !timers[i]() )
- timers.splice(i--, 1);
-
- if ( !timers.length ) {
- clearInterval( timerId );
- timerId = undefined;
- }
- }, 13);
- }
- },
-
- // Simple 'show' function
- show: function(){
- // Remember where we started, so that we can go back to it later
- this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
- this.options.show = true;
-
- // Begin the animation
- // Make sure that we start at a small width/height to avoid any
- // flash of content
- this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
-
- // Start by showing the element
- jQuery(this.elem).show();
- },
-
- // Simple 'hide' function
- hide: function(){
- // Remember where we started, so that we can go back to it later
- this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
- this.options.hide = true;
-
- // Begin the animation
- this.custom(this.cur(), 0);
- },
-
- // Each step of an animation
- step: function(gotoEnd){
- var t = now();
-
- if ( gotoEnd || t >= this.options.duration + this.startTime ) {
- this.now = this.end;
- this.pos = this.state = 1;
- this.update();
-
- this.options.curAnim[ this.prop ] = true;
-
- var done = true;
- for ( var i in this.options.curAnim )
- if ( this.options.curAnim[i] !== true )
- done = false;
-
- if ( done ) {
- if ( this.options.display != null ) {
- // Reset the overflow
- this.elem.style.overflow = this.options.overflow;
-
- // Reset the display
- this.elem.style.display = this.options.display;
- if ( jQuery.css(this.elem, "display") == "none" )
- this.elem.style.display = "block";
- }
-
- // Hide the element if the "hide" operation was done
- if ( this.options.hide )
- jQuery(this.elem).hide();
-
- // Reset the properties, if the item has been hidden or shown
- if ( this.options.hide || this.options.show )
- for ( var p in this.options.curAnim )
- jQuery.attr(this.elem.style, p, this.options.orig[p]);
-
- // Execute the complete function
- this.options.complete.call( this.elem );
- }
-
- return false;
- } else {
- var n = t - this.startTime;
- this.state = n / this.options.duration;
-
- // Perform the easing function, defaults to swing
- this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
- this.now = this.start + ((this.end - this.start) * this.pos);
-
- // Perform the next step of the animation
- this.update();
- }
-
- return true;
- }
-
-};
-
-jQuery.extend( jQuery.fx, {
- speeds:{
- slow: 600,
- fast: 200,
- // Default speed
- _default: 400
- },
- step: {
-
- opacity: function(fx){
- jQuery.attr(fx.elem.style, "opacity", fx.now);
- },
-
- _default: function(fx){
- if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
- fx.elem.style[ fx.prop ] = fx.now + fx.unit;
- else
- fx.elem[ fx.prop ] = fx.now;
- }
- }
-});
-if ( document.documentElement["getBoundingClientRect"] )
- jQuery.fn.offset = function() {
- if ( !this[0] ) return { top: 0, left: 0 };
- if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
- var box = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
- clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
- top = box.top + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
- left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
- return { top: top, left: left };
- };
-else
- jQuery.fn.offset = function() {
- if ( !this[0] ) return { top: 0, left: 0 };
- if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
- jQuery.offset.initialized || jQuery.offset.initialize();
-
- var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
- doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
- body = doc.body, defaultView = doc.defaultView,
- prevComputedStyle = defaultView.getComputedStyle(elem, null),
- top = elem.offsetTop, left = elem.offsetLeft;
-
- while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
- computedStyle = defaultView.getComputedStyle(elem, null);
- top -= elem.scrollTop, left -= elem.scrollLeft;
- if ( elem === offsetParent ) {
- top += elem.offsetTop, left += elem.offsetLeft;
- if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
- top += parseInt( computedStyle.borderTopWidth, 10) || 0,
- left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
- prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
- }
- if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
- top += parseInt( computedStyle.borderTopWidth, 10) || 0,
- left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
- prevComputedStyle = computedStyle;
- }
-
- if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
- top += body.offsetTop,
- left += body.offsetLeft;
-
- if ( prevComputedStyle.position === "fixed" )
- top += Math.max(docElem.scrollTop, body.scrollTop),
- left += Math.max(docElem.scrollLeft, body.scrollLeft);
-
- return { top: top, left: left };
- };
-
-jQuery.offset = {
- initialize: function() {
- if ( this.initialized ) return;
- var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
- html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
-
- rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
- for ( prop in rules ) container.style[prop] = rules[prop];
-
- container.innerHTML = html;
- body.insertBefore(container, body.firstChild);
- innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
-
- this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
- this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
-
- innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
- this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
-
- body.style.marginTop = '1px';
- this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
- body.style.marginTop = bodyMarginTop;
-
- body.removeChild(container);
- this.initialized = true;
- },
-
- bodyOffset: function(body) {
- jQuery.offset.initialized || jQuery.offset.initialize();
- var top = body.offsetTop, left = body.offsetLeft;
- if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
- top += parseInt( jQuery.curCSS(body, 'marginTop', true), 10 ) || 0,
- left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
- return { top: top, left: left };
- }
-};
-
-
-jQuery.fn.extend({
- position: function() {
- var left = 0, top = 0, results;
-
- if ( this[0] ) {
- // Get *real* offsetParent
- var offsetParent = this.offsetParent(),
-
- // Get correct offsets
- offset = this.offset(),
- parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
-
- // Subtract element margins
- // note: when an element has margin: auto the offsetLeft and marginLeft
- // are the same in Safari causing offset.left to incorrectly be 0
- offset.top -= num( this, 'marginTop' );
- offset.left -= num( this, 'marginLeft' );
-
- // Add offsetParent borders
- parentOffset.top += num( offsetParent, 'borderTopWidth' );
- parentOffset.left += num( offsetParent, 'borderLeftWidth' );
-
- // Subtract the two offsets
- results = {
- top: offset.top - parentOffset.top,
- left: offset.left - parentOffset.left
- };
- }
-
- return results;
- },
-
- offsetParent: function() {
- var offsetParent = this[0].offsetParent || document.body;
- while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
- offsetParent = offsetParent.offsetParent;
- return jQuery(offsetParent);
- }
-});
-
-
-// Create scrollLeft and scrollTop methods
-jQuery.each( ['Left', 'Top'], function(i, name) {
- var method = 'scroll' + name;
-
- jQuery.fn[ method ] = function(val) {
- if (!this[0]) return null;
-
- return val !== undefined ?
-
- // Set the scroll offset
- this.each(function() {
- this == window || this == document ?
- window.scrollTo(
- !i ? val : jQuery(window).scrollLeft(),
- i ? val : jQuery(window).scrollTop()
- ) :
- this[ method ] = val;
- }) :
-
- // Return the scroll offset
- this[0] == window || this[0] == document ?
- self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
- jQuery.boxModel && document.documentElement[ method ] ||
- document.body[ method ] :
- this[0][ method ];
- };
-});
-// Create innerHeight, innerWidth, outerHeight and outerWidth methods
-jQuery.each([ "Height", "Width" ], function(i, name){
-
- var tl = i ? "Left" : "Top", // top or left
- br = i ? "Right" : "Bottom", // bottom or right
- lower = name.toLowerCase();
-
- // innerHeight and innerWidth
- jQuery.fn["inner" + name] = function(){
- return this[0] ?
- jQuery.css( this[0], lower, false, "padding" ) :
- null;
- };
-
- // outerHeight and outerWidth
- jQuery.fn["outer" + name] = function(margin) {
- return this[0] ?
- jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
- null;
- };
-
- var type = name.toLowerCase();
-
- jQuery.fn[ type ] = function( size ) {
- // Get window width or height
- return this[0] == window ?
- // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
- document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
- document.body[ "client" + name ] :
-
- // Get document width or height
- this[0] == document ?
- // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
- Math.max(
- document.documentElement["client" + name],
- document.body["scroll" + name], document.documentElement["scroll" + name],
- document.body["offset" + name], document.documentElement["offset" + name]
- ) :
-
- // Get or set width or height on the element
- size === undefined ?
- // Get width or height on the element
- (this.length ? jQuery.css( this[0], type ) : null) :
-
- // Set the width or height on the element (default to pixels if value is unitless)
- this.css( type, typeof size === "string" ? size : size + "px" );
- };
-
-});
-})();
+/*!
+ * jQuery JavaScript Library v1.3.2
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
+ * Revision: 6246
+ */
+(function(){
+
+var
+ // Will speed up references to window, and allows munging its name.
+ window = this,
+ // Will speed up references to undefined, and allows munging its name.
+ undefined,
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ jQuery = window.jQuery = window.$ = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // A simple way to check for HTML strings or ID strings
+ // (both of which we optimize for)
+ quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
+ // Is it a simple selector
+ isSimple = /^.[^:#\[\.,]*$/;
+
+jQuery.fn = jQuery.prototype = {
+ init: function( selector, context ) {
+ // Make sure that a selection was provided
+ selector = selector || document;
+
+ // Handle $(DOMElement)
+ if ( selector.nodeType ) {
+ this[0] = selector;
+ this.length = 1;
+ this.context = selector;
+ return this;
+ }
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ // Are we dealing with HTML string or an ID?
+ var match = quickExpr.exec( selector );
+
+ // Verify a match, and that no context was specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] )
+ selector = jQuery.clean( [ match[1] ], context );
+
+ // HANDLE: $("#id")
+ else {
+ var elem = document.getElementById( match[3] );
+
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem && elem.id != match[3] )
+ return jQuery().find( selector );
+
+ // Otherwise, we inject the element directly into the jQuery object
+ var ret = jQuery( elem || [] );
+ ret.context = document;
+ ret.selector = selector;
+ return ret;
+ }
+
+ // HANDLE: $(expr, [context])
+ // (which is just equivalent to: $(content).find(expr)
+ } else
+ return jQuery( context ).find( selector );
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) )
+ return jQuery( document ).ready( selector );
+
+ // Make sure that old selector state is passed along
+ if ( selector.selector && selector.context ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return this.setArray(jQuery.isArray( selector ) ?
+ selector :
+ jQuery.makeArray(selector));
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The current version of jQuery being used
+ jquery: "1.3.2",
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num === undefined ?
+
+ // Return a 'clean' array
+ Array.prototype.slice.call( this ) :
+
+ // Return just the object
+ this[ num ];
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems, name, selector ) {
+ // Build a new jQuery matched element set
+ var ret = jQuery( elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ ret.context = this.context;
+
+ if ( name === "find" )
+ ret.selector = this.selector + (this.selector ? " " : "") + selector;
+ else if ( name )
+ ret.selector = this.selector + "." + name + "(" + selector + ")";
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Force the current matched set of elements to become
+ // the specified array of elements (destroying the stack in the process)
+ // You should use pushStack() in order to do this, but maintain the stack
+ setArray: function( elems ) {
+ // Resetting the length to 0, then using the native Array push
+ // is a super-fast way to populate an object with array-like properties
+ this.length = 0;
+ Array.prototype.push.apply( this, elems );
+
+ return this;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem && elem.jquery ? elem[0] : elem
+ , this );
+ },
+
+ attr: function( name, value, type ) {
+ var options = name;
+
+ // Look for the case where we're accessing a style value
+ if ( typeof name === "string" )
+ if ( value === undefined )
+ return this[0] && jQuery[ type || "attr" ]( this[0], name );
+
+ else {
+ options = {};
+ options[ name ] = value;
+ }
+
+ // Check to see if we're setting style values
+ return this.each(function(i){
+ // Set all the styles
+ for ( name in options )
+ jQuery.attr(
+ type ?
+ this.style :
+ this,
+ name, jQuery.prop( this, options[ name ], type, i, name )
+ );
+ });
+ },
+
+ css: function( key, value ) {
+ // ignore negative width and height values
+ if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
+ value = undefined;
+ return this.attr( key, value, "curCSS" );
+ },
+
+ text: function( text ) {
+ if ( typeof text !== "object" && text != null )
+ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+
+ var ret = "";
+
+ jQuery.each( text || this, function(){
+ jQuery.each( this.childNodes, function(){
+ if ( this.nodeType != 8 )
+ ret += this.nodeType != 1 ?
+ this.nodeValue :
+ jQuery.fn.text( [ this ] );
+ });
+ });
+
+ return ret;
+ },
+
+ wrapAll: function( html ) {
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).clone();
+
+ if ( this[0].parentNode )
+ wrap.insertBefore( this[0] );
+
+ wrap.map(function(){
+ var elem = this;
+
+ while ( elem.firstChild )
+ elem = elem.firstChild;
+
+ return elem;
+ }).append(this);
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ return this.each(function(){
+ jQuery( this ).contents().wrapAll( html );
+ });
+ },
+
+ wrap: function( html ) {
+ return this.each(function(){
+ jQuery( this ).wrapAll( html );
+ });
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function(elem){
+ if (this.nodeType == 1)
+ this.appendChild( elem );
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function(elem){
+ if (this.nodeType == 1)
+ this.insertBefore( elem, this.firstChild );
+ });
+ },
+
+ before: function() {
+ return this.domManip(arguments, false, function(elem){
+ this.parentNode.insertBefore( elem, this );
+ });
+ },
+
+ after: function() {
+ return this.domManip(arguments, false, function(elem){
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ });
+ },
+
+ end: function() {
+ return this.prevObject || jQuery( [] );
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: [].push,
+ sort: [].sort,
+ splice: [].splice,
+
+ find: function( selector ) {
+ if ( this.length === 1 ) {
+ var ret = this.pushStack( [], "find", selector );
+ ret.length = 0;
+ jQuery.find( selector, this[0], ret );
+ return ret;
+ } else {
+ return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
+ return jQuery.find( selector, elem );
+ })), "find", selector );
+ }
+ },
+
+ clone: function( events ) {
+ // Do the clone
+ var ret = this.map(function(){
+ if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
+ // IE copies events bound via attachEvent when
+ // using cloneNode. Calling detachEvent on the
+ // clone will also remove the events from the orignal
+ // In order to get around this, we use innerHTML.
+ // Unfortunately, this means some modifications to
+ // attributes in IE that are actually only stored
+ // as properties will not be copied (such as the
+ // the name attribute on an input).
+ var html = this.outerHTML;
+ if ( !html ) {
+ var div = this.ownerDocument.createElement("div");
+ div.appendChild( this.cloneNode(true) );
+ html = div.innerHTML;
+ }
+
+ return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
+ } else
+ return this.cloneNode(true);
+ });
+
+ // Copy the events from the original to the clone
+ if ( events === true ) {
+ var orig = this.find("*").andSelf(), i = 0;
+
+ ret.find("*").andSelf().each(function(){
+ if ( this.nodeName !== orig[i].nodeName )
+ return;
+
+ var events = jQuery.data( orig[i], "events" );
+
+ for ( var type in events ) {
+ for ( var handler in events[ type ] ) {
+ jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
+ }
+ }
+
+ i++;
+ });
+ }
+
+ // Return the cloned set
+ return ret;
+ },
+
+ filter: function( selector ) {
+ return this.pushStack(
+ jQuery.isFunction( selector ) &&
+ jQuery.grep(this, function(elem, i){
+ return selector.call( elem, i );
+ }) ||
+
+ jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
+ return elem.nodeType === 1;
+ }) ), "filter", selector );
+ },
+
+ closest: function( selector ) {
+ var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
+ closer = 0;
+
+ return this.map(function(){
+ var cur = this;
+ while ( cur && cur.ownerDocument ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
+ jQuery.data(cur, "closest", closer);
+ return cur;
+ }
+ cur = cur.parentNode;
+ closer++;
+ }
+ });
+ },
+
+ not: function( selector ) {
+ if ( typeof selector === "string" )
+ // test special case where just one selector is passed in
+ if ( isSimple.test( selector ) )
+ return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
+ else
+ selector = jQuery.multiFilter( selector, this );
+
+ var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+ return this.filter(function() {
+ return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+ });
+ },
+
+ add: function( selector ) {
+ return this.pushStack( jQuery.unique( jQuery.merge(
+ this.get(),
+ typeof selector === "string" ?
+ jQuery( selector ) :
+ jQuery.makeArray( selector )
+ )));
+ },
+
+ is: function( selector ) {
+ return !!selector && jQuery.multiFilter( selector, this ).length > 0;
+ },
+
+ hasClass: function( selector ) {
+ return !!selector && this.is( "." + selector );
+ },
+
+ val: function( value ) {
+ if ( value === undefined ) {
+ var elem = this[0];
+
+ if ( elem ) {
+ if( jQuery.nodeName( elem, 'option' ) )
+ return (elem.attributes.value || {}).specified ? elem.value : elem.text;
+
+ // We need to handle select boxes special
+ if ( jQuery.nodeName( elem, "select" ) ) {
+ var index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type == "select-one";
+
+ // Nothing was selected
+ if ( index < 0 )
+ return null;
+
+ // Loop through all the selected options
+ for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+ var option = options[ i ];
+
+ if ( option.selected ) {
+ // Get the specifc value for the option
+ value = jQuery(option).val();
+
+ // We don't need an array for one selects
+ if ( one )
+ return value;
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ }
+
+ // Everything else, we just grab the value
+ return (elem.value || "").replace(/\r/g, "");
+
+ }
+
+ return undefined;
+ }
+
+ if ( typeof value === "number" )
+ value += '';
+
+ return this.each(function(){
+ if ( this.nodeType != 1 )
+ return;
+
+ if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
+ this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+ jQuery.inArray(this.name, value) >= 0);
+
+ else if ( jQuery.nodeName( this, "select" ) ) {
+ var values = jQuery.makeArray(value);
+
+ jQuery( "option", this ).each(function(){
+ this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
+ jQuery.inArray( this.text, values ) >= 0);
+ });
+
+ if ( !values.length )
+ this.selectedIndex = -1;
+
+ } else
+ this.value = value;
+ });
+ },
+
+ html: function( value ) {
+ return value === undefined ?
+ (this[0] ?
+ this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
+ null) :
+ this.empty().append( value );
+ },
+
+ replaceWith: function( value ) {
+ return this.after( value ).remove();
+ },
+
+ eq: function( i ) {
+ return this.slice( i, +i + 1 );
+ },
+
+ slice: function() {
+ return this.pushStack( Array.prototype.slice.apply( this, arguments ),
+ "slice", Array.prototype.slice.call(arguments).join(",") );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function(elem, i){
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ andSelf: function() {
+ return this.add( this.prevObject );
+ },
+
+ domManip: function( args, table, callback ) {
+ if ( this[0] ) {
+ var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
+ scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
+ first = fragment.firstChild;
+
+ if ( first )
+ for ( var i = 0, l = this.length; i < l; i++ )
+ callback.call( root(this[i], first), this.length > 1 || i > 0 ?
+ fragment.cloneNode(true) : fragment );
+
+ if ( scripts )
+ jQuery.each( scripts, evalScript );
+ }
+
+ return this;
+
+ function root( elem, cur ) {
+ return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
+ (elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+ elem;
+ }
+ }
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+function evalScript( i, elem ) {
+ if ( elem.src )
+ jQuery.ajax({
+ url: elem.src,
+ async: false,
+ dataType: "script"
+ });
+
+ else
+ jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+
+ if ( elem.parentNode )
+ elem.parentNode.removeChild( elem );
+}
+
+function now(){
+ return +new Date;
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+ // copy reference to target object
+ var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) )
+ target = {};
+
+ // extend jQuery itself if only one argument is passed
+ if ( length == i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ )
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null )
+ // Extend the base object
+ for ( var name in options ) {
+ var src = target[ name ], copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy )
+ continue;
+
+ // Recurse if we're merging object values
+ if ( deep && copy && typeof copy === "object" && !copy.nodeType )
+ target[ name ] = jQuery.extend( deep,
+ // Never move original objects, clone them
+ src || ( copy.length != null ? [ ] : { } )
+ , copy );
+
+ // Don't bring in undefined values
+ else if ( copy !== undefined )
+ target[ name ] = copy;
+
+ }
+
+ // Return the modified object
+ return target;
+};
+
+// exclude the following css properties to add px
+var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
+ // cache defaultView
+ defaultView = document.defaultView || {},
+ toString = Object.prototype.toString;
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ window.$ = _$;
+
+ if ( deep )
+ window.jQuery = _jQuery;
+
+ return jQuery;
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return toString.call(obj) === "[object Function]";
+ },
+
+ isArray: function( obj ) {
+ return toString.call(obj) === "[object Array]";
+ },
+
+ // check if an element is in a (or is an) XML document
+ isXMLDoc: function( elem ) {
+ return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+ !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
+ },
+
+ // Evalulates a script in a global context
+ globalEval: function( data ) {
+ if ( data && /\S/.test(data) ) {
+ // Inspired by code by Andrea Giammarchi
+ // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+ var head = document.getElementsByTagName("head")[0] || document.documentElement,
+ script = document.createElement("script");
+
+ script.type = "text/javascript";
+ if ( jQuery.support.scriptEval )
+ script.appendChild( document.createTextNode( data ) );
+ else
+ script.text = data;
+
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709).
+ head.insertBefore( script, head.firstChild );
+ head.removeChild( script );
+ }
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+ },
+
+ // args is for internal usage only
+ each: function( object, callback, args ) {
+ var name, i = 0, length = object.length;
+
+ if ( args ) {
+ if ( length === undefined ) {
+ for ( name in object )
+ if ( callback.apply( object[ name ], args ) === false )
+ break;
+ } else
+ for ( ; i < length; )
+ if ( callback.apply( object[ i++ ], args ) === false )
+ break;
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( length === undefined ) {
+ for ( name in object )
+ if ( callback.call( object[ name ], name, object[ name ] ) === false )
+ break;
+ } else
+ for ( var value = object[0];
+ i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+ }
+
+ return object;
+ },
+
+ prop: function( elem, value, type, i, name ) {
+ // Handle executable functions
+ if ( jQuery.isFunction( value ) )
+ value = value.call( elem, i );
+
+ // Handle passing in a number to a CSS property
+ return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
+ value + "px" :
+ value;
+ },
+
+ className: {
+ // internal only, use addClass("class")
+ add: function( elem, classNames ) {
+ jQuery.each((classNames || "").split(/\s+/), function(i, className){
+ if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+ elem.className += (elem.className ? " " : "") + className;
+ });
+ },
+
+ // internal only, use removeClass("class")
+ remove: function( elem, classNames ) {
+ if (elem.nodeType == 1)
+ elem.className = classNames !== undefined ?
+ jQuery.grep(elem.className.split(/\s+/), function(className){
+ return !jQuery.className.has( classNames, className );
+ }).join(" ") :
+ "";
+ },
+
+ // internal only, use hasClass("class")
+ has: function( elem, className ) {
+ return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+ }
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback ) {
+ var old = {};
+ // Remember the old values, and insert the new ones
+ for ( var name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ callback.call( elem );
+
+ // Revert the old values
+ for ( var name in options )
+ elem.style[ name ] = old[ name ];
+ },
+
+ css: function( elem, name, force, extra ) {
+ if ( name == "width" || name == "height" ) {
+ var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+
+ function getWH() {
+ val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+
+ if ( extra === "border" )
+ return;
+
+ jQuery.each( which, function() {
+ if ( !extra )
+ val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+ if ( extra === "margin" )
+ val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
+ else
+ val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+ });
+ }
+
+ if ( elem.offsetWidth !== 0 )
+ getWH();
+ else
+ jQuery.swap( elem, props, getWH );
+
+ return Math.max(0, Math.round(val));
+ }
+
+ return jQuery.curCSS( elem, name, force );
+ },
+
+ curCSS: function( elem, name, force ) {
+ var ret, style = elem.style;
+
+ // We need to handle opacity special in IE
+ if ( name == "opacity" && !jQuery.support.opacity ) {
+ ret = jQuery.attr( style, "opacity" );
+
+ return ret == "" ?
+ "1" :
+ ret;
+ }
+
+ // Make sure we're using the right name for getting the float value
+ if ( name.match( /float/i ) )
+ name = styleFloat;
+
+ if ( !force && style && style[ name ] )
+ ret = style[ name ];
+
+ else if ( defaultView.getComputedStyle ) {
+
+ // Only "float" is needed here
+ if ( name.match( /float/i ) )
+ name = "float";
+
+ name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+
+ var computedStyle = defaultView.getComputedStyle( elem, null );
+
+ if ( computedStyle )
+ ret = computedStyle.getPropertyValue( name );
+
+ // We should always get a number back from opacity
+ if ( name == "opacity" && ret == "" )
+ ret = "1";
+
+ } else if ( elem.currentStyle ) {
+ var camelCase = name.replace(/\-(\w)/g, function(all, letter){
+ return letter.toUpperCase();
+ });
+
+ ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+ // Remember the original values
+ var left = style.left, rsLeft = elem.runtimeStyle.left;
+
+ // Put in the new values to get a computed value out
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ style.left = ret || 0;
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ elem.runtimeStyle.left = rsLeft;
+ }
+ }
+
+ return ret;
+ },
+
+ clean: function( elems, context, fragment ) {
+ context = context || document;
+
+ // !context.createElement fails in IE with an error but returns typeof 'object'
+ if ( typeof context.createElement === "undefined" )
+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+
+ // If a single string is passed in and it's a single tag
+ // just do a createElement and skip the rest
+ if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
+ var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
+ if ( match )
+ return [ context.createElement( match[1] ) ];
+ }
+
+ var ret = [], scripts = [], div = context.createElement("div");
+
+ jQuery.each(elems, function(i, elem){
+ if ( typeof elem === "number" )
+ elem += '';
+
+ if ( !elem )
+ return;
+
+ // Convert html string into DOM nodes
+ if ( typeof elem === "string" ) {
+ // Fix "XHTML"-style tags in all browsers
+ elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+ return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
+ all :
+ front + "></" + tag + ">";
+ });
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
+
+ var wrap =
+ // option or optgroup
+ !tags.indexOf("<opt") &&
+ [ 1, "<select multiple='multiple'>", "</select>" ] ||
+
+ !tags.indexOf("<leg") &&
+ [ 1, "<fieldset>", "</fieldset>" ] ||
+
+ tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+ [ 1, "<table>", "</table>" ] ||
+
+ !tags.indexOf("<tr") &&
+ [ 2, "<table><tbody>", "</tbody></table>" ] ||
+
+ // <thead> matched above
+ (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
+ [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+
+ !tags.indexOf("<col") &&
+ [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+
+ // IE can't serialize <link> and <script> tags normally
+ !jQuery.support.htmlSerialize &&
+ [ 1, "div<div>", "</div>" ] ||
+
+ [ 0, "", "" ];
+
+ // Go to html and back, then peel off extra wrappers
+ div.innerHTML = wrap[1] + elem + wrap[2];
+
+ // Move to the right depth
+ while ( wrap[0]-- )
+ div = div.lastChild;
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ var hasBody = /<tbody/i.test(elem),
+ tbody = !tags.indexOf("<table") && !hasBody ?
+ div.firstChild && div.firstChild.childNodes :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] == "<table>" && !hasBody ?
+ div.childNodes :
+ [];
+
+ for ( var j = tbody.length - 1; j >= 0 ; --j )
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+
+ }
+
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
+ div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+
+ elem = jQuery.makeArray( div.childNodes );
+ }
+
+ if ( elem.nodeType )
+ ret.push( elem );
+ else
+ ret = jQuery.merge( ret, elem );
+
+ });
+
+ if ( fragment ) {
+ for ( var i = 0; ret[i]; i++ ) {
+ if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+ scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+ } else {
+ if ( ret[i].nodeType === 1 )
+ ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+ fragment.appendChild( ret[i] );
+ }
+ }
+
+ return scripts;
+ }
+
+ return ret;
+ },
+
+ attr: function( elem, name, value ) {
+ // don't set attributes on text and comment nodes
+ if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+ return undefined;
+
+ var notxml = !jQuery.isXMLDoc( elem ),
+ // Whether we are setting (or getting)
+ set = value !== undefined;
+
+ // Try to normalize/fix the name
+ name = notxml && jQuery.props[ name ] || name;
+
+ // Only do all the following if this is a node (faster for style)
+ // IE elem.getAttribute passes even for style
+ if ( elem.tagName ) {
+
+ // These attributes require special treatment
+ var special = /href|src|style/.test( name );
+
+ // Safari mis-reports the default selected property of a hidden option
+ // Accessing the parent's selectedIndex property fixes it
+ if ( name == "selected" && elem.parentNode )
+ elem.parentNode.selectedIndex;
+
+ // If applicable, access the attribute via the DOM 0 way
+ if ( name in elem && notxml && !special ) {
+ if ( set ){
+ // We can't allow the type property to be changed (since it causes problems in IE)
+ if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+ throw "type property can't be changed";
+
+ elem[ name ] = value;
+ }
+
+ // browsers index elements by id/name on forms, give priority to attributes.
+ if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
+ return elem.getAttributeNode( name ).nodeValue;
+
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ if ( name == "tabIndex" ) {
+ var attributeNode = elem.getAttributeNode( "tabIndex" );
+ return attributeNode && attributeNode.specified
+ ? attributeNode.value
+ : elem.nodeName.match(/(button|input|object|select|textarea)/i)
+ ? 0
+ : elem.nodeName.match(/^(a|area)$/i) && elem.href
+ ? 0
+ : undefined;
+ }
+
+ return elem[ name ];
+ }
+
+ if ( !jQuery.support.style && notxml && name == "style" )
+ return jQuery.attr( elem.style, "cssText", value );
+
+ if ( set )
+ // convert the value to a string (all browsers do this but IE) see #1070
+ elem.setAttribute( name, "" + value );
+
+ var attr = !jQuery.support.hrefNormalized && notxml && special
+ // Some attributes require a special call on IE
+ ? elem.getAttribute( name, 2 )
+ : elem.getAttribute( name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return attr === null ? undefined : attr;
+ }
+
+ // elem is actually elem.style ... set the style
+
+ // IE uses filters for opacity
+ if ( !jQuery.support.opacity && name == "opacity" ) {
+ if ( set ) {
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ elem.zoom = 1;
+
+ // Set the alpha filter to set the opacity
+ elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
+ (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+ }
+
+ return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
+ (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
+ "";
+ }
+
+ name = name.replace(/-([a-z])/ig, function(all, letter){
+ return letter.toUpperCase();
+ });
+
+ if ( set )
+ elem[ name ] = value;
+
+ return elem[ name ];
+ },
+
+ trim: function( text ) {
+ return (text || "").replace( /^\s+|\s+$/g, "" );
+ },
+
+ makeArray: function( array ) {
+ var ret = [];
+
+ if( array != null ){
+ var i = array.length;
+ // The window, strings (and functions) also have 'length'
+ if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
+ ret[0] = array;
+ else
+ while( i )
+ ret[--i] = array[i];
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, array ) {
+ for ( var i = 0, length = array.length; i < length; i++ )
+ // Use === because on IE, window == document
+ if ( array[ i ] === elem )
+ return i;
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ // We have to loop this way because IE & Opera overwrite the length
+ // expando of getElementsByTagName
+ var i = 0, elem, pos = first.length;
+ // Also, we need to make sure that the correct elements are being returned
+ // (IE returns comment nodes in a '*' query)
+ if ( !jQuery.support.getAll ) {
+ while ( (elem = second[ i++ ]) != null )
+ if ( elem.nodeType != 8 )
+ first[ pos++ ] = elem;
+
+ } else
+ while ( (elem = second[ i++ ]) != null )
+ first[ pos++ ] = elem;
+
+ return first;
+ },
+
+ unique: function( array ) {
+ var ret = [], done = {};
+
+ try {
+
+ for ( var i = 0, length = array.length; i < length; i++ ) {
+ var id = jQuery.data( array[ i ] );
+
+ if ( !done[ id ] ) {
+ done[ id ] = true;
+ ret.push( array[ i ] );
+ }
+ }
+
+ } catch( e ) {
+ ret = array;
+ }
+
+ return ret;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var ret = [];
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( var i = 0, length = elems.length; i < length; i++ )
+ if ( !inv != !callback( elems[ i ], i ) )
+ ret.push( elems[ i ] );
+
+ return ret;
+ },
+
+ map: function( elems, callback ) {
+ var ret = [];
+
+ // Go through the array, translating each of the items to their
+ // new value (or values).
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ var value = callback( elems[ i ], i );
+
+ if ( value != null )
+ ret[ ret.length ] = value;
+ }
+
+ return ret.concat.apply( [], ret );
+ }
+});
+
+// Use of jQuery.browser is deprecated.
+// It's included for backwards compatibility and plugins,
+// although they should work to migrate away.
+
+var userAgent = navigator.userAgent.toLowerCase();
+
+// Figure out what browser is being used
+jQuery.browser = {
+ version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
+ safari: /webkit/.test( userAgent ),
+ opera: /opera/.test( userAgent ),
+ msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
+ mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
+};
+
+jQuery.each({
+ parent: function(elem){return elem.parentNode;},
+ parents: function(elem){return jQuery.dir(elem,"parentNode");},
+ next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
+ prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
+ nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
+ prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
+ siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
+ children: function(elem){return jQuery.sibling(elem.firstChild);},
+ contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
+}, function(name, fn){
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = jQuery.map( this, fn );
+
+ if ( selector && typeof selector == "string" )
+ ret = jQuery.multiFilter( selector, ret );
+
+ return this.pushStack( jQuery.unique( ret ), name, selector );
+ };
+});
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function(name, original){
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = [], insert = jQuery( selector );
+
+ for ( var i = 0, l = insert.length; i < l; i++ ) {
+ var elems = (i > 0 ? this.clone(true) : this).get();
+ jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
+ ret = ret.concat( elems );
+ }
+
+ return this.pushStack( ret, name, selector );
+ };
+});
+
+jQuery.each({
+ removeAttr: function( name ) {
+ jQuery.attr( this, name, "" );
+ if (this.nodeType == 1)
+ this.removeAttribute( name );
+ },
+
+ addClass: function( classNames ) {
+ jQuery.className.add( this, classNames );
+ },
+
+ removeClass: function( classNames ) {
+ jQuery.className.remove( this, classNames );
+ },
+
+ toggleClass: function( classNames, state ) {
+ if( typeof state !== "boolean" )
+ state = !jQuery.className.has( this, classNames );
+ jQuery.className[ state ? "add" : "remove" ]( this, classNames );
+ },
+
+ remove: function( selector ) {
+ if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
+ // Prevent memory leaks
+ jQuery( "*", this ).add([this]).each(function(){
+ jQuery.event.remove(this);
+ jQuery.removeData(this);
+ });
+ if (this.parentNode)
+ this.parentNode.removeChild( this );
+ }
+ },
+
+ empty: function() {
+ // Remove element nodes and prevent memory leaks
+ jQuery(this).children().remove();
+
+ // Remove any remaining nodes
+ while ( this.firstChild )
+ this.removeChild( this.firstChild );
+ }
+}, function(name, fn){
+ jQuery.fn[ name ] = function(){
+ return this.each( fn, arguments );
+ };
+});
+
+// Helper function used by the dimensions and offset modules
+function num(elem, prop) {
+ return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
+}
+var expando = "jQuery" + now(), uuid = 0, windowData = {};
+
+jQuery.extend({
+ cache: {},
+
+ data: function( elem, name, data ) {
+ elem = elem == window ?
+ windowData :
+ elem;
+
+ var id = elem[ expando ];
+
+ // Compute a unique ID for the element
+ if ( !id )
+ id = elem[ expando ] = ++uuid;
+
+ // Only generate the data cache if we're
+ // trying to access or manipulate it
+ if ( name && !jQuery.cache[ id ] )
+ jQuery.cache[ id ] = {};
+
+ // Prevent overriding the named cache with undefined values
+ if ( data !== undefined )
+ jQuery.cache[ id ][ name ] = data;
+
+ // Return the named cache data, or the ID for the element
+ return name ?
+ jQuery.cache[ id ][ name ] :
+ id;
+ },
+
+ removeData: function( elem, name ) {
+ elem = elem == window ?
+ windowData :
+ elem;
+
+ var id = elem[ expando ];
+
+ // If we want to remove a specific section of the element's data
+ if ( name ) {
+ if ( jQuery.cache[ id ] ) {
+ // Remove the section of cache data
+ delete jQuery.cache[ id ][ name ];
+
+ // If we've removed all the data, remove the element's cache
+ name = "";
+
+ for ( name in jQuery.cache[ id ] )
+ break;
+
+ if ( !name )
+ jQuery.removeData( elem );
+ }
+
+ // Otherwise, we want to remove all of the element's data
+ } else {
+ // Clean up the element expando
+ try {
+ delete elem[ expando ];
+ } catch(e){
+ // IE has trouble directly removing the expando
+ // but it's ok with using removeAttribute
+ if ( elem.removeAttribute )
+ elem.removeAttribute( expando );
+ }
+
+ // Completely remove the data cache
+ delete jQuery.cache[ id ];
+ }
+ },
+ queue: function( elem, type, data ) {
+ if ( elem ){
+
+ type = (type || "fx") + "queue";
+
+ var q = jQuery.data( elem, type );
+
+ if ( !q || jQuery.isArray(data) )
+ q = jQuery.data( elem, type, jQuery.makeArray(data) );
+ else if( data )
+ q.push( data );
+
+ }
+ return q;
+ },
+
+ dequeue: function( elem, type ){
+ var queue = jQuery.queue( elem, type ),
+ fn = queue.shift();
+
+ if( !type || type === "fx" )
+ fn = queue[0];
+
+ if( fn !== undefined )
+ fn.call(elem);
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ){
+ var parts = key.split(".");
+ parts[1] = parts[1] ? "." + parts[1] : "";
+
+ if ( value === undefined ) {
+ var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+ if ( data === undefined && this.length )
+ data = jQuery.data( this[0], key );
+
+ return data === undefined && parts[1] ?
+ this.data( parts[0] ) :
+ data;
+ } else
+ return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
+ jQuery.data( this, key, value );
+ });
+ },
+
+ removeData: function( key ){
+ return this.each(function(){
+ jQuery.removeData( this, key );
+ });
+ },
+ queue: function(type, data){
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ }
+
+ if ( data === undefined )
+ return jQuery.queue( this[0], type );
+
+ return this.each(function(){
+ var queue = jQuery.queue( this, type, data );
+
+ if( type == "fx" && queue.length == 1 )
+ queue[0].call(this);
+ });
+ },
+ dequeue: function(type){
+ return this.each(function(){
+ jQuery.dequeue( this, type );
+ });
+ }
+});/*!
+ * Sizzle CSS Selector Engine - v0.9.3
+ * Copyright 2009, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
+ done = 0,
+ toString = Object.prototype.toString;
+
+var Sizzle = function(selector, context, results, seed) {
+ results = results || [];
+ context = context || document;
+
+ if ( context.nodeType !== 1 && context.nodeType !== 9 )
+ return [];
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ var parts = [], m, set, checkSet, check, mode, extra, prune = true;
+
+ // Reset the position of the chunker regexp (start from head)
+ chunker.lastIndex = 0;
+
+ while ( (m = chunker.exec(selector)) !== null ) {
+ parts.push( m[1] );
+
+ if ( m[2] ) {
+ extra = RegExp.rightContext;
+ break;
+ }
+ }
+
+ if ( parts.length > 1 && origPOS.exec( selector ) ) {
+ if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+ set = posProcess( parts[0] + parts[1], context );
+ } else {
+ set = Expr.relative[ parts[0] ] ?
+ [ context ] :
+ Sizzle( parts.shift(), context );
+
+ while ( parts.length ) {
+ selector = parts.shift();
+
+ if ( Expr.relative[ selector ] )
+ selector += parts.shift();
+
+ set = posProcess( selector, set );
+ }
+ }
+ } else {
+ var ret = seed ?
+ { expr: parts.pop(), set: makeArray(seed) } :
+ Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
+ set = Sizzle.filter( ret.expr, ret.set );
+
+ if ( parts.length > 0 ) {
+ checkSet = makeArray(set);
+ } else {
+ prune = false;
+ }
+
+ while ( parts.length ) {
+ var cur = parts.pop(), pop = cur;
+
+ if ( !Expr.relative[ cur ] ) {
+ cur = "";
+ } else {
+ pop = parts.pop();
+ }
+
+ if ( pop == null ) {
+ pop = context;
+ }
+
+ Expr.relative[ cur ]( checkSet, pop, isXML(context) );
+ }
+ }
+
+ if ( !checkSet ) {
+ checkSet = set;
+ }
+
+ if ( !checkSet ) {
+ throw "Syntax error, unrecognized expression: " + (cur || selector);
+ }
+
+ if ( toString.call(checkSet) === "[object Array]" ) {
+ if ( !prune ) {
+ results.push.apply( results, checkSet );
+ } else if ( context.nodeType === 1 ) {
+ for ( var i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
+ results.push( set[i] );
+ }
+ }
+ } else {
+ for ( var i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+ results.push( set[i] );
+ }
+ }
+ }
+ } else {
+ makeArray( checkSet, results );
+ }
+
+ if ( extra ) {
+ Sizzle( extra, context, results, seed );
+
+ if ( sortOrder ) {
+ hasDuplicate = false;
+ results.sort(sortOrder);
+
+ if ( hasDuplicate ) {
+ for ( var i = 1; i < results.length; i++ ) {
+ if ( results[i] === results[i-1] ) {
+ results.splice(i--, 1);
+ }
+ }
+ }
+ }
+ }
+
+ return results;
+};
+
+Sizzle.matches = function(expr, set){
+ return Sizzle(expr, null, null, set);
+};
+
+Sizzle.find = function(expr, context, isXML){
+ var set, match;
+
+ if ( !expr ) {
+ return [];
+ }
+
+ for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+ var type = Expr.order[i], match;
+
+ if ( (match = Expr.match[ type ].exec( expr )) ) {
+ var left = RegExp.leftContext;
+
+ if ( left.substr( left.length - 1 ) !== "\\" ) {
+ match[1] = (match[1] || "").replace(/\\/g, "");
+ set = Expr.find[ type ]( match, context, isXML );
+ if ( set != null ) {
+ expr = expr.replace( Expr.match[ type ], "" );
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !set ) {
+ set = context.getElementsByTagName("*");
+ }
+
+ return {set: set, expr: expr};
+};
+
+Sizzle.filter = function(expr, set, inplace, not){
+ var old = expr, result = [], curLoop = set, match, anyFound,
+ isXMLFilter = set && set[0] && isXML(set[0]);
+
+ while ( expr && set.length ) {
+ for ( var type in Expr.filter ) {
+ if ( (match = Expr.match[ type ].exec( expr )) != null ) {
+ var filter = Expr.filter[ type ], found, item;
+ anyFound = false;
+
+ if ( curLoop == result ) {
+ result = [];
+ }
+
+ if ( Expr.preFilter[ type ] ) {
+ match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+ if ( !match ) {
+ anyFound = found = true;
+ } else if ( match === true ) {
+ continue;
+ }
+ }
+
+ if ( match ) {
+ for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+ if ( item ) {
+ found = filter( item, match, i, curLoop );
+ var pass = not ^ !!found;
+
+ if ( inplace && found != null ) {
+ if ( pass ) {
+ anyFound = true;
+ } else {
+ curLoop[i] = false;
+ }
+ } else if ( pass ) {
+ result.push( item );
+ anyFound = true;
+ }
+ }
+ }
+ }
+
+ if ( found !== undefined ) {
+ if ( !inplace ) {
+ curLoop = result;
+ }
+
+ expr = expr.replace( Expr.match[ type ], "" );
+
+ if ( !anyFound ) {
+ return [];
+ }
+
+ break;
+ }
+ }
+ }
+
+ // Improper expression
+ if ( expr == old ) {
+ if ( anyFound == null ) {
+ throw "Syntax error, unrecognized expression: " + expr;
+ } else {
+ break;
+ }
+ }
+
+ old = expr;
+ }
+
+ return curLoop;
+};
+
+var Expr = Sizzle.selectors = {
+ order: [ "ID", "NAME", "TAG" ],
+ match: {
+ ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+ CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+ NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
+ ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+ TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
+ CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
+ POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
+ PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
+ },
+ attrMap: {
+ "class": "className",
+ "for": "htmlFor"
+ },
+ attrHandle: {
+ href: function(elem){
+ return elem.getAttribute("href");
+ }
+ },
+ relative: {
+ "+": function(checkSet, part, isXML){
+ var isPartStr = typeof part === "string",
+ isTag = isPartStr && !/\W/.test(part),
+ isPartStrNotTag = isPartStr && !isTag;
+
+ if ( isTag && !isXML ) {
+ part = part.toUpperCase();
+ }
+
+ for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+ if ( (elem = checkSet[i]) ) {
+ while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+ checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
+ elem || false :
+ elem === part;
+ }
+ }
+
+ if ( isPartStrNotTag ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ },
+ ">": function(checkSet, part, isXML){
+ var isPartStr = typeof part === "string";
+
+ if ( isPartStr && !/\W/.test(part) ) {
+ part = isXML ? part : part.toUpperCase();
+
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ var parent = elem.parentNode;
+ checkSet[i] = parent.nodeName === part ? parent : false;
+ }
+ }
+ } else {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ checkSet[i] = isPartStr ?
+ elem.parentNode :
+ elem.parentNode === part;
+ }
+ }
+
+ if ( isPartStr ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ }
+ },
+ "": function(checkSet, part, isXML){
+ var doneName = done++, checkFn = dirCheck;
+
+ if ( !part.match(/\W/) ) {
+ var nodeCheck = part = isXML ? part : part.toUpperCase();
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
+ },
+ "~": function(checkSet, part, isXML){
+ var doneName = done++, checkFn = dirCheck;
+
+ if ( typeof part === "string" && !part.match(/\W/) ) {
+ var nodeCheck = part = isXML ? part : part.toUpperCase();
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
+ }
+ },
+ find: {
+ ID: function(match, context, isXML){
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ return m ? [m] : [];
+ }
+ },
+ NAME: function(match, context, isXML){
+ if ( typeof context.getElementsByName !== "undefined" ) {
+ var ret = [], results = context.getElementsByName(match[1]);
+
+ for ( var i = 0, l = results.length; i < l; i++ ) {
+ if ( results[i].getAttribute("name") === match[1] ) {
+ ret.push( results[i] );
+ }
+ }
+
+ return ret.length === 0 ? null : ret;
+ }
+ },
+ TAG: function(match, context){
+ return context.getElementsByTagName(match[1]);
+ }
+ },
+ preFilter: {
+ CLASS: function(match, curLoop, inplace, result, not, isXML){
+ match = " " + match[1].replace(/\\/g, "") + " ";
+
+ if ( isXML ) {
+ return match;
+ }
+
+ for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+ if ( elem ) {
+ if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
+ if ( !inplace )
+ result.push( elem );
+ } else if ( inplace ) {
+ curLoop[i] = false;
+ }
+ }
+ }
+
+ return false;
+ },
+ ID: function(match){
+ return match[1].replace(/\\/g, "");
+ },
+ TAG: function(match, curLoop){
+ for ( var i = 0; curLoop[i] === false; i++ ){}
+ return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
+ },
+ CHILD: function(match){
+ if ( match[1] == "nth" ) {
+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+ var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+ match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
+ !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+ // calculate the numbers (first)n+(last) including if they are negative
+ match[2] = (test[1] + (test[2] || 1)) - 0;
+ match[3] = test[3] - 0;
+ }
+
+ // TODO: Move to normal caching system
+ match[0] = done++;
+
+ return match;
+ },
+ ATTR: function(match, curLoop, inplace, result, not, isXML){
+ var name = match[1].replace(/\\/g, "");
+
+ if ( !isXML && Expr.attrMap[name] ) {
+ match[1] = Expr.attrMap[name];
+ }
+
+ if ( match[2] === "~=" ) {
+ match[4] = " " + match[4] + " ";
+ }
+
+ return match;
+ },
+ PSEUDO: function(match, curLoop, inplace, result, not){
+ if ( match[1] === "not" ) {
+ // If we're dealing with a complex expression, or a simple one
+ if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
+ match[3] = Sizzle(match[3], null, null, curLoop);
+ } else {
+ var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+ if ( !inplace ) {
+ result.push.apply( result, ret );
+ }
+ return false;
+ }
+ } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+ return true;
+ }
+
+ return match;
+ },
+ POS: function(match){
+ match.unshift( true );
+ return match;
+ }
+ },
+ filters: {
+ enabled: function(elem){
+ return elem.disabled === false && elem.type !== "hidden";
+ },
+ disabled: function(elem){
+ return elem.disabled === true;
+ },
+ checked: function(elem){
+ return elem.checked === true;
+ },
+ selected: function(elem){
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ elem.parentNode.selectedIndex;
+ return elem.selected === true;
+ },
+ parent: function(elem){
+ return !!elem.firstChild;
+ },
+ empty: function(elem){
+ return !elem.firstChild;
+ },
+ has: function(elem, i, match){
+ return !!Sizzle( match[3], elem ).length;
+ },
+ header: function(elem){
+ return /h\d/i.test( elem.nodeName );
+ },
+ text: function(elem){
+ return "text" === elem.type;
+ },
+ radio: function(elem){
+ return "radio" === elem.type;
+ },
+ checkbox: function(elem){
+ return "checkbox" === elem.type;
+ },
+ file: function(elem){
+ return "file" === elem.type;
+ },
+ password: function(elem){
+ return "password" === elem.type;
+ },
+ submit: function(elem){
+ return "submit" === elem.type;
+ },
+ image: function(elem){
+ return "image" === elem.type;
+ },
+ reset: function(elem){
+ return "reset" === elem.type;
+ },
+ button: function(elem){
+ return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
+ },
+ input: function(elem){
+ return /input|select|textarea|button/i.test(elem.nodeName);
+ }
+ },
+ setFilters: {
+ first: function(elem, i){
+ return i === 0;
+ },
+ last: function(elem, i, match, array){
+ return i === array.length - 1;
+ },
+ even: function(elem, i){
+ return i % 2 === 0;
+ },
+ odd: function(elem, i){
+ return i % 2 === 1;
+ },
+ lt: function(elem, i, match){
+ return i < match[3] - 0;
+ },
+ gt: function(elem, i, match){
+ return i > match[3] - 0;
+ },
+ nth: function(elem, i, match){
+ return match[3] - 0 == i;
+ },
+ eq: function(elem, i, match){
+ return match[3] - 0 == i;
+ }
+ },
+ filter: {
+ PSEUDO: function(elem, match, i, array){
+ var name = match[1], filter = Expr.filters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ } else if ( name === "contains" ) {
+ return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
+ } else if ( name === "not" ) {
+ var not = match[3];
+
+ for ( var i = 0, l = not.length; i < l; i++ ) {
+ if ( not[i] === elem ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ },
+ CHILD: function(elem, match){
+ var type = match[1], node = elem;
+ switch (type) {
+ case 'only':
+ case 'first':
+ while (node = node.previousSibling) {
+ if ( node.nodeType === 1 ) return false;
+ }
+ if ( type == 'first') return true;
+ node = elem;
+ case 'last':
+ while (node = node.nextSibling) {
+ if ( node.nodeType === 1 ) return false;
+ }
+ return true;
+ case 'nth':
+ var first = match[2], last = match[3];
+
+ if ( first == 1 && last == 0 ) {
+ return true;
+ }
+
+ var doneName = match[0],
+ parent = elem.parentNode;
+
+ if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
+ var count = 0;
+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
+ if ( node.nodeType === 1 ) {
+ node.nodeIndex = ++count;
+ }
+ }
+ parent.sizcache = doneName;
+ }
+
+ var diff = elem.nodeIndex - last;
+ if ( first == 0 ) {
+ return diff == 0;
+ } else {
+ return ( diff % first == 0 && diff / first >= 0 );
+ }
+ }
+ },
+ ID: function(elem, match){
+ return elem.nodeType === 1 && elem.getAttribute("id") === match;
+ },
+ TAG: function(elem, match){
+ return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
+ },
+ CLASS: function(elem, match){
+ return (" " + (elem.className || elem.getAttribute("class")) + " ")
+ .indexOf( match ) > -1;
+ },
+ ATTR: function(elem, match){
+ var name = match[1],
+ result = Expr.attrHandle[ name ] ?
+ Expr.attrHandle[ name ]( elem ) :
+ elem[ name ] != null ?
+ elem[ name ] :
+ elem.getAttribute( name ),
+ value = result + "",
+ type = match[2],
+ check = match[4];
+
+ return result == null ?
+ type === "!=" :
+ type === "=" ?
+ value === check :
+ type === "*=" ?
+ value.indexOf(check) >= 0 :
+ type === "~=" ?
+ (" " + value + " ").indexOf(check) >= 0 :
+ !check ?
+ value && result !== false :
+ type === "!=" ?
+ value != check :
+ type === "^=" ?
+ value.indexOf(check) === 0 :
+ type === "$=" ?
+ value.substr(value.length - check.length) === check :
+ type === "|=" ?
+ value === check || value.substr(0, check.length + 1) === check + "-" :
+ false;
+ },
+ POS: function(elem, match, i, array){
+ var name = match[2], filter = Expr.setFilters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ }
+ }
+ }
+};
+
+var origPOS = Expr.match.POS;
+
+for ( var type in Expr.match ) {
+ Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
+}
+
+var makeArray = function(array, results) {
+ array = Array.prototype.slice.call( array );
+
+ if ( results ) {
+ results.push.apply( results, array );
+ return results;
+ }
+
+ return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+try {
+ Array.prototype.slice.call( document.documentElement.childNodes );
+
+// Provide a fallback method if it does not work
+} catch(e){
+ makeArray = function(array, results) {
+ var ret = results || [];
+
+ if ( toString.call(array) === "[object Array]" ) {
+ Array.prototype.push.apply( ret, array );
+ } else {
+ if ( typeof array.length === "number" ) {
+ for ( var i = 0, l = array.length; i < l; i++ ) {
+ ret.push( array[i] );
+ }
+ } else {
+ for ( var i = 0; array[i]; i++ ) {
+ ret.push( array[i] );
+ }
+ }
+ }
+
+ return ret;
+ };
+}
+
+var sortOrder;
+
+if ( document.documentElement.compareDocumentPosition ) {
+ sortOrder = function( a, b ) {
+ var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
+ if ( ret === 0 ) {
+ hasDuplicate = true;
+ }
+ return ret;
+ };
+} else if ( "sourceIndex" in document.documentElement ) {
+ sortOrder = function( a, b ) {
+ var ret = a.sourceIndex - b.sourceIndex;
+ if ( ret === 0 ) {
+ hasDuplicate = true;
+ }
+ return ret;
+ };
+} else if ( document.createRange ) {
+ sortOrder = function( a, b ) {
+ var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
+ aRange.selectNode(a);
+ aRange.collapse(true);
+ bRange.selectNode(b);
+ bRange.collapse(true);
+ var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
+ if ( ret === 0 ) {
+ hasDuplicate = true;
+ }
+ return ret;
+ };
+}
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+ // We're going to inject a fake input element with a specified name
+ var form = document.createElement("form"),
+ id = "script" + (new Date).getTime();
+ form.innerHTML = "<input name='" + id + "'/>";
+
+ // Inject it into the root element, check its status, and remove it quickly
+ var root = document.documentElement;
+ root.insertBefore( form, root.firstChild );
+
+ // The workaround has to do additional checks after a getElementById
+ // Which slows things down for other browsers (hence the branching)
+ if ( !!document.getElementById( id ) ) {
+ Expr.find.ID = function(match, context, isXML){
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
+ }
+ };
+
+ Expr.filter.ID = function(elem, match){
+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+ return elem.nodeType === 1 && node && node.nodeValue === match;
+ };
+ }
+
+ root.removeChild( form );
+})();
+
+(function(){
+ // Check to see if the browser returns only elements
+ // when doing getElementsByTagName("*")
+
+ // Create a fake element
+ var div = document.createElement("div");
+ div.appendChild( document.createComment("") );
+
+ // Make sure no comments are found
+ if ( div.getElementsByTagName("*").length > 0 ) {
+ Expr.find.TAG = function(match, context){
+ var results = context.getElementsByTagName(match[1]);
+
+ // Filter out possible comments
+ if ( match[1] === "*" ) {
+ var tmp = [];
+
+ for ( var i = 0; results[i]; i++ ) {
+ if ( results[i].nodeType === 1 ) {
+ tmp.push( results[i] );
+ }
+ }
+
+ results = tmp;
+ }
+
+ return results;
+ };
+ }
+
+ // Check to see if an attribute returns normalized href attributes
+ div.innerHTML = "<a href='#'></a>";
+ if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+ div.firstChild.getAttribute("href") !== "#" ) {
+ Expr.attrHandle.href = function(elem){
+ return elem.getAttribute("href", 2);
+ };
+ }
+})();
+
+if ( document.querySelectorAll ) (function(){
+ var oldSizzle = Sizzle, div = document.createElement("div");
+ div.innerHTML = "<p class='TEST'></p>";
+
+ // Safari can't handle uppercase or unicode characters when
+ // in quirks mode.
+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+ return;
+ }
+
+ Sizzle = function(query, context, extra, seed){
+ context = context || document;
+
+ // Only use querySelectorAll on non-XML documents
+ // (ID selectors don't work in non-HTML documents)
+ if ( !seed && context.nodeType === 9 && !isXML(context) ) {
+ try {
+ return makeArray( context.querySelectorAll(query), extra );
+ } catch(e){}
+ }
+
+ return oldSizzle(query, context, extra, seed);
+ };
+
+ Sizzle.find = oldSizzle.find;
+ Sizzle.filter = oldSizzle.filter;
+ Sizzle.selectors = oldSizzle.selectors;
+ Sizzle.matches = oldSizzle.matches;
+})();
+
+if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
+ var div = document.createElement("div");
+ div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+ // Opera can't find a second classname (in 9.6)
+ if ( div.getElementsByClassName("e").length === 0 )
+ return;
+
+ // Safari caches class attributes, doesn't catch changes (in 3.2)
+ div.lastChild.className = "e";
+
+ if ( div.getElementsByClassName("e").length === 1 )
+ return;
+
+ Expr.order.splice(1, 0, "CLASS");
+ Expr.find.CLASS = function(match, context, isXML) {
+ if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+ return context.getElementsByClassName(match[1]);
+ }
+ };
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ var sibDir = dir == "previousSibling" && !isXML;
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ if ( sibDir && elem.nodeType === 1 ){
+ elem.sizcache = doneName;
+ elem.sizset = i;
+ }
+ elem = elem[dir];
+ var match = false;
+
+ while ( elem ) {
+ if ( elem.sizcache === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 && !isXML ){
+ elem.sizcache = doneName;
+ elem.sizset = i;
+ }
+
+ if ( elem.nodeName === cur ) {
+ match = elem;
+ break;
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ var sibDir = dir == "previousSibling" && !isXML;
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ if ( sibDir && elem.nodeType === 1 ) {
+ elem.sizcache = doneName;
+ elem.sizset = i;
+ }
+ elem = elem[dir];
+ var match = false;
+
+ while ( elem ) {
+ if ( elem.sizcache === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 ) {
+ if ( !isXML ) {
+ elem.sizcache = doneName;
+ elem.sizset = i;
+ }
+ if ( typeof cur !== "string" ) {
+ if ( elem === cur ) {
+ match = true;
+ break;
+ }
+
+ } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+ match = elem;
+ break;
+ }
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+var contains = document.compareDocumentPosition ? function(a, b){
+ return a.compareDocumentPosition(b) & 16;
+} : function(a, b){
+ return a !== b && (a.contains ? a.contains(b) : true);
+};
+
+var isXML = function(elem){
+ return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+ !!elem.ownerDocument && isXML( elem.ownerDocument );
+};
+
+var posProcess = function(selector, context){
+ var tmpSet = [], later = "", match,
+ root = context.nodeType ? [context] : context;
+
+ // Position selectors must be done after the filter
+ // And so must :not(positional) so we move all PSEUDOs to the end
+ while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+ later += match[0];
+ selector = selector.replace( Expr.match.PSEUDO, "" );
+ }
+
+ selector = Expr.relative[selector] ? selector + "*" : selector;
+
+ for ( var i = 0, l = root.length; i < l; i++ ) {
+ Sizzle( selector, root[i], tmpSet );
+ }
+
+ return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.filter = Sizzle.filter;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+
+Sizzle.selectors.filters.hidden = function(elem){
+ return elem.offsetWidth === 0 || elem.offsetHeight === 0;
+};
+
+Sizzle.selectors.filters.visible = function(elem){
+ return elem.offsetWidth > 0 || elem.offsetHeight > 0;
+};
+
+Sizzle.selectors.filters.animated = function(elem){
+ return jQuery.grep(jQuery.timers, function(fn){
+ return elem === fn.elem;
+ }).length;
+};
+
+jQuery.multiFilter = function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return Sizzle.matches(expr, elems);
+};
+
+jQuery.dir = function( elem, dir ){
+ var matched = [], cur = elem[dir];
+ while ( cur && cur != document ) {
+ if ( cur.nodeType == 1 )
+ matched.push( cur );
+ cur = cur[dir];
+ }
+ return matched;
+};
+
+jQuery.nth = function(cur, result, dir, elem){
+ result = result || 1;
+ var num = 0;
+
+ for ( ; cur; cur = cur[dir] )
+ if ( cur.nodeType == 1 && ++num == result )
+ break;
+
+ return cur;
+};
+
+jQuery.sibling = function(n, elem){
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType == 1 && n != elem )
+ r.push( n );
+ }
+
+ return r;
+};
+
+return;
+
+window.Sizzle = Sizzle;
+
+})();
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+ // Bind an event to an element
+ // Original by Dean Edwards
+ add: function(elem, types, handler, data) {
+ if ( elem.nodeType == 3 || elem.nodeType == 8 )
+ return;
+
+ // For whatever reason, IE has trouble passing the window object
+ // around, causing it to be cloned in the process
+ if ( elem.setInterval && elem != window )
+ elem = window;
+
+ // Make sure that the function being executed has a unique ID
+ if ( !handler.guid )
+ handler.guid = this.guid++;
+
+ // if data is passed, bind to handler
+ if ( data !== undefined ) {
+ // Create temporary function pointer to original handler
+ var fn = handler;
+
+ // Create unique handler function, wrapped around original handler
+ handler = this.proxy( fn );
+
+ // Store data in unique handler
+ handler.data = data;
+ }
+
+ // Init the element's event structure
+ var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+ handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
+ // Handle the second event of a trigger and when
+ // an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+ jQuery.event.handle.apply(arguments.callee.elem, arguments) :
+ undefined;
+ });
+ // Add elem as a property of the handle function
+ // This is to prevent a memory leak with non-native
+ // event in IE.
+ handle.elem = elem;
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ jQuery.each(types.split(/\s+/), function(index, type) {
+ // Namespaced event handlers
+ var namespaces = type.split(".");
+ type = namespaces.shift();
+ handler.type = namespaces.slice().sort().join(".");
+
+ // Get the current list of functions bound to this event
+ var handlers = events[type];
+
+ if ( jQuery.event.specialAll[type] )
+ jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
+
+ // Init the event handler queue
+ if (!handlers) {
+ handlers = events[type] = {};
+
+ // Check for a special event handler
+ // Only use addEventListener/attachEvent if the special
+ // events handler returns false
+ if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
+ // Bind the global event handler to the element
+ if (elem.addEventListener)
+ elem.addEventListener(type, handle, false);
+ else if (elem.attachEvent)
+ elem.attachEvent("on" + type, handle);
+ }
+ }
+
+ // Add the function to the element's handler list
+ handlers[handler.guid] = handler;
+
+ // Keep track of which events have been used, for global triggering
+ jQuery.event.global[type] = true;
+ });
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ guid: 1,
+ global: {},
+
+ // Detach an event or set of events from an element
+ remove: function(elem, types, handler) {
+ // don't do events on text and comment nodes
+ if ( elem.nodeType == 3 || elem.nodeType == 8 )
+ return;
+
+ var events = jQuery.data(elem, "events"), ret, index;
+
+ if ( events ) {
+ // Unbind all events for the element
+ if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
+ for ( var type in events )
+ this.remove( elem, type + (types || "") );
+ else {
+ // types is actually an event object here
+ if ( types.type ) {
+ handler = types.handler;
+ types = types.type;
+ }
+
+ // Handle multiple events seperated by a space
+ // jQuery(...).unbind("mouseover mouseout", fn);
+ jQuery.each(types.split(/\s+/), function(index, type){
+ // Namespaced event handlers
+ var namespaces = type.split(".");
+ type = namespaces.shift();
+ var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+ if ( events[type] ) {
+ // remove the given handler for the given type
+ if ( handler )
+ delete events[type][handler.guid];
+
+ // remove all handlers for the given type
+ else
+ for ( var handle in events[type] )
+ // Handle the removal of namespaced events
+ if ( namespace.test(events[type][handle].type) )
+ delete events[type][handle];
+
+ if ( jQuery.event.specialAll[type] )
+ jQuery.event.specialAll[type].teardown.call(elem, namespaces);
+
+ // remove generic event handler if no more handlers exist
+ for ( ret in events[type] ) break;
+ if ( !ret ) {
+ if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
+ if (elem.removeEventListener)
+ elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+ else if (elem.detachEvent)
+ elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+ }
+ ret = null;
+ delete events[type];
+ }
+ }
+ });
+ }
+
+ // Remove the expando if it's no longer used
+ for ( ret in events ) break;
+ if ( !ret ) {
+ var handle = jQuery.data( elem, "handle" );
+ if ( handle ) handle.elem = null;
+ jQuery.removeData( elem, "events" );
+ jQuery.removeData( elem, "handle" );
+ }
+ }
+ },
+
+ // bubbling is internal
+ trigger: function( event, data, elem, bubbling ) {
+ // Event object or event type
+ var type = event.type || event;
+
+ if( !bubbling ){
+ event = typeof event === "object" ?
+ // jQuery.Event object
+ event[expando] ? event :
+ // Object literal
+ jQuery.extend( jQuery.Event(type), event ) :
+ // Just the event type (string)
+ jQuery.Event(type);
+
+ if ( type.indexOf("!") >= 0 ) {
+ event.type = type = type.slice(0, -1);
+ event.exclusive = true;
+ }
+
+ // Handle a global trigger
+ if ( !elem ) {
+ // Don't bubble custom events when global (to avoid too much overhead)
+ event.stopPropagation();
+ // Only trigger if we've ever bound an event for it
+ if ( this.global[type] )
+ jQuery.each( jQuery.cache, function(){
+ if ( this.events && this.events[type] )
+ jQuery.event.trigger( event, data, this.handle.elem );
+ });
+ }
+
+ // Handle triggering a single element
+
+ // don't do events on text and comment nodes
+ if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
+ return undefined;
+
+ // Clean up in case it is reused
+ event.result = undefined;
+ event.target = elem;
+
+ // Clone the incoming data, if any
+ data = jQuery.makeArray(data);
+ data.unshift( event );
+ }
+
+ event.currentTarget = elem;
+
+ // Trigger the event, it is assumed that "handle" is a function
+ var handle = jQuery.data(elem, "handle");
+ if ( handle )
+ handle.apply( elem, data );
+
+ // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
+ if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+ event.result = false;
+
+ // Trigger the native events (except for clicks on links)
+ if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+ this.triggered = true;
+ try {
+ elem[ type ]();
+ // prevent IE from throwing an error for some hidden elements
+ } catch (e) {}
+ }
+
+ this.triggered = false;
+
+ if ( !event.isPropagationStopped() ) {
+ var parent = elem.parentNode || elem.ownerDocument;
+ if ( parent )
+ jQuery.event.trigger(event, data, parent, true);
+ }
+ },
+
+ handle: function(event) {
+ // returned undefined or false
+ var all, handlers;
+
+ event = arguments[0] = jQuery.event.fix( event || window.event );
+ event.currentTarget = this;
+
+ // Namespaced event handlers
+ var namespaces = event.type.split(".");
+ event.type = namespaces.shift();
+
+ // Cache this now, all = true means, any handler
+ all = !namespaces.length && !event.exclusive;
+
+ var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+ handlers = ( jQuery.data(this, "events") || {} )[event.type];
+
+ for ( var j in handlers ) {
+ var handler = handlers[j];
+
+ // Filter the functions by class
+ if ( all || namespace.test(handler.type) ) {
+ // Pass in a reference to the handler function itself
+ // So that we can later remove it
+ event.handler = handler;
+ event.data = handler.data;
+
+ var ret = handler.apply(this, arguments);
+
+ if( ret !== undefined ){
+ event.result = ret;
+ if ( ret === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+
+ if( event.isImmediatePropagationStopped() )
+ break;
+
+ }
+ }
+ },
+
+ props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+
+ fix: function(event) {
+ if ( event[expando] )
+ return event;
+
+ // store a copy of the original event object
+ // and "clone" to set read-only properties
+ var originalEvent = event;
+ event = jQuery.Event( originalEvent );
+
+ for ( var i = this.props.length, prop; i; ){
+ prop = this.props[ --i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Fix target property, if necessary
+ if ( !event.target )
+ event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+
+ // check if target is a textnode (safari)
+ if ( event.target.nodeType == 3 )
+ event.target = event.target.parentNode;
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && event.fromElement )
+ event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && event.clientX != null ) {
+ var doc = document.documentElement, body = document.body;
+ event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+ event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+ }
+
+ // Add which for key events
+ if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
+ event.which = event.charCode || event.keyCode;
+
+ // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+ if ( !event.metaKey && event.ctrlKey )
+ event.metaKey = event.ctrlKey;
+
+ // Add which for click: 1 == left; 2 == middle; 3 == right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && event.button )
+ event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+
+ return event;
+ },
+
+ proxy: function( fn, proxy ){
+ proxy = proxy || function(){ return fn.apply(this, arguments); };
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
+ // So proxy can be declared as an argument
+ return proxy;
+ },
+
+ special: {
+ ready: {
+ // Make sure the ready event is setup
+ setup: bindReady,
+ teardown: function() {}
+ }
+ },
+
+ specialAll: {
+ live: {
+ setup: function( selector, namespaces ){
+ jQuery.event.add( this, namespaces[0], liveHandler );
+ },
+ teardown: function( namespaces ){
+ if ( namespaces.length ) {
+ var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
+
+ jQuery.each( (jQuery.data(this, "events").live || {}), function(){
+ if ( name.test(this.type) )
+ remove++;
+ });
+
+ if ( remove < 1 )
+ jQuery.event.remove( this, namespaces[0], liveHandler );
+ }
+ }
+ }
+ }
+};
+
+jQuery.Event = function( src ){
+ // Allow instantiation without the 'new' keyword
+ if( !this.preventDefault )
+ return new jQuery.Event(src);
+
+ // Event object
+ if( src && src.type ){
+ this.originalEvent = src;
+ this.type = src.type;
+ // Event type
+ }else
+ this.type = src;
+
+ // timeStamp is buggy for some events on Firefox(#3843)
+ // So we won't rely on the native value
+ this.timeStamp = now();
+
+ // Mark it as fixed
+ this[expando] = true;
+};
+
+function returnFalse(){
+ return false;
+}
+function returnTrue(){
+ return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if( !e )
+ return;
+ // if preventDefault exists run it on the original event
+ if (e.preventDefault)
+ e.preventDefault();
+ // otherwise set the returnValue property of the original event to false (IE)
+ e.returnValue = false;
+ },
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
+
+ var e = this.originalEvent;
+ if( !e )
+ return;
+ // if stopPropagation exists run it on the original event
+ if (e.stopPropagation)
+ e.stopPropagation();
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation:function(){
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+};
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event) {
+ // Check if mouse(over|out) are still within the same parent element
+ var parent = event.relatedTarget;
+ // Traverse up the tree
+ while ( parent && parent != this )
+ try { parent = parent.parentNode; }
+ catch(e) { parent = this; }
+
+ if( parent != this ){
+ // set the correct event type
+ event.type = event.data;
+ // handle event if we actually just moused on to a non sub-element
+ jQuery.event.handle.apply( this, arguments );
+ }
+};
+
+jQuery.each({
+ mouseover: 'mouseenter',
+ mouseout: 'mouseleave'
+}, function( orig, fix ){
+ jQuery.event.special[ fix ] = {
+ setup: function(){
+ jQuery.event.add( this, orig, withinElement, fix );
+ },
+ teardown: function(){
+ jQuery.event.remove( this, orig, withinElement );
+ }
+ };
+});
+
+jQuery.fn.extend({
+ bind: function( type, data, fn ) {
+ return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+ jQuery.event.add( this, type, fn || data, fn && data );
+ });
+ },
+
+ one: function( type, data, fn ) {
+ var one = jQuery.event.proxy( fn || data, function(event) {
+ jQuery(this).unbind(event, one);
+ return (fn || data).apply( this, arguments );
+ });
+ return this.each(function(){
+ jQuery.event.add( this, type, one, fn && data);
+ });
+ },
+
+ unbind: function( type, fn ) {
+ return this.each(function(){
+ jQuery.event.remove( this, type, fn );
+ });
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function(){
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+
+ triggerHandler: function( type, data ) {
+ if( this[0] ){
+ var event = jQuery.Event(type);
+ event.preventDefault();
+ event.stopPropagation();
+ jQuery.event.trigger( event, data, this[0] );
+ return event.result;
+ }
+ },
+
+ toggle: function( fn ) {
+ // Save reference to arguments for access in closure
+ var args = arguments, i = 1;
+
+ // link all the functions, so any of them can unbind this click handler
+ while( i < args.length )
+ jQuery.event.proxy( fn, args[i++] );
+
+ return this.click( jQuery.event.proxy( fn, function(event) {
+ // Figure out which function to execute
+ this.lastToggle = ( this.lastToggle || 0 ) % i;
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ this.lastToggle++ ].apply( this, arguments ) || false;
+ }));
+ },
+
+ hover: function(fnOver, fnOut) {
+ return this.mouseenter(fnOver).mouseleave(fnOut);
+ },
+
+ ready: function(fn) {
+ // Attach the listeners
+ bindReady();
+
+ // If the DOM is already ready
+ if ( jQuery.isReady )
+ // Execute the function immediately
+ fn.call( document, jQuery );
+
+ // Otherwise, remember the function for later
+ else
+ // Add the function to the wait list
+ jQuery.readyList.push( fn );
+
+ return this;
+ },
+
+ live: function( type, fn ){
+ var proxy = jQuery.event.proxy( fn );
+ proxy.guid += this.selector + type;
+
+ jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
+
+ return this;
+ },
+
+ die: function( type, fn ){
+ jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
+ return this;
+ }
+});
+
+function liveHandler( event ){
+ var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
+ stop = true,
+ elems = [];
+
+ jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
+ if ( check.test(fn.type) ) {
+ var elem = jQuery(event.target).closest(fn.data)[0];
+ if ( elem )
+ elems.push({ elem: elem, fn: fn });
+ }
+ });
+
+ elems.sort(function(a,b) {
+ return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
+ });
+
+ jQuery.each(elems, function(){
+ if ( this.fn.call(this.elem, event, this.fn.data) === false )
+ return (stop = false);
+ });
+
+ return stop;
+}
+
+function liveConvert(type, selector){
+ return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
+}
+
+jQuery.extend({
+ isReady: false,
+ readyList: [],
+ // Handle when the DOM is ready
+ ready: function() {
+ // Make sure that the DOM is not already loaded
+ if ( !jQuery.isReady ) {
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If there are functions bound, to execute
+ if ( jQuery.readyList ) {
+ // Execute all of them
+ jQuery.each( jQuery.readyList, function(){
+ this.call( document, jQuery );
+ });
+
+ // Reset the list of functions
+ jQuery.readyList = null;
+ }
+
+ // Trigger any bound ready events
+ jQuery(document).triggerHandler("ready");
+ }
+ }
+});
+
+var readyBound = false;
+
+function bindReady(){
+ if ( readyBound ) return;
+ readyBound = true;
+
+ // Mozilla, Opera and webkit nightlies currently support this event
+ if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", function(){
+ document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
+ jQuery.ready();
+ }, false );
+
+ // If IE event model is used
+ } else if ( document.attachEvent ) {
+ // ensure firing before onload,
+ // maybe late but safe also for iframes
+ document.attachEvent("onreadystatechange", function(){
+ if ( document.readyState === "complete" ) {
+ document.detachEvent( "onreadystatechange", arguments.callee );
+ jQuery.ready();
+ }
+ });
+
+ // If IE and not an iframe
+ // continually check to see if the document is ready
+ if ( document.documentElement.doScroll && window == window.top ) (function(){
+ if ( jQuery.isReady ) return;
+
+ try {
+ // If IE is used, use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ document.documentElement.doScroll("left");
+ } catch( error ) {
+ setTimeout( arguments.callee, 0 );
+ return;
+ }
+
+ // and execute any waiting functions
+ jQuery.ready();
+ })();
+ }
+
+ // A fallback to window.onload, that will always work
+ jQuery.event.add( window, "load", jQuery.ready );
+}
+
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+ "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
+ "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
+
+ // Handle event binding
+ jQuery.fn[name] = function(fn){
+ return fn ? this.bind(name, fn) : this.trigger(name);
+ };
+});
+
+// Prevent memory leaks in IE
+// And prevent errors on refresh with events like mouseover in other browsers
+// Window isn't included so as not to unbind existing unload events
+jQuery( window ).bind( 'unload', function(){
+ for ( var id in jQuery.cache )
+ // Skip the window
+ if ( id != 1 && jQuery.cache[ id ].handle )
+ jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+});
+(function(){
+
+ jQuery.support = {};
+
+ var root = document.documentElement,
+ script = document.createElement("script"),
+ div = document.createElement("div"),
+ id = "script" + (new Date).getTime();
+
+ div.style.display = "none";
+ div.innerHTML = ' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
+
+ var all = div.getElementsByTagName("*"),
+ a = div.getElementsByTagName("a")[0];
+
+ // Can't get basic test support
+ if ( !all || !all.length || !a ) {
+ return;
+ }
+
+ jQuery.support = {
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: div.firstChild.nodeType == 3,
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that you can get all elements in an <object> element
+ // IE 7 always returns no results
+ objectAll: !!div.getElementsByTagName("object")[0]
+ .getElementsByTagName("*").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText insted)
+ style: /red/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: a.getAttribute("href") === "/a",
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ opacity: a.style.opacity === "0.5",
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Will be defined later
+ scriptEval: false,
+ noCloneEvent: true,
+ boxModel: null
+ };
+
+ script.type = "text/javascript";
+ try {
+ script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
+ } catch(e){}
+
+ root.insertBefore( script, root.firstChild );
+
+ // Make sure that the execution of code works by injecting a script
+ // tag with appendChild/createTextNode
+ // (IE doesn't support this, fails, and uses .text instead)
+ if ( window[ id ] ) {
+ jQuery.support.scriptEval = true;
+ delete window[ id ];
+ }
+
+ root.removeChild( script );
+
+ if ( div.attachEvent && div.fireEvent ) {
+ div.attachEvent("onclick", function(){
+ // Cloning a node shouldn't copy over any
+ // bound event handlers (IE does this)
+ jQuery.support.noCloneEvent = false;
+ div.detachEvent("onclick", arguments.callee);
+ });
+ div.cloneNode(true).fireEvent("onclick");
+ }
+
+ // Figure out if the W3C box model works as expected
+ // document.body must exist before we can do this
+ jQuery(function(){
+ var div = document.createElement("div");
+ div.style.width = div.style.paddingLeft = "1px";
+
+ document.body.appendChild( div );
+ jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+ document.body.removeChild( div ).style.display = 'none';
+ });
+})();
+
+var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
+
+jQuery.props = {
+ "for": "htmlFor",
+ "class": "className",
+ "float": styleFloat,
+ cssFloat: styleFloat,
+ styleFloat: styleFloat,
+ readonly: "readOnly",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ rowspan: "rowSpan",
+ tabindex: "tabIndex"
+};
+jQuery.fn.extend({
+ // Keep a copy of the old load
+ _load: jQuery.fn.load,
+
+ load: function( url, params, callback ) {
+ if ( typeof url !== "string" )
+ return this._load( url );
+
+ var off = url.indexOf(" ");
+ if ( off >= 0 ) {
+ var selector = url.slice(off, url.length);
+ url = url.slice(0, off);
+ }
+
+ // Default to a GET request
+ var type = "GET";
+
+ // If the second parameter was provided
+ if ( params )
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+ // We assume that it's the callback
+ callback = params;
+ params = null;
+
+ // Otherwise, build a param string
+ } else if( typeof params === "object" ) {
+ params = jQuery.param( params );
+ type = "POST";
+ }
+
+ var self = this;
+
+ // Request the remote document
+ jQuery.ajax({
+ url: url,
+ type: type,
+ dataType: "html",
+ data: params,
+ complete: function(res, status){
+ // If successful, inject the HTML into all the matched elements
+ if ( status == "success" || status == "notmodified" )
+ // See if a selector was specified
+ self.html( selector ?
+ // Create a dummy div to hold the results
+ jQuery("<div/>")
+ // inject the contents of the document in, removing the scripts
+ // to avoid any 'Permission Denied' errors in IE
+ .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+
+ // Locate the specified elements
+ .find(selector) :
+
+ // If not, just inject the full result
+ res.responseText );
+
+ if( callback )
+ self.each( callback, [res.responseText, status, res] );
+ }
+ });
+ return this;
+ },
+
+ serialize: function() {
+ return jQuery.param(this.serializeArray());
+ },
+ serializeArray: function() {
+ return this.map(function(){
+ return this.elements ? jQuery.makeArray(this.elements) : this;
+ })
+ .filter(function(){
+ return this.name && !this.disabled &&
+ (this.checked || /select|textarea/i.test(this.nodeName) ||
+ /text|hidden|password|search/i.test(this.type));
+ })
+ .map(function(i, elem){
+ var val = jQuery(this).val();
+ return val == null ? null :
+ jQuery.isArray(val) ?
+ jQuery.map( val, function(val, i){
+ return {name: elem.name, value: val};
+ }) :
+ {name: elem.name, value: val};
+ }).get();
+ }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
+ jQuery.fn[o] = function(f){
+ return this.bind(o, f);
+ };
+});
+
+var jsc = now();
+
+jQuery.extend({
+
+ get: function( url, data, callback, type ) {
+ // shift arguments if data argument was ommited
+ if ( jQuery.isFunction( data ) ) {
+ callback = data;
+ data = null;
+ }
+
+ return jQuery.ajax({
+ type: "GET",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get(url, null, callback, "script");
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get(url, data, callback, "json");
+ },
+
+ post: function( url, data, callback, type ) {
+ if ( jQuery.isFunction( data ) ) {
+ callback = data;
+ data = {};
+ }
+
+ return jQuery.ajax({
+ type: "POST",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+
+ ajaxSetup: function( settings ) {
+ jQuery.extend( jQuery.ajaxSettings, settings );
+ },
+
+ ajaxSettings: {
+ url: location.href,
+ global: true,
+ type: "GET",
+ contentType: "application/x-www-form-urlencoded",
+ processData: true,
+ async: true,
+ /*
+ timeout: 0,
+ data: null,
+ username: null,
+ password: null,
+ */
+ // Create the request object; Microsoft failed to properly
+ // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+ // This function can be overriden by calling jQuery.ajaxSetup
+ xhr:function(){
+ return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+ },
+ accepts: {
+ xml: "application/xml, text/xml",
+ html: "text/html",
+ script: "text/javascript, application/javascript",
+ json: "application/json, text/javascript",
+ text: "text/plain",
+ _default: "*/*"
+ }
+ },
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+
+ ajax: function( s ) {
+ // Extend the settings, but re-extend 's' so that it can be
+ // checked again later (in the test suite, specifically)
+ s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+
+ var jsonp, jsre = /=\?(&|$)/g, status, data,
+ type = s.type.toUpperCase();
+
+ // convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" )
+ s.data = jQuery.param(s.data);
+
+ // Handle JSONP Parameter Callbacks
+ if ( s.dataType == "jsonp" ) {
+ if ( type == "GET" ) {
+ if ( !s.url.match(jsre) )
+ s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+ } else if ( !s.data || !s.data.match(jsre) )
+ s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+ s.dataType = "json";
+ }
+
+ // Build temporary JSONP function
+ if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+ jsonp = "jsonp" + jsc++;
+
+ // Replace the =? sequence both in the query string and the data
+ if ( s.data )
+ s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+ s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+ // We need to make sure
+ // that a JSONP style response is executed properly
+ s.dataType = "script";
+
+ // Handle JSONP-style loading
+ window[ jsonp ] = function(tmp){
+ data = tmp;
+ success();
+ complete();
+ // Garbage collect
+ window[ jsonp ] = undefined;
+ try{ delete window[ jsonp ]; } catch(e){}
+ if ( head )
+ head.removeChild( script );
+ };
+ }
+
+ if ( s.dataType == "script" && s.cache == null )
+ s.cache = false;
+
+ if ( s.cache === false && type == "GET" ) {
+ var ts = now();
+ // try replacing _= if it is there
+ var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+ // if nothing was replaced, add timestamp to the end
+ s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+ }
+
+ // If data is available, append data to url for get requests
+ if ( s.data && type == "GET" ) {
+ s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+
+ // IE likes to send both get and post data, prevent this
+ s.data = null;
+ }
+
+ // Watch for a new set of requests
+ if ( s.global && ! jQuery.active++ )
+ jQuery.event.trigger( "ajaxStart" );
+
+ // Matches an absolute URL, and saves the domain
+ var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
+
+ // If we're requesting a remote document
+ // and trying to load JSON or Script with a GET
+ if ( s.dataType == "script" && type == "GET" && parts
+ && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
+
+ var head = document.getElementsByTagName("head")[0];
+ var script = document.createElement("script");
+ script.src = s.url;
+ if (s.scriptCharset)
+ script.charset = s.scriptCharset;
+
+ // Handle Script loading
+ if ( !jsonp ) {
+ var done = false;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function(){
+ if ( !done && (!this.readyState ||
+ this.readyState == "loaded" || this.readyState == "complete") ) {
+ done = true;
+ success();
+ complete();
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+ head.removeChild( script );
+ }
+ };
+ }
+
+ head.appendChild(script);
+
+ // We handle everything using the script element injection
+ return undefined;
+ }
+
+ var requestDone = false;
+
+ // Create the request object
+ var xhr = s.xhr();
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if( s.username )
+ xhr.open(type, s.url, s.async, s.username, s.password);
+ else
+ xhr.open(type, s.url, s.async);
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ // Set the correct header, if data is being sent
+ if ( s.data )
+ xhr.setRequestHeader("Content-Type", s.contentType);
+
+ // Set the If-Modified-Since header, if ifModified mode.
+ if ( s.ifModified )
+ xhr.setRequestHeader("If-Modified-Since",
+ jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+
+ // Set header so the called script knows that it's an XMLHttpRequest
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+
+ // Set the Accepts header for the server, depending on the dataType
+ xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+ s.accepts[ s.dataType ] + ", */*" :
+ s.accepts._default );
+ } catch(e){}
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active )
+ jQuery.event.trigger( "ajaxStop" );
+ // close opended socket
+ xhr.abort();
+ return false;
+ }
+
+ if ( s.global )
+ jQuery.event.trigger("ajaxSend", [xhr, s]);
+
+ // Wait for a response to come back
+ var onreadystatechange = function(isTimeout){
+ // The request was aborted, clear the interval and decrement jQuery.active
+ if (xhr.readyState == 0) {
+ if (ival) {
+ // clear poll interval
+ clearInterval(ival);
+ ival = null;
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active )
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ // The transfer is complete and the data is available, or the request timed out
+ } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
+ requestDone = true;
+
+ // clear poll interval
+ if (ival) {
+ clearInterval(ival);
+ ival = null;
+ }
+
+ status = isTimeout == "timeout" ? "timeout" :
+ !jQuery.httpSuccess( xhr ) ? "error" :
+ s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
+ "success";
+
+ if ( status == "success" ) {
+ // Watch for, and catch, XML document parse errors
+ try {
+ // process the data (runs the xml through httpData regardless of callback)
+ data = jQuery.httpData( xhr, s.dataType, s );
+ } catch(e) {
+ status = "parsererror";
+ }
+ }
+
+ // Make sure that the request was successful or notmodified
+ if ( status == "success" ) {
+ // Cache Last-Modified header, if ifModified mode.
+ var modRes;
+ try {
+ modRes = xhr.getResponseHeader("Last-Modified");
+ } catch(e) {} // swallow exception thrown by FF if header is not available
+
+ if ( s.ifModified && modRes )
+ jQuery.lastModified[s.url] = modRes;
+
+ // JSONP handles its own success callback
+ if ( !jsonp )
+ success();
+ } else
+ jQuery.handleError(s, xhr, status);
+
+ // Fire the complete handlers
+ complete();
+
+ if ( isTimeout )
+ xhr.abort();
+
+ // Stop memory leaks
+ if ( s.async )
+ xhr = null;
+ }
+ };
+
+ if ( s.async ) {
+ // don't attach the handler to the request, just poll it instead
+ var ival = setInterval(onreadystatechange, 13);
+
+ // Timeout checker
+ if ( s.timeout > 0 )
+ setTimeout(function(){
+ // Check to see if the request is still happening
+ if ( xhr && !requestDone )
+ onreadystatechange( "timeout" );
+ }, s.timeout);
+ }
+
+ // Send the data
+ try {
+ xhr.send(s.data);
+ } catch(e) {
+ jQuery.handleError(s, xhr, null, e);
+ }
+
+ // firefox 1.5 doesn't fire statechange for sync requests
+ if ( !s.async )
+ onreadystatechange();
+
+ function success(){
+ // If a local callback was specified, fire it and pass it the data
+ if ( s.success )
+ s.success( data, status );
+
+ // Fire the global callback
+ if ( s.global )
+ jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
+ }
+
+ function complete(){
+ // Process result
+ if ( s.complete )
+ s.complete(xhr, status);
+
+ // The request was completed
+ if ( s.global )
+ jQuery.event.trigger( "ajaxComplete", [xhr, s] );
+
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active )
+ jQuery.event.trigger( "ajaxStop" );
+ }
+
+ // return XMLHttpRequest to allow aborting the request etc.
+ return xhr;
+ },
+
+ handleError: function( s, xhr, status, e ) {
+ // If a local callback was specified, fire it
+ if ( s.error ) s.error( xhr, status, e );
+
+ // Fire the global callback
+ if ( s.global )
+ jQuery.event.trigger( "ajaxError", [xhr, s, e] );
+ },
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Determines if an XMLHttpRequest was successful or not
+ httpSuccess: function( xhr ) {
+ try {
+ // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+ return !xhr.status && location.protocol == "file:" ||
+ ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
+ } catch(e){}
+ return false;
+ },
+
+ // Determines if an XMLHttpRequest returns NotModified
+ httpNotModified: function( xhr, url ) {
+ try {
+ var xhrRes = xhr.getResponseHeader("Last-Modified");
+
+ // Firefox always returns 200. check Last-Modified date
+ return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
+ } catch(e){}
+ return false;
+ },
+
+ httpData: function( xhr, type, s ) {
+ var ct = xhr.getResponseHeader("content-type"),
+ xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
+ data = xml ? xhr.responseXML : xhr.responseText;
+
+ if ( xml && data.documentElement.tagName == "parsererror" )
+ throw "parsererror";
+
+ // Allow a pre-filtering function to sanitize the response
+ // s != null is checked to keep backwards compatibility
+ if( s && s.dataFilter )
+ data = s.dataFilter( data, type );
+
+ // The filter can actually parse the response
+ if( typeof data === "string" ){
+
+ // If the type is "script", eval it in global context
+ if ( type == "script" )
+ jQuery.globalEval( data );
+
+ // Get the JavaScript object, if JSON is used.
+ if ( type == "json" )
+ data = window["eval"]("(" + data + ")");
+ }
+
+ return data;
+ },
+
+ // Serialize an array of form elements or a set of
+ // key/values into a query string
+ param: function( a ) {
+ var s = [ ];
+
+ function add( key, value ){
+ s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
+ };
+
+ // If an array was passed in, assume that it is an array
+ // of form elements
+ if ( jQuery.isArray(a) || a.jquery )
+ // Serialize the form elements
+ jQuery.each( a, function(){
+ add( this.name, this.value );
+ });
+
+ // Otherwise, assume that it's an object of key/value pairs
+ else
+ // Serialize the key/values
+ for ( var j in a )
+ // If the value is an array then the key names need to be repeated
+ if ( jQuery.isArray(a[j]) )
+ jQuery.each( a[j], function(){
+ add( j, this );
+ });
+ else
+ add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
+
+ // Return the resulting serialization
+ return s.join("&").replace(/%20/g, "+");
+ }
+
+});
+var elemdisplay = {},
+ timerId,
+ fxAttrs = [
+ // height animations
+ [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+ // width animations
+ [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+ // opacity animations
+ [ "opacity" ]
+ ];
+
+function genFx( type, num ){
+ var obj = {};
+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
+ obj[ this ] = type;
+ });
+ return obj;
+}
+
+jQuery.fn.extend({
+ show: function(speed,callback){
+ if ( speed ) {
+ return this.animate( genFx("show", 3), speed, callback);
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ){
+ var old = jQuery.data(this[i], "olddisplay");
+
+ this[i].style.display = old || "";
+
+ if ( jQuery.css(this[i], "display") === "none" ) {
+ var tagName = this[i].tagName, display;
+
+ if ( elemdisplay[ tagName ] ) {
+ display = elemdisplay[ tagName ];
+ } else {
+ var elem = jQuery("<" + tagName + " />").appendTo("body");
+
+ display = elem.css("display");
+ if ( display === "none" )
+ display = "block";
+
+ elem.remove();
+
+ elemdisplay[ tagName ] = display;
+ }
+
+ jQuery.data(this[i], "olddisplay", display);
+ }
+ }
+
+ // Set the display of the elements in a second loop
+ // to avoid the constant reflow
+ for ( var i = 0, l = this.length; i < l; i++ ){
+ this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
+ }
+
+ return this;
+ }
+ },
+
+ hide: function(speed,callback){
+ if ( speed ) {
+ return this.animate( genFx("hide", 3), speed, callback);
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ){
+ var old = jQuery.data(this[i], "olddisplay");
+ if ( !old && old !== "none" )
+ jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
+ }
+
+ // Set the display of the elements in a second loop
+ // to avoid the constant reflow
+ for ( var i = 0, l = this.length; i < l; i++ ){
+ this[i].style.display = "none";
+ }
+
+ return this;
+ }
+ },
+
+ // Save the old toggle function
+ _toggle: jQuery.fn.toggle,
+
+ toggle: function( fn, fn2 ){
+ var bool = typeof fn === "boolean";
+
+ return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+ this._toggle.apply( this, arguments ) :
+ fn == null || bool ?
+ this.each(function(){
+ var state = bool ? fn : jQuery(this).is(":hidden");
+ jQuery(this)[ state ? "show" : "hide" ]();
+ }) :
+ this.animate(genFx("toggle", 3), fn, fn2);
+ },
+
+ fadeTo: function(speed,to,callback){
+ return this.animate({opacity: to}, speed, callback);
+ },
+
+ animate: function( prop, speed, easing, callback ) {
+ var optall = jQuery.speed(speed, easing, callback);
+
+ return this[ optall.queue === false ? "each" : "queue" ](function(){
+
+ var opt = jQuery.extend({}, optall), p,
+ hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
+ self = this;
+
+ for ( p in prop ) {
+ if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+ return opt.complete.call(this);
+
+ if ( ( p == "height" || p == "width" ) && this.style ) {
+ // Store display property
+ opt.display = jQuery.css(this, "display");
+
+ // Make sure that nothing sneaks out
+ opt.overflow = this.style.overflow;
+ }
+ }
+
+ if ( opt.overflow != null )
+ this.style.overflow = "hidden";
+
+ opt.curAnim = jQuery.extend({}, prop);
+
+ jQuery.each( prop, function(name, val){
+ var e = new jQuery.fx( self, opt, name );
+
+ if ( /toggle|show|hide/.test(val) )
+ e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+ else {
+ var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+ start = e.cur(true) || 0;
+
+ if ( parts ) {
+ var end = parseFloat(parts[2]),
+ unit = parts[3] || "px";
+
+ // We need to compute starting value
+ if ( unit != "px" ) {
+ self.style[ name ] = (end || 1) + unit;
+ start = ((end || 1) / e.cur(true)) * start;
+ self.style[ name ] = start + unit;
+ }
+
+ // If a +=/-= token was provided, we're doing a relative animation
+ if ( parts[1] )
+ end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+
+ e.custom( start, end, unit );
+ } else
+ e.custom( start, val, "" );
+ }
+ });
+
+ // For JS strict compliance
+ return true;
+ });
+ },
+
+ stop: function(clearQueue, gotoEnd){
+ var timers = jQuery.timers;
+
+ if (clearQueue)
+ this.queue([]);
+
+ this.each(function(){
+ // go in reverse order so anything added to the queue during the loop is ignored
+ for ( var i = timers.length - 1; i >= 0; i-- )
+ if ( timers[i].elem == this ) {
+ if (gotoEnd)
+ // force the next step to be the last
+ timers[i](true);
+ timers.splice(i, 1);
+ }
+ });
+
+ // start the next in the queue if the last step wasn't forced
+ if (!gotoEnd)
+ this.dequeue();
+
+ return this;
+ }
+
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx("show", 1),
+ slideUp: genFx("hide", 1),
+ slideToggle: genFx("toggle", 1),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" }
+}, function( name, props ){
+ jQuery.fn[ name ] = function( speed, callback ){
+ return this.animate( props, speed, callback );
+ };
+});
+
+jQuery.extend({
+
+ speed: function(speed, easing, fn) {
+ var opt = typeof speed === "object" ? speed : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
+
+ // Queueing
+ opt.old = opt.complete;
+ opt.complete = function(){
+ if ( opt.queue !== false )
+ jQuery(this).dequeue();
+ if ( jQuery.isFunction( opt.old ) )
+ opt.old.call( this );
+ };
+
+ return opt;
+ },
+
+ easing: {
+ linear: function( p, n, firstNum, diff ) {
+ return firstNum + diff * p;
+ },
+ swing: function( p, n, firstNum, diff ) {
+ return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+ }
+ },
+
+ timers: [],
+
+ fx: function( elem, options, prop ){
+ this.options = options;
+ this.elem = elem;
+ this.prop = prop;
+
+ if ( !options.orig )
+ options.orig = {};
+ }
+
+});
+
+jQuery.fx.prototype = {
+
+ // Simple function for setting a style value
+ update: function(){
+ if ( this.options.step )
+ this.options.step.call( this.elem, this.now, this );
+
+ (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+ // Set display property to block for height/width animations
+ if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
+ this.elem.style.display = "block";
+ },
+
+ // Get the current size
+ cur: function(force){
+ if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
+ return this.elem[ this.prop ];
+
+ var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+ return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+ },
+
+ // Start an animation from one number to another
+ custom: function(from, to, unit){
+ this.startTime = now();
+ this.start = from;
+ this.end = to;
+ this.unit = unit || this.unit || "px";
+ this.now = this.start;
+ this.pos = this.state = 0;
+
+ var self = this;
+ function t(gotoEnd){
+ return self.step(gotoEnd);
+ }
+
+ t.elem = this.elem;
+
+ if ( t() && jQuery.timers.push(t) && !timerId ) {
+ timerId = setInterval(function(){
+ var timers = jQuery.timers;
+
+ for ( var i = 0; i < timers.length; i++ )
+ if ( !timers[i]() )
+ timers.splice(i--, 1);
+
+ if ( !timers.length ) {
+ clearInterval( timerId );
+ timerId = undefined;
+ }
+ }, 13);
+ }
+ },
+
+ // Simple 'show' function
+ show: function(){
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+ this.options.show = true;
+
+ // Begin the animation
+ // Make sure that we start at a small width/height to avoid any
+ // flash of content
+ this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
+
+ // Start by showing the element
+ jQuery(this.elem).show();
+ },
+
+ // Simple 'hide' function
+ hide: function(){
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+ this.options.hide = true;
+
+ // Begin the animation
+ this.custom(this.cur(), 0);
+ },
+
+ // Each step of an animation
+ step: function(gotoEnd){
+ var t = now();
+
+ if ( gotoEnd || t >= this.options.duration + this.startTime ) {
+ this.now = this.end;
+ this.pos = this.state = 1;
+ this.update();
+
+ this.options.curAnim[ this.prop ] = true;
+
+ var done = true;
+ for ( var i in this.options.curAnim )
+ if ( this.options.curAnim[i] !== true )
+ done = false;
+
+ if ( done ) {
+ if ( this.options.display != null ) {
+ // Reset the overflow
+ this.elem.style.overflow = this.options.overflow;
+
+ // Reset the display
+ this.elem.style.display = this.options.display;
+ if ( jQuery.css(this.elem, "display") == "none" )
+ this.elem.style.display = "block";
+ }
+
+ // Hide the element if the "hide" operation was done
+ if ( this.options.hide )
+ jQuery(this.elem).hide();
+
+ // Reset the properties, if the item has been hidden or shown
+ if ( this.options.hide || this.options.show )
+ for ( var p in this.options.curAnim )
+ jQuery.attr(this.elem.style, p, this.options.orig[p]);
+
+ // Execute the complete function
+ this.options.complete.call( this.elem );
+ }
+
+ return false;
+ } else {
+ var n = t - this.startTime;
+ this.state = n / this.options.duration;
+
+ // Perform the easing function, defaults to swing
+ this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+ this.now = this.start + ((this.end - this.start) * this.pos);
+
+ // Perform the next step of the animation
+ this.update();
+ }
+
+ return true;
+ }
+
+};
+
+jQuery.extend( jQuery.fx, {
+ speeds:{
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+ },
+ step: {
+
+ opacity: function(fx){
+ jQuery.attr(fx.elem.style, "opacity", fx.now);
+ },
+
+ _default: function(fx){
+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
+ fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+ else
+ fx.elem[ fx.prop ] = fx.now;
+ }
+ }
+});
+if ( document.documentElement["getBoundingClientRect"] )
+ jQuery.fn.offset = function() {
+ if ( !this[0] ) return { top: 0, left: 0 };
+ if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+ var box = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
+ clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
+ top = box.top + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
+ left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
+ return { top: top, left: left };
+ };
+else
+ jQuery.fn.offset = function() {
+ if ( !this[0] ) return { top: 0, left: 0 };
+ if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+ jQuery.offset.initialized || jQuery.offset.initialize();
+
+ var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
+ doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
+ body = doc.body, defaultView = doc.defaultView,
+ prevComputedStyle = defaultView.getComputedStyle(elem, null),
+ top = elem.offsetTop, left = elem.offsetLeft;
+
+ while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+ computedStyle = defaultView.getComputedStyle(elem, null);
+ top -= elem.scrollTop, left -= elem.scrollLeft;
+ if ( elem === offsetParent ) {
+ top += elem.offsetTop, left += elem.offsetLeft;
+ if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
+ top += parseInt( computedStyle.borderTopWidth, 10) || 0,
+ left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+ prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
+ }
+ if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
+ top += parseInt( computedStyle.borderTopWidth, 10) || 0,
+ left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+ prevComputedStyle = computedStyle;
+ }
+
+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
+ top += body.offsetTop,
+ left += body.offsetLeft;
+
+ if ( prevComputedStyle.position === "fixed" )
+ top += Math.max(docElem.scrollTop, body.scrollTop),
+ left += Math.max(docElem.scrollLeft, body.scrollLeft);
+
+ return { top: top, left: left };
+ };
+
+jQuery.offset = {
+ initialize: function() {
+ if ( this.initialized ) return;
+ var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
+ html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
+
+ rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
+ for ( prop in rules ) container.style[prop] = rules[prop];
+
+ container.innerHTML = html;
+ body.insertBefore(container, body.firstChild);
+ innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
+
+ this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+ this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+
+ innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
+ this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+
+ body.style.marginTop = '1px';
+ this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
+ body.style.marginTop = bodyMarginTop;
+
+ body.removeChild(container);
+ this.initialized = true;
+ },
+
+ bodyOffset: function(body) {
+ jQuery.offset.initialized || jQuery.offset.initialize();
+ var top = body.offsetTop, left = body.offsetLeft;
+ if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
+ top += parseInt( jQuery.curCSS(body, 'marginTop', true), 10 ) || 0,
+ left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
+ return { top: top, left: left };
+ }
+};
+
+
+jQuery.fn.extend({
+ position: function() {
+ var left = 0, top = 0, results;
+
+ if ( this[0] ) {
+ // Get *real* offsetParent
+ var offsetParent = this.offsetParent(),
+
+ // Get correct offsets
+ offset = this.offset(),
+ parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+ // Subtract element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ offset.top -= num( this, 'marginTop' );
+ offset.left -= num( this, 'marginLeft' );
+
+ // Add offsetParent borders
+ parentOffset.top += num( offsetParent, 'borderTopWidth' );
+ parentOffset.left += num( offsetParent, 'borderLeftWidth' );
+
+ // Subtract the two offsets
+ results = {
+ top: offset.top - parentOffset.top,
+ left: offset.left - parentOffset.left
+ };
+ }
+
+ return results;
+ },
+
+ offsetParent: function() {
+ var offsetParent = this[0].offsetParent || document.body;
+ while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
+ offsetParent = offsetParent.offsetParent;
+ return jQuery(offsetParent);
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ['Left', 'Top'], function(i, name) {
+ var method = 'scroll' + name;
+
+ jQuery.fn[ method ] = function(val) {
+ if (!this[0]) return null;
+
+ return val !== undefined ?
+
+ // Set the scroll offset
+ this.each(function() {
+ this == window || this == document ?
+ window.scrollTo(
+ !i ? val : jQuery(window).scrollLeft(),
+ i ? val : jQuery(window).scrollTop()
+ ) :
+ this[ method ] = val;
+ }) :
+
+ // Return the scroll offset
+ this[0] == window || this[0] == document ?
+ self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
+ jQuery.boxModel && document.documentElement[ method ] ||
+ document.body[ method ] :
+ this[0][ method ];
+ };
+});
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function(i, name){
+
+ var tl = i ? "Left" : "Top", // top or left
+ br = i ? "Right" : "Bottom", // bottom or right
+ lower = name.toLowerCase();
+
+ // innerHeight and innerWidth
+ jQuery.fn["inner" + name] = function(){
+ return this[0] ?
+ jQuery.css( this[0], lower, false, "padding" ) :
+ null;
+ };
+
+ // outerHeight and outerWidth
+ jQuery.fn["outer" + name] = function(margin) {
+ return this[0] ?
+ jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
+ null;
+ };
+
+ var type = name.toLowerCase();
+
+ jQuery.fn[ type ] = function( size ) {
+ // Get window width or height
+ return this[0] == window ?
+ // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+ document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
+ document.body[ "client" + name ] :
+
+ // Get document width or height
+ this[0] == document ?
+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+ Math.max(
+ document.documentElement["client" + name],
+ document.body["scroll" + name], document.documentElement["scroll" + name],
+ document.body["offset" + name], document.documentElement["offset" + name]
+ ) :
+
+ // Get or set width or height on the element
+ size === undefined ?
+ // Get width or height on the element
+ (this.length ? jQuery.css( this[0], type ) : null) :
+
+ // Set the width or height on the element (default to pixels if value is unitless)
+ this.css( type, typeof size === "string" ? size : size + "px" );
+ };
+
+});
+})();
diff --git a/config/snort-dev/javascript/jquery.blockUI.js b/config/snort-dev/javascript/jquery.blockUI.js
index 99e7211d..57318334 100644
--- a/config/snort-dev/javascript/jquery.blockUI.js
+++ b/config/snort-dev/javascript/jquery.blockUI.js
@@ -1,463 +1,463 @@
-/*!
- * jQuery blockUI plugin
- * Version 2.26 (09-SEP-2009)
- * @requires jQuery v1.2.3 or later
- *
- * Examples at: http://malsup.com/jquery/block/
- * Copyright (c) 2007-2008 M. Alsup
- * Dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- *
- * Thanks to Amir-Hossein Sobhi for some excellent contributions!
- */
-
-;(function($) {
-
-if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) {
- alert('blockUI requires jQuery v1.2.3 or later! You are using v' + $.fn.jquery);
- return;
-}
-
-$.fn._fadeIn = $.fn.fadeIn;
-
-// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
-// retarded userAgent strings on Vista)
-var mode = document.documentMode || 0;
-var setExpr = $.browser.msie && (($.browser.version < 8 && !mode) || mode < 8);
-var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent) && !mode;
-
-// global $ methods for blocking/unblocking the entire page
-$.blockUI = function(opts) { install(window, opts); };
-$.unblockUI = function(opts) { remove(window, opts); };
-
-// convenience method for quick growl-like notifications (http://www.google.com/search?q=growl)
-$.growlUI = function(title, message, timeout, onClose) {
- var $m = $('<div class="growlUI"></div>');
- if (title) $m.append('<h1>'+title+'</h1>');
- if (message) $m.append('<h2>'+message+'</h2>');
- if (timeout == undefined) timeout = 3000;
- $.blockUI({
- message: $m, fadeIn: 700, fadeOut: 1000, centerY: false,
- timeout: timeout, showOverlay: false,
- onUnblock: onClose,
- css: $.blockUI.defaults.growlCSS
- });
-};
-
-// plugin method for blocking element content
-$.fn.block = function(opts) {
- return this.unblock({ fadeOut: 0 }).each(function() {
- if ($.css(this,'position') == 'static')
- this.style.position = 'relative';
- if ($.browser.msie)
- this.style.zoom = 1; // force 'hasLayout'
- install(this, opts);
- });
-};
-
-// plugin method for unblocking element content
-$.fn.unblock = function(opts) {
- return this.each(function() {
- remove(this, opts);
- });
-};
-
-$.blockUI.version = 2.26; // 2nd generation blocking at no extra cost!
-
-// override these in your code to change the default behavior and style
-$.blockUI.defaults = {
- // message displayed when blocking (use null for no message)
- message: '<h1>Please wait...</h1>',
-
- title: null, // title string; only used when theme == true
- draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded)
-
- theme: false, // set to true to use with jQuery UI themes
-
- // styles for the message when blocking; if you wish to disable
- // these and use an external stylesheet then do this in your code:
- // $.blockUI.defaults.css = {};
- css: {
- padding: 0,
- margin: 0,
- width: '30%',
- top: '40%',
- left: '35%',
- textAlign: 'center',
- color: '#000',
- border: '3px solid #aaa',
- backgroundColor:'#fff',
- cursor: 'wait'
- },
-
- // minimal style set used when themes are used
- themedCSS: {
- width: '30%',
- top: '40%',
- left: '35%'
- },
-
- // styles for the overlay
- overlayCSS: {
- backgroundColor: '#000',
- opacity: 0.6,
- cursor: 'wait'
- },
-
- // styles applied when using $.growlUI
- growlCSS: {
- width: '350px',
- top: '10px',
- left: '',
- right: '10px',
- border: 'none',
- padding: '5px',
- opacity: 0.6,
- cursor: 'default',
- color: '#fff',
- backgroundColor: '#000',
- '-webkit-border-radius': '10px',
- '-moz-border-radius': '10px'
- },
-
- // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
- // (hat tip to Jorge H. N. de Vasconcelos)
- iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',
-
- // force usage of iframe in non-IE browsers (handy for blocking applets)
- forceIframe: false,
-
- // z-index for the blocking overlay
- baseZ: 1000,
-
- // set these to true to have the message automatically centered
- centerX: true, // <-- only effects element blocking (page block controlled via css above)
- centerY: true,
-
- // allow body element to be stetched in ie6; this makes blocking look better
- // on "short" pages. disable if you wish to prevent changes to the body height
- allowBodyStretch: true,
-
- // enable if you want key and mouse events to be disabled for content that is blocked
- bindEvents: true,
-
- // be default blockUI will supress tab navigation from leaving blocking content
- // (if bindEvents is true)
- constrainTabKey: true,
-
- // fadeIn time in millis; set to 0 to disable fadeIn on block
- fadeIn: 200,
-
- // fadeOut time in millis; set to 0 to disable fadeOut on unblock
- fadeOut: 400,
-
- // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
- timeout: 0,
-
- // disable if you don't want to show the overlay
- showOverlay: true,
-
- // if true, focus will be placed in the first available input field when
- // page blocking
- focusInput: true,
-
- // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
- applyPlatformOpacityRules: true,
-
- // callback method invoked when unblocking has completed; the callback is
- // passed the element that has been unblocked (which is the window object for page
- // blocks) and the options that were passed to the unblock call:
- // onUnblock(element, options)
- onUnblock: null,
-
- // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
- quirksmodeOffsetHack: 4
-};
-
-// private data and functions follow...
-
-var pageBlock = null;
-var pageBlockEls = [];
-
-function install(el, opts) {
- var full = (el == window);
- var msg = opts && opts.message !== undefined ? opts.message : undefined;
- opts = $.extend({}, $.blockUI.defaults, opts || {});
- opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
- var css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
- var themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
- msg = msg === undefined ? opts.message : msg;
-
- // remove the current block (if there is one)
- if (full && pageBlock)
- remove(window, {fadeOut:0});
-
- // if an existing element is being used as the blocking content then we capture
- // its current place in the DOM (and current display style) so we can restore
- // it when we unblock
- if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
- var node = msg.jquery ? msg[0] : msg;
- var data = {};
- $(el).data('blockUI.history', data);
- data.el = node;
- data.parent = node.parentNode;
- data.display = node.style.display;
- data.position = node.style.position;
- if (data.parent)
- data.parent.removeChild(node);
- }
-
- var z = opts.baseZ;
-
- // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
- // layer1 is the iframe layer which is used to supress bleed through of underlying content
- // layer2 is the overlay layer which has opacity and a wait cursor (by default)
- // layer3 is the message content that is displayed while blocking
-
- var lyr1 = ($.browser.msie || opts.forceIframe)
- ? $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>')
- : $('<div class="blockUI" style="display:none"></div>');
- var lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
-
- var lyr3;
- if (opts.theme && full) {
- var s = '<div class="blockUI blockMsg blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+z+';display:none;position:fixed">' +
- '<div class="ui-widget-header ui-dialog-titlebar blockTitle">'+(opts.title || '&nbsp;')+'</div>' +
- '<div class="ui-widget-content ui-dialog-content"></div>' +
- '</div>';
- lyr3 = $(s);
- }
- else {
- lyr3 = full ? $('<div class="blockUI blockMsg blockPage" style="z-index:'+z+';display:none;position:fixed"></div>')
- : $('<div class="blockUI blockMsg blockElement" style="z-index:'+z+';display:none;position:absolute"></div>');
- }
-
- // if we have a message, style it
- if (msg) {
- if (opts.theme) {
- lyr3.css(themedCSS);
- lyr3.addClass('ui-widget-content');
- }
- else
- lyr3.css(css);
- }
-
- // style the overlay
- if (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform)))
- lyr2.css(opts.overlayCSS);
- lyr2.css('position', full ? 'fixed' : 'absolute');
-
- // make iframe layer transparent in IE
- if ($.browser.msie || opts.forceIframe)
- lyr1.css('opacity',0.0);
-
- $([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
-
- if (opts.theme && opts.draggable && $.fn.draggable) {
- lyr3.draggable({
- handle: '.ui-dialog-titlebar',
- cancel: 'li'
- });
- }
-
- // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
- var expr = setExpr && (!$.boxModel || $('object,embed', full ? null : el).length > 0);
- if (ie6 || expr) {
- // give body 100% height
- if (full && opts.allowBodyStretch && $.boxModel)
- $('html,body').css('height','100%');
-
- // fix ie6 issue when blocked element has a border width
- if ((ie6 || !$.boxModel) && !full) {
- var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
- var fixT = t ? '(0 - '+t+')' : 0;
- var fixL = l ? '(0 - '+l+')' : 0;
- }
-
- // simulate fixed position
- $.each([lyr1,lyr2,lyr3], function(i,o) {
- var s = o[0].style;
- s.position = 'absolute';
- if (i < 2) {
- full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"')
- : s.setExpression('height','this.parentNode.offsetHeight + "px"');
- full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')
- : s.setExpression('width','this.parentNode.offsetWidth + "px"');
- if (fixL) s.setExpression('left', fixL);
- if (fixT) s.setExpression('top', fixT);
- }
- else if (opts.centerY) {
- if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
- s.marginTop = 0;
- }
- else if (!opts.centerY && full) {
- var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0;
- var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
- s.setExpression('top',expression);
- }
- });
- }
-
- // show the message
- if (msg) {
- if (opts.theme)
- lyr3.find('.ui-widget-content').append(msg);
- else
- lyr3.append(msg);
- if (msg.jquery || msg.nodeType)
- $(msg).show();
- }
-
- if (($.browser.msie || opts.forceIframe) && opts.showOverlay)
- lyr1.show(); // opacity is zero
- if (opts.fadeIn) {
- if (opts.showOverlay)
- lyr2._fadeIn(opts.fadeIn);
- if (msg)
- lyr3.fadeIn(opts.fadeIn);
- }
- else {
- if (opts.showOverlay)
- lyr2.show();
- if (msg)
- lyr3.show();
- }
-
- // bind key and mouse events
- bind(1, el, opts);
-
- if (full) {
- pageBlock = lyr3[0];
- pageBlockEls = $(':input:enabled:visible',pageBlock);
- if (opts.focusInput)
- setTimeout(focus, 20);
- }
- else
- center(lyr3[0], opts.centerX, opts.centerY);
-
- if (opts.timeout) {
- // auto-unblock
- var to = setTimeout(function() {
- full ? $.unblockUI(opts) : $(el).unblock(opts);
- }, opts.timeout);
- $(el).data('blockUI.timeout', to);
- }
-};
-
-// remove the block
-function remove(el, opts) {
- var full = (el == window);
- var $el = $(el);
- var data = $el.data('blockUI.history');
- var to = $el.data('blockUI.timeout');
- if (to) {
- clearTimeout(to);
- $el.removeData('blockUI.timeout');
- }
- opts = $.extend({}, $.blockUI.defaults, opts || {});
- bind(0, el, opts); // unbind events
-
- var els;
- if (full) // crazy selector to handle odd field errors in ie6/7
- els = $('body').children().filter('.blockUI').add('body > .blockUI');
- else
- els = $('.blockUI', el);
-
- if (full)
- pageBlock = pageBlockEls = null;
-
- if (opts.fadeOut) {
- els.fadeOut(opts.fadeOut);
- setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
- }
- else
- reset(els, data, opts, el);
-};
-
-// move blocking element back into the DOM where it started
-function reset(els,data,opts,el) {
- els.each(function(i,o) {
- // remove via DOM calls so we don't lose event handlers
- if (this.parentNode)
- this.parentNode.removeChild(this);
- });
-
- if (data && data.el) {
- data.el.style.display = data.display;
- data.el.style.position = data.position;
- if (data.parent)
- data.parent.appendChild(data.el);
- $(data.el).removeData('blockUI.history');
- }
-
- if (typeof opts.onUnblock == 'function')
- opts.onUnblock(el,opts);
-};
-
-// bind/unbind the handler
-function bind(b, el, opts) {
- var full = el == window, $el = $(el);
-
- // don't bother unbinding if there is nothing to unbind
- if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
- return;
- if (!full)
- $el.data('blockUI.isBlocked', b);
-
- // don't bind events when overlay is not in use or if bindEvents is false
- if (!opts.bindEvents || (b && !opts.showOverlay))
- return;
-
- // bind anchors and inputs for mouse and key events
- var events = 'mousedown mouseup keydown keypress';
- b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler);
-
-// former impl...
-// var $e = $('a,:input');
-// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
-};
-
-// event handler to suppress keyboard/mouse events when blocking
-function handler(e) {
- // allow tab navigation (conditionally)
- if (e.keyCode && e.keyCode == 9) {
- if (pageBlock && e.data.constrainTabKey) {
- var els = pageBlockEls;
- var fwd = !e.shiftKey && e.target == els[els.length-1];
- var back = e.shiftKey && e.target == els[0];
- if (fwd || back) {
- setTimeout(function(){focus(back)},10);
- return false;
- }
- }
- }
- // allow events within the message content
- if ($(e.target).parents('div.blockMsg').length > 0)
- return true;
-
- // allow events for content that is not being blocked
- return $(e.target).parents().children().filter('div.blockUI').length == 0;
-};
-
-function focus(back) {
- if (!pageBlockEls)
- return;
- var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
- if (e)
- e.focus();
-};
-
-function center(el, x, y) {
- var p = el.parentNode, s = el.style;
- var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
- var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
- if (x) s.left = l > 0 ? (l+'px') : '0';
- if (y) s.top = t > 0 ? (t+'px') : '0';
-};
-
-function sz(el, p) {
- return parseInt($.css(el,p))||0;
-};
-
-})(jQuery);
+/*!
+ * jQuery blockUI plugin
+ * Version 2.26 (09-SEP-2009)
+ * @requires jQuery v1.2.3 or later
+ *
+ * Examples at: http://malsup.com/jquery/block/
+ * Copyright (c) 2007-2008 M. Alsup
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Thanks to Amir-Hossein Sobhi for some excellent contributions!
+ */
+
+;(function($) {
+
+if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) {
+ alert('blockUI requires jQuery v1.2.3 or later! You are using v' + $.fn.jquery);
+ return;
+}
+
+$.fn._fadeIn = $.fn.fadeIn;
+
+// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
+// retarded userAgent strings on Vista)
+var mode = document.documentMode || 0;
+var setExpr = $.browser.msie && (($.browser.version < 8 && !mode) || mode < 8);
+var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent) && !mode;
+
+// global $ methods for blocking/unblocking the entire page
+$.blockUI = function(opts) { install(window, opts); };
+$.unblockUI = function(opts) { remove(window, opts); };
+
+// convenience method for quick growl-like notifications (http://www.google.com/search?q=growl)
+$.growlUI = function(title, message, timeout, onClose) {
+ var $m = $('<div class="growlUI"></div>');
+ if (title) $m.append('<h1>'+title+'</h1>');
+ if (message) $m.append('<h2>'+message+'</h2>');
+ if (timeout == undefined) timeout = 3000;
+ $.blockUI({
+ message: $m, fadeIn: 700, fadeOut: 1000, centerY: false,
+ timeout: timeout, showOverlay: false,
+ onUnblock: onClose,
+ css: $.blockUI.defaults.growlCSS
+ });
+};
+
+// plugin method for blocking element content
+$.fn.block = function(opts) {
+ return this.unblock({ fadeOut: 0 }).each(function() {
+ if ($.css(this,'position') == 'static')
+ this.style.position = 'relative';
+ if ($.browser.msie)
+ this.style.zoom = 1; // force 'hasLayout'
+ install(this, opts);
+ });
+};
+
+// plugin method for unblocking element content
+$.fn.unblock = function(opts) {
+ return this.each(function() {
+ remove(this, opts);
+ });
+};
+
+$.blockUI.version = 2.26; // 2nd generation blocking at no extra cost!
+
+// override these in your code to change the default behavior and style
+$.blockUI.defaults = {
+ // message displayed when blocking (use null for no message)
+ message: '<h1>Please wait...</h1>',
+
+ title: null, // title string; only used when theme == true
+ draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded)
+
+ theme: false, // set to true to use with jQuery UI themes
+
+ // styles for the message when blocking; if you wish to disable
+ // these and use an external stylesheet then do this in your code:
+ // $.blockUI.defaults.css = {};
+ css: {
+ padding: 0,
+ margin: 0,
+ width: '30%',
+ top: '40%',
+ left: '35%',
+ textAlign: 'center',
+ color: '#000',
+ border: '3px solid #aaa',
+ backgroundColor:'#fff',
+ cursor: 'wait'
+ },
+
+ // minimal style set used when themes are used
+ themedCSS: {
+ width: '30%',
+ top: '40%',
+ left: '35%'
+ },
+
+ // styles for the overlay
+ overlayCSS: {
+ backgroundColor: '#000',
+ opacity: 0.6,
+ cursor: 'wait'
+ },
+
+ // styles applied when using $.growlUI
+ growlCSS: {
+ width: '350px',
+ top: '10px',
+ left: '',
+ right: '10px',
+ border: 'none',
+ padding: '5px',
+ opacity: 0.6,
+ cursor: 'default',
+ color: '#fff',
+ backgroundColor: '#000',
+ '-webkit-border-radius': '10px',
+ '-moz-border-radius': '10px'
+ },
+
+ // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
+ // (hat tip to Jorge H. N. de Vasconcelos)
+ iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',
+
+ // force usage of iframe in non-IE browsers (handy for blocking applets)
+ forceIframe: false,
+
+ // z-index for the blocking overlay
+ baseZ: 1000,
+
+ // set these to true to have the message automatically centered
+ centerX: true, // <-- only effects element blocking (page block controlled via css above)
+ centerY: true,
+
+ // allow body element to be stetched in ie6; this makes blocking look better
+ // on "short" pages. disable if you wish to prevent changes to the body height
+ allowBodyStretch: true,
+
+ // enable if you want key and mouse events to be disabled for content that is blocked
+ bindEvents: true,
+
+ // be default blockUI will supress tab navigation from leaving blocking content
+ // (if bindEvents is true)
+ constrainTabKey: true,
+
+ // fadeIn time in millis; set to 0 to disable fadeIn on block
+ fadeIn: 200,
+
+ // fadeOut time in millis; set to 0 to disable fadeOut on unblock
+ fadeOut: 400,
+
+ // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
+ timeout: 0,
+
+ // disable if you don't want to show the overlay
+ showOverlay: true,
+
+ // if true, focus will be placed in the first available input field when
+ // page blocking
+ focusInput: true,
+
+ // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
+ applyPlatformOpacityRules: true,
+
+ // callback method invoked when unblocking has completed; the callback is
+ // passed the element that has been unblocked (which is the window object for page
+ // blocks) and the options that were passed to the unblock call:
+ // onUnblock(element, options)
+ onUnblock: null,
+
+ // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
+ quirksmodeOffsetHack: 4
+};
+
+// private data and functions follow...
+
+var pageBlock = null;
+var pageBlockEls = [];
+
+function install(el, opts) {
+ var full = (el == window);
+ var msg = opts && opts.message !== undefined ? opts.message : undefined;
+ opts = $.extend({}, $.blockUI.defaults, opts || {});
+ opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
+ var css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
+ var themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
+ msg = msg === undefined ? opts.message : msg;
+
+ // remove the current block (if there is one)
+ if (full && pageBlock)
+ remove(window, {fadeOut:0});
+
+ // if an existing element is being used as the blocking content then we capture
+ // its current place in the DOM (and current display style) so we can restore
+ // it when we unblock
+ if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
+ var node = msg.jquery ? msg[0] : msg;
+ var data = {};
+ $(el).data('blockUI.history', data);
+ data.el = node;
+ data.parent = node.parentNode;
+ data.display = node.style.display;
+ data.position = node.style.position;
+ if (data.parent)
+ data.parent.removeChild(node);
+ }
+
+ var z = opts.baseZ;
+
+ // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
+ // layer1 is the iframe layer which is used to supress bleed through of underlying content
+ // layer2 is the overlay layer which has opacity and a wait cursor (by default)
+ // layer3 is the message content that is displayed while blocking
+
+ var lyr1 = ($.browser.msie || opts.forceIframe)
+ ? $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>')
+ : $('<div class="blockUI" style="display:none"></div>');
+ var lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
+
+ var lyr3;
+ if (opts.theme && full) {
+ var s = '<div class="blockUI blockMsg blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+z+';display:none;position:fixed">' +
+ '<div class="ui-widget-header ui-dialog-titlebar blockTitle">'+(opts.title || '&nbsp;')+'</div>' +
+ '<div class="ui-widget-content ui-dialog-content"></div>' +
+ '</div>';
+ lyr3 = $(s);
+ }
+ else {
+ lyr3 = full ? $('<div class="blockUI blockMsg blockPage" style="z-index:'+z+';display:none;position:fixed"></div>')
+ : $('<div class="blockUI blockMsg blockElement" style="z-index:'+z+';display:none;position:absolute"></div>');
+ }
+
+ // if we have a message, style it
+ if (msg) {
+ if (opts.theme) {
+ lyr3.css(themedCSS);
+ lyr3.addClass('ui-widget-content');
+ }
+ else
+ lyr3.css(css);
+ }
+
+ // style the overlay
+ if (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform)))
+ lyr2.css(opts.overlayCSS);
+ lyr2.css('position', full ? 'fixed' : 'absolute');
+
+ // make iframe layer transparent in IE
+ if ($.browser.msie || opts.forceIframe)
+ lyr1.css('opacity',0.0);
+
+ $([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
+
+ if (opts.theme && opts.draggable && $.fn.draggable) {
+ lyr3.draggable({
+ handle: '.ui-dialog-titlebar',
+ cancel: 'li'
+ });
+ }
+
+ // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
+ var expr = setExpr && (!$.boxModel || $('object,embed', full ? null : el).length > 0);
+ if (ie6 || expr) {
+ // give body 100% height
+ if (full && opts.allowBodyStretch && $.boxModel)
+ $('html,body').css('height','100%');
+
+ // fix ie6 issue when blocked element has a border width
+ if ((ie6 || !$.boxModel) && !full) {
+ var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
+ var fixT = t ? '(0 - '+t+')' : 0;
+ var fixL = l ? '(0 - '+l+')' : 0;
+ }
+
+ // simulate fixed position
+ $.each([lyr1,lyr2,lyr3], function(i,o) {
+ var s = o[0].style;
+ s.position = 'absolute';
+ if (i < 2) {
+ full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"')
+ : s.setExpression('height','this.parentNode.offsetHeight + "px"');
+ full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')
+ : s.setExpression('width','this.parentNode.offsetWidth + "px"');
+ if (fixL) s.setExpression('left', fixL);
+ if (fixT) s.setExpression('top', fixT);
+ }
+ else if (opts.centerY) {
+ if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
+ s.marginTop = 0;
+ }
+ else if (!opts.centerY && full) {
+ var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0;
+ var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
+ s.setExpression('top',expression);
+ }
+ });
+ }
+
+ // show the message
+ if (msg) {
+ if (opts.theme)
+ lyr3.find('.ui-widget-content').append(msg);
+ else
+ lyr3.append(msg);
+ if (msg.jquery || msg.nodeType)
+ $(msg).show();
+ }
+
+ if (($.browser.msie || opts.forceIframe) && opts.showOverlay)
+ lyr1.show(); // opacity is zero
+ if (opts.fadeIn) {
+ if (opts.showOverlay)
+ lyr2._fadeIn(opts.fadeIn);
+ if (msg)
+ lyr3.fadeIn(opts.fadeIn);
+ }
+ else {
+ if (opts.showOverlay)
+ lyr2.show();
+ if (msg)
+ lyr3.show();
+ }
+
+ // bind key and mouse events
+ bind(1, el, opts);
+
+ if (full) {
+ pageBlock = lyr3[0];
+ pageBlockEls = $(':input:enabled:visible',pageBlock);
+ if (opts.focusInput)
+ setTimeout(focus, 20);
+ }
+ else
+ center(lyr3[0], opts.centerX, opts.centerY);
+
+ if (opts.timeout) {
+ // auto-unblock
+ var to = setTimeout(function() {
+ full ? $.unblockUI(opts) : $(el).unblock(opts);
+ }, opts.timeout);
+ $(el).data('blockUI.timeout', to);
+ }
+};
+
+// remove the block
+function remove(el, opts) {
+ var full = (el == window);
+ var $el = $(el);
+ var data = $el.data('blockUI.history');
+ var to = $el.data('blockUI.timeout');
+ if (to) {
+ clearTimeout(to);
+ $el.removeData('blockUI.timeout');
+ }
+ opts = $.extend({}, $.blockUI.defaults, opts || {});
+ bind(0, el, opts); // unbind events
+
+ var els;
+ if (full) // crazy selector to handle odd field errors in ie6/7
+ els = $('body').children().filter('.blockUI').add('body > .blockUI');
+ else
+ els = $('.blockUI', el);
+
+ if (full)
+ pageBlock = pageBlockEls = null;
+
+ if (opts.fadeOut) {
+ els.fadeOut(opts.fadeOut);
+ setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
+ }
+ else
+ reset(els, data, opts, el);
+};
+
+// move blocking element back into the DOM where it started
+function reset(els,data,opts,el) {
+ els.each(function(i,o) {
+ // remove via DOM calls so we don't lose event handlers
+ if (this.parentNode)
+ this.parentNode.removeChild(this);
+ });
+
+ if (data && data.el) {
+ data.el.style.display = data.display;
+ data.el.style.position = data.position;
+ if (data.parent)
+ data.parent.appendChild(data.el);
+ $(data.el).removeData('blockUI.history');
+ }
+
+ if (typeof opts.onUnblock == 'function')
+ opts.onUnblock(el,opts);
+};
+
+// bind/unbind the handler
+function bind(b, el, opts) {
+ var full = el == window, $el = $(el);
+
+ // don't bother unbinding if there is nothing to unbind
+ if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
+ return;
+ if (!full)
+ $el.data('blockUI.isBlocked', b);
+
+ // don't bind events when overlay is not in use or if bindEvents is false
+ if (!opts.bindEvents || (b && !opts.showOverlay))
+ return;
+
+ // bind anchors and inputs for mouse and key events
+ var events = 'mousedown mouseup keydown keypress';
+ b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler);
+
+// former impl...
+// var $e = $('a,:input');
+// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
+};
+
+// event handler to suppress keyboard/mouse events when blocking
+function handler(e) {
+ // allow tab navigation (conditionally)
+ if (e.keyCode && e.keyCode == 9) {
+ if (pageBlock && e.data.constrainTabKey) {
+ var els = pageBlockEls;
+ var fwd = !e.shiftKey && e.target == els[els.length-1];
+ var back = e.shiftKey && e.target == els[0];
+ if (fwd || back) {
+ setTimeout(function(){focus(back)},10);
+ return false;
+ }
+ }
+ }
+ // allow events within the message content
+ if ($(e.target).parents('div.blockMsg').length > 0)
+ return true;
+
+ // allow events for content that is not being blocked
+ return $(e.target).parents().children().filter('div.blockUI').length == 0;
+};
+
+function focus(back) {
+ if (!pageBlockEls)
+ return;
+ var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
+ if (e)
+ e.focus();
+};
+
+function center(el, x, y) {
+ var p = el.parentNode, s = el.style;
+ var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
+ var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
+ if (x) s.left = l > 0 ? (l+'px') : '0';
+ if (y) s.top = t > 0 ? (t+'px') : '0';
+};
+
+function sz(el, p) {
+ return parseInt($.css(el,p))||0;
+};
+
+})(jQuery);
diff --git a/config/snort-dev/javascript/sortableTable.js b/config/snort-dev/javascript/sortableTable.js
index 02c83ab5..096f8d4c 100644
--- a/config/snort-dev/javascript/sortableTable.js
+++ b/config/snort-dev/javascript/sortableTable.js
@@ -1,288 +1,288 @@
-
-
-/**************************************************************
-
- Script : Sortable Table
- Version : 1.4
- Authors : Samuel Birch
- Desc : Sorts and filters table elements
- Licence : Open Source MIT Licence
-
-**************************************************************/
-
-var sortableTable = new Class({
-
- getOptions: function(){
- return {
- overCls: false,
- onClick: false,
- sortOn: 0,
- sortBy: 'ASC',
- filterHide: true,
- filterHideCls: 'hide',
- filterSelectedCls: 'selected'
- };
- },
-
- initialize: function(table, options){
- this.setOptions(this.getOptions(), options);
- this.table = $(table);
- this.tHead = this.table.getElement('thead');
- this.tBody = this.table.getElement('tbody');
- this.tFoot = this.table.getElement('tfoot');
- this.elements = this.tBody.getElements('tr');
- this.filtered = false;
-
- /*for(i=0;i<10;i++){
- this.elements.clone().injectInside(this.tBody);
- }
- this.elements = this.tBody.getElements('tr');*/
-
- this.elements.each(function(el,i){
- if(this.options.overCls){
- el.addEvent('mouseover', function(){
- el.addClass(options.overCls);
- }, this);
- el.addEvent('mouseout', function(){
- el.removeClass(options.overCls);
- });
- }
- if(this.options.onClick){
- el.addEvent('click', options.onClick);
- }
- }, this);
-
- //setup header
- this.tHead.getElements('th').each(function(el,i){
- if(el.axis){
- el.addEvent('click', this.sort.bind(this,i));
- el.addEvent('mouseover', function(){
- el.addClass('tableHeaderOver');
- });
- el.addEvent('mouseout', function(){
- el.removeClass('tableHeaderOver');
- });
- el.getdate = function(str){
- // inner util function to convert 2-digit years to 4
- function fixYear(yr) {
- yr = +yr;
- if (yr<50) { yr += 2000; }
- else if (yr<100) { yr += 1900; }
- return yr;
- };
- var ret;
- //
- if (str.length>12){
- strtime = str.substring(str.lastIndexOf(' ')+1);
- strtime = strtime.substring(0,2)+strtime.substr(-2)
- }else{
- strtime = '0000';
- }
- //
- // YYYY-MM-DD
- if (ret=str.match(/(\d{2,4})-(\d{1,2})-(\d{1,2})/)) {
- return (fixYear(ret[1])*10000) + (ret[2]*100) + (+ret[3]) + strtime;
- }
- // DD/MM/YY[YY] or DD-MM-YY[YY]
- if (ret=str.match(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{2,4})/)) {
- return (fixYear(ret[3])*10000) + (ret[2]*100) + (+ret[1]) + strtime;
- }
- return 999999990000; // So non-parsed dates will be last, not first
- };
- //
- el.findData = function(elem){
- var child = elem.getFirst();
- if(child){
- return el.findData(child);
- }else{
- return elem.innerHTML.trim();
- }
- };
- //
- el.compare = function(a,b){
- var1 = el.findData(a.getChildren()[i]);
- var2 = el.findData(b.getChildren()[i]);
- //var1 = a.getChildren()[i].firstChild.data;
- //var2 = b.getChildren()[i].firstChild.data;
-
- if(el.axis == 'number'){
- var1 = parseFloat(var1);
- var2 = parseFloat(var2);
-
- if(el.sortBy == 'ASC'){
- return var1-var2;
- }else{
- return var2-var1;
- }
-
- }else if(el.axis == 'string'){
- var1 = var1.toUpperCase();
- var2 = var2.toUpperCase();
-
- if(var1==var2){return 0};
- if(el.sortBy == 'ASC'){
- if(var1<var2){return -1};
- }else{
- if(var1>var2){return -1};
- }
- return 1;
-
- }else if(el.axis == 'date'){
- var1 = parseFloat(el.getdate(var1));
- var2 = parseFloat(el.getdate(var2));
-
- if(el.sortBy == 'ASC'){
- return var1-var2;
- }else{
- return var2-var1;
- }
-
- }else if(el.axis == 'currency'){
- var1 = parseFloat(var1.substr(1).replace(',',''));
- var2 = parseFloat(var2.substr(1).replace(',',''));
-
- if(el.sortBy == 'ASC'){
- return var1-var2;
- }else{
- return var2-var1;
- }
-
- }
-
- }
-
- if(i == this.options.sortOn){
- el.fireEvent('click');
- }
- }
- }, this);
- },
-
- sort: function(index){
- if(this.options.onStart){
- this.fireEvent('onStart');
- }
- //
- this.options.sortOn = index;
- var header = this.tHead.getElements('th');
- var el = header[index];
-
- header.each(function(e,i){
- if(i != index){
- e.removeClass('sortedASC');
- e.removeClass('sortedDESC');
- }
- });
-
- if(el.hasClass('sortedASC')){
- el.removeClass('sortedASC');
- el.addClass('sortedDESC');
- el.sortBy = 'DESC';
- }else if(el.hasClass('sortedDESC')){
- el.removeClass('sortedDESC');
- el.addClass('sortedASC');
- el.sortBy = 'ASC';
- }else{
- if(this.options.sortBy == 'ASC'){
- el.addClass('sortedASC');
- el.sortBy = 'ASC';
- }else if(this.options.sortBy == 'DESC'){
- el.addClass('sortedDESC');
- el.sortBy = 'DESC';
- }
- }
- //
- this.elements.sort(el.compare);
- this.elements.injectInside(this.tBody);
- //
- if(this.filtered){
- this.filteredAltRow();
- }else{
- this.altRow();
- }
-
- //
- if(this.options.onComplete){
- this.fireEvent('onComplete');
- }
- },
-
- altRow: function(){
- this.elements.each(function(el,i){
- if(i % 2){
- el.removeClass('altRow');
- }else{
- el.addClass('altRow');
- }
- });
- },
-
- filteredAltRow: function(){
- this.table.getElements('.'+this.options.filterSelectedCls).each(function(el,i){
- if(i % 2){
- el.removeClass('altRow');
- }else{
- el.addClass('altRow');
- }
- });
- },
-
- filter: function(form){
- var form = $(form);
- var col = 0;
- var key = '';
-
- form.getChildren().each(function(el,i){
- if(el.id == 'column'){
- col = Number(el.value);
- }
- if(el.id == 'keyword'){
- key = el.value.toLowerCase();
- }
- if(el.type == 'reset'){
- el.addEvent('click',this.clearFilter.bind(this));
- }
- }, this);
-
- if(key){
- this.elements.each(function(el,i){
- if(this.options.filterHide){
- el.removeClass('altRow');
- }
- if(el.getChildren()[col].firstChild.data.toLowerCase().indexOf(key) > -1){
- el.addClass(this.options.filterSelectedCls);
- if(this.options.filterHide){
- el.removeClass(this.options.filterHideCls);
- }
- }else{
- el.removeClass(this.options.filterSelectedCls);
- if(this.options.filterHide){
- el.addClass(this.options.filterHideCls);
- }
- }
- }, this);
- if(this.options.filterHide){
- this.filteredAltRow();
- this.filtered = true;
- }
- }
- },
-
- clearFilter: function(){
- this.elements.each(function(el,i){
- el.removeClass(this.options.filterSelectedCls);
- if(this.options.filterHide){
- el.removeClass(this.options.filterHideCls);
- }
- }, this);
- if(this.options.filterHide){
- this.altRow();
- this.filtered = false;
- }
- }
-
-});
-sortableTable.implement(new Events);
-sortableTable.implement(new Options);
-
-/*************************************************************/
+
+
+/**************************************************************
+
+ Script : Sortable Table
+ Version : 1.4
+ Authors : Samuel Birch
+ Desc : Sorts and filters table elements
+ Licence : Open Source MIT Licence
+
+**************************************************************/
+
+var sortableTable = new Class({
+
+ getOptions: function(){
+ return {
+ overCls: false,
+ onClick: false,
+ sortOn: 0,
+ sortBy: 'ASC',
+ filterHide: true,
+ filterHideCls: 'hide',
+ filterSelectedCls: 'selected'
+ };
+ },
+
+ initialize: function(table, options){
+ this.setOptions(this.getOptions(), options);
+ this.table = $(table);
+ this.tHead = this.table.getElement('thead');
+ this.tBody = this.table.getElement('tbody');
+ this.tFoot = this.table.getElement('tfoot');
+ this.elements = this.tBody.getElements('tr');
+ this.filtered = false;
+
+ /*for(i=0;i<10;i++){
+ this.elements.clone().injectInside(this.tBody);
+ }
+ this.elements = this.tBody.getElements('tr');*/
+
+ this.elements.each(function(el,i){
+ if(this.options.overCls){
+ el.addEvent('mouseover', function(){
+ el.addClass(options.overCls);
+ }, this);
+ el.addEvent('mouseout', function(){
+ el.removeClass(options.overCls);
+ });
+ }
+ if(this.options.onClick){
+ el.addEvent('click', options.onClick);
+ }
+ }, this);
+
+ //setup header
+ this.tHead.getElements('th').each(function(el,i){
+ if(el.axis){
+ el.addEvent('click', this.sort.bind(this,i));
+ el.addEvent('mouseover', function(){
+ el.addClass('tableHeaderOver');
+ });
+ el.addEvent('mouseout', function(){
+ el.removeClass('tableHeaderOver');
+ });
+ el.getdate = function(str){
+ // inner util function to convert 2-digit years to 4
+ function fixYear(yr) {
+ yr = +yr;
+ if (yr<50) { yr += 2000; }
+ else if (yr<100) { yr += 1900; }
+ return yr;
+ };
+ var ret;
+ //
+ if (str.length>12){
+ strtime = str.substring(str.lastIndexOf(' ')+1);
+ strtime = strtime.substring(0,2)+strtime.substr(-2)
+ }else{
+ strtime = '0000';
+ }
+ //
+ // YYYY-MM-DD
+ if (ret=str.match(/(\d{2,4})-(\d{1,2})-(\d{1,2})/)) {
+ return (fixYear(ret[1])*10000) + (ret[2]*100) + (+ret[3]) + strtime;
+ }
+ // DD/MM/YY[YY] or DD-MM-YY[YY]
+ if (ret=str.match(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{2,4})/)) {
+ return (fixYear(ret[3])*10000) + (ret[2]*100) + (+ret[1]) + strtime;
+ }
+ return 999999990000; // So non-parsed dates will be last, not first
+ };
+ //
+ el.findData = function(elem){
+ var child = elem.getFirst();
+ if(child){
+ return el.findData(child);
+ }else{
+ return elem.innerHTML.trim();
+ }
+ };
+ //
+ el.compare = function(a,b){
+ var1 = el.findData(a.getChildren()[i]);
+ var2 = el.findData(b.getChildren()[i]);
+ //var1 = a.getChildren()[i].firstChild.data;
+ //var2 = b.getChildren()[i].firstChild.data;
+
+ if(el.axis == 'number'){
+ var1 = parseFloat(var1);
+ var2 = parseFloat(var2);
+
+ if(el.sortBy == 'ASC'){
+ return var1-var2;
+ }else{
+ return var2-var1;
+ }
+
+ }else if(el.axis == 'string'){
+ var1 = var1.toUpperCase();
+ var2 = var2.toUpperCase();
+
+ if(var1==var2){return 0};
+ if(el.sortBy == 'ASC'){
+ if(var1<var2){return -1};
+ }else{
+ if(var1>var2){return -1};
+ }
+ return 1;
+
+ }else if(el.axis == 'date'){
+ var1 = parseFloat(el.getdate(var1));
+ var2 = parseFloat(el.getdate(var2));
+
+ if(el.sortBy == 'ASC'){
+ return var1-var2;
+ }else{
+ return var2-var1;
+ }
+
+ }else if(el.axis == 'currency'){
+ var1 = parseFloat(var1.substr(1).replace(',',''));
+ var2 = parseFloat(var2.substr(1).replace(',',''));
+
+ if(el.sortBy == 'ASC'){
+ return var1-var2;
+ }else{
+ return var2-var1;
+ }
+
+ }
+
+ }
+
+ if(i == this.options.sortOn){
+ el.fireEvent('click');
+ }
+ }
+ }, this);
+ },
+
+ sort: function(index){
+ if(this.options.onStart){
+ this.fireEvent('onStart');
+ }
+ //
+ this.options.sortOn = index;
+ var header = this.tHead.getElements('th');
+ var el = header[index];
+
+ header.each(function(e,i){
+ if(i != index){
+ e.removeClass('sortedASC');
+ e.removeClass('sortedDESC');
+ }
+ });
+
+ if(el.hasClass('sortedASC')){
+ el.removeClass('sortedASC');
+ el.addClass('sortedDESC');
+ el.sortBy = 'DESC';
+ }else if(el.hasClass('sortedDESC')){
+ el.removeClass('sortedDESC');
+ el.addClass('sortedASC');
+ el.sortBy = 'ASC';
+ }else{
+ if(this.options.sortBy == 'ASC'){
+ el.addClass('sortedASC');
+ el.sortBy = 'ASC';
+ }else if(this.options.sortBy == 'DESC'){
+ el.addClass('sortedDESC');
+ el.sortBy = 'DESC';
+ }
+ }
+ //
+ this.elements.sort(el.compare);
+ this.elements.injectInside(this.tBody);
+ //
+ if(this.filtered){
+ this.filteredAltRow();
+ }else{
+ this.altRow();
+ }
+
+ //
+ if(this.options.onComplete){
+ this.fireEvent('onComplete');
+ }
+ },
+
+ altRow: function(){
+ this.elements.each(function(el,i){
+ if(i % 2){
+ el.removeClass('altRow');
+ }else{
+ el.addClass('altRow');
+ }
+ });
+ },
+
+ filteredAltRow: function(){
+ this.table.getElements('.'+this.options.filterSelectedCls).each(function(el,i){
+ if(i % 2){
+ el.removeClass('altRow');
+ }else{
+ el.addClass('altRow');
+ }
+ });
+ },
+
+ filter: function(form){
+ var form = $(form);
+ var col = 0;
+ var key = '';
+
+ form.getChildren().each(function(el,i){
+ if(el.id == 'column'){
+ col = Number(el.value);
+ }
+ if(el.id == 'keyword'){
+ key = el.value.toLowerCase();
+ }
+ if(el.type == 'reset'){
+ el.addEvent('click',this.clearFilter.bind(this));
+ }
+ }, this);
+
+ if(key){
+ this.elements.each(function(el,i){
+ if(this.options.filterHide){
+ el.removeClass('altRow');
+ }
+ if(el.getChildren()[col].firstChild.data.toLowerCase().indexOf(key) > -1){
+ el.addClass(this.options.filterSelectedCls);
+ if(this.options.filterHide){
+ el.removeClass(this.options.filterHideCls);
+ }
+ }else{
+ el.removeClass(this.options.filterSelectedCls);
+ if(this.options.filterHide){
+ el.addClass(this.options.filterHideCls);
+ }
+ }
+ }, this);
+ if(this.options.filterHide){
+ this.filteredAltRow();
+ this.filtered = true;
+ }
+ }
+ },
+
+ clearFilter: function(){
+ this.elements.each(function(el,i){
+ el.removeClass(this.options.filterSelectedCls);
+ if(this.options.filterHide){
+ el.removeClass(this.options.filterHideCls);
+ }
+ }, this);
+ if(this.options.filterHide){
+ this.altRow();
+ this.filtered = false;
+ }
+ }
+
+});
+sortableTable.implement(new Events);
+sortableTable.implement(new Options);
+
+/*************************************************************/
diff --git a/config/snort-dev/javascript/tabs.js b/config/snort-dev/javascript/tabs.js
index c042d74d..40e54f0e 100644
--- a/config/snort-dev/javascript/tabs.js
+++ b/config/snort-dev/javascript/tabs.js
@@ -1,123 +1,123 @@
-// CSS helper functions
-CSS = {
- // Adds a class to an element.
- AddClass: function (e, c) {
- if (!e.className.match(new RegExp("\\b" + c + "\\b", "i")))
- e.className += (e.className ? " " : "") + c;
- },
-
- // Removes a class from an element.
- RemoveClass: function (e, c) {
- e.className = e.className.replace(new RegExp(" \\b" + c + "\\b|\\b" + c + "\\b ?", "gi"), "");
- }
-};
-
-// Functions for handling tabs.
-Tabs = {
- // Changes to the tab with the specified ID.
- GoTo: function (contentId, skipReplace) {
- // This variable will be true if a tab for the specified
- // content ID was found.
- var foundTab = false;
-
- // Get the TOC element.
- var toc = document.getElementById("toc");
- if (toc) {
- var lis = toc.getElementsByTagName("li");
- for (var j = 0; j < lis.length; j++) {
- var li = lis[j];
-
- // Give the current tab link the class "current" and
- // remove the class from any other TOC links.
- var anchors = li.getElementsByTagName("a");
- for (var k = 0; k < anchors.length; k++) {
- if (anchors[k].hash == "#" + contentId) {
- CSS.AddClass(li, "current");
- foundTab = true;
- break;
- } else {
- CSS.RemoveClass(li, "current");
- }
- }
- }
- }
-
- // Show the content with the specified ID.
- var divsToHide = [];
- var divs = document.getElementsByTagName("div");
- for (var i = 0; i < divs.length; i++) {
- var div = divs[i];
-
- if (div.className.match(/\bcontent\b/i)) {
- if (div.id == "_" + contentId)
- div.style.display = "block";
- else
- divsToHide.push(div);
- }
- }
-
- // Hide the other content boxes.
- for (var i = 0; i < divsToHide.length; i++)
- divsToHide[i].style.display = "none";
-
- // Change the address bar.
- if (!skipReplace) window.location.replace("#" + contentId);
- },
-
- OnClickHandler: function (e) {
- // Stop the event (to stop it from scrolling or
- // making an entry in the history).
- if (!e) e = window.event;
- if (e.preventDefault) e.preventDefault(); else e.returnValue = false;
-
- // Get the name of the anchor of the link that was clicked.
- Tabs.GoTo(this.hash.substring(1));
- },
-
- Init: function () {
- if (!document.getElementsByTagName) return;
-
- // Attach an onclick event to all the anchor links on the page.
- var anchors = document.getElementsByTagName("a");
- for (var i = 0; i < anchors.length; i++) {
- var a = anchors[i];
- if (a.hash) a.onclick = Tabs.OnClickHandler;
- }
-
- var contentId;
- if (window.location.hash) contentId = window.location.hash.substring(1);
-
- var divs = document.getElementsByTagName("div");
- for (var i = 0; i < divs.length; i++) {
- var div = divs[i];
-
- if (div.className.match(/\bcontent\b/i)) {
- if (!contentId) contentId = div.id;
- div.id = "_" + div.id;
- }
- }
-
- if (contentId) Tabs.GoTo(contentId, true);
- }
-};
-
-// Hook up the OnLoad event to the tab initialization function.
-window.onload = Tabs.Init;
-
-// Hide the content while waiting for the onload event to trigger.
-var contentId = window.location.hash || "#Introduction";
-
-if (document.createStyleSheet) {
- var style = document.createStyleSheet();
- style.addRule("div.content", "display: none;");
- style.addRule("div" + contentId, "display: block;");
-} else {
- var head = document.getElementsByTagName("head")[0];
- if (head) {
- var style = document.createElement("style");
- style.setAttribute("type", "text/css");
- style.appendChild(document.createTextNode("div.content { display: none; }"));
- style.appendChild(document.createTextNode("div" + contentId + " { display: block; }"));
- head.appendChild(style);
- }
+// CSS helper functions
+CSS = {
+ // Adds a class to an element.
+ AddClass: function (e, c) {
+ if (!e.className.match(new RegExp("\\b" + c + "\\b", "i")))
+ e.className += (e.className ? " " : "") + c;
+ },
+
+ // Removes a class from an element.
+ RemoveClass: function (e, c) {
+ e.className = e.className.replace(new RegExp(" \\b" + c + "\\b|\\b" + c + "\\b ?", "gi"), "");
+ }
+};
+
+// Functions for handling tabs.
+Tabs = {
+ // Changes to the tab with the specified ID.
+ GoTo: function (contentId, skipReplace) {
+ // This variable will be true if a tab for the specified
+ // content ID was found.
+ var foundTab = false;
+
+ // Get the TOC element.
+ var toc = document.getElementById("toc");
+ if (toc) {
+ var lis = toc.getElementsByTagName("li");
+ for (var j = 0; j < lis.length; j++) {
+ var li = lis[j];
+
+ // Give the current tab link the class "current" and
+ // remove the class from any other TOC links.
+ var anchors = li.getElementsByTagName("a");
+ for (var k = 0; k < anchors.length; k++) {
+ if (anchors[k].hash == "#" + contentId) {
+ CSS.AddClass(li, "current");
+ foundTab = true;
+ break;
+ } else {
+ CSS.RemoveClass(li, "current");
+ }
+ }
+ }
+ }
+
+ // Show the content with the specified ID.
+ var divsToHide = [];
+ var divs = document.getElementsByTagName("div");
+ for (var i = 0; i < divs.length; i++) {
+ var div = divs[i];
+
+ if (div.className.match(/\bcontent\b/i)) {
+ if (div.id == "_" + contentId)
+ div.style.display = "block";
+ else
+ divsToHide.push(div);
+ }
+ }
+
+ // Hide the other content boxes.
+ for (var i = 0; i < divsToHide.length; i++)
+ divsToHide[i].style.display = "none";
+
+ // Change the address bar.
+ if (!skipReplace) window.location.replace("#" + contentId);
+ },
+
+ OnClickHandler: function (e) {
+ // Stop the event (to stop it from scrolling or
+ // making an entry in the history).
+ if (!e) e = window.event;
+ if (e.preventDefault) e.preventDefault(); else e.returnValue = false;
+
+ // Get the name of the anchor of the link that was clicked.
+ Tabs.GoTo(this.hash.substring(1));
+ },
+
+ Init: function () {
+ if (!document.getElementsByTagName) return;
+
+ // Attach an onclick event to all the anchor links on the page.
+ var anchors = document.getElementsByTagName("a");
+ for (var i = 0; i < anchors.length; i++) {
+ var a = anchors[i];
+ if (a.hash) a.onclick = Tabs.OnClickHandler;
+ }
+
+ var contentId;
+ if (window.location.hash) contentId = window.location.hash.substring(1);
+
+ var divs = document.getElementsByTagName("div");
+ for (var i = 0; i < divs.length; i++) {
+ var div = divs[i];
+
+ if (div.className.match(/\bcontent\b/i)) {
+ if (!contentId) contentId = div.id;
+ div.id = "_" + div.id;
+ }
+ }
+
+ if (contentId) Tabs.GoTo(contentId, true);
+ }
+};
+
+// Hook up the OnLoad event to the tab initialization function.
+window.onload = Tabs.Init;
+
+// Hide the content while waiting for the onload event to trigger.
+var contentId = window.location.hash || "#Introduction";
+
+if (document.createStyleSheet) {
+ var style = document.createStyleSheet();
+ style.addRule("div.content", "display: none;");
+ style.addRule("div" + contentId, "display: block;");
+} else {
+ var head = document.getElementsByTagName("head")[0];
+ if (head) {
+ var style = document.createElement("style");
+ style.setAttribute("type", "text/css");
+ style.appendChild(document.createTextNode("div.content { display: none; }"));
+ style.appendChild(document.createTextNode("div" + contentId + " { display: block; }"));
+ head.appendChild(style);
+ }
} \ No newline at end of file
diff --git a/config/snort-dev/snort.inc b/config/snort-dev/snort.inc
index b9dc590c..cd8ba9a2 100644
--- a/config/snort-dev/snort.inc
+++ b/config/snort-dev/snort.inc
@@ -30,6 +30,8 @@
*/
require_once("pfsense-utils.inc");
+require_once("config.inc");
+require_once("functions.inc");
// Needed on 2.0 because of filter_get_vpns_list()
require_once("filter.inc");
@@ -42,39 +44,131 @@ if ($pfsense_ver_chk == '1.2.3-RELEASE')
$pfsense_stable = 'yes';
}else{
$pfsense_stable = 'no';
-}
+}
-/* check if uniq snort proc is running */
-function uniq_snort_proc($id, $if_real)
-{
- global $config, $g, $id, $if_real;
+/* checks to see if snort is running yes/no and stop/start */
+ function Running_Ck($snort_uuid, $if_real, $id) {
+ global $config;
+
+ $snort_up_ck = exec("/bin/ps -auwx | /usr/bin/grep -v grep | /usr/bin/grep snort | /usr/bin/awk '{print \$2;}' | sed 1q");
-$snort_uuid = $config['installedpackages']['snortglobal']['rule'][$id]['uuid'];
-$snort_up_ck = exec("/bin/ps -auwx | /usr/bin/grep -v grep | /usr/bin/grep snort | /usr/bin/awk '{print \$2;}' | sed 1q");
+ if(snort_up_ck == ''){
+ $snort_up = 'no';
+ return $snort_up;
+ }
- if ($snort_up_ck == '')
- {
- $snort_up = 'false';
+ if(snort_up_ck != ''){
+
+ //$snort_up_pre = exec("/usr/bin/top -a -U snort -u | grep -v grep | grep \"R {$snort_uuid}_{$if_real}\" | awk '{print \$1;}'");
+ //$snort_up_s = exec("/usr/bin/top -U snort -u | grep snort | grep {$snort_up_pre} | /usr/bin/awk '{print \$1;}'");
+ //$snort_up_r = exec("/usr/bin/top -U root -u | grep snort | grep {$snort_up_pre} | /usr/bin/awk '{print \$1;}'");
+
+ /* use ob_clean to clear output buffer, this code needs to be watched */
+ ob_clean();
+ $snort_up_prell = exec("/usr/bin/top -a -U snort -u | grep -v grep | grep \"R {$snort_uuid}_{$if_real}\" | awk '{print \$1;}'", $retval);
+
+ if ($snort_up_prell != "") {
+ $snort_uph = 'yes';
+ }else{
+ $snort_uph = 'no';
+ }
+ }
+
+ return $snort_uph;
}
- if ($snort_up_ck != '')
- {
- $snort_up_pre = exec("/usr/bin/top -a -U snort -u | grep -v grep | grep \"R {$snort_uuid}_{$if_real}\" | awk '{print \$1;}'");
+/* checks to see if barnyard2 is running yes/no */
+ function Running_Ck_b($snort_uuid, $if_real, $id) {
+ global $config;
+
+ $snort_up_ck_b = exec("/bin/ps -auwx | /usr/bin/grep -v grep | /usr/bin/grep barnyard2 | /usr/bin/awk '{print \$2;}' | sed 1q");
+
+ if($snort_up_ck_b == ''){
+ $snort_up_b = 'no';
+ return $snort_up_b;
+ }
+
+ if(snort_up_ck_b != ''){
+
+ //$snort_up_pre_b = exec("/usr/bin/top -a -U snort -u | grep -v grep | grep \"f snort_{$snort_uuid}_{$if_real}.u2\" | awk '{print \$1;}'");
+ //$snort_up_s_b = exec("/usr/bin/top -U snort -u | grep barnyard2 | grep {$snort_up_pre_b} | /usr/bin/awk '{print \$1;}'");
+ //$snort_up_r_b = exec("/usr/bin/top -U root -u | grep barnyard2 | grep {$snort_up_pre_b} | /usr/bin/awk '{print \$1;}'");
+
+ /* use ob_clean to clear output buffer, this code needs to be watched */
+ ob_clean();
+ $snort_up_pre_b = exec("/usr/bin/top -a -U snort -u | grep -v grep | grep \"f snort_{$snort_uuid}_{$if_real}.u2\" | awk '{print \$1;}'");
+
+ if ($snort_up_pre_b != '') {
+ $snort_up_b = 'yes';
+ }else{
+ $snort_up_b = 'no';
+ }
+ }
+
+ return $snort_up_b;
+ }
- $snort_up_s = exec("/usr/bin/top -U snort -u | grep snort | grep {$snort_up_pre} | /usr/bin/awk '{print \$1;}'");
- $snort_up_r = exec("/usr/bin/top -U root -u | grep snort | grep {$snort_up_pre} | /usr/bin/awk '{print \$1;}'");
+ function Running_Stop($snort_uuid, $if_real, $id) {
+ global $config;
+
+ $start_up_pre = exec("/usr/bin/top -a -U snort -u | grep -v grep | grep \"R {$snort_uuid}_{$if_real}\" | awk '{print \$1;}'");
+ $start_up_s = exec("/usr/bin/top -U snort -u | grep snort | grep {$start_up_pre} | awk '{ print $1; }'");
+ $start_up_r = exec("/usr/bin/top -U root -u | grep snort | grep {$start_up_pre} | awk '{ print $1; }'");
+
+ $start2_upb_pre = exec("/usr/bin/top -a -U snort -u | grep -v grep | grep \"snort_{$snort_uuid}_{$if_real}.u2\" | awk '{print \$1;}'");
+ $start2_upb_s = exec("/usr/bin/top -U snort -u | grep barnyard2 | grep {$start2_upb_pre} | awk '{ print $1; }'");
+ $start2_upb_r = exec("/usr/bin/top -U root -u | grep barnyard2 | grep {$start2_upb_pre} | awk '{ print $1; }'");
- if ($snort_up_s != '' || $snort_up_r != '')
+ if ($start_up_s != "" || $start_up_r != "" || $start2_upb_s != "" || $start2_upb_r != "")
{
- $snort_up = 'true';
- }else{
- $snort_up = 'false';
+ if ($start_up_s != "")
+ {
+ exec("/bin/kill {$start_up_s}");
+ exec("/bin/rm /var/run/snort_{$snort_uuid}_{$if_real}*");
+ }
+
+ if ($start2_upb_s != "")
+ {
+ exec("/bin/kill {$start2_upb_s}");
+ exec("/bin/rm /var/run/barnyard2_{$snort_uuid}_{$if_real}*");
+ }
+
+ if ($start_up_r != "")
+ {
+ exec("/bin/kill {$start_up_r}");
+ exec("/bin/rm /var/run/snort_{$snort_uuid}_{$if_real}*");
+ }
+
+ if ($start2_upb_r != "")
+ {
+ exec("/bin/kill {$start2_upb_r}");
+ exec("/bin/rm /var/run/barnyard2_{$snort_uuid}_{$if_real}*");
+ }
+
+ /* Log Iface stop */
+ exec("/usr/bin/logger -p daemon.info -i -t SnortStartup 'Interface Rule STOP for {$snort_uuid}_{$if_real}...'");
}
- return $snort_up;
- }else{
- return $snort_up;
}
-}
+
+
+ function Running_Start($snort_uuid, $if_real, $id) {
+ global $config;
+
+ $snort_info_chk = $config['installedpackages']['snortglobal']['rule'][$id]['enable'];
+ if ($snort_info_chk == 'on') {
+ exec("/usr/local/bin/snort -u snort -g snort -R \"{$snort_uuid}_{$if_real}\" -D -q -l /var/log/snort -G {$snort_uuid} -c /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/snort.conf -i {$if_real}");
+ }
+ /* define snortbarnyardlog_chk */
+ /* top will have trouble if the uuid is to far back */
+ $snortbarnyardlog_info_chk = $config['installedpackages']['snortglobal']['rule'][$id]['barnyard_enable'];
+ $snortbarnyardlog_mysql_info_chk = $config['installedpackages']['snortglobal']['rule'][$id]['barnyard_mysql'];
+ if ($snortbarnyardlog_info_chk == 'on' && $snortbarnyardlog_mysql_info_chk != '' && $snort_info_chk == 'on') {
+ exec("/usr/local/bin/barnyard2 -f \"snort_{$snort_uuid}_{$if_real}.u2\" -u snort -g snort -c /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -w /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/barnyard2.waldo -D -q");
+ }
+
+ /* Log Iface stop */
+ exec("/usr/bin/logger -p daemon.info -i -t SnortStartup 'Interface Rule START for {$id}_{$snort_uuid}_{$if_real}...'");
+ }
/* get the real iface name of wan */
function convert_friendly_interface_to_real_interface_name2($interface)
@@ -113,8 +207,10 @@ function snort_postinstall()
global $config;
conf_mount_rw();
- if(!file_exists("/var/log/snort/"))
+ if(!file_exists("/var/log/snort/")) {
mwexec("mkdir -p /var/log/snort/");
+ mwexec("mkdir -p /var/log/snort/barnyard2");
+ }
if(!file_exists("/var/log/snort/alert"))
touch("/var/log/snort/alert");
@@ -171,6 +267,15 @@ function snort_postinstall()
exec('/bin/rm /usr/local/lib/snort/dynamicpreprocessor/lib_sfdynamic_preprocessor_example*');
}
+ /* find out if were in 1.2.3-RELEASE */
+ $pfsense_ver_chk = exec('/bin/cat /etc/version');
+ if ($pfsense_ver_chk == '1.2.3-RELEASE')
+ {
+ $pfsense_stable = 'yes';
+ }else{
+ $pfsense_stable = 'no';
+ }
+
/* move files around, make it look clean */
exec('/bin/mkdir -p /usr/local/www/snort/css');
exec('/bin/mkdir -p /usr/local/www/snort/images');
@@ -191,6 +296,7 @@ function snort_postinstall()
exec('/usr/bin/fetch http://www.pfsense.com/packages/config/snort-dev/images/logo.jpg');
exec('/usr/bin/fetch http://www.pfsense.com/packages/config/snort-dev/images/footer.jpg');
exec('/usr/bin/fetch http://www.pfsense.com/packages/config/snort-dev/images/footer2.jpg');
+ exec('/usr/bin/fetch http://www.pfsense.com/packages/config/snort-dev/images/icon_excli.png');
chdir ("/usr/local/www/snort/javascript/");
exec('/usr/bin/fetch http://www.pfsense.com/packages/config/snort-dev/javascript/jquery.blockUI.js');
exec('/usr/bin/fetch http://www.pfsense.com/packages/config/snort-dev/javascript/jquery-1.3.2.js');
@@ -198,6 +304,15 @@ function snort_postinstall()
exec('/usr/bin/fetch http://www.pfsense.com/packages/config/snort-dev/javascript/sortableTable.js');
exec('/usr/bin/fetch http://www.pfsense.com/packages/config/snort-dev/javascript/tabs.js');
+ /* install barnyard2 for 2.0 and 1.2.3 */
+ chdir ("/usr/local/bin/");
+ if ($pfsense_stable == 'yes') {
+ exec('/usr/bin/fetch http://www.pfsense.com/packages/config/snort-dev/bin/7.2.x86/barnyard2');
+ }else{
+ exec('/usr/bin/fetch http://www.pfsense.com/packages/config/snort-dev/bin/8.0.x86/barnyard2');
+ }
+ exec('/bin/chmod 077 /usr/local/bin/barnyard2');
+
/* back to default */
chdir ("/root/");
@@ -486,11 +601,8 @@ $snort_dir_filter_search_result = array_diff($snort_dir_filter, $snort_rules_lis
foreach ($snort_dir_filter_search_result as $value)
{
exec("rm -r /usr/local/etc/snort/$value");
- exec("echo \"rm -r /usr/local/etc/snort/$value\" >> /root/test.log");
}
- exec("echo \"Function remove ....\" >> /root/test.log");
-
}
/* make sure this func on writes to files and does not start snort */
@@ -499,8 +611,6 @@ function sync_snort_package()
global $config, $g;
conf_mount_rw();
-
-
/* all new files are for the user snort nologin */
if(!file_exists("/var/log/snort"))
{
@@ -514,7 +624,6 @@ function sync_snort_package()
exec("/bin/chmod -R 755 /usr/local/etc/snort");
exec("/bin/chmod -R 755 /usr/local/lib/snort");
- exec("echo \"Funtion sync package....\" >> /root/test.log");
conf_mount_ro();
}
@@ -560,7 +669,6 @@ if ($id != '' && $if_real != '') //new
sync_snort_package();
- exec("echo \"Funtion sync all $id $if_real $snort_uuid....\" >> /root/test.log");
conf_mount_ro();
}
}
@@ -591,7 +699,9 @@ function sync_snort_package_empty()
$result_lan = $config['installedpackages']['snortglobal']['rule'][$id]['interface'];
$if_real = convert_friendly_interface_to_real_interface_name2($result_lan);
+ $snort_uuid = $config['installedpackages']['snortglobal']['rule'][$id]['uuid'];
+ if ($if_real != '' && $snort_uuid != '') {
/* create snort configuration file */
create_snort_conf($id, $if_real, $snort_uuid);
@@ -602,14 +712,14 @@ function sync_snort_package_empty()
$snortbarnyardlog_info_chk = $config['installedpackages']['snortglobal']['rule'][$id]['barnyard_enable'];
if ($snortbarnyardlog_info_chk == 'on')
create_barnyard2_conf($id, $if_real, $snort_uuid);
-
+ }
}
/* create snort bootup file snort.sh only create once */
create_snort_sh();
sync_snort_package();
- exec("echo \"Funtion sync empty create files foreach $if_real $id....\" >> /root/test.log");
+
}
}
}
@@ -617,8 +727,6 @@ function sync_snort_package_empty()
/* Start of main config files */
/* Start of main config files */
-////////////////////////// >>>>>>>>>>
-
/* open snort.sh for writing" */
function create_snort_sh()
@@ -628,17 +736,6 @@ function create_snort_sh()
global $config, $g;
conf_mount_rw();
-exec("echo \"Craete snort.sh $snort_uuid $if_real $id....\" >> /root/test.log");
-
- $snortbarnyardlog_info_chk = $config['installedpackages']['snortglobal']['rule'][$id]['barnyard_enable'];
-
- /* define snortbarnyardlog_chk */
- if ($snortbarnyardlog_info_chk == on) {
-
- $start_barnyard2 = "sleep 4/n/usr/local/bin/barnyard2 -u snort -g snort -c /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -d /var/log/snort -f snort.u2_{$snort_uuid}_{$if_real} -w /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/barnyard2.waldo -D -q";
-
-}
-
/* do not start config build if rules is empty */
if (!empty($config['installedpackages']['snortglobal']['rule']))
{
@@ -656,7 +753,15 @@ exec("echo \"Craete snort.sh $snort_uuid $if_real $id....\" >> /root/test.log")
$result_lan = $config['installedpackages']['snortglobal']['rule'][$id]['interface'];
$if_real = convert_friendly_interface_to_real_interface_name($result_lan);
- /* Get all interface startup commands ready */
+ /* define snortbarnyardlog_chk */
+ $snortbarnyardlog_info_chk = $config['installedpackages']['snortglobal']['rule'][$id]['barnyard_enable'];
+ $snortbarnyardlog_mysql_info_chk = $config['installedpackages']['snortglobal']['rule'][$id]['barnyard_mysql'];
+
+ if ($snortbarnyardlog_info_chk == 'on' && $snortbarnyardlog_mysql_info_chk != '') {
+ $start_barnyard2 = "sleep 4;/usr/local/bin/barnyard2 -f snort_{$snort_uuid}_{$if_real}.u2 -u snort -g snort -c /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -w /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/barnyard2.waldo -D -q";
+ }
+
+/* Get all interface startup commands ready */
$snort_sh_text2[] = <<<EOD
###### For Each Iface
@@ -701,7 +806,7 @@ $snort_sh_text4[] = <<<EOF
pid_s=`/bin/ps -auwx | /usr/bin/grep -v grep | /usr/bin/grep "R {$snort_uuid}_{$if_real}" | /usr/bin/awk '{print \$2;}'`
sleep 3
- pid_b=`/bin/ps -auwx | /usr/bin/grep -v grep | /usr/bin/grep "snort.u2_{$snort_uuid}_{$if_real}" | /usr/bin/awk '{print \$2;}'`
+ pid_b=`/bin/ps -auwx | /usr/bin/grep -v grep | /usr/bin/grep "snort_{$snort_uuid}_{$if_real}.u2" | /usr/bin/awk '{print \$2;}'`
if [ \${pid_s} ] ; then
@@ -838,9 +943,6 @@ function create_rules_iface($id, $if_real, $snort_uuid)
global $config, $g;
conf_mount_rw();
-exec("echo \"Create rules $snort_uuid $if_real $id ....\" >> /root/test.log");
-
-
$if_rule_dir = "/usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/rules";
$folder_chk = (count(glob("$if_rule_dir/*")) === 0) ? 'empty' : 'full';
@@ -857,17 +959,15 @@ exec("echo \"Create rules $snort_uuid $if_real $id ....\" >> /root/test.log");
/* open barnyard2.conf for writing */
function create_barnyard2_conf($id, $if_real, $snort_uuid) {
- global $bconfig, $bg, $id, $if_real;
+ global $bconfig, $g;
/* write out barnyard2_conf */
-exec("echo \"Create barnyard.conf $if_real $id....\" >> /root/test.log");
-
if(!file_exists("/usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/barnyard2.conf"))
{
exec("/bin//usr/bin/touch /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/barnyard2.conf");
}
- $barnyard2_conf_text = generate_barnyard2_conf();
+ $barnyard2_conf_text = generate_barnyard2_conf($id, $if_real, $snort_uuid);
$bconf = fopen("/usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/barnyard2.conf", "w");
if(!$bconf) {
log_error("Could not open /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/barnyard2.conf for writing.");
@@ -878,13 +978,13 @@ exec("echo \"Create barnyard.conf $if_real $id....\" >> /root/test.log");
}
/* open barnyard2.conf for writing" */
-function generate_barnyard2_conf() {
+function generate_barnyard2_conf($id, $if_real, $snort_uuid) {
- global $config, $g, $id, $if_real;
+ global $config, $g;
conf_mount_rw();
/* define snortbarnyardlog */
-/* TODO add support for the other 5 output plugins */
+/* TODO: add support for the other 5 output plugins */
$snortbarnyardlog_database_info_chk = $config['installedpackages']['snortglobal']['rule'][$id]['barnyard_mysql'];
$snortbarnyardlog_hostname_info_chk = exec("/bin/hostname");
@@ -918,10 +1018,11 @@ $barnyard2_conf_text = <<<EOD
#
# set the appropriate paths to the file(s) your Snort process is using
-config reference-map: /usr/local/etc/snort/reference.config
-config class-map: /usr/local/etc/snort/classification.config
-config gen-msg-map: /usr/local/etc/snort/gen-msg.map
-config sid-msg-map: /usr/local/etc/snort/sid-msg.map
+
+config reference_file: /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/reference.config
+config classification_file: /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/classification.config
+config gen_file: /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/gen-msg.map
+config sid_file: /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/sid-msg.map
config hostname: $snortbarnyardlog_hostname_info_chk
config interface: {$snort_uuid}_{$if_real}
@@ -929,6 +1030,8 @@ config interface: {$snort_uuid}_{$if_real}
# Step 2: setup the input plugins
input unified2
+config logdir: /var/log/snort
+
# database: log to a variety of databases
# output database: log, mysql, user=xxxx password=xxxxxx dbname=xxxx host=xxx.xxx.xxx.xxxx
@@ -942,10 +1045,10 @@ EOD;
function create_snort_conf($id, $if_real, $snort_uuid)
{
- global $config, $g, $id, $if_real, $snort_uuid;
+ global $config, $g;
/* write out snort.conf */
-
-exec("echo \"Create sonrt.conf $snort_uuid $if_real $id....\" >> /root/test.log");
+
+ if ($if_real != '' && $snort_uuid != '') {
$snort_conf_text = generate_snort_conf($id, $if_real, $snort_uuid);
conf_mount_rw();
@@ -957,8 +1060,7 @@ exec("echo \"Create sonrt.conf $snort_uuid $if_real $id....\" >> /root/test.log
fwrite($conf, $snort_conf_text);
fclose($conf);
conf_mount_ro();
-
-
+ }
}
function snort_deinstall()
@@ -967,8 +1069,6 @@ function snort_deinstall()
global $config, $g, $id, $if_real;
conf_mount_rw();
-exec("echo \"Snort Deinstall $if_real $id....\" >> /root/test.log");
-
/* remove custom sysctl */
remove_text_from_file("/etc/sysctl.conf", "sysctl net.bpf.bufsize=20480");
/* decrease bpf buffers back to 4096, from 20480 */
@@ -986,6 +1086,9 @@ exec("echo \"Snort Deinstall $if_real $id....\" >> /root/test.log");
exec("rm -rf /usr/local/etc/snort*");
//exec("cd /var/db/pkg && pkg_delete `ls | grep barnyard2`");
exec("cd /var/db/pkg && pkg_delete `ls | grep snort`");
+ exec("cd /var/db/pkg && pkg_delete `ls | grep mysql`");
+ exec("cd /var/db/pkg && pkg_delete `ls | grep pcre`");
+ exec("cd /var/db/pkg && pkg_delete `ls | grep perl`");
/* Remove snort cron entries Ugly code needs smoothness*/
@@ -994,8 +1097,6 @@ function snort_rm_blocked_deinstall_cron($should_install)
global $config, $g;
conf_mount_rw();
-exec("echo \"Deinstall cron block....\" >> /root/test.log");
-
$is_installed = false;
if(!$config['cron']['item'])
@@ -1033,8 +1134,6 @@ exec("echo \"Deinstall cron block....\" >> /root/test.log");
{
global $config, $g;
conf_mount_rw();
-
-exec("echo \"Deinstall rules up ....\" >> /root/test.log");
$is_installed = false;
@@ -1072,6 +1171,7 @@ snort_rules_up_deinstall_cron("");
exec("rm -r /usr/local/www/snort");
exec("rm -r /usr/local/pkg/snort");
exec("rm -r /usr/local/lib/snort/");
+ exec("rm -r /var/log/snort/");
conf_mount_ro();
@@ -1080,17 +1180,14 @@ snort_rules_up_deinstall_cron("");
function generate_snort_conf($id, $if_real, $snort_uuid)
{
- global $config, $g, $id, $if_real, $snort_uuid;
+ global $config, $g;
+
conf_mount_rw();
-exec("echo \"Generate snort.conf $snort_uuid $if_real $id....\" >> /root/test.log");
-
/* obtain external interface */
/* XXX: make multi wan friendly */
$snort_ext_int = $config['installedpackages']['snortglobal']['rule'][$id]['interface'];
-// $snort_config_pass_thru = $config['installedpackages']['snortglobal']['rule'][$id]['configpassthru'];
-
/* create basic files */
if(!file_exists("/usr/local/etc/snort/snort/snort_{$snort_uuid}_{$if_real}"))
{
@@ -1131,7 +1228,7 @@ if ($tcpdumplog_info_chk == on)
/* define snortunifiedlog */
$snortunifiedlog_info_chk = $config['installedpackages']['snortglobal']['rule'][$id]['snortunifiedlog'];
if ($snortunifiedlog_info_chk == on)
- $snortunifiedlog_type = "output unified2: filename snort.u2_{$snort_uuid}_{$if_real}, limit 128";
+ $snortunifiedlog_type = "output unified2: filename snort_{$snort_uuid}_{$if_real}.u2, limit 128";
/* define spoink (DISABLED)*/
$spoink_info_chk = $config['installedpackages']['snortglobal']['rule'][$id]['blockoffenders7'];
@@ -1529,6 +1626,12 @@ if ($def_perform_stat_info_chk == "on")
else
$def_perform_stat_type = "";
+$def_flow_depth_info_chk = $config['installedpackages']['snortglobal']['rule'][$id]['flow_depth'];
+if ($def_flow_depth_info_chk == '')
+ $def_flow_depth_type = '0';
+else
+ $def_flow_depth_type = $config['installedpackages']['snortglobal']['rule'][$id]['flow_depth'];
+
/* def http_inspect */
$snort_http_inspect = <<<EOD
#################
@@ -1543,7 +1646,7 @@ preprocessor http_inspect_server: server default \
ports { 80 8080 } \
non_strict \
non_rfc_char { 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 } \
- flow_depth 0 \
+ flow_depth {$def_flow_depth_type} \
apache_whitespace no \
directory no \
iis_backslash no \
@@ -2002,7 +2105,6 @@ function check_for_common_errors($filename) {
hide_progress_bar_status();
} else {
log_error("An error occured. Scroll down to inspect it's contents.");
- echo "An error occured. Scroll down to inspect it's contents.";
}
if(!$console_mode) {
update_output_window(strip_tags("$contents"));
diff --git a/config/snort-dev/snort.sh b/config/snort-dev/snort.sh
index 5b725cfe..5b725cfe 100755..100644
--- a/config/snort-dev/snort.sh
+++ b/config/snort-dev/snort.sh
diff --git a/config/snort-dev/snort.xml b/config/snort-dev/snort.xml
index 36659a11..37ce9967 100644
--- a/config/snort-dev/snort.xml
+++ b/config/snort-dev/snort.xml
@@ -47,7 +47,7 @@
<faq>Currently there are no FAQ items provided.</faq>
<name>Snort</name>
<version>2.8.5.3</version>
- <title>Services: Snort 2.8.5.2 pkg v. 1.12</title>
+ <title>Services: Snort 2.8.5.2 pkg v. 1.18</title>
<include_file>/usr/local/pkg/snort/snort.inc</include_file>
<menu>
<name>Snort</name>
@@ -69,9 +69,9 @@
<item>http://www.pfsense.com/packages/config/snort-dev/snort.inc</item>
</additional_files_needed>
<additional_files_needed>
- <prefix>/usr/local/bin/</prefix>
+ <prefix>/usr/local/www/snort/</prefix>
<chmod>077</chmod>
- <item>http://www.pfsense.com/packages/config/snort-dev/bin/7.2.x86/barnyard2</item>
+ <item>http://www.pfsense.com/packages/config/snort-dev/snort_fbegin.inc</item>
</additional_files_needed>
<additional_files_needed>
<prefix>/usr/local/bin/</prefix>
diff --git a/config/snort-dev/snort_alerts.php b/config/snort-dev/snort_alerts.php
index 933db502..4f0ddb03 100644
--- a/config/snort-dev/snort_alerts.php
+++ b/config/snort-dev/snort_alerts.php
@@ -34,9 +34,9 @@
POSSIBILITY OF SUCH DAMAGE.
*/
-require("globals.inc");
-require("guiconfig.inc");
-require("/usr/local/pkg/snort/snort.inc");
+require_once("globals.inc");
+require_once("guiconfig.inc");
+require_once("/usr/local/pkg/snort/snort.inc");
$snortalertlogt = $config['installedpackages']['snortglobal']['snortalertlogtype'];
$snort_logfile = '/var/log/snort/alert';
@@ -311,7 +311,7 @@ include("head.inc");
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
<?php
-include("fbegin.inc");
+include("./snort_fbegin.inc");
echo "<p class=\"pgtitle\">";
if($pfsense_stable == 'yes'){echo $pgtitle;}
diff --git a/config/snort-dev/snort_barnyard.php b/config/snort-dev/snort_barnyard.php
index 667de21a..b8f05c47 100644
--- a/config/snort-dev/snort_barnyard.php
+++ b/config/snort-dev/snort_barnyard.php
@@ -38,8 +38,10 @@ Important add error checking
*/
-require("guiconfig.inc");
-require("/usr/local/pkg/snort/snort.inc");
+require_once("globals.inc");
+require_once("guiconfig.inc");
+require_once("/usr/local/pkg/snort/snort.inc");
+require_once("/usr/local/pkg/snort/snort_gui.inc");
if (!is_array($config['installedpackages']['snortglobal']['rule'])) {
$config['installedpackages']['snortglobal']['rule'] = array();
@@ -94,7 +96,7 @@ if (isset($id) && $a_nat[$id]) {
$pconfig['def_imap_servers'] = $a_nat[$id]['def_imap_servers'];
$pconfig['def_imap_ports'] = $a_nat[$id]['def_imap_ports'];
$pconfig['def_sip_proxy_ip'] = $a_nat[$id]['def_sip_proxy_ip'];
- $pconfig['ip def_sip_proxy_ports'] = $a_nat[$id]['ip def_sip_proxy_ports'];
+ $pconfig['def_sip_proxy_ports'] = $a_nat[$id]['def_sip_proxy_ports'];
$pconfig['def_auth_ports'] = $a_nat[$id]['def_auth_ports'];
$pconfig['def_finger_ports'] = $a_nat[$id]['def_finger_ports'];
$pconfig['def_irc_ports'] = $a_nat[$id]['def_irc_ports'];
@@ -127,8 +129,30 @@ if (isset($_GET['dup']))
unset($id);
$if_real = convert_friendly_interface_to_real_interface_name($pconfig['interface']);
+$snort_uuid = $config['installedpackages']['snortglobal']['rule'][$id]['uuid'];
-if ($_POST) {
+
+ /* alert file */
+$d_snortconfdirty_path = "/var/run/snort_conf_{$snort_uuid}_{$if_real}.dirty";
+
+ /* this will exec when alert says apply */
+ if ($_POST['apply']) {
+
+ if (file_exists($d_snortconfdirty_path)) {
+
+ write_config();
+
+ sync_snort_package_all();
+ sync_snort_package();
+
+ unlink($d_snortconfdirty_path);
+
+ }
+
+ }
+
+
+ if ($_POST["Submit"]) {
/* check for overlaps */
foreach ($a_nat as $natent) {
@@ -187,7 +211,7 @@ if ($_POST) {
if ($pconfig['def_imap_servers'] != "") { $natent['def_imap_servers'] = $pconfig['def_imap_servers']; }
if ($pconfig['def_imap_ports'] != "") { $natent['def_imap_ports'] = $pconfig['def_imap_ports']; }
if ($pconfig['def_sip_proxy_ip'] != "") { $natent['def_sip_proxy_ip'] = $pconfig['def_sip_proxy_ip']; }
- if ($pconfig['ip def_sip_proxy_ports'] != "") { $natent['ip def_sip_proxy_ports'] = $pconfig['ip def_sip_proxy_ports']; }
+ if ($pconfig['def_sip_proxy_ports'] != "") { $natent['def_sip_proxy_ports'] = $pconfig['def_sip_proxy_ports']; }
if ($pconfig['def_auth_ports'] != "") { $natent['def_auth_ports'] = $pconfig['def_auth_ports']; }
if ($pconfig['def_finger_ports'] != "") { $natent['def_finger_ports'] = $pconfig['def_finger_ports']; }
if ($pconfig['def_irc_ports'] != "") { $natent['def_irc_ports'] = $pconfig['def_irc_ports']; }
@@ -213,12 +237,16 @@ if ($_POST) {
$a_nat[] = $natent;
}
- /* enable this if you want the user to aprove changes */
- // touch($d_natconfdirty_path);
-
write_config();
/* after click go to this page */
+ touch($d_snortconfdirty_path);
+ header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
+ header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
+ header( 'Cache-Control: no-store, no-cache, must-revalidate' );
+ header( 'Cache-Control: post-check=0, pre-check=0', false );
+ header( 'Pragma: no-cache' );
+ sleep(2);
header("Location: snort_barnyard.php?id=$id");
exit;
}
@@ -230,7 +258,7 @@ include("head.inc");
?>
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
<?php
-include("fbegin.inc");
+include("./snort_fbegin.inc");
?>
<p class="pgtitle"><?if($pfsense_stable == 'yes'){echo $pgtitle;}?></p>
<style type="text/css">
@@ -269,9 +297,34 @@ echo "
//-->
</script>
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
-<?php if ($input_errors) print_input_errors($input_errors); ?>
-<?php if ($savemsg) print_info_box($savemsg); ?>
<form action="snort_barnyard.php" method="post" enctype="multipart/form-data" name="iform" id="iform">
+
+<?php
+
+ /* Display Alert message */
+ if ($input_errors) {
+ print_input_errors($input_errors); // TODO: add checks
+ }
+
+ if ($savemsg) {
+ print_info_box2($savemsg);
+ }
+
+ if (file_exists($d_snortconfdirty_path)) {
+ echo '<p>';
+
+ if($savemsg) {
+ print_info_box_np2("{$savemsg}");
+ }else{
+ print_info_box_np2('
+ The Snort configuration has changed and snort needs to be restarted on this interface.<br>
+ You must apply the changes in order for them to take effect.<br>
+ ');
+ }
+ }
+
+?>
+
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td class="tabnavtbl">
<?php
@@ -362,7 +415,7 @@ if($id != "")
<tr>
<td width="22%" valign="top">&nbsp;</td>
<td width="78%">
- <input name="Submit" type="submit" class="formbtn" value="Save"> <input name="Submit2" type="submit" class="formbtn" value="Start" onClick="enable_change(true)"> <input type="button" class="formbtn" value="Cancel" onclick="history.back()">
+ <input name="Submit" type="submit" class="formbtn" value="Save"><input type="button" class="formbtn" value="Cancel" onclick="history.back()">
<?php if (isset($id) && $a_nat[$id]): ?>
<input name="id" type="hidden" value="<?=$id;?>">
<?php endif; ?>
diff --git a/config/snort-dev/snort_blocked.php b/config/snort-dev/snort_blocked.php
index 39e9d5d1..293679d9 100644
--- a/config/snort-dev/snort_blocked.php
+++ b/config/snort-dev/snort_blocked.php
@@ -30,8 +30,9 @@
POSSIBILITY OF SUCH DAMAGE.
*/
-require("guiconfig.inc");
-require("/usr/local/pkg/snort/snort.inc");
+require_once("globals.inc");
+require_once("guiconfig.inc");
+require_once("/usr/local/pkg/snort/snort.inc");
$pconfig['brefresh'] = $config['installedpackages']['snortglobal']['alertsblocks']['brefresh'];
$pconfig['blertnumber'] = $config['installedpackages']['snortglobal']['alertsblocks']['blertnumber'];
@@ -232,7 +233,7 @@ include("head.inc");
<body link="#000000" vlink="#000000" alink="#000000">
<?php
-include("fbegin.inc");
+include("./snort_fbegin.inc");
echo "<p class=\"pgtitle\">";
if($pfsense_stable == 'yes'){echo $pgtitle;}
diff --git a/config/snort-dev/snort_check_for_rule_updates.php b/config/snort-dev/snort_check_for_rule_updates.php
index e626d895..6f95b101 100644
--- a/config/snort-dev/snort_check_for_rule_updates.php
+++ b/config/snort-dev/snort_check_for_rule_updates.php
@@ -39,8 +39,9 @@ $emergingthreats_filename = "emerging.rules.tar.gz";
$pfsense_rules_filename_md5 = "pfsense_rules.tar.gz.md5";
$pfsense_rules_filename = "pfsense_rules.tar.gz";
-require_once("config.inc");
-// require("/usr/local/pkg/snort/snort.inc");
+require_once("globals.inc");
+require_once("guiconfig.inc");
+require_once("/usr/local/pkg/snort/snort.inc");
/* define checks */
$oinkid = $config['installedpackages']['snortglobal']['oinkmastercode'];
diff --git a/config/snort-dev/snort_define_servers.php b/config/snort-dev/snort_define_servers.php
index 550cf153..dfda630b 100644
--- a/config/snort-dev/snort_define_servers.php
+++ b/config/snort-dev/snort_define_servers.php
@@ -38,12 +38,15 @@ Important add error checking
*/
-require("guiconfig.inc");
-require("/usr/local/pkg/snort/snort.inc");
+require_once("globals.inc");
+require_once("guiconfig.inc");
+require_once("/usr/local/pkg/snort/snort.inc");
+require_once("/usr/local/pkg/snort/snort_gui.inc");
if (!is_array($config['installedpackages']['snortglobal']['rule'])) {
$config['installedpackages']['snortglobal']['rule'] = array();
}
+
//nat_rules_sort();
$a_nat = &$config['installedpackages']['snortglobal']['rule'];
@@ -56,6 +59,7 @@ if (isset($_GET['dup'])) {
$after = $_GET['dup'];
}
+
if (isset($id) && $a_nat[$id]) {
/* old options */
@@ -94,7 +98,7 @@ if (isset($id) && $a_nat[$id]) {
$pconfig['def_imap_servers'] = $a_nat[$id]['def_imap_servers'];
$pconfig['def_imap_ports'] = $a_nat[$id]['def_imap_ports'];
$pconfig['def_sip_proxy_ip'] = $a_nat[$id]['def_sip_proxy_ip'];
- $pconfig['ip def_sip_proxy_ports'] = $a_nat[$id]['ip def_sip_proxy_ports'];
+ $pconfig['def_sip_proxy_ports'] = $a_nat[$id]['def_sip_proxy_ports'];
$pconfig['def_auth_ports'] = $a_nat[$id]['def_auth_ports'];
$pconfig['def_finger_ports'] = $a_nat[$id]['def_finger_ports'];
$pconfig['def_irc_ports'] = $a_nat[$id]['def_irc_ports'];
@@ -124,7 +128,8 @@ if (isset($_GET['dup']))
/* convert fake interfaces to real */
$if_real = convert_friendly_interface_to_real_interface_name($pconfig['interface']);
-if ($_POST) {
+
+ if ($_POST["Submit"]) {
/* check for overlaps */
@@ -155,7 +160,7 @@ if ($_POST) {
if ($pconfig['barnyard_mysql'] != "") { $natent['barnyard_mysql'] = $pconfig['barnyard_mysql']; }
if ($pconfig['rulesets'] != "") { $natent['rulesets'] = $pconfig['rulesets']; }
if ($pconfig['rule_sid_off'] != "") { $natent['rule_sid_off'] = $pconfig['rule_sid_off']; }
- if ($pconfig['rule_sid_on'] != "") { $natent['rule_sid_on'] = $pconfig['brule_sid_on']; }
+ if ($pconfig['rule_sid_on'] != "") { $natent['rule_sid_on'] = $pconfig['rule_sid_on']; }
/* post new options */
@@ -203,24 +208,52 @@ if ($_POST) {
$a_nat[] = $natent;
}
- /* enable this if you want the user to aprove changes */
- // touch($d_natconfdirty_path);
-
write_config();
/* after click go to this page */
+
+ touch($d_snortconfdirty_path);
+
+ header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
+ header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
+ header( 'Cache-Control: no-store, no-cache, must-revalidate' );
+ header( 'Cache-Control: post-check=0, pre-check=0', false );
+ header( 'Pragma: no-cache' );
+ sleep(2);
+
header("Location: snort_define_servers.php?id=$id");
+
exit;
}
}
+
+ /* alert file */
+$d_snortconfdirty_path = "/var/run/snort_conf_{$pconfig['uuid']}_{$if_real}.dirty";
+
+ /* this will exec when alert says apply */
+ if ($_POST['apply']) {
+
+ if (file_exists($d_snortconfdirty_path)) {
+
+ write_config();
+
+ sync_snort_package_all();
+ sync_snort_package();
+
+ unlink($d_snortconfdirty_path);
+
+ }
+
+ }
+
$pgtitle = "Snort: Interface $id$if_real Define Servers";
include("head.inc");
?>
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
<?php
-include("fbegin.inc");
+include("./snort_fbegin.inc");
?>
<p class="pgtitle"><?if($pfsense_stable == 'yes'){echo $pgtitle;}?></p>
<style type="text/css">
@@ -239,9 +272,36 @@ padding: 15px 10px 85% 50px;
<noscript><div class="alert" ALIGN=CENTER><img src="/themes/nervecenter/images/icons/icon_alert.gif"/><strong>Please enable JavaScript to view this content</CENTER></div></noscript>
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
-<?php if ($input_errors) print_input_errors($input_errors); ?>
-<?php if ($savemsg) print_info_box($savemsg); ?>
+
<form action="snort_define_servers.php" method="post" enctype="multipart/form-data" name="iform" id="iform">
+
+<?php
+
+ /* Display message */
+
+ if ($input_errors) {
+ print_input_errors($input_errors); // TODO: add checks
+ }
+
+ if ($savemsg) {
+ print_info_box2($savemsg);
+ }
+
+ if (file_exists($d_snortconfdirty_path)) {
+ echo '<p>';
+
+ if($savemsg) {
+ print_info_box_np2("{$savemsg}");
+ }else{
+ print_info_box_np2('
+ The Snort configuration has changed and snort needs to be restarted on this interface.<br>
+ You must apply the changes in order for them to take effect.<br>
+ ');
+ }
+ }
+
+?>
+
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td class="tabnavtbl">
<?php
diff --git a/config/snort-dev/snort_download_rules.php b/config/snort-dev/snort_download_rules.php
index c150a934..b2bcb748 100644
--- a/config/snort-dev/snort_download_rules.php
+++ b/config/snort-dev/snort_download_rules.php
@@ -30,10 +30,11 @@
/* Setup enviroment */
-require("guiconfig.inc");
+/* TODO: review if include files are needed */
+require_once("guiconfig.inc");
require_once("functions.inc");
require_once("service-utils.inc");
-require("/usr/local/pkg/snort/snort.inc");
+require_once("/usr/local/pkg/snort/snort.inc");
$tmpfname = "/tmp/snort_rules_up";
$snortdir = "/usr/local/etc/snort";
@@ -74,16 +75,44 @@ $emergingthreats = $config['installedpackages']['snortglobal']['emergingthreats'
$if_mrule_dir = "/usr/local/etc/snort/rules";
$mfolder_chk = (count(glob("$if_mrule_dir/*")) === 0) ? 'empty' : 'full';
+
+if (file_exists('/var/run/snort.conf.dirty')) {
+ $snort_dirty_d = 'stop';
+}
+
+
+
/* If no id show the user a button */
-if ($id_d == "" || $snort_emrging_info == "stop" || $snort_oinkid_info == "stop") {
+if ($id_d == "" || $snort_emrging_info == "stop" || $snort_oinkid_info == "stop" || $snort_dirty_d == 'stop') {
$pgtitle = "Services: Snort: Rule Updates";
include("head.inc");
-include("fbegin.inc");
+include("./snort_fbegin.inc");
echo "<p class=\"pgtitle\">";
if($pfsense_stable == 'yes'){echo $pgtitle;}
echo "</p>\n";
+
+ echo "<table height=\"32\" width=\"100%\">\n";
+ echo " <tr>\n";
+ echo " <td>\n";
+ echo " <div style='background-color:#E0E0E0' id='redbox'>\n";
+ echo " <table width='100%'><tr><td width='8%'>\n";
+ echo " &nbsp;&nbsp;&nbsp;<img style='vertical-align:middle' src=\"/snort/images/icon_excli.png\" width=\"40\" height=\"32\">\n";
+ echo " </td>\n";
+ echo " <td width='70%'><font color='#FF850A'><b>NOTE:</b></font><font color='#000000'>&nbsp;&nbsp;Snort.org and Emergingthreats.net will go down from time to time. Please be patient.</font>\n";
+ echo " </td>";
+ echo " </tr></table>\n";
+ echo " </div>\n";
+ echo " </td>\n";
+ echo "</table>\n";
+ echo "<script type=\"text/javascript\">\n";
+ echo "NiftyCheck();\n";
+ echo "Rounded(\"div#redbox\",\"all\",\"#FFF\",\"#E0E0E0\",\"smooth\");\n";
+ echo "Rounded(\"td#blackbox\",\"all\",\"#FFF\",\"#000000\",\"smooth\");\n";
+ echo "</script>\n";
+ echo "\n<br>\n";
+
/* make sure user has javascript on */
echo "<style type=\"text/css\">
.alert {
@@ -145,6 +174,9 @@ if ($snort_oinkid_info == "stop") {
echo "<span class=\"red\"><strong>WARNING:</strong></span> &nbsp;&nbsp;Click on the <strong>\"Global Settings\"</strong> tab and enter a <strong>oinkmaster</strong> code. <br><br> \n";
}
+if ($snort_dirty_d == "stop") {
+echo "<span class=\"red\"><strong>WARNING:</span> CHANGES HAVE NOT BEEN APPLIED</strong> &nbsp;&nbsp;Click on the <strong>\"Apply Settings\"</strong> button at the main interface tab.<br><br> \n";
+}
echo " </td>\n
</tr>\n
@@ -219,7 +251,7 @@ setTimeout($.unblockUI, 2000);
</script>
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
-<?php include("/usr/local/www/fbegin.inc"); ?>
+<?php include("./snort_fbegin.inc"); ?>
<p class="pgtitle"><?if($pfsense_stable == 'yes'){echo $pgtitle;}?></p>
<form action="snort_download_rules.php" method="post">
diff --git a/config/snort-dev/snort_fbegin.inc b/config/snort-dev/snort_fbegin.inc
new file mode 100644
index 00000000..b8faff09
--- /dev/null
+++ b/config/snort-dev/snort_fbegin.inc
@@ -0,0 +1,288 @@
+<?php
+
+require_once("globals.inc");
+require_once("notices.inc");
+/* $Id$ */
+ function return_ext_menu($section) {
+ global $config;
+ $htmltext = "";
+ if($config['installedpackages']['menu'] <> "") {
+ foreach($config['installedpackages']['menu'] as $menuitem) {
+ if($menuitem['section'] != $section) continue;
+ if($menuitem['url'] <> "") {
+ $addresswithport = getenv("HTTP_HOST");
+ $colonpos = strpos($addresswithport, ":");
+ if ($colonpos !== False){
+ //my url is actually just the IP address of the pfsense box
+ $myurl = substr($addresswithport, 0, $colonpos);
+ }
+ else
+ {
+ $myurl = $addresswithport;
+ }
+
+ $description = str_replace('$myurl', $myurl, $menuitem['url']);
+ } else {
+ $description = '/pkg.php?xml=' . $menuitem['configfile'];
+ }
+ $htmltext .= '<li><a href="' . $description . ' "class="navlnk">' . $menuitem['name'] . '</a></li>' . "\n";
+ }
+ }
+ return $htmltext;
+ }
+
+
+
+
+ /* NOTICE ACKNOWLEDGE CODE by Erik Kristensen */
+ if ($_REQUEST['noticeaction'] == 'acknowledge') {
+ $notice_id = $_REQUEST['noticeid'];
+ close_notice($notice_id);
+ }
+ /**********************************************/
+?>
+
+<div id="wrapper">
+
+ <div id="header">
+ <div id="header-left"><a href="../index.php" id="status-link"><img src="/themes/<?= $g['theme']; ?>/images/transparent.gif" border="0"></img></a></div>
+ <div id="header-right">
+ <div class="container">
+ <div class="left">webConfigurator</div>
+ <div class="right">
+<?
+ if (are_notices_pending()) {
+ $notices = get_notices();
+
+ $requests=array();
+
+ ## Get Query Arguments from URL ###
+ foreach ($_REQUEST as $key => $value) {
+ if ($key != "PHPSESSID")
+ $requests[] = $key.'='.$value;
+ }
+ if(is_array($requests))
+ $request_string = implode("&", $requests);
+
+ if(is_array($notices)) {
+ foreach ($notices as $key => $value) {
+ $date = date("m-d-y H:i:s", $key);
+ $noticemsg = str_replace("'", "", $value['notice']);
+ $noticemsg = str_replace('"', "", $noticemsg);
+ $noticemsg = str_replace("\n", "", $noticemsg);
+ $noticemsg = str_replace("<p>", "", $noticemsg);
+ $noticemsg = str_replace("<pre>", "", $noticemsg);
+ $noticemsg = str_replace("</pre>", "", $noticemsg);
+ $noticemsg = str_replace("</p>", "", $noticemsg);
+ $noticemsg = str_replace("<br>", "", $noticemsg);
+ $extra_args = "";
+ if($_GET['xml'])
+ $extraargs="&xml=" . $_GET['xml'];
+ if($_POST['xml'])
+ $extraargs="&xml=" . $_POST['xml'];
+ if($_GET['id'])
+ $extraargs="&xml=" . $_GET['id'];
+ if($_POST['id'])
+ $extraargs="&xml=" . $_POST['id'];
+ $notice_msgs = '<a href="?noticeaction=acknowledge&noticeid=all' . $extraargs . '">Acknowledge All</a> &nbsp;&nbsp;&nbsp;&nbsp;.:.&nbsp;&nbsp;&nbsp;&nbsp; ';
+ if ($value['url']) {
+ $notice_msgs .= $date.' - <a href="'.$url.'?'.$request_string.'&noticeaction=acknowledge&noticeid='.$key.'">['.$value['id'].']</a>';
+ } else {
+ $notice_msgs .= $date.' - <a href="?'.$request_string.'&noticeaction=acknowledge&noticeid='.$key.'">['.$value['id'].']'.$noticemsg.'</a>';
+ }
+ $notice_msgs .= " &nbsp;&nbsp;&nbsp;&nbsp;.:.&nbsp;&nbsp;&nbsp;&nbsp; ";
+ }
+ }
+?>
+ <div id="alerts">
+ <script type="text/javascript">
+ var content='<div id="marquee-text"><?= $notice_msgs; ?></div>'
+ </script>
+ <script type="text/javascript" src="/ticker.js"></script>
+ </div>
+<?
+ } else {
+?>
+ <div id="hostname">
+ <? print $config['system']['hostname'] . "." . $config['system']['domain']; ?>
+ </div>
+<?
+ }
+?>
+ </div>
+ </div>
+ </div>
+ </div> <!-- Header DIV -->
+ <div id="content">
+ <div id="left">
+ <div id="navigation" style="z-index:1000">
+ <ul id="menu">
+ <li class="firstdrop">
+ <div>System</div>
+ <ul class="subdrop">
+ <li><a href="/system_advanced.php" class="navlnk">Advanced</a></li>
+ <li><a href="/system_firmware.php" class="navlnk">Firmware</a></li>
+ <li><a href="/system.php" class="navlnk">General Setup</a></li>
+ <?php if($g['platform'] == "pfSense" or $g['platform'] == "nanobsd"): ?>
+ <li><a href="/pkg_mgr.php" class="navlnk">Packages</a></li>
+ <?php endif; ?>
+ <li><a href="/wizard.php?xml=setup_wizard.xml" class="navlnk">Setup wizard</a></li>
+ <li><a href="/system_routes.php" class="navlnk">Static routes</a></li>
+ </ul>
+ </li>
+ <li class="drop">
+ <div>Interfaces</div>
+ <ul class="subdrop">
+ <?php if (!isset($config['system']['webgui']['noassigninterfaces'])): ?><li><a href="/interfaces_assign.php" class="navlnks">(assign)</a></li><?php endif; ?>
+ <li><a href="/interfaces_wan.php" class="navlnk">WAN</a></li>
+ <li><a href="/interfaces_lan.php" class="navlnk">LAN</a></li>
+ <?php for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++): if (!isset($config['interfaces']['opt' . $i]['ovpn'])): ?>
+ <li><a href="/interfaces_opt.php?index=<?=$i;?>" class="navlnk"><?=htmlspecialchars($config['interfaces']['opt' . $i]['descr']);?></a></li>
+ <?php endif; endfor; ?>
+ <?php echo return_ext_menu("Interfaces"); ?>
+ </ul>
+ </li>
+<?php
+ if($config['system']['shapertype'] <> "m0n0")
+ $shaper = "firewall_shaper.php";
+ else
+ $shaper = "m0n0/firewall_shaper.php";
+?>
+ <li class="drop">
+ <div>Firewall</div>
+ <ul class="subdrop">
+ <li><a href="/firewall_aliases.php" class="navlnk">Aliases</a></li>
+ <li><a href="/firewall_nat.php" class="navlnk">NAT</a></li>
+ <li><a href="/firewall_rules.php" class="navlnk">Rules</a></li>
+ <li><a href="/firewall_schedule.php" class="navlnk">Schedules</a></li>
+ <li><a href="<?=$shaper?>" class="navlnk">Traffic Shaper</a></li>
+ <li><a href="/firewall_virtual_ip.php" class="navlnk">Virtual IPs</a></li>
+ <?php echo return_ext_menu("Firewall"); ?>
+ </ul>
+ </li>
+ <li class="drop">
+ <div>Services</div>
+ <ul class="subdrop">
+ <li><a href="/services_captiveportal.php" class="navlnk">Captive portal</a></li>
+ <li><a href="/services_dnsmasq.php" class="navlnk">DNS forwarder</a></li>
+ <li><a href="/services_dhcp_relay.php" class="navlnk">DHCP relay</a></li>
+ <li><a href="/services_dhcp.php" class="navlnk">DHCP server</a></li>
+ <li><a href="/services_dyndns.php" class="navlnk">Dynamic DNS</a></li>
+ <li><a href="/load_balancer_pool.php" class="navlnk">Load Balancer</a></li>
+ <li><a href="/pkg_edit.php?xml=olsrd.xml&id=0" class="navlnk">OLSR</a></li>
+ <li><a href="/vpn_pppoe.php" class="navlnk">PPPoE Server</a></li>
+ <li><a href="/pkg_edit.php?xml=routed/routed.xml&id=0" class="navlnk">RIP</a></li>
+ <li><a href="/services_snmp.php" class="navlnk">SNMP</a></li>
+ <li><a href="/pkg_edit.php?xml=miniupnpd.xml&id=0" class="navlnk">UPnP</a></li>
+ <li><a href="/pkg_edit.php?xml=openntpd.xml&id=0" class="navlnk">OpenNTPD</a></li>
+ <li><a href="/services_wol.php" class="navlnk">Wake on LAN</a></li>
+ <?php echo return_ext_menu("Services"); ?>
+ </ul>
+ </li>
+ <li class="drop">
+ <div>VPN</div>
+ <ul class="subdrop">
+ <li><a href="/vpn_ipsec.php" class="navlnk">IPsec</a></li>
+ <li><a href="/pkg.php?xml=openvpn.xml" class="navlnk">OpenVPN</a></li>
+ <li><a href="/vpn_pptp.php" class="navlnk">PPTP</a></li>
+ <?php echo return_ext_menu("VPN"); ?>
+ </ul>
+ </li>
+ <li class="drop">
+ <div>Status</div>
+ <ul class="subdrop">
+ <?php if (isset($config['captiveportal']['enable'])): ?>
+ <li><a href="/status_captiveportal.php" class="navlnk">Captive portal</a></li>
+ <?php endif; ?>
+ <li><a href="/carp_status.php" class="navlnk">CARP (failover)</a></li>
+ <li><a href="/diag_dhcp_leases.php" class="navlnk">DHCP leases</a></li>
+ <li><a href="/status_filter_reload.php" class="navlnk">Filter Reload Status</a></li>
+ <li><a href="/status_interfaces.php" class="navlnk">Interfaces</a></li>
+ <li><a href="/diag_ipsec.php" class="navlnk">IPsec</a></li>
+ <li><a href="/status_slbd_pool.php" class="navlnk">Load Balancer</a></li>
+ <?php if($g['platform'] == "pfSense"): ?>
+ <li><a href="/diag_pkglogs.php" class="navlnk">Package logs</a></li>
+ <?php endif; ?>
+ <li><a href="/status_queues.php" class="navlnk">Queues</a></li>
+ <li><a href="/status_rrd_graph.php" class="navlnk">RRD Graphs</a></li>
+ <li><a href="/status_services.php" class="navlnk">Services</a></li>
+ <li><a href="/index.php" class="navlnk">System</a></li>
+ <li><a href="/diag_logs.php" class="navlnk">System logs</a></li>
+ <li><a href="/status_graph.php?if=wan" class="navlnk">Traffic graph</a></li>
+ <li><a href="/status_upnp.php" class="navlnk">UPnP</a></li>
+ <?php $i = 0; $ifdescrs = array();
+ if (is_array($config['interfaces']['wan']['wireless']) &&
+ preg_match($g['wireless_regex'], $config['interfaces']['wan']['if']))
+ $ifdescrs['wan'] = 'WAN';
+ if (is_array($config['interfaces']['lan']['wireless']) &&
+ preg_match($g['wireless_regex'], $config['interfaces']['lan']['if']))
+ $ifdescrs['lan'] = 'LAN';
+ for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
+ if (is_array($config['interfaces']['opt' . $j]['wireless']) &&
+ isset($config['interfaces']['opt' . $j]['enable']) &&
+ preg_match($g['wireless_regex'], $config['interfaces']['opt' . $j]['if']))
+ $ifdescrs['opt' . $j] = $config['interfaces']['opt' . $j]['descr'];
+ }
+ if (count($ifdescrs) > 0): ?>
+ <li><a href="/status_wireless.php" class="navlnk">Wireless</a></li>
+ <?php endif; ?>
+ <?php echo return_ext_menu("Status"); ?>
+ </ul>
+ </li>
+ <li class="lastdrop">
+ <div>Diagnostics</div>
+ <ul id="diag" class="subdrop">
+ <li><a href="/diag_arp.php" class="navlnk">ARP Tables</a></li>
+ <li><a href="/diag_backup.php" class="navlnk">Backup/Restore</a></li>
+ <li><a href="/exec.php" class="navlnk">Command Prompt</a></li>
+ <li><a href="/edit.php" class="navlnk">Edit File</a></li>
+ <li><a href="/diag_defaults.php" class="navlnk">Factory defaults </a></li>
+ <li><a href="/halt.php" class="navlnk">Halt system</a></li>
+<?php if($g['platform']=="nanobsd"): ?>
+ <li><a href="/diag_nanobsd.php" class="navlnk">NanoBSD</a></li>
+<?php endif; ?>
+ <li><a href="/diag_ping.php" class="navlnk">Ping</a></li>
+ <li><a href="/reboot.php" class="navlnk">Reboot system</a></li>
+ <li><a href="/diag_routes.php" class="navlnk">Routes</a></li>
+ <li><a href="/diag_dump_states.php" class="navlnk">States</a></li>
+ <li><a href="/diag_traceroute.php" class="navlnk">Traceroute</a></li>
+ <li><a href="/diag_packet_capture.php" class="navlnk">Packet Capture</a></li>
+ <?php echo return_ext_menu("Diagnostics"); ?>
+ <?php if(isset($config['system']['developer'])): ?>
+ <li><hr width="80%"/></li>
+ <li><a href="/restart_httpd.php" class="navlnk">Restart HTTPD</a></li>
+ <?php endif; ?>
+ </ul>
+ </li>
+ </ul>
+ </div>
+
+ </div> <!-- Left DIV -->
+
+ <div id="right">
+
+
+<?php
+ /* display a top alert bar if need be */
+ $need_alert_display = false;
+ $found_notices = are_notices_pending();
+ if($found_notices == true) {
+ $notices = get_notices();
+ if(!$notices) {
+ $need_alert_display = true;
+ $display_text = print_notices() . "<br>";
+ }
+ }
+ if($need_alert_display == true) {
+ echo "<div style=\"background-color:#000000\" id=\"roundalert\">";
+ echo "<table>";
+ echo "<tr><td><font color=\"#ffffff\">";
+ echo "&nbsp;&nbsp;<img align=\"middle\" src=\"/top_notification.gif\">&nbsp;&nbsp;&nbsp;";
+ echo $display_text;
+ echo "</td>";
+ echo "</tr>";
+ echo "</table>";
+ echo "</div>";
+ }
+
+?> \ No newline at end of file
diff --git a/config/snort-dev/snort_gui.inc b/config/snort-dev/snort_gui.inc
index c485d1ac..95a0e597 100644
--- a/config/snort-dev/snort_gui.inc
+++ b/config/snort-dev/snort_gui.inc
@@ -59,10 +59,8 @@ function print_info_box_np2($msg) {
echo "</script>\n";
echo "\n<br>\n";
- exec("echo \"Funtion print info ....\" >> /root/test.log");
-
}
-?> \ No newline at end of file
+?>
diff --git a/config/snort-dev/snort_help_info.php b/config/snort-dev/snort_help_info.php
index f8d57d91..5355ec77 100644
--- a/config/snort-dev/snort_help_info.php
+++ b/config/snort-dev/snort_help_info.php
@@ -1,107 +1,191 @@
-<?php
-/* $Id$ */
-/*
- halt.php
- part of pfSense
- Copyright (C) 2004 Scott Ullrich
- All rights reserved.
-
- part of m0n0wall as reboot.php (http://m0n0.ch/wall)
- Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
-*/
-
-require("guiconfig.inc");
-
-header("snort_help_info.php");
-header( "Expires: Mon, 20 Dec 1998 01:00:00 GMT" );
-header( "Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT" );
-header( "Cache-Control: no-cache, must-revalidate" );
-header( "Pragma: no-cache" );
-
-$pgtitle = "Snort: Services: Help and Info";
-include('head.inc');
-?>
-<style type="text/css">
-iframe
-{
- border: 0;
-}
-
-#footer2
-{
- position: relative;
- top: -2px;
- background-color: #cccccc;
- background-image: none;
- background-repeat: repeat;
- background-attachment: scroll;
- background-position: 0% 0%;
- padding-top: 0px;
- padding-right: 0px;
- padding-bottom: 0px;
- padding-left: 0px;
-}
-
-</style>
-<body>
-<?php include("fbegin.inc"); ?>
-
-<table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tr>
- <td>
-<?php
- $tab_array = array();
- $tab_array[] = array("Snort Interfaces", false, "/snort/snort_interfaces.php");
- $tab_array[] = array("Global Settings", false, "/snort/snort_interfaces_global.php");
- $tab_array[] = array("Rule Updates", false, "/snort/snort_download_rules.php");
- $tab_array[] = array("Alerts", false, "/snort/snort_alerts.php");
- $tab_array[] = array("Blocked", false, "/snort/snort_blocked.php");
- $tab_array[] = array("Whitelists", false, "/pkg.php?xml=/snort/snort_whitelist.xml");
- $tab_array[] = array("Help & Info", true, "/snort/snort_help_info.php");
- display_top_tabs($tab_array);
-?>
- </td>
-</tr>
-</table>
-<div>
- <iframe style="width: 780px; height: 600px; overflow-x: hidden;" src='/snort/help_and_info.php'></iframe>
-</div>
-</div>
- <div id="footer2">
- <IMG SRC="./images/footer.jpg" width="780px" height="63" ALT="Apps">
- <font size="1">Snort® is a registered trademark of Sourcefire, Inc., Barnyard2® is a registered trademark of securixlive.com., Orion® copyright Robert Zelaya.,
- Emergingthreats is a registered trademark of emergingthreats.net., Mysql® is a registered trademark of Mysql.com.</font>
- </div>
-</div>
- <div id="footer">
- <a target="_blank" href="http://www.pfsense.org/?gui12" class="redlnk">pfSense</a> is &copy;
- 2004 - 2009 by <a href="http://www.bsdperimeter.com" class="tblnk">BSD Perimeter LLC</a>. All Rights Reserved.
- <a href="/license.php" class="tblnk">view license</a>]
- <br/>
-
- <a target="_blank" href="https://portal.pfsense.org/?guilead=true" class="tblnk">Commercial Support Available</a>
- </div> <!-- Footer DIV -->
-</body>
-</html>
+<?php
+/* $Id$ */
+/*
+ halt.php
+ part of pfSense
+ Copyright (C) 2004 Scott Ullrich
+ All rights reserved.
+
+ part of m0n0wall as reboot.php (http://m0n0.ch/wall)
+ Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once("guiconfig.inc");
+require_once("/usr/local/pkg/snort/snort.inc");
+
+header("snort_help_info.php");
+header( "Expires: Mon, 20 Dec 1998 01:00:00 GMT" );
+header( "Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT" );
+header( "Cache-Control: no-cache, must-revalidate" );
+header( "Pragma: no-cache" );
+
+$pgtitle = "Snort: Services: Help and Info";
+include('head.inc');
+?>
+<style type="text/css">
+iframe
+{
+ border: 0;
+}
+
+#footer2
+{
+
+top: 135px;
+position: relative;
+background-color: #FFFFFF;
+background-image: url("./images/footer.jpg");
+background-repeat: no-repeat;
+background-attachment: scroll;
+background-position: 0px 0px;
+bottom: 0px;
+width: 780px;
+height: 63px;
+color: #000000;
+text-align: center;
+font-size: 0.8em;
+padding-top:64px;
+padding-left: 0px;
+clear: both;
+
+}
+
+</style>
+<body>
+<?php include("./snort_fbegin.inc"); ?>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("Snort Interfaces", false, "/snort/snort_interfaces.php");
+ $tab_array[] = array("Global Settings", false, "/snort/snort_interfaces_global.php");
+ $tab_array[] = array("Rule Updates", false, "/snort/snort_download_rules.php");
+ $tab_array[] = array("Alerts", false, "/snort/snort_alerts.php");
+ $tab_array[] = array("Blocked", false, "/snort/snort_blocked.php");
+ $tab_array[] = array("Whitelists", false, "/pkg.php?xml=/snort/snort_whitelist.xml");
+ $tab_array[] = array("Help & Info", true, "/snort/snort_help_info.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+</tr>
+</table>
+
+<?php
+/* TODO: remove when 2.0 stable */
+if ($pfsense_stable == 'yes') {
+
+$footer2 = "
+
+<style type=\"text/css\">
+
+#footer2
+{
+ position: relative;
+ top: 27px;
+ background-color: #cccccc;
+ background-image: none;
+ background-repeat: repeat;
+ background-attachment: scroll;
+ background-position: 0% 0%;
+ width: 810px;
+ right: 15px;
+ font-size: 0.8em;
+ text-align: center;
+ padding-top: 0px;
+ padding-right: 0px;
+ padding-bottom: 0px;
+ padding-left: 0px;
+ clear: both;
+}
+
+</style>
+
+ <div id=\"footer2\">
+ <IMG SRC=\"./images/footer2.jpg\" width=\"800px\" height=\"35\" ALT=\"Apps\">
+ Snort is a registered trademark of Sourcefire, Inc, Barnyard2 is a registered trademark of securixlive.com, Orion copyright Robert Zelaya,
+ Emergingthreats is a registered trademark of emergingthreats.net, Mysql is a registered trademark of Mysql.com
+ </div>\n";
+}
+
+if ($pfsense_stable != 'yes') {
+$footer3 = "
+
+<style type=\"text/css\">
+
+#footer3
+{
+
+top: 105px;
+position: relative;
+background-color: #FFFFFF;
+background-image: url(\"./images/footer2.jpg\");
+background-repeat: no-repeat;
+background-attachment: scroll;
+background-position: 0px 0px;
+bottom: 0px;
+width: 770px;
+height: 35px;
+color: #000000;
+text-align: center;
+font-size: 0.8em;
+padding-top: 35px;
+padding-left: 0px;
+clear: both;
+
+}
+
+</style>
+
+ <div id=\"footer3\">
+ Snort is a registered trademark of Sourcefire, Inc, Barnyard2 is a registered trademark of securixlive.com, Orion copyright Robert Zelaya,
+ Emergingthreats is a registered trademark of emergingthreats.net, Mysql is a registered trademark of Mysql.com
+ </div>\n";
+}
+?>
+
+
+<div>
+ <iframe style="width: 780px; height: 600px; overflow-x: hidden;" src='/snort/help_and_info.php'></iframe>
+</div>
+
+<?php echo $footer2;?>
+
+</div>
+</div>
+
+<?php //echo $footer3;?>
+
+ <div id="footer">
+ <a target="_blank" href="http://www.pfsense.org/?gui12" class="redlnk">pfSense</a> is &copy;
+ 2004 - 2009 by <a href="http://www.bsdperimeter.com" class="tblnk">BSD Perimeter LLC</a>. All Rights Reserved.
+ <a href="/license.php" class="tblnk">view license</a>]
+ <br/>
+
+ <a target="_blank" href="https://portal.pfsense.org/?guilead=true" class="tblnk">Commercial Support Available</a>
+ </div> <!-- Footer DIV -->
+</body>
+</html>
diff --git a/config/snort-dev/snort_interfaces.php b/config/snort-dev/snort_interfaces.php
index b5bb7781..b2f72aad 100644
--- a/config/snort-dev/snort_interfaces.php
+++ b/config/snort-dev/snort_interfaces.php
@@ -29,63 +29,59 @@
POSSIBILITY OF SUCH DAMAGE.
*/
-require("guiconfig.inc");
-require("/usr/local/pkg/snort/snort_gui.inc");
-include_once("/usr/local/pkg/snort/snort.inc");
+require_once("guiconfig.inc");
+require_once("/usr/local/pkg/snort/snort_gui.inc");
+require_once("/usr/local/pkg/snort/snort.inc");
+
$id = $_GET['id'];
if (isset($_POST['id']))
$id = $_POST['id'];
+
if (!is_array($config['installedpackages']['snortglobal']['rule']))
$config['installedpackages']['snortglobal']['rule'] = array();
$a_nat = &$config['installedpackages']['snortglobal']['rule'];
-///////////
-
if (isset($config['installedpackages']['snortglobal']['rule'])) {
$id_gen = count($config['installedpackages']['snortglobal']['rule']);
}else{
$id_gen = '0';
}
-///////////
-
-/* if a custom message has been passed along, lets process it */
-if ($_GET['savemsg'])
- $savemsg = $_GET['savemsg'];
-
-if ($_POST) {
-
- $pconfig = $_POST;
+/* alert file */
+$d_snortconfdirty_path_ls = exec('/bin/ls /var/run/snort_conf_*.dirty');
+
+ /* this will exec when alert says apply */
if ($_POST['apply']) {
-
- write_config();
-
- $retval = 0;
-
- if(stristr($retval, "error") <> true)
- $savemsg = get_std_save_message($retval);
- else
- $savemsg = $retval;
-
- unlink_if_exists("/tmp/config.cache");
- $retval |= filter_configure();
-
- if ($retval == 0) {
- if (file_exists($d_natconfdirty_path))
- unlink($d_natconfdirty_path);
- if (file_exists($d_filterconfdirty_path))
- unlink($d_filterconfdirty_path);
+
+ if ($d_snortconfdirty_path_ls != '') {
+
+ write_config();
+
+ sync_snort_package_empty();
+ sync_snort_package();
+
+ exec('/bin/rm /var/run/snort_conf_*.dirty');
+
+ header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
+ header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
+ header( 'Cache-Control: no-store, no-cache, must-revalidate' );
+ header( 'Cache-Control: post-check=0, pre-check=0', false );
+ header( 'Pragma: no-cache' );
+ sleep(2);
+ header("Location: /snort/snort_interfaces.php");
+
+ exit;
+
}
-
- exec("echo \"Sync Empty on POST on interfaces.php....\" >> /root/test.log");
-
+
}
-}
-
+
+
+
if (isset($_POST['del_x'])) {
/* delete selected rules */
if (is_array($_POST['rule']) && count($_POST['rule'])) {
@@ -164,14 +160,21 @@ if (isset($_POST['del_x'])) {
unset($a_nat[$rulei]);
}
- exec("echo \"Removing old files ....\" >> /root/test.log");
conf_mount_rw();
exec("/bin/rm /var/log/snort/snort.u2_{$snort_uuid}_{$if_real}*");
exec("/bin/rm -r /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}");
conf_mount_ro();
write_config();
- touch($d_natconfdirty_path);
+
+ touch("/var/run/snort_conf_delete.dirty");
+
+ header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
+ header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
+ header( 'Cache-Control: no-store, no-cache, must-revalidate' );
+ header( 'Cache-Control: post-check=0, pre-check=0', false );
+ header( 'Pragma: no-cache' );
+ sleep(2);
header("Location: /snort/snort_interfaces.php");
exit;
}
@@ -180,67 +183,23 @@ if (isset($_POST['del_x'])) {
/* start/stop snort */
-if ($_GET['act'] == "toggle" && $_GET['id'] != "")
+if ($_GET['act'] == 'toggle' && $_GET['id'] != '')
{
- $if_real2 = convert_friendly_interface_to_real_interface_name($a_nat[$id]['interface']);
-
- $snort_uuid = $a_nat[$id]['uuid'];
-
- $start_up_pre = exec("/usr/bin/top -a -U snort -u | grep -v grep | grep \"R {$snort_uuid}_{$if_real2}\" | awk '{print \$1;}'");
- $start_up_s = exec("/usr/bin/top -U snort -u | grep snort | grep {$start_up_pre} | awk '{ print $1; }'");
- $start_up_r = exec("/usr/bin/top -U root -u | grep snort | grep {$start_up_pre} | awk '{ print $1; }'");
-
- //$start2_upb_pre = exec("/bin/cat /var/run/barnyard2_{$id}{$if_real2}.pid");
- //$start2_upb_s = exec("/usr/bin/top -U snort -u | grep barnyard2 | grep {$start2_upb_pre} | awk '{ print $1; }'");
- //$start2_upb_r = exec("/usr/bin/top -U root -u | grep barnyard2 | grep {$start2_upb_pre} | awk '{ print $1; }'");
-
+ $if_real = convert_friendly_interface_to_real_interface_name($config['installedpackages']['snortglobal']['rule'][$id]['interface']);
+ $snort_uuid = $config['installedpackages']['snortglobal']['rule'][$id]['uuid'];
- if ($start_up_s != "" || $start_up_r != "" || $start2_upb_s != "" || $start2_upb_r != "")
- {
+ /* Log Iface stop */
+ exec("/usr/bin/logger -p daemon.info -i -t SnortStartup 'Toggle for {$snort_uuid}_{$if_real}...'");
- /* stop syslog flood code */
- //exec("/bin/cp /var/log/system.log /var/log/system.log.bk");
- //sleep(3);
+ $tester2 = Running_Ck($snort_uuid, $if_real, $id);
- if ($start_up_s != "")
- {
- exec("/bin/kill {$start_up_s}");
- exec("/bin/rm /var/run/snort_{$snort_uuid}_{$if_real2}*");
- }
-
- //if ($start2_upb_s != "")
- //{
- //exec("/bin/kill {$start2_upb_s}");
- //exec("/bin/rm /var/run/barnyard2_$id$if_real2*");
- //}
-
- if ($start_up_r != "")
- {
- exec("/bin/kill {$start_up_r}");
- exec("/bin/rm /var/run/snort_{$snort_uuid}_{$if_real2}*");
- }
-
- //if ($start2_upb_r != "")
- //{
- //exec("/bin/kill {$start2_upb_r}");
- //exec("/bin/rm /var/run/barnyard2_$id$if_real2*");
- //}
-
- /* stop syslog flood code */
- $if_real_wan_id = $a_nat[$id]['interface'];
- $if_real_wan_id2 = convert_friendly_interface_to_real_interface_name2($if_real_wan_id);
- exec("/sbin/ifconfig $if_real_wan_id2 -promisc");
- //exec("/bin/cp /var/log/system.log /var/log/snort/snort_sys_$id$if_real2.log");
- //exec("/usr/bin/killall syslogd");
- //exec("/usr/sbin/clog -i -s 262144 /var/log/system.log");
- //exec("/usr/sbin/syslogd -c -ss -f /var/etc/syslog.conf");
- //sleep(2);
- //exec("/bin/cp /var/log/system.log.bk /var/log/system.log");
- //$after_mem2 = exec("/usr/bin/top | /usr/bin/grep Wired | /usr/bin/awk '{ print $2 }'");
- //exec("/usr/bin/logger -p daemon.info -i -t SnortStartup 'MEM after {$id}{$if_real2} STOP {$after_mem2}'");
- //exec("/usr/bin/logger -p daemon.info -i -t SnortStartup 'Interface Rule STOP for {$id}{$if_real2}...'");
+ if ($tester2 == 'yes') {
+ /* Log Iface stop */
+ exec("/usr/bin/logger -p daemon.info -i -t SnortStartup '{$tester2} yn for {$snort_uuid}_{$if_real}...'");
+
+ Running_Stop($snort_uuid, $if_real, $id);
header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
@@ -251,11 +210,12 @@ if ($_GET['act'] == "toggle" && $_GET['id'] != "")
header("Location: /snort/snort_interfaces.php");
}else{
- //sync_snort_package_all();
-
- exec("/usr/local/bin/snort -u snort -g snort -R \"{$snort_uuid}_{$if_real2}\" -D -q -l /var/log/snort -G {$snort_uuid} -c /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real2}/snort.conf -i {$if_real2}");
- //print_r("$id $if_real2");
-
+
+ sync_snort_package_all($id, $if_real);
+ sync_snort_package();
+
+ Running_Start($snort_uuid, $if_real, $id);
+
header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
@@ -264,15 +224,16 @@ if ($_GET['act'] == "toggle" && $_GET['id'] != "")
sleep(2);
header("Location: /snort/snort_interfaces.php");
}
+}
+
-}
-$pgtitle = "Services: Snort 2.8.5.3 pkg v. 1.15 Beta";
+$pgtitle = "Services: Snort 2.8.5.3 pkg v. 1.18 RC Final";
include("head.inc");
?>
<body link="#000000" vlink="#000000" alink="#000000">
-<?php include("fbegin.inc"); ?>
+<?php include("./snort_fbegin.inc"); ?>
<p class="pgtitle"><?if($pfsense_stable == 'yes'){echo $pgtitle;}?></p>
<style type="text/css">
@@ -309,43 +270,47 @@ padding: 15px 10px 50% 50px;
padding-top: 4px;
padding-bottom: 4px;
}
-#footer2
-{
- position: relative;
- //top: 135px;
- top: -17px;
- background-color: #cccccc;
- background-image: none;
- background-repeat: repeat;
- background-attachment: scroll;
- background-position: 0% 0%;
- padding-top: 0px;
- padding-right: 0px;
- padding-bottom: 0px;
- padding-left: 10px;
- //padding-left: 0px;
- clear: both;
-}
</style>
<noscript><div class="alert" ALIGN=CENTER><img src="../themes/nervecenter/images/icons/icon_alert.gif"/><strong>Please enable JavaScript to view this content</CENTER></div></noscript>
-<form action="snort_interfaces.php" method="post" name="iform">
-<?php if (file_exists($d_natconfdirty_path)): ?><p>
+<form action="/snort/snort_interfaces.php" method="post" name="iform">
+
<?php
- if($savemsg)
- print_info_box_np2("{$savemsg}<br>The Snort configuration has been changed.<br>You must apply the changes in order for them to take effect.");
- else
- print_info_box_np2("The Snort configuration has been changed.<br>You must apply the changes in order for them to take effect.");
+
+ /* Display Alert message */
+
+ if ($input_errors) {
+ print_input_errors($input_errors); // TODO: add checks
+ }
+
+ if ($savemsg) {
+ print_info_box2($savemsg);
+ }
+
+ //if (file_exists($d_snortconfdirty_path)) {
+ if ($d_snortconfdirty_path_ls != '') {
+ echo '<p>';
+
+ if($savemsg) {
+ print_info_box_np2("{$savemsg}");
+ }else{
+ print_info_box_np2('
+ The Snort configuration has changed for one or more interfaces.<br>
+ You must apply the changes in order for them to take effect.<br>
+ ');
+ }
+ }
+
?>
-<?php endif; ?>
+
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td>
<?php
$tab_array = array();
- $tab_array[] = array("Snort Inertfaces", true, "/snort/snort_interfaces.php");
+ $tab_array[] = array("Snort Interfaces", true, "/snort/snort_interfaces.php");
$tab_array[] = array("Global Settings", false, "/snort/snort_interfaces_global.php");
$tab_array[] = array("Rule Updates", false, "/snort/snort_download_rules.php");
$tab_array[] = array("Alerts", false, "/snort/snort_alerts.php");
@@ -360,7 +325,7 @@ padding: 15px 10px 50% 50px;
<div id="mainarea">
<table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr id="frheader">
- <td width="4%" class="list">&nbsp;</td>
+ <td width="5%" class="list">&nbsp;</td>
<td width="1%" class="list">&nbsp;</td>
<td width="10%" class="listhdrr">If</td>
<td width="10%" class="listhdrr">Snort</td>
@@ -386,33 +351,19 @@ padding: 15px 10px 50% 50px;
$if_real = convert_friendly_interface_to_real_interface_name($natent['interface']);
$snort_uuid = $natent['uuid'];
- $color_up_ck = exec("/bin/ps -auwx | /usr/bin/grep -v grep | /usr/bin/grep snort | /usr/bin/awk '{print \$2;}' | sed 1q");
-
- if ($color_up_ck == "")
- {
- $iconfn = "pass";
- $class_color_up = "listbg";
- }
+ $tester2 = Running_Ck($snort_uuid, $if_real, $id);
- if ($color_up_ck != "")
- {
- //$color_up_pre = exec("/bin/cat /var/run/snort_{$if_real}{$nnats}{$if_real}.pid");
- $color_up_pre = exec("/usr/bin/top -a -U snort -u | grep -v grep | grep \"R {$snort_uuid}_{$if_real}\" | awk '{print \$1;}'");
-
- // /bin/ps -auwx | grep -v grep | grep "$id$if_real -c" | awk '{print $2;}'
- $color_up_s = exec("/usr/bin/top -U snort -u | grep snort | grep {$color_up_pre} | /usr/bin/awk '{print \$1;}'");
- $color_up_r = exec("/usr/bin/top -U root -u | grep snort | grep {$color_up_pre} | /usr/bin/awk '{print \$1;}'");
- if ($color_up_s != "" || $color_up_r != "") {
- $class_color_up = "listbg2";
- $iconfn = "block";
+ if ($tester2 == 'no')
+ {
+ $iconfn = 'pass';
+ $class_color_up = 'listbg';
}else{
- $class_color_up = "listbg";
- $iconfn = "pass";
- }
+ $class_color_up = 'listbg2';
+ $iconfn = 'block';
}
?>
- <td class="listt"><a href="?act=toggle&id=<?=$i;?>"><img src="../themes/<?= $g['theme']; ?>/images/icons/icon_<?=$iconfn;?>.gif" width="13" height="13" border="0" title="click to toggle start/stop snort"></a><input type="checkbox" id="frc<?=$nnats;?>" name="rule[]" value="<?=$i;?>" onClick="fr_bgcolor('<?=$nnats;?>')" style="margin: 0; padding: 0; width: 7px; height: 7px;"></td>
+ <td class="listt"><a href="?act=toggle&id=<?=$i;?>"><img src="../themes/<?= $g['theme']; ?>/images/icons/icon_<?=$iconfn;?>.gif" width="13" height="13" border="0" title="click to toggle start/stop snort"></a><input type="checkbox" id="frc<?=$nnats;?>" name="rule[]" value="<?=$i;?>" onClick="fr_bgcolor('<?=$nnats;?>')" style="margin: 0; padding: 0;"></td>
<td class="listt" align="center"></td>
<td class="<?=$class_color_up;?>" onClick="fr_toggle(<?=$nnats;?>)" id="frd<?=$nnats;?>" ondblclick="document.location='snort_interfaces_edit.php?id=<?=$nnats;?>';">
<?php
@@ -464,15 +415,13 @@ padding: 15px 10px 50% 50px;
<?=strtoupper($check_blockoffenders);?>
</td>
<?php
-
- $color2_udp_pre = exec("/bin/cat /var/run/barnyard2_{$nnats}{$if_real}.pid");
-
- $color2_upb_s = exec("/usr/bin/top -U snort -u | grep barnyard2 | grep {$color2_udp_pre}");
- $color2_upb_r = exec("/usr/bin/top -U root -u | grep barnyard2 | grep {$color2_udp_pre}");
- if ($color2_upb_s != "" || $color2_upb_r != "") {
- $class_color_upb = "listbg2";
+
+ $color2_upb = Running_Ck_b($snort_uuid, $if_real, $id);
+
+ if ($color2_upb == 'yes') {
+ $class_color_upb = 'listbg2';
}else{
- $class_color_upb = "listbg";
+ $class_color_upb = 'listbg';
}
?>
@@ -524,9 +473,9 @@ padding: 15px 10px 50% 50px;
<br>
Please edit the <strong>Global Settings</strong> tab before adding an interface.
<br><br>
- <strong>Click</strong> on the <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0" title="Add Icon"> icon to add a interface.&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp<strong>Click</strong> on the <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_pass.gif" width="13" height="13" border="0" title="Start Icon"> icon to <strong>start</strong> snort and barnyard.
+ <strong>Click</strong> on the <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0" title="Add Icon"> icon to add a interface.<strong>Click</strong> on the <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_pass.gif" width="13" height="13" border="0" title="Start Icon"> icon to <strong>start</strong> snort and barnyard.
<br>
- <strong>Click</strong> on the <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0" title="Edit Icon"> icon to edit a interface and settings.&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp<strong>Click</strong> on the <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_block.gif" width="13" height="13" border="0" title="Stop Icon"> icon to <strong>stop</strong> snort and barnyard.
+ <strong>Click</strong> on the <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0" title="Edit Icon"> icon to edit a interface and settings.<strong>Click</strong> on the <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_block.gif" width="13" height="13" border="0" title="Stop Icon"> icon to <strong>stop</strong> snort and barnyard.
<br>
<strong> Click</strong> on the <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0" title="Delete Icon"> icon to delete a interface and settings.
</td>
@@ -540,14 +489,83 @@ if ($pkg['tabs'] <> "") {
</form>
+<?php
+/* TODO: remove when 2.0 stable */
+if ($pfsense_stable == 'yes') {
+
+$footer2 = "
+
+<style type=\"text/css\">
+
+#footer2
+{
+ position: relative;
+ top: -17px;
+ background-color: #cccccc;
+ background-image: none;
+ background-repeat: repeat;
+ background-attachment: scroll;
+ background-position: 0% 0%;
+ font-size: 0.8em;
+ text-align: center;
+ padding-top: 0px;
+ padding-right: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ clear: both;
+}
+
+</style>
+
+ <div id=\"footer2\">
+ <IMG SRC=\"./images/footer2.jpg\" width=\"780px\" height=\"35\" ALT=\"Apps\">
+ Snort is a registered trademark of Sourcefire, Inc, Barnyard2 is a registered trademark of securixlive.com, Orion copyright Robert Zelaya,
+ Emergingthreats is a registered trademark of emergingthreats.net, Mysql is a registered trademark of Mysql.com
+ </div>\n";
+}
+
+if ($pfsense_stable != 'yes') {
+$footer3 = "
+
+<style type=\"text/css\">
+
+#footer2
+{
+
+top: 105px;
+position: relative;
+background-color: #FFFFFF;
+background-image: url(\"./images/footer2.jpg\");
+background-repeat: no-repeat;
+background-attachment: scroll;
+background-position: 0px 0px;
+bottom: 0px;
+width: 770px;
+height: 35px;
+color: #000000;
+text-align: center;
+font-size: 0.8em;
+padding-top: 35px;
+padding-left: 0px;
+clear: both;
+
+}
+
+</style>
+
+ <div id=\"footer2\">
+ Snort is a registered trademark of Sourcefire, Inc, Barnyard2 is a registered trademark of securixlive.com, Orion copyright Robert Zelaya,
+ Emergingthreats is a registered trademark of emergingthreats.net, Mysql is a registered trademark of Mysql.com
+ </div>\n";
+}
+?>
+
+<?php echo $footer3;?>
+
</div> <!-- Right DIV -->
</div> <!-- Content DIV -->
- <div id="footer2"> <!-- style="width:760px; -->
- <IMG SRC="./images/footer2.jpg" width="780px" height="35" ALT="Apps">
- <font size="1">Snort® is a registered trademark of Sourcefire, Inc., Barnyard2® is a registered trademark of securixlive.com., Orion® copyright Robert Zelaya.,
- Emergingthreats is a registered trademark of emergingthreats.net., Mysql® is a registered trademark of Mysql.com.</font>
- </div>
+<?php echo $footer2;?>
<div id="footer">
<a target="_blank" href="http://www.pfsense.org/?gui12" class="redlnk">pfSense</a> is &copy;
diff --git a/config/snort-dev/snort_interfaces_edit.php b/config/snort-dev/snort_interfaces_edit.php
index 551c0460..164f154a 100644
--- a/config/snort-dev/snort_interfaces_edit.php
+++ b/config/snort-dev/snort_interfaces_edit.php
@@ -30,8 +30,10 @@
POSSIBILITY OF SUCH DAMAGE.
*/
-require("guiconfig.inc");
-include_once("/usr/local/pkg/snort/snort.inc");
+require_once("guiconfig.inc");
+require_once("/usr/local/pkg/snort/snort.inc");
+require_once("/usr/local/pkg/snort/snort_gui.inc");
+
if (!is_array($config['installedpackages']['snortglobal']['rule'])) {
$config['installedpackages']['snortglobal']['rule'] = array();
@@ -48,6 +50,7 @@ if (isset($_GET['dup'])) {
$after = $_GET['dup'];
}
+
/* always have a limit of (65535) numbers only or snort will not start do to id limits */
/* TODO: When inline gets added make the uuid the port number lisstening */
//function gen_snort_uuid($fileline)
@@ -61,10 +64,20 @@ if (isset($_GET['dup'])) {
//}
/* gen uuid for each iface !inportant */
-if ($a_nat[$id]['interface'] == '') {
+if ($config['installedpackages']['snortglobal']['rule'][$id]['uuid'] == '') {
//$snort_uuid = gen_snort_uuid(strrev(uniqid(true)));
- $snort_uuid = mt_rand(0, 65534);
+$snort_uuid = 0;
+while ($snort_uuid > 65535 || $snort_uuid == 0) {
+ $snort_uuid = mt_rand(1, 65535);
$pconfig['uuid'] = $snort_uuid;
+ }
+}
+
+/* convert fake interfaces to real */
+$if_real = convert_friendly_interface_to_real_interface_name($a_nat[$id]['interface']);
+
+if ($config['installedpackages']['snortglobal']['rule'][$id]['uuid'] != '') {
+ $snort_uuid = $config['installedpackages']['snortglobal']['rule'][$id]['uuid'];
}
if (isset($id) && $a_nat[$id]) {
@@ -105,7 +118,7 @@ if (isset($id) && $a_nat[$id]) {
$pconfig['def_imap_servers'] = $a_nat[$id]['def_imap_servers'];
$pconfig['def_imap_ports'] = $a_nat[$id]['def_imap_ports'];
$pconfig['def_sip_proxy_ip'] = $a_nat[$id]['def_sip_proxy_ip'];
- $pconfig['ip def_sip_proxy_ports'] = $a_nat[$id]['ip def_sip_proxy_ports'];
+ $pconfig['def_sip_proxy_ports'] = $a_nat[$id]['def_sip_proxy_ports'];
$pconfig['def_auth_ports'] = $a_nat[$id]['def_auth_ports'];
$pconfig['def_finger_ports'] = $a_nat[$id]['def_finger_ports'];
$pconfig['def_irc_ports'] = $a_nat[$id]['def_irc_ports'];
@@ -138,57 +151,43 @@ if (isset($id) && $a_nat[$id]) {
if (isset($_GET['dup']))
unset($id);
-
-/* convert fake interfaces to real */
-$if_real = convert_friendly_interface_to_real_interface_name($pconfig['interface']);
-
-if ($_POST["Submit"]) {
-
- /* input validation */
-// if(strtoupper($_POST['proto']) == "TCP" or strtoupper($_POST['proto']) == "UDP" or strtoupper($_POST['proto']) == "TCP/UDP") {
-// $reqdfields = explode(" ", "interface proto beginport endport localip localbeginport");
-// $reqdfieldsn = explode(",", "Interface,Protocol,External port from,External port to,NAT IP,Local port");
-// } else {
-// $reqdfields = explode(" ", "interface proto localip");
-// $reqdfieldsn = explode(",", "Interface,Protocol,NAT IP");
-// }
-// do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
-
-// if (($_POST['localip'] && !is_ipaddroralias($_POST['localip']))) {
-// $input_errors[] = "\"{$_POST['localip']}\" is not valid NAT IP address or host alias.";
-// }
-
- /* only validate the ports if the protocol is TCP, UDP or TCP/UDP */
-// if(strtoupper($_POST['proto']) == "TCP" or strtoupper($_POST['proto']) == "UDP" or strtoupper($_POST['proto']) == "TCP/UDP") {
-
-// if (($_POST['beginport'] && !is_ipaddroralias($_POST['beginport']) && !is_port($_POST['beginport']))) {
-// $input_errors[] = "The start port must be an integer between 1 and 65535.";
-// }
-
-// if (($_POST['endport'] && !is_ipaddroralias($_POST['endport']) && !is_port($_POST['endport']))) {
-// $input_errors[] = "The end port must be an integer between 1 and 65535.";
-// }
-
-// if (($_POST['localbeginport'] && !is_ipaddroralias($_POST['localbeginport']) && !is_port($_POST['localbeginport']))) {
-// $input_errors[] = "The local port must be an integer between 1 and 65535.";
-// }
+/* alert file */
+$d_snortconfdirty_path = "/var/run/snort_conf_{$snort_uuid}_{$if_real}.dirty";
+
+ /* this will exec when alert says apply */
+ if ($_POST['apply']) {
+
+ if (file_exists("/var/run/snort_conf_{$snort_uuid}_.dirty")) {
+
+ write_config();
+
+ sync_snort_package_empty();
+ sync_snort_package();
+
+ unlink("/var/run/snort_conf_{$snort_uuid}_.dirty");
+
+ }
+
+ if (file_exists($d_snortconfdirty_path)) {
+
+ write_config();
+
+ sync_snort_package_all();
+ sync_snort_package();
-// if ($_POST['beginport'] > $_POST['endport']) {
- /* swap */
-// $tmp = $_POST['endport'];
-// $_POST['endport'] = $_POST['beginport'];
-// $_POST['beginport'] = $tmp;
-// }
+ unlink($d_snortconfdirty_path);
+
+ }
+
+ }
-// if (!$input_errors) {
-// if (($_POST['endport'] - $_POST['beginport'] + $_POST['localbeginport']) > 65535)
-// $input_errors[] = "The target port range must be an integer between 1 and 65535.";
-// }
+if ($_POST["Submit"]) {
-
+
+
// if ($config['installedpackages']['snortglobal']['rule']) {
- if ($_POST['descr'] == "") {
+ if ($_POST['descr'] == '' && $pconfig['descr'] == '') {
$input_errors[] = "Please enter a description for your reference.";
}
@@ -273,7 +272,7 @@ if ($_POST["Submit"]) {
if ($pconfig['def_imap_servers'] != "") { $natent['def_imap_servers'] = $pconfig['def_imap_servers']; }
if ($pconfig['def_imap_ports'] != "") { $natent['def_imap_ports'] = $pconfig['def_imap_ports']; }
if ($pconfig['def_sip_proxy_ip'] != "") { $natent['def_sip_proxy_ip'] = $pconfig['def_sip_proxy_ip']; }
- if ($pconfig['ip def_sip_proxy_ports'] != "") { $natent['ip def_sip_proxy_ports'] = $pconfig['ip def_sip_proxy_ports']; }
+ if ($pconfig['def_sip_proxy_ports'] != "") { $natent['def_sip_proxy_ports'] = $pconfig['def_sip_proxy_ports']; }
if ($pconfig['def_auth_ports'] != "") { $natent['def_auth_ports'] = $pconfig['def_auth_ports']; }
if ($pconfig['def_finger_ports'] != "") { $natent['def_finger_ports'] = $pconfig['def_finger_ports']; }
if ($pconfig['def_irc_ports'] != "") { $natent['def_irc_ports'] = $pconfig['def_irc_ports']; }
@@ -298,13 +297,9 @@ if ($_POST["Submit"]) {
}
write_config();
- // stop_service("snort");
-
- if ($pconfig['interface'] != "") {
- sync_snort_package_all();
- }
- //touch($d_natconfdirty_path);
+ touch("$d_snortconfdirty_path");
+
header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
@@ -316,23 +311,15 @@ if ($_POST["Submit"]) {
exit;
}
}
-
- if (isset($config['installedpackages']['snortglobal']['rule'][$id]['interface']))
- {
- if (uniq_snort_proc($id, $if_real) == 'false')
- {
- $snort_up_ck = '<input name="Submit2" type="submit" class="formbtn" value="Start" onClick="enable_change(true)">';
- }else{
- $snort_up_ck = '<input name="Submit3" type="submit" class="formbtn" value="Stop" onClick="enable_change(true)">';
- }
- }else{
- $snort_up_ck = '';
- }
-
+
if ($_POST["Submit2"]) {
- sync_snort_package_all($id, $if_real);
+
+ sync_snort_package_all();
+ sync_snort_package();
sleep(1);
- exec("/usr/local/bin/snort -u snort -g snort -R \"{$snort_uuid}_{$if_real}\" -D -q -l /var/log/snort -G {$snort_uuid} -c /usr/local/etc/snort/snort_{$snort_uuid}_{$if_real}/snort.conf -i {$if_real}");
+
+ Running_Start($snort_uuid, $if_real, $id);
+
header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
@@ -344,24 +331,9 @@ if ($_POST["Submit"]) {
if ($_POST["Submit3"])
{
- sync_snort_package_all($id, $if_real);
- sleep(1);
-
- $start_up_pre = exec("/usr/bin/top -a -U snort -u | grep -v grep | grep \"R {$snort_uuid}_{$if_real}\" | awk '{print \$1;}'");
- $start_up_s = exec("/usr/bin/top -U snort -u | grep snort | grep {$start_up_pre} | awk '{ print $1; }'");
- $start_up_r = exec("/usr/bin/top -U root -u | grep snort | grep {$start_up_pre} | awk '{ print $1; }'");
-
- if ($start_up_s != '')
- {
- exec("/bin/kill {$start_up_s}");
- exec("/bin/rm /var/run/snort_{$snort_uuid}_{$if_real}*");
- }
- if ($start_up_r != '')
- {
- exec("/bin/kill {$start_up_r}");
- exec("/bin/rm /var/run/snort_{$snort_uuid}_{$if_real}*");
- }
+ Running_Stop($snort_uuid, $if_real, $id);
+
header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
@@ -370,17 +342,32 @@ if ($_POST["Submit"]) {
sleep(2);
header("Location: /snort/snort_interfaces_edit.php?id=$id");
-
}
-$iface_uuid = $a_nat[$id]['uuid'];
-$pgtitle = "Snort: Interface Edit: $id $iface_uuid $if_real";
+ /* This code needs to be below headers */
+ if (isset($config['installedpackages']['snortglobal']['rule'][$id]['interface']))
+ {
+
+ $snort_up_ck2_info = Running_Ck($snort_uuid, $if_real, $id);
+
+ if ($snort_up_ck2_info == 'no') {
+ $snort_up_ck = '<input name="Submit2" type="submit" class="formbtn" value="Start" onClick="enable_change(true)">';
+ }else{
+ $snort_up_ck = '<input name="Submit3" type="submit" class="formbtn" value="Stop" onClick="enable_change(true)">';
+ }
+
+ }else{
+ $snort_up_ck = '';
+ }
+
+
+$pgtitle = "Snort: Interface Edit: $id $snort_uuid $if_real";
include("head.inc");
?>
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
<?php
-include("fbegin.inc");
+include("./snort_fbegin.inc");
?>
<style type="text/css">
.alert {
@@ -395,7 +382,7 @@ border-bottom:2px solid #DBAC48;
padding: 15px 10px 85% 50px;
}
</style>
-<noscript><div class="alert" ALIGN=CENTER><img src="/themes/nervecenter/images/icons/icon_alert.gif"/><strong>Please enable JavaScript to view this content</CENTER></div></noscript>
+<noscript><div class="alert" ALIGN=CENTER><img src="/themes/nervecenter/images/icons/icon_alert.gif"/><strong>Please enable JavaScript to view this content</strong></div></noscript>
<script language="JavaScript">
<!--
@@ -407,7 +394,7 @@ function enable_change(enable_change) {
<?php
/* make shure all the settings exist or function hide will not work */
/* if $id is emty allow if and discr to be open */
-if($iface_uuid != '')
+if($config['installedpackages']['snortglobal']['rule'][$id]['interface'] != '')
{
echo "
document.iform.interface.disabled = endis2;
@@ -416,18 +403,45 @@ echo "
?>
document.iform.performance.disabled = endis;
document.iform.blockoffenders7.disabled = endis;
- document.iform.snortalertlogtype.disabled = endis;
document.iform.alertsystemlog.disabled = endis;
document.iform.tcpdumplog.disabled = endis;
document.iform.snortunifiedlog.disabled = endis;
}
//-->
</script>
-<p class="pgtitle"><?=$pgtitle?></p>
+<p class="pgtitle"><?php if($pfsense_stable == 'yes'){echo $pgtitle;}?></p>
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
-<?php if ($input_errors) print_input_errors($input_errors); ?>
-<?php if ($savemsg) print_info_box($savemsg); ?>
+
<form action="snort_interfaces_edit.php<?php echo "?id=$id";?>" method="post" enctype="multipart/form-data" name="iform" id="iform">
+
+<?php
+
+ /* Display Alert message */
+
+ if ($input_errors) {
+ print_input_errors($input_errors); // TODO: add checks
+ }
+
+ if ($savemsg) {
+ print_info_box2($savemsg);
+ }
+
+ //if (file_exists($d_snortconfdirty_path)) {
+ if (file_exists($d_snortconfdirty_path) || file_exists("/var/run/snort_conf_{$snort_uuid}_.dirty")) {
+ echo '<p>';
+
+ if($savemsg) {
+ print_info_box_np2("{$savemsg}");
+ }else{
+ print_info_box_np2('
+ The Snort configuration has changed and snort needs to be restarted on this interface.<br>
+ You must apply the changes in order for them to take effect.<br>
+ ');
+ }
+ }
+
+?>
+
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td class="tabnavtbl">
<?php
@@ -462,14 +476,21 @@ if ($a_nat[$id]['interface'] != '') {
}
$tab_array = array();
+ if (!file_exists("/var/run/snort_conf_{$snort_uuid}_.dirty")) {
$tab_array[] = array("Snort Interfaces", false, "/snort/snort_interfaces.php");
+ }
$tab_array[] = array("If Settings", true, "/snort/snort_interfaces_edit.php?id={$id}");
+ /* hide user tabs when no settings have be saved */
+ if ($config['installedpackages']['snortglobal']['rule'][$id]['interface'] != '') {
+ if (!file_exists("/var/run/snort_conf_{$snort_uuid}_.dirty")) {
//$tab_array[] = array("upload", false, "/snort/snort_conf_upload.php?id={$id}");
$tab_array[] = array("Categories", false, "/snort/snort_rulesets.php?id={$id}");
$tab_array[] = array("Rules", false, "/snort/snort_rules.php?id={$id}");
$tab_array[] = array("Servers", false, "/snort/snort_define_servers.php?id={$id}");
$tab_array[] = array("Preprocessors", false, "/snort/snort_preprocessors.php?id={$id}");
$tab_array[] = array("Barnyard2", false, "/snort/snort_barnyard.php?id={$id}");
+ }
+ }
display_top_tabs($tab_array);
?>
@@ -549,7 +570,7 @@ if ($a_nat[$id]['interface'] != '') {
<td width="22%" valign="top" class="vncell">Log to a Tcpdump file</td>
<td width="78%" class="vtable">
<input name="tcpdumplog" type="checkbox" value="on" <?php if ($pconfig['tcpdumplog'] == "on") echo "checked"; ?> onClick="enable_change(false)"><br>
- Snort will log packets to a tcpdump-formatted file. The file then can be analyzed by an application such as Wireshark which understands pcap file formats. WARNING: File may become large.</td>
+ Snort will log packets to a tcpdump-formatted file. The file then can be analyzed by an application such as Wireshark which understands pcap file formats. <span class="red"><strong>WARNING:</strong></span> File may become large.</td>
</tr>
<tr>
<td width="22%" valign="top" class="vncell">Log Alerts to a snort unified2 file</td>
@@ -558,7 +579,7 @@ if ($a_nat[$id]['interface'] != '') {
Snort will log Alerts to a file in the UNIFIED2 format. This is a requirement for barnyard2.</td>
</tr>
<tr>
- <td width="22%" valign="top">&nbsp;</td>
+ <td width="22%" valign="top"></td>
<td width="78%">
<input name="Submit" type="submit" class="formbtn" value="Save"> <?php echo $snort_up_ck; ?> <input type="button" class="formbtn" value="Cancel" onclick="history.back()">
<?php if (isset($id) && $a_nat[$id]): ?>
diff --git a/config/snort-dev/snort_interfaces_global.php b/config/snort-dev/snort_interfaces_global.php
index 95b55517..ff3620a3 100644
--- a/config/snort-dev/snort_interfaces_global.php
+++ b/config/snort-dev/snort_interfaces_global.php
@@ -33,8 +33,8 @@
*/
$pgtitle = "Services: Snort: Global Settings";
-require("guiconfig.inc");
-require("/usr/local/pkg/snort/snort.inc");
+require_once("guiconfig.inc");
+require_once("/usr/local/pkg/snort/snort.inc");
/* make things short */
$pconfig['snortdownload'] = $config['installedpackages']['snortglobal']['snortdownload'];
@@ -57,38 +57,13 @@ if ($_POST) {
if ($_POST['enable'])
{
-// if ($_POST['timeout'] && (!is_numeric($_POST['timeout']) || ($_POST['timeout'] < 1))) {
-// $input_errors[] = "The timeout must be at least 1 minute.";
-// }
-// if ($_POST['idletimeout'] && (!is_numeric($_POST['idletimeout']) || ($_POST['idletimeout'] < 1))) {
-// $input_errors[] = "The idle timeout must be at least 1 minute.";
-// }
-// if (($_POST['radiusip'] && !is_ipaddr($_POST['radiusip']))) {
-// $input_errors[] = "A valid IP address must be specified. [".$_POST['radiusip']."]";
-// }
-// if (($_POST['radiusip2'] && !is_ipaddr($_POST['radiusip2']))) {
-// $input_errors[] = "A valid IP address must be specified. [".$_POST['radiusip2']."]";
-// }
-// if (($_POST['radiusport'] && !is_port($_POST['radiusport']))) {
-// $input_errors[] = "A valid port number must be specified. [".$_POST['radiusport']."]";
-// }
-// if (($_POST['radiusport2'] && !is_port($_POST['radiusport2']))) {
-// $input_errors[] = "A valid port number must be specified. [".$_POST['radiusport2']."]";
-// }
-// if (($_POST['radiusacctport'] && !is_port($_POST['radiusacctport']))) {
-// $input_errors[] = "A valid port number must be specified. [".$_POST['radiusacctport']."]";
-// }
-// if ($_POST['maxproc'] && (!is_numeric($_POST['maxproc']) || ($_POST['maxproc'] < 4) || ($_POST['maxproc'] > 100))) {
-// $input_errors[] = "The total maximum number of concurrent connections must be between 4 and 100.";
-// }
-// $mymaxproc = $_POST['maxproc'] ? $_POST['maxproc'] : 16;
-// if ($_POST['maxprocperip'] && (!is_numeric($_POST['maxprocperip']) || ($_POST['maxprocperip'] > $mymaxproc))) {
-// $input_errors[] = "The maximum number of concurrent connections per client IP address may not be larger than the global maximum.";
-// }
+/* TODO:a dd check user input code. */
}
if (!$input_errors) {
+
+ if ($_POST["Submit"]) {
$config['installedpackages']['snortglobal']['snortdownload'] = $_POST['snortdownload'];
$config['installedpackages']['snortglobal']['oinkmastercode'] = $_POST['oinkmastercode'];
@@ -134,11 +109,139 @@ if ($_POST) {
$savemsg = get_std_save_message($retval);
+
+ }
+
+ sync_snort_package_all();
+ sync_snort_package();
+
+}
+
+
+ if ($_POST["Reset"]) {
+
+//////>>>>>>>>>
+
+ function snort_deinstall_settings()
+{
+
+ global $config, $g, $id, $if_real;
+ conf_mount_rw();
+
+
+ exec("/usr/usr/bin/killall snort");
+ sleep(2);
+ exec("/usr/usr/bin/killall -9 snort");
+ sleep(2);
+ exec("/usr/usr/bin/killall barnyard2");
+ sleep(2);
+ exec("/usr/usr/bin/killall -9 barnyard2");
+ sleep(2);
+
+ /* Remove snort cron entries Ugly code needs smoothness*/
+function snort_rm_blocked_deinstall_cron($should_install)
+{
+ global $config, $g;
+ conf_mount_rw();
+
+ $is_installed = false;
+
+ if(!$config['cron']['item'])
+ return;
+
+ $x=0;
+ foreach($config['cron']['item'] as $item)
+ {
+ if (strstr($item['command'], "snort2c"))
+ {
+ $is_installed = true;
+ break;
+ }
+
+ $x++;
+
+ }
+ if($is_installed == true)
+ {
+ if($x > 0)
+ {
+ unset($config['cron']['item'][$x]);
+ write_config();
+ conf_mount_rw();
+ }
+
+ configure_cron();
+
+ }
+ conf_mount_ro();
+
+}
+
+ function snort_rules_up_deinstall_cron($should_install)
+{
+ global $config, $g;
+ conf_mount_rw();
+
+ $is_installed = false;
+
+ if(!$config['cron']['item'])
+ return;
+
+ $x=0;
+ foreach($config['cron']['item'] as $item) {
+ if (strstr($item['command'], "snort_check_for_rule_updates.php")) {
+ $is_installed = true;
+ break;
+ }
+ $x++;
+ }
+ if($is_installed == true) {
+ if($x > 0) {
+ unset($config['cron']['item'][$x]);
+ write_config();
+ conf_mount_rw();
+ }
+ configure_cron();
+ }
+}
+
+snort_rm_blocked_deinstall_cron("");
+snort_rules_up_deinstall_cron("");
+
+
+ /* Unset snort registers in conf.xml IMPORTANT snort will not start with out this */
+ /* Keep this as a last step */
+ unset($config['installedpackages']['snortglobal']);
+ write_config();
+ conf_mount_rw();
+
+ /* remove all snort iface dir */
+ exec('rm -r /usr/local/etc/snort/snort_*');
+ exec('rm /var/log/snort/*');
+
+ conf_mount_ro();
+
+}
+
+ snort_deinstall_settings();
+
+ header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
+ header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
+ header( 'Cache-Control: no-store, no-cache, must-revalidate' );
+ header( 'Cache-Control: post-check=0, pre-check=0', false );
+ header( 'Pragma: no-cache' );
+ sleep(2);
+ header("Location: /snort/snort_interfaces_global.php");
+
+ exit;
+
+//////>>>>>>>>>
}
}
+
include("head.inc");
?>
-<?php include("fbegin.inc"); ?>
+<?php include("./snort_fbegin.inc"); ?>
<p class="pgtitle"><?if($pfsense_stable == 'yes'){echo $pgtitle;}?></p>
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
@@ -190,7 +293,6 @@ include("head.inc");
<td class="vncell" valign="top">Code</td>
<td class="vtable"><input name="oinkmastercode" type="text" class="formfld" id="oinkmastercode" size="52" value="<?=htmlspecialchars($pconfig['oinkmastercode']);?>"><br>
Obtain a snort.org Oinkmaster code and paste here.</td>
- </td>
</table>
</tr>
<tr>
@@ -250,16 +352,12 @@ include("head.inc");
<span class="vexpl">Please choose the type of Alert logging you will like see in your alert file.<br>
Hint: Best pratice is to chose full logging.</span>&nbsp;<span class="red"><strong>WARNING:</strong></span>&nbsp;<strong>On change, alert file will be cleared.</strong></td>
</tr>
- <tr>
- <td width="22%" valign="top" class="vncell">Associate events on Blocked tab</td>
- <td width="78%" class="vtable">
- <input name="associatealertip" type="checkbox" value="yes" <?php if ($config['installedpackages']['snortglobal']['associatealertip'] == "on") echo "checked"; ?> onClick="enable_change(false)"><br>
- Checking this option will automatically associate the blocked reason from the snort alerts file.</td>
- </tr>
<tr>
- <td width="22%" valign="top">&nbsp;</td>
+ <td width="22%" valign="top"><input name="Reset" type="submit" class="formbtn" value="Reset" onclick="return confirm('Do you really want to delete all global and interface settings?')"><span class="red"><strong>&nbsp;WARNING:</strong><br>
+ This will reset all global and interface settings.</span>
+ </td>
<td width="78%">
- <input name="Submit" type="submit" class="formbtn" value="Save" onClick="enable_change(true)">
+ <input name="Submit" type="submit" class="formbtn" value="Save" onClick="enable_change(true)"> <input type="button" class="formbtn" value="Cancel" onclick="history.back()">
</td>
</tr>
<tr>
diff --git a/config/snort-dev/snort_preprocessors.php b/config/snort-dev/snort_preprocessors.php
index 8072484d..c522a643 100644
--- a/config/snort-dev/snort_preprocessors.php
+++ b/config/snort-dev/snort_preprocessors.php
@@ -30,16 +30,10 @@
POSSIBILITY OF SUCH DAMAGE.
*/
-/*
-TODO: Nov 12 09
-Clean this code up its ugly
-Important add error checking
-
-*/
-
-require("guiconfig.inc");
-require("/usr/local/pkg/snort/snort.inc");
+require_once("guiconfig.inc");
+require_once("/usr/local/pkg/snort/snort.inc");
+require_once("/usr/local/pkg/snort/snort_gui.inc");
if (!is_array($config['installedpackages']['snortglobal']['rule'])) {
$config['installedpackages']['snortglobal']['rule'] = array();
@@ -96,7 +90,7 @@ if (isset($id) && $a_nat[$id]) {
$pconfig['def_imap_servers'] = $a_nat[$id]['def_imap_servers'];
$pconfig['def_imap_ports'] = $a_nat[$id]['def_imap_ports'];
$pconfig['def_sip_proxy_ip'] = $a_nat[$id]['def_sip_proxy_ip'];
- $pconfig['ip def_sip_proxy_ports'] = $a_nat[$id]['ip def_sip_proxy_ports'];
+ $pconfig['def_sip_proxy_ports'] = $a_nat[$id]['def_sip_proxy_ports'];
$pconfig['def_auth_ports'] = $a_nat[$id]['def_auth_ports'];
$pconfig['def_finger_ports'] = $a_nat[$id]['def_finger_ports'];
$pconfig['def_irc_ports'] = $a_nat[$id]['def_irc_ports'];
@@ -127,7 +121,29 @@ if (isset($_GET['dup']))
/* convert fake interfaces to real */
$if_real = convert_friendly_interface_to_real_interface_name($pconfig['interface']);
-if ($_POST) {
+
+
+ /* alert file */
+$d_snortconfdirty_path = "/var/run/snort_conf_{$pconfig['uuid']}_{$if_real}.dirty";
+
+ /* this will exec when alert says apply */
+ if ($_POST['apply']) {
+
+ if (file_exists($d_snortconfdirty_path)) {
+
+ write_config();
+
+ sync_snort_package_all();
+ sync_snort_package();
+
+ unlink($d_snortconfdirty_path);
+
+ }
+
+ }
+
+
+ if ($_POST["Submit"]) {
/* check for overlaps */
@@ -171,7 +187,7 @@ if ($_POST) {
if ($pconfig['def_imap_servers'] != "") { $natent['def_imap_servers'] = $pconfig['def_imap_servers']; }
if ($pconfig['def_imap_ports'] != "") { $natent['def_imap_ports'] = $pconfig['def_imap_ports']; }
if ($pconfig['def_sip_proxy_ip'] != "") { $natent['def_sip_proxy_ip'] = $pconfig['def_sip_proxy_ip']; }
- if ($pconfig['ip def_sip_proxy_ports'] != "") { $natent['ip def_sip_proxy_ports'] = $pconfig['ip def_sip_proxy_ports']; }
+ if ($pconfig['def_sip_proxy_ports'] != "") { $natent['def_sip_proxy_ports'] = $pconfig['def_sip_proxy_ports']; }
if ($pconfig['def_auth_ports'] != "") { $natent['def_auth_ports'] = $pconfig['def_auth_ports']; }
if ($pconfig['def_finger_ports'] != "") { $natent['def_finger_ports'] = $pconfig['def_finger_ports']; }
if ($pconfig['def_irc_ports'] != "") { $natent['def_irc_ports'] = $pconfig['def_irc_ports']; }
@@ -205,12 +221,16 @@ if ($_POST) {
$a_nat[] = $natent;
}
- /* enable this if you want the user to aprove changes */
- // touch($d_natconfdirty_path);
-
write_config();
/* after click go to this page */
+ touch($d_snortconfdirty_path);
+ header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
+ header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
+ header( 'Cache-Control: no-store, no-cache, must-revalidate' );
+ header( 'Cache-Control: post-check=0, pre-check=0', false );
+ header( 'Pragma: no-cache' );
+ sleep(2);
header("Location: snort_preprocessors.php?id=$id");
exit;
}
@@ -222,7 +242,7 @@ include("head.inc");
?>
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
<?php
-include("fbegin.inc");
+include("./snort_fbegin.inc");
?>
<p class="pgtitle"><?if($pfsense_stable == 'yes'){echo $pgtitle;}?></p>
<style type="text/css">
@@ -241,9 +261,35 @@ padding: 15px 10px 85% 50px;
<noscript><div class="alert" ALIGN=CENTER><img src="../themes/nervecenter/images/icons/icon_alert.gif"/><strong>Please enable JavaScript to view this content</CENTER></div></noscript>
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
-<?php if ($input_errors) print_input_errors($input_errors); ?>
-<?php if ($savemsg) print_info_box($savemsg); ?>
<form action="snort_preprocessors.php" method="post" enctype="multipart/form-data" name="iform" id="iform">
+
+<?php
+
+ /* Display Alert message */
+
+ if ($input_errors) {
+ print_input_errors($input_errors); // TODO: add checks
+ }
+
+ if ($savemsg) {
+ print_info_box2($savemsg);
+ }
+
+ if (file_exists($d_snortconfdirty_path)) {
+ echo '<p>';
+
+ if($savemsg) {
+ print_info_box_np2("{$savemsg}");
+ }else{
+ print_info_box_np2('
+ The Snort configuration has changed and snort needs to be restarted on this interface.<br>
+ You must apply the changes in order for them to take effect.<br>
+ ');
+ }
+ }
+
+?>
+
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td class="tabnavtbl">
<?php
@@ -327,10 +373,10 @@ if($id != "")
Normalize/Decode RPC traffic and detects Back Orifice traffic on the network.</td>
</tr>
<tr>
- <td width="22%" valign="top" class="vncell">Enable <br>FTP & Telnet Normalizer</td>
+ <td width="22%" valign="top" class="vncell">Enable <br>FTP and Telnet Normalizer</td>
<td width="78%" class="vtable">
<input name="ftp_preprocessor" type="checkbox" value="on" <?php if ($pconfig['ftp_preprocessor']=="on") echo "checked"; ?> onClick="enable_change(false)"><br>
- Normalize/Decode FTP & Telnet traffic and protocol anomalies.</td>
+ Normalize/Decode FTP and Telnet traffic and protocol anomalies.</td>
</tr>
<tr>
<td width="22%" valign="top" class="vncell">Enable <br>SMTP Normalizer</td>
diff --git a/config/snort-dev/snort_rules.php b/config/snort-dev/snort_rules.php
index 99e932b7..c95d76ca 100644
--- a/config/snort-dev/snort_rules.php
+++ b/config/snort-dev/snort_rules.php
@@ -27,10 +27,11 @@
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
-require("guiconfig.inc");
-require("config.inc");
-require("/usr/local/pkg/snort/snort_gui.inc");
-require("/usr/local/pkg/snort/snort.inc");
+
+
+require_once("guiconfig.inc");
+require_once("/usr/local/pkg/snort/snort_gui.inc");
+require_once("/usr/local/pkg/snort/snort.inc");
if (!is_array($config['installedpackages']['snortglobal']['rule'])) {
$config['installedpackages']['snortglobal']['rule'] = array();
@@ -64,7 +65,7 @@ $isrulesfolderempty = exec("ls -A /usr/local/etc/snort/snort_{$iface_uuid}_{$if_
if ($isrulesfolderempty == "") {
include("head.inc");
-include("fbegin.inc");
+include("./snort_fbegin.inc");
echo "<body link=\"#000000\" vlink=\"#000000\" alink=\"#000000\">";
@@ -411,7 +412,7 @@ $pgtitle = "Snort: $id $iface_uuid $if_real Category: $currentruleset";
?>
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
-<?php include("fbegin.inc"); ?>
+<?php include("./snort_fbegin.inc"); ?>
<p class="pgtitle"><?if($pfsense_stable == 'yes'){echo $pgtitle;}?></p>
<?php
@@ -453,7 +454,7 @@ function popup(url)
return false;
}
// -->
-</script
+</script>
<table width="99%" border="0" cellpadding="0" cellspacing="0">
<tr>
@@ -590,7 +591,8 @@ function popup(url)
$textss\n";
?>
<a href="?id=<?=$id;?>&openruleset=<?=$rulefile;?>&act=toggle&ids=<?=$counter;?>"><img src="../themes/<?= $g['theme']; ?>/images/icons/<?=$iconb;?>" width="10" height="10" border="0" title="click to toggle enabled/disabled status"></a>
- <input name="enable" type="checkbox" value="yes" <?= $ischecked; ?> onClick="enable_change(false)">
+ <!-- <input name="enable" type="checkbox" value="yes" <?= $ischecked; ?> onClick="enable_change(false)"> -->
+ <!-- TODO: add checkbox and save so that that disabling is nicer -->
<?php
echo "$textse
</td>
@@ -662,7 +664,8 @@ function popup(url)
</tr>
<table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
- <td><pre><input name="Submit" type="submit" class="formbtn" value="Save"> <input type="button" class="formbtn" value="Cancel" onclick="history.back()"><pre></td>
+ <!-- TODO: add save and cancel for checkbox options -->
+ <!-- <td><pre><input name="Submit" type="submit" class="formbtn" value="Save"> <input type="button" class="formbtn" value="Cancel" onclick="history.back()"><pre></td> -->
</tr>
</table>
<tr>
diff --git a/config/snort-dev/snort_rules_edit.php b/config/snort-dev/snort_rules_edit.php
index 412024d8..b770867f 100644
--- a/config/snort-dev/snort_rules_edit.php
+++ b/config/snort-dev/snort_rules_edit.php
@@ -1,243 +1,243 @@
-#!/usr/local/bin/php
-<?php
-/*
- system_edit.php
- Copyright (C) 2004, 2005 Scott Ullrich
- All rights reserved.
-
- Adapted for FreeNAS by Volker Theile (votdev@gmx.de)
- Copyright (C) 2006-2009 Volker Theile
-
- Adapted for Pfsense Snort package by Robert Zelaya
- Copyright (C) 2008-2009 Robert Zelaya
-
- Using dp.SyntaxHighlighter for syntax highlighting
- http://www.dreamprojections.com/SyntaxHighlighter
- Copyright (C) 2004-2006 Alex Gorbatchev. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
-*/
-require("guiconfig.inc");
-require("config.inc");
-
-//////////////////
-
-if (!is_array($config['installedpackages']['snortglobal']['rule'])) {
- $config['installedpackages']['snortglobal']['rule'] = array();
-}
-
-//nat_rules_sort();
-$a_nat = &$config['installedpackages']['snortglobal']['rule'];
-
-$id = $_GET['id'];
-if (isset($_POST['id']))
- $id = $_POST['id'];
-
-$ids = $_GET['ids'];
-if (isset($_POST['ids']))
- $ids = $_POST['ids'];
-
-
-if (isset($id) && $a_nat[$id]) {
-
- $pconfig['enable'] = $a_nat[$id]['enable'];
- $pconfig['interface'] = $a_nat[$id]['interface'];
- $pconfig['rulesets'] = $a_nat[$id]['rulesets'];
-}
-
-/* convert fake interfaces to real */
-$if_real = convert_friendly_interface_to_real_interface_name($pconfig['interface']);
-
-
-$file = $_GET['openruleset'];
-
-//read snort file
-$filehandle = fopen($file, "r");
-
-//get rule id
-$lineid = $_GET['ids'];
-
-//read file into string, and get filesize
-$contents2 = fread($filehandle, filesize($file));
-
-//close handler
-fclose ($filehandle);
-
-//delimiter for each new rule is a new line
-$delimiter = "\n";
-
-//split the contents of the string file into an array using the delimiter
-$splitcontents = explode($delimiter, $contents2);
-
-//copy rule contents from array into string
-$tempstring = $splitcontents[$lineid];
-
-function write_rule_file($content_changed, $received_file)
-{
- //read snort file with writing enabled
- $filehandle = fopen($received_file, "w");
-
- //delimiter for each new rule is a new line
- $delimiter = "\n";
-
- //implode the array back into a string for writing purposes
- $fullfile = implode($delimiter, $content_changed);
-
- //write data to file
- fwrite($filehandle, $fullfile);
-
- //close file handle
- fclose($filehandle);
-
-}
-
-
-
-if($_POST['highlight'] <> "") {
- if($_POST['highlight'] == "yes" or
- $_POST['highlight'] == "enabled") {
- $highlight = "yes";
- } else {
- $highlight = "no";
- }
-} else {
- $highlight = "no";
-}
-
-if($_POST['rows'] <> "")
- $rows = $_POST['rows'];
-else
- $rows = 1;
-
-if($_POST['cols'] <> "")
- $cols = $_POST['cols'];
-else
- $cols = 66;
-
-if ($_POST)
-{
- if ($_POST['save']) {
-
- /* get the changes */
- $rule_content2 = $_POST['code'];
-
- //copy string into file array for writing
- $splitcontents[$lineid] = $rule_content2;
-
- //write the new .rules file
- write_rule_file($splitcontents, $file);
-
- header("Location: /snort/snort_rules_edit.php?id=$id&openruleset=$file&ids=$ids");
-
- }
-}
-
-$pgtitle = array(gettext("Advanced"), gettext("File Editor"));
-
-//
-?>
-
-<?php include("head.inc");?>
-
-<body link="#000000" vlink="#000000" alink="#000000">
-<table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tr>
- <td class="tabcont">
- <form action="snort_rules_edit.php?id=<?=$id; ?>&openruleset=<?=$file; ?>&ids=<?=$ids; ?>" method="post">
- <?php if ($savemsg) print_info_box($savemsg);?>
- <table width="100%" cellpadding='9' cellspacing='9' bgcolor='#eeeeee'>
- <tr>
- <td>
- <input name="save" type="submit" class="formbtn" id="save" value="save" /> <input type="button" class="formbtn" value="Cancel" onclick="history.back()">
- <hr noshade="noshade" />
- <?=gettext("Disable original rule"); ?>:
- <input id="highlighting_enabled" name="highlight2" type="radio" value="yes" <?php if($highlight == "yes") echo " checked=\"checked\""; ?> />
- <label for="highlighting_enabled"><?=gettext("Enabled"); ?></label>
- <input id="highlighting_disabled" name="highlight2" type="radio" value="no"<?php if($highlight == "no") echo " checked=\"checked\""; ?> />
- <label for="highlighting_disabled"><?=gettext("Disabled"); ?></label>
- </td>
- </tr>
- </table>
- <table width='100%'>
- <tr>
- <td valign="top" class="label">
- <div style="background: #eeeeee;" id="textareaitem">
- <!-- NOTE: The opening *and* the closing textarea tag must be on the same line. -->
- <textarea wrap="off" style="width: 98%; margin: 7px;" class="<?php echo $language; ?>:showcolumns" rows="<?php echo $rows; ?>" cols="<?php echo $cols; ?>" name="code"><?php echo $tempstring;?></textarea>
- </div>
- </td>
- </tr>
- </table>
- <table width='100%'>
- <tr>
- <td valign="top" class="label">
- <div style="background: #eeeeee;" id="textareaitem">
- <!-- NOTE: The opening *and* the closing textarea tag must be on the same line. -->
- <textarea disabled wrap="off" style="width: 98%; margin: 7px;" class="<?php echo $language; ?>:showcolumns" rows="33" cols="<?php echo $cols; ?>" name="code2"><?php echo $contents2;?></textarea>
- </div>
- </td>
- </tr>
- </table>
- <?php // include("formend.inc");?>
- </form>
- </td>
- </tr>
-</table>
-<script class="javascript" src="/snort/syntaxhighlighter/shCore.js"></script>
-<script class="javascript" src="/snort/syntaxhighlighter/shBrushCSharp.js"></script>
-<script class="javascript" src="/snort/syntaxhighlighter/shBrushPhp.js"></script>
-<script class="javascript" src="/snort/syntaxhighlighter/shBrushJScript.js"></script>
-<script class="javascript" src="/snort/syntaxhighlighter/shBrushJava.js"></script>
-<script class="javascript" src="/snort/syntaxhighlighter/shBrushVb.js"></script>
-<script class="javascript" src="/snort/syntaxhighlighter/shBrushSql.js"></script>
-<script class="javascript" src="/snort/syntaxhighlighter/shBrushXml.js"></script>
-<script class="javascript" src="/snort/syntaxhighlighter/shBrushDelphi.js"></script>
-<script class="javascript" src="/snort/syntaxhighlighter/shBrushPython.js"></script>
-<script class="javascript" src="/snort/syntaxhighlighter/shBrushRuby.js"></script>
-<script class="javascript" src="/snort/syntaxhighlighter/shBrushCss.js"></script>
-<script class="javascript">
-<!--
- // Set focus.
- document.forms[0].savetopath.focus();
-
- // Append css for syntax highlighter.
- var head = document.getElementsByTagName("head")[0];
- var linkObj = document.createElement("link");
- linkObj.setAttribute("type","text/css");
- linkObj.setAttribute("rel","stylesheet");
- linkObj.setAttribute("href","/snort/syntaxhighlighter/SyntaxHighlighter.css");
- head.appendChild(linkObj);
-
- // Activate dp.SyntaxHighlighter?
- <?php
- if($_POST['highlight'] == "yes") {
- echo "dp.SyntaxHighlighter.HighlightAll('code', true, true);\n";
- // Disable 'Save' button.
- echo "document.forms[0].Save.disabled = 1;\n";
- }
-?>
-//-->
-</script>
-<?php //include("fend.inc");?>
-
-</body>
-</html>
+#!/usr/local/bin/php
+<?php
+/*
+ system_edit.php
+ Copyright (C) 2004, 2005 Scott Ullrich
+ All rights reserved.
+
+ Adapted for FreeNAS by Volker Theile (votdev@gmx.de)
+ Copyright (C) 2006-2009 Volker Theile
+
+ Adapted for Pfsense Snort package by Robert Zelaya
+ Copyright (C) 2008-2009 Robert Zelaya
+
+ Using dp.SyntaxHighlighter for syntax highlighting
+ http://www.dreamprojections.com/SyntaxHighlighter
+ Copyright (C) 2004-2006 Alex Gorbatchev. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once("guiconfig.inc");
+require_once("config.inc");
+
+
+if (!is_array($config['installedpackages']['snortglobal']['rule'])) {
+ $config['installedpackages']['snortglobal']['rule'] = array();
+}
+
+//nat_rules_sort();
+$a_nat = &$config['installedpackages']['snortglobal']['rule'];
+
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+$ids = $_GET['ids'];
+if (isset($_POST['ids']))
+ $ids = $_POST['ids'];
+
+
+if (isset($id) && $a_nat[$id]) {
+
+ $pconfig['enable'] = $a_nat[$id]['enable'];
+ $pconfig['interface'] = $a_nat[$id]['interface'];
+ $pconfig['rulesets'] = $a_nat[$id]['rulesets'];
+}
+
+/* convert fake interfaces to real */
+$if_real = convert_friendly_interface_to_real_interface_name($pconfig['interface']);
+
+
+$file = $_GET['openruleset'];
+
+//read snort file
+$filehandle = fopen($file, "r");
+
+//get rule id
+$lineid = $_GET['ids'];
+
+//read file into string, and get filesize
+$contents2 = fread($filehandle, filesize($file));
+
+//close handler
+fclose ($filehandle);
+
+//delimiter for each new rule is a new line
+$delimiter = "\n";
+
+//split the contents of the string file into an array using the delimiter
+$splitcontents = explode($delimiter, $contents2);
+
+//copy rule contents from array into string
+$tempstring = $splitcontents[$lineid];
+
+function write_rule_file($content_changed, $received_file)
+{
+ //read snort file with writing enabled
+ $filehandle = fopen($received_file, "w");
+
+ //delimiter for each new rule is a new line
+ $delimiter = "\n";
+
+ //implode the array back into a string for writing purposes
+ $fullfile = implode($delimiter, $content_changed);
+
+ //write data to file
+ fwrite($filehandle, $fullfile);
+
+ //close file handle
+ fclose($filehandle);
+
+}
+
+
+
+if($_POST['highlight'] <> "") {
+ if($_POST['highlight'] == "yes" or
+ $_POST['highlight'] == "enabled") {
+ $highlight = "yes";
+ } else {
+ $highlight = "no";
+ }
+} else {
+ $highlight = "no";
+}
+
+if($_POST['rows'] <> "")
+ $rows = $_POST['rows'];
+else
+ $rows = 1;
+
+if($_POST['cols'] <> "")
+ $cols = $_POST['cols'];
+else
+ $cols = 66;
+
+if ($_POST)
+{
+ if ($_POST['save']) {
+
+ /* get the changes */
+ $rule_content2 = $_POST['code'];
+
+ //copy string into file array for writing
+ $splitcontents[$lineid] = $rule_content2;
+
+ //write the new .rules file
+ write_rule_file($splitcontents, $file);
+
+ header("Location: /snort/snort_rules_edit.php?id=$id&openruleset=$file&ids=$ids");
+
+ }
+}
+
+$pgtitle = array(gettext("Advanced"), gettext("File Editor"));
+
+//
+?>
+
+<?php include("head.inc");?>
+
+<body link="#000000" vlink="#000000" alink="#000000">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont">
+ <form action="snort_rules_edit.php?id=<?=$id; ?>&openruleset=<?=$file; ?>&ids=<?=$ids; ?>" method="post">
+ <?php if ($savemsg) print_info_box($savemsg);?>
+ <table width="100%" cellpadding='9' cellspacing='9' bgcolor='#eeeeee'>
+ <tr>
+ <td>
+ <input name="save" type="submit" class="formbtn" id="save" value="save" /> <input type="button" class="formbtn" value="Cancel" onclick="history.back()">
+ <hr noshade="noshade" />
+ <?=gettext("Disable original rule"); ?>:
+ <input id="highlighting_enabled" name="highlight2" type="radio" value="yes" <?php if($highlight == "yes") echo " checked=\"checked\""; ?> />
+ <label for="highlighting_enabled"><?=gettext("Enabled"); ?></label>
+ <input id="highlighting_disabled" name="highlight2" type="radio" value="no"<?php if($highlight == "no") echo " checked=\"checked\""; ?> />
+ <label for="highlighting_disabled"><?=gettext("Disabled"); ?></label>
+ </td>
+ </tr>
+ </table>
+ <table width='100%'>
+ <tr>
+ <td valign="top" class="label">
+ <div style="background: #eeeeee;" id="textareaitem">
+ <!-- NOTE: The opening *and* the closing textarea tag must be on the same line. -->
+ <textarea wrap="off" style="width: 98%; margin: 7px;" class="<?php echo $language; ?>:showcolumns" rows="<?php echo $rows; ?>" cols="<?php echo $cols; ?>" name="code"><?php echo $tempstring;?></textarea>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <table width='100%'>
+ <tr>
+ <td valign="top" class="label">
+ <div style="background: #eeeeee;" id="textareaitem">
+ <!-- NOTE: The opening *and* the closing textarea tag must be on the same line. -->
+ <textarea disabled wrap="off" style="width: 98%; margin: 7px;" class="<?php echo $language; ?>:showcolumns" rows="33" cols="<?php echo $cols; ?>" name="code2"><?php echo $contents2;?></textarea>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <?php // include("formend.inc");?>
+ </form>
+ </td>
+ </tr>
+</table>
+<script class="javascript" src="/snort/syntaxhighlighter/shCore.js"></script>
+<script class="javascript" src="/snort/syntaxhighlighter/shBrushCSharp.js"></script>
+<script class="javascript" src="/snort/syntaxhighlighter/shBrushPhp.js"></script>
+<script class="javascript" src="/snort/syntaxhighlighter/shBrushJScript.js"></script>
+<script class="javascript" src="/snort/syntaxhighlighter/shBrushJava.js"></script>
+<script class="javascript" src="/snort/syntaxhighlighter/shBrushVb.js"></script>
+<script class="javascript" src="/snort/syntaxhighlighter/shBrushSql.js"></script>
+<script class="javascript" src="/snort/syntaxhighlighter/shBrushXml.js"></script>
+<script class="javascript" src="/snort/syntaxhighlighter/shBrushDelphi.js"></script>
+<script class="javascript" src="/snort/syntaxhighlighter/shBrushPython.js"></script>
+<script class="javascript" src="/snort/syntaxhighlighter/shBrushRuby.js"></script>
+<script class="javascript" src="/snort/syntaxhighlighter/shBrushCss.js"></script>
+<script class="javascript">
+<!--
+ // Set focus.
+ document.forms[0].savetopath.focus();
+
+ // Append css for syntax highlighter.
+ var head = document.getElementsByTagName("head")[0];
+ var linkObj = document.createElement("link");
+ linkObj.setAttribute("type","text/css");
+ linkObj.setAttribute("rel","stylesheet");
+ linkObj.setAttribute("href","/snort/syntaxhighlighter/SyntaxHighlighter.css");
+ head.appendChild(linkObj);
+
+ // Activate dp.SyntaxHighlighter?
+ <?php
+ if($_POST['highlight'] == "yes") {
+ echo "dp.SyntaxHighlighter.HighlightAll('code', true, true);\n";
+ // Disable 'Save' button.
+ echo "document.forms[0].Save.disabled = 1;\n";
+ }
+?>
+//-->
+</script>
+<?php //include("fend.inc");?>
+
+</body>
+</html>
diff --git a/config/snort-dev/snort_rulesets.php b/config/snort-dev/snort_rulesets.php
index dc3320fe..ece409e1 100644
--- a/config/snort-dev/snort_rulesets.php
+++ b/config/snort-dev/snort_rulesets.php
@@ -29,10 +29,10 @@
*/
require("guiconfig.inc");
-require_once("filter.inc");
-require_once("service-utils.inc");
+//require_once("filter.inc");
+//require_once("service-utils.inc");
include_once("/usr/local/pkg/snort/snort.inc");
-
+require_once("/usr/local/pkg/snort/snort_gui.inc");
if (!is_array($config['installedpackages']['snortglobal']['rule'])) {
@@ -57,23 +57,19 @@ if (isset($id) && $a_nat[$id]) {
/* convert fake interfaces to real */
$if_real = convert_friendly_interface_to_real_interface_name($pconfig['interface']);
-//if(!is_dir("/usr/local/etc/snort/rules"))
-// exec('mkdir /usr/local/etc/snort/rules/');
$iface_uuid = $a_nat[$id]['uuid'];
$pgtitle = "Snort: Interface $id $iface_uuid $if_real Categories";
-
-
/* Check if the rules dir is empy if so warn the user */
/* TODO give the user the option to delete the installed rules rules */
$isrulesfolderempty = exec("ls -A /usr/local/etc/snort/snort_{$iface_uuid}_{$if_real}/rules/*.rules");
if ($isrulesfolderempty == "") {
include("head.inc");
-include("fbegin.inc");
+include("./snort_fbegin.inc");
echo "<p class=\"pgtitle\">";
if($pfsense_stable == 'yes'){echo $pgtitle;}
@@ -81,8 +77,7 @@ echo "</p>\n";
echo "<body link=\"#000000\" vlink=\"#000000\" alink=\"#000000\">";
-echo "<script src=\"/row_toggle.js\" type=\"text/javascript\"></script>\n
-<script src=\"/javascript/sorttable.js\" type=\"text/javascript\"></script>\n
+echo "
<table width=\"99%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n
<tr>\n
<td>\n";
@@ -128,7 +123,26 @@ exit(0);
}
-if($_POST) {
+ /* alert file */
+$d_snortconfdirty_path = "/var/run/snort_conf_{$iface_uuid}_{$if_real}.dirty";
+
+ /* this will exec when alert says apply */
+ if ($_POST['apply']) {
+
+ if (file_exists($d_snortconfdirty_path)) {
+
+ write_config();
+
+ sync_snort_package_all();
+ sync_snort_package();
+
+ unlink($d_snortconfdirty_path);
+
+ }
+
+ }
+
+ if ($_POST["Submit"]) {
$enabled_items = "";
$isfirst = true;
if (is_array($_POST['toenable'])) {
@@ -142,12 +156,20 @@ if($_POST) {
$enabled_items = $_POST['toenable'];
}
$a_nat[$id]['rulesets'] = $enabled_items;
+
write_config();
-// stop_service("snort");
-// create_snort_conf();
-// sleep(2);
-// start_service("snort");
- $savemsg = "The snort ruleset selections have been saved.";
+
+ touch($d_snortconfdirty_path);
+
+ header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
+ header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
+ header( 'Cache-Control: no-store, no-cache, must-revalidate' );
+ header( 'Cache-Control: post-check=0, pre-check=0', false );
+ header( 'Pragma: no-cache' );
+ sleep(2);
+ sync_snort_package_all();
+ header("Location: /snort/snort_rulesets.php?id=$id");
+
}
$enabled_rulesets = $a_nat[$id]['rulesets'];
@@ -159,17 +181,41 @@ include("head.inc");
?>
<body link="#000000" vlink="#000000" alink="#000000">
-<?php include("fbegin.inc"); ?>
-<p class="pgtitle"><?if($pfsense_stable == 'yes'){echo $pgtitle;}?></p>
+<?php include("./snort_fbegin.inc"); ?>
+<p class="pgtitle"><?php if($pfsense_stable == 'yes'){echo $pgtitle;}?></p>
<?php
echo "<form action=\"snort_rulesets.php?id={$id}\" method=\"post\" name=\"iform\" id=\"iform\">";
?>
-<script src="/row_toggle.js" type="text/javascript"></script>
-<script src="/javascript/sorttable.js" type="text/javascript"></script>
-<?php if ($savemsg) print_info_box($savemsg); ?>
+<?php
+
+ /* Display message */
+
+ if ($input_errors) {
+ print_input_errors($input_errors); // TODO: add checks
+ }
+
+ if ($savemsg) {
+ print_info_box2($savemsg);
+ }
+
+ if (file_exists($d_snortconfdirty_path)) {
+ echo '<p>';
+
+ if($savemsg) {
+ print_info_box_np2("{$savemsg}");
+ }else{
+ print_info_box_np2('
+ The Snort configuration has changed and snort needs to be restarted on this interface.<br>
+ You must apply the changes in order for them to take effect.<br>
+ ');
+ }
+ }
+
+?>
+
<table width="99%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
@@ -221,7 +267,7 @@ echo "<form action=\"snort_rulesets.php?id={$id}\" method=\"post\" name=\"iform\
echo " <input type='checkbox' name='toenable[]' value='$file' {$CHECKED} />";
echo "</td>";
echo "<td>";
- echo "<a href='snort_rules.php?openruleset=/usr/local/etc/snort/snort_{$iface_uuid}_{$if_real}/rules/" . urlencode($file) . "'>{$file}</a>";
+ echo "<a href='snort_rules.php?id={$id}&openruleset=/usr/local/etc/snort/snort_{$iface_uuid}_{$if_real}/rules/" . urlencode($file) . "'>{$file}</a>";
echo "</td>";
//echo "<td>";
//echo "description";
@@ -235,7 +281,7 @@ echo "<form action=\"snort_rulesets.php?id={$id}\" method=\"post\" name=\"iform\
<tr><td>&nbsp;</td></tr>
<tr><td>Check the rulesets that you would like Snort to load at startup.</td></tr>
<tr><td>&nbsp;</td></tr>
- <tr><td><input value="Save" type="submit" name="save" id="save" /></td></tr>
+ <tr><td><input value="Save" type="submit" name="Submit" id="Submit" /></td></tr>
</table>
</div>
</td>
diff --git a/config/squid-8/proxy_monitor.sh b/config/squid-8/proxy_monitor.sh
new file mode 100644
index 00000000..fab2ee54
--- /dev/null
+++ b/config/squid-8/proxy_monitor.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+# $Id$ */
+#
+# proxy_monitor.sh
+# Copyright (C) 2006 Scott Ullrich
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+set -e
+
+LOOP_SLEEP=55
+
+if [ -f /var/run/squid_alarm ]; then
+ rm /var/run/squid_alarm
+fi
+
+# Sleep 5 seconds on startup not to mangle with existing boot scripts.
+sleep 5
+
+# Squid monitor 1.2
+while [ /bin/true ]; do
+ if [ ! -f /var/run/squid_alarm ]; then
+ NUM_PROCS=`ps auxw | grep "[s]quid -D"|awk '{print $2}'| wc -l | awk '{ print $1 }'`
+ if [ $NUM_PROCS -lt 1 ]; then
+ # squid is down
+ echo "Squid has exited. Reconfiguring filter." | \
+ logger -p daemon.info -i -t Squid_Alarm
+ echo "Attempting restart..." | logger -p daemon.info -i -t Squid_Alarm
+ /usr/local/etc/rc.d/squid.sh start
+ sleep 3
+ echo "Reconfiguring filter..." | logger -p daemon.info -i -t Squid_Alarm
+ /etc/rc.filter_configure_sync
+ touch /var/run/squid_alarm
+ fi
+ fi
+ NUM_PROCS=`ps auxw | grep "[s]quid -D"|awk '{print $2}'| wc -l | awk '{ print $1 }'`
+ if [ $NUM_PROCS -gt 0 ]; then
+ if [ -f /var/run/squid_alarm ]; then
+ echo "Squid has resumed. Reconfiguring filter." | \
+ logger -p daemon.info -i -t Squid_Alarm
+ /etc/rc.filter_configure_sync
+ rm /var/run/squid_alarm
+ fi
+ fi
+ sleep $LOOP_SLEEP
+done
+
+if [ -f /var/run/squid_alarm ]; then
+ rm /var/run/squid_alarm
+fi
+
diff --git a/config/squid-8/squid.inc b/config/squid-8/squid.inc
new file mode 100644
index 00000000..1f264a64
--- /dev/null
+++ b/config/squid-8/squid.inc
@@ -0,0 +1,1319 @@
+<?php
+/* $Id$ */
+/*
+ squid.inc
+ Copyright (C) 2006-2009 Scott Ullrich
+ Copyright (C) 2006 Fernando Lemos
+ Copyright (C) 2008 Martin Fuchs
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once('globals.inc');
+require_once('config.inc');
+require_once('util.inc');
+require_once('pfsense-utils.inc');
+require_once('pkg-utils.inc');
+require_once('service-utils.inc');
+
+if(!function_exists("filter_configure"))
+ require_once("filter.inc");
+
+define('SQUID_CONFBASE', '/usr/local/etc/squid');
+define('SQUID_ACLDIR', '/var/squid/acl');
+define('SQUID_PASSWD', '/var/etc/squid.passwd');
+
+$valid_acls = array();
+
+function squid_get_real_interface_address($iface) {
+ global $config;
+
+ $iface = convert_friendly_interface_to_real_interface_name($iface);
+ $line = trim(shell_exec("ifconfig $iface | grep inet | grep -v inet6"));
+ list($dummy, $ip, $dummy2, $netmask) = explode(" ", $line);
+
+ return array($ip, long2ip(hexdec($netmask)));
+}
+
+function squid_chown_recursive($dir, $user, $group) {
+ chown($dir, $user);
+ chgrp($dir, $group);
+ $handle = opendir($dir) ;
+ while (($item = readdir($handle)) !== false) {
+ if (($item != ".") && ($item != "..")) {
+ $path = "$dir/$item";
+ if (is_dir($path))
+ squid_chown_recursive($path, $user, $group);
+ else {
+ chown($path, $user);
+ chgrp($path, $group);
+ }
+ }
+ }
+}
+
+/* setup cache */
+function squid_dash_z() {
+ global $config;
+ $settings = $config['installedpackages']['squidcache']['config'][0];
+ $cachedir =($settings['harddisk_cache_location'] ? $settings['harddisk_cache_location'] : '/var/squid/cache');
+
+ if(!is_dir($cachedir.'/')) {
+ log_error("Creating Squid cache dir $cachedir");
+ make_dirs($cachedir);
+ squid_chown_recursive($cachedir, 'proxy', 'proxy');
+ }
+
+ if(!is_dir($cachedir.'/00/')) {
+ log_error("Creating squid cache subdirs in $cachedir");
+ mwexec("/usr/local/sbin/squid -k shutdown");
+ sleep(5);
+ mwexec("/usr/local/sbin/squid -k kill");
+ mwexec("/usr/local/sbin/squid -z");
+ }
+
+ if(file_exists("/var/squid/cache/swap.state"))
+ exec("chmod a+rw /var/squid/cache/swap.state");
+
+}
+
+function squid_is_valid_acl($acl) {
+ global $valid_acls;
+ if(!is_array($valid_acls))
+ return;
+ return in_array($acl, $valid_acls);
+}
+
+function squid_install_command() {
+ global $config;
+ /* migrate existing csv config fields */
+ $settingsauth = $config['installedpackages']['squidauth']['config'][0];
+ $settingscache = $config['installedpackages']['squidcache']['config'][0];
+ $settingsnac = $config['installedpackages']['squidnac']['config'][0];
+
+ /* migrate auth settings */
+ if (!empty($settingsauth['no_auth_hosts'])) {
+ if(strstr($settingsauth['no_auth_hosts'], ",")) {
+ $settingsauth['no_auth_hosts'] = base64_encode(implode("\n", explode(",", $settingsauth['no_auth_hosts'])));
+ $config['installedpackages']['squidauth']['config'][0]['no_auth_hosts'] = $settingsauth['no_auth_hosts'];
+ }
+ }
+
+ /* migrate cache settings */
+ if (!empty($settingscache['donotcache'])) {
+ if(strstr($settingscache['donotcache'], ",")) {
+ $settingscache['donotcache'] = base64_encode(implode("\n", explode(",", $settingscache['donotcache'])));
+ $config['installedpackages']['squidcache']['config'][0]['donotcache'] = $settingscache['donotcache'];
+ }
+ }
+
+ /* migrate nac settings */
+ if(! empty($settingsnac['allowed_subnets'])) {
+ if(strstr($settingsnac['allowed_subnets'], ",")) {
+ $settingsnac['allowed_subnets'] = base64_encode(implode("\n", explode(",", $settingsnac['allowed_subnets'])));
+ $config['installedpackages']['squidnac']['config'][0]['allowed_subnets'] = $settingsnac['allowed_subnets'];
+ }
+ }
+
+ if(! empty($settingsnac['banned_hosts'])) {
+ if(strstr($settingsnac['banned_hosts'], ",")) {
+ $settingsnac['banned_hosts'] = base64_encode(implode("\n", explode(",", $settingsnac['banned_hosts'])));
+ $config['installedpackages']['squidnac']['config'][0]['banned_hosts'] = $settingsnac['banned_hosts'];
+ }
+ }
+
+ if(! empty($settingsnac['banned_macs'])) {
+ if(strstr($settingsnac['banned_macs'], ",")) {
+ $settingsnac['banned_macs'] = base64_encode(implode("\n", explode(",", $settingsnac['banned_macs'])));
+ $config['installedpackages']['squidnac']['config'][0]['banned_macs'] = $settingsnac['banned_macs'];
+ }
+ }
+
+ if(! empty($settingsnac['unrestricted_hosts'])) {
+ if(strstr($settingsnac['unrestricted_hosts'], ",")) {
+ $settingsnac['unrestricted_hosts'] = base64_encode(implode("\n", explode(",", $settingsnac['unrestricted_hosts'])));
+ $config['installedpackages']['squidnac']['config'][0]['unrestricted_hosts'] = $settingsnac['unrestricted_hosts'];
+ }
+ }
+
+ if(! empty($settingsnac['unrestricted_macs'])) {
+ if(strstr($settingsnac['unrestricted_macs'], ",")) {
+ $settingsnac['unrestricted_macs'] = base64_encode(implode("\n", explode(",", $settingsnac['unrestricted_macs'])));
+ $config['installedpackages']['squidnac']['config'][0]['unrestricted_macs'] = $settingsnac['unrestricted_macs'];
+ }
+ }
+
+ if(! empty($settingsnac['whitelist'])) {
+ if(strstr($settingsnac['whitelist'], ",")) {
+ $settingsnac['whitelist'] = base64_encode(implode("\n", explode(",", $settingsnac['whitelist'])));
+ $config['installedpackages']['squidnac']['config'][0]['whitelist'] = $settingsnac['whitelist'];
+ }
+ }
+
+ if(! empty($settingsnac['blacklist'])) {
+ if(strstr($settingsnac['blacklist'], ",")) {
+ $settingsnac['blacklist'] = base64_encode(implode("\n", explode(",", $settingsnac['blacklist'])));
+ $config['installedpackages']['squidnac']['config'][0]['blacklist'] = $settingsnac['blacklist'];
+ }
+ }
+
+ update_status("Writing configuration... One moment please...");
+
+ write_config();
+
+ /* create cache */
+ update_status("Creating squid cache pools... One moment please...");
+ squid_dash_z();
+ /* make sure pinger is executable */
+ if(file_exists("/usr/local/libexec/squid/pinger"))
+ exec("/bin/chmod a+x /usr/local/libexec/squid/pinger");
+ if(file_exists("/usr/local/etc/rc.d/squid"))
+ exec("/bin/rm /usr/local/etc/rc.d/squid");
+ $rc = array();
+ $rc['file'] = 'squid.sh';
+ $rc['start'] = <<<EOD
+if [ -z "`ps auxw | grep "[s]quid -D"|awk '{print $2}'`" ];then
+ /usr/local/sbin/squid -D
+fi
+
+EOD;
+ $rc['stop'] = <<<EOD
+/usr/local/sbin/squid -k shutdown
+# Just to be sure...
+sleep 5
+killall -9 squid 2>/dev/null
+killall pinger 2>/dev/null
+
+EOD;
+ $rc['restart'] = <<<EOD
+if [ -z "`ps auxw | grep "[s]quid -D"|awk '{print $2}'`" ];then
+ /usr/local/sbin/squid -D
+ else
+ /usr/local/sbin/squid -k reconfigure
+ fi
+
+EOD;
+ update_status("Writing rc.d files... One moment please...");
+ write_rcfile($rc);
+
+ exec("chmod a+rx /usr/local/libexec/squid/dnsserver");
+
+ foreach (array( SQUID_CONFBASE,
+ SQUID_ACLDIR,
+ ) as $dir) {
+ make_dirs($dir);
+ squid_chown_recursive($dir, 'proxy', 'proxy');
+ }
+
+ /* kill any running proxy alarm scripts */
+ update_status("Checking for running processes... One moment please...");
+ log_error("Stopping any running proxy monitors");
+ mwexec("ps awux | grep \"proxy_monitor\" | grep -v \"grep\" | grep -v \"php\" | awk '{ print $2 }' | xargs kill");
+ sleep(1);
+
+ if (!file_exists(SQUID_CONFBASE . '/mime.conf') && file_exists(SQUID_CONFBASE . '/mime.conf.default'))
+ copy(SQUID_CONFBASE . '/mime.conf.default', SQUID_CONFBASE . '/mime.conf');
+
+ update_status("Checking cache... One moment please...");
+ squid_dash_z();
+
+ if (!is_service_running('squid')) {
+ update_status("Starting... One moment please...");
+ log_error("Starting Squid");
+ mwexec_bg("/usr/local/sbin/squid -D");
+ } else {
+ update_status("Reloading Squid for configuration sync... One moment please...");
+ log_error("Reloading Squid for configuration sync");
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ }
+
+ /* restart proxy alarm scripts */
+ log_error("Starting a proxy monitor script");
+ mwexec_bg("/usr/local/etc/rc.d/proxy_monitor.sh");
+
+ update_status("Reconfiguring filter... One moment please...");
+ filter_configure();
+}
+
+function squid_deinstall_command() {
+ global $config, $g;
+ $plswait_txt = "This operation may take quite some time, please be patient. Do not press stop or attempt to navigate away from this page during this process.";
+ squid_install_cron(false);
+ $settings = &$config['installedpackages']['squidcache']['config'][0];
+ $cachedir =($settings['harddisk_cache_location'] ? $settings['harddisk_cache_location'] : '/var/squid/cache');
+ $logdir = ($settings['log_dir'] ? $settings['log_dir'] : '/var/squid/log');
+ update_status("Removing swap.state ... One moment please...");
+ update_output_window("$plswait_txt");
+ mwexec('rm -rf $cachedir/swap.state');
+ mwexec('rm -rf $logdir');
+ update_status("Finishing package cleanup.");
+ mwexec('rm -f /usr/local/etc/rc.d/proxy_monitor.sh');
+ mwexec("ps awux | grep \"proxy_monitor\" | grep -v \"grep\" | grep -v \"php\" | awk '{ print $2 }' | xargs kill");
+ mwexec("ps awux | grep \"squid\" | grep -v \"grep\" | awk '{ print $2 }' | xargs kill");
+ mwexec("ps awux | grep \"dnsserver\" | grep -v \"grep\" | awk '{ print $2 }' | xargs kill");
+ mwexec("ps awux | grep \"unlinkd\" | grep -v \"grep\" | awk '{ print $2 }' | xargs kill");
+ update_status("Reloading filter...");
+ filter_configure_sync();
+}
+
+function squid_before_form_general($pkg) {
+ $values = get_dir(SQUID_CONFBASE . '/errors/');
+ // Get rid of '..' and '.'
+ array_shift($values);
+ array_shift($values);
+ $name = array();
+ foreach ($values as $value)
+ $names[] = implode(" ", explode("_", $value));
+
+ $i = 0;
+ foreach ($pkg['fields']['field'] as $field) {
+ if ($field['fieldname'] == 'error_language')
+ break;
+ $i++;
+ }
+ $field = &$pkg['fields']['field'][$i];
+
+ for ($i = 0; $i < count($values) - 1; $i++)
+ $field['options']['option'][] = array('name' => $names[$i], 'value' => $values[$i]);
+}
+
+function squid_validate_general($post, $input_errors) {
+ global $config;
+ $settings = $config['installedpackages']['squid']['config'][0];
+ $port = ($settings['proxy_port'] ? $settings['proxy_port'] : 3128);
+ $port = $post['proxy_port'] ? $post['proxy_port'] : $port;
+
+ $icp_port = trim($post['icp_port']);
+ if (!empty($icp_port) && !is_port($icp_port))
+ $input_errors[] = 'You must enter a valid port number in the \'ICP port\' field';
+
+ if (substr($post['log_dir'], -1, 1) == '/')
+ $input_errors[] = 'You may not end log location with an / mark';
+
+ if ($post['log_dir']{0} != '/')
+ $input_errors[] = 'You must start log location with a / mark';
+ if (strlen($post['log_dir']) <= 3)
+ $input_errors[] = "That is not a valid log location dir";
+
+ $log_rotate = trim($post['log_rotate']);
+ if (!empty($log_rotate) && (!is_numeric($log_rotate) or ($log_rotate < 1)))
+ $input_errors[] = 'You must enter a valid number of days \'Log rotate\' field';
+
+ $webgui_port = $config['system']['webgui']['port'];
+ if(($config['system']['webgui']['port'] == "") && ($config['system']['webgui']['protocol'] == "http")) {
+ $webgui_port = 80;
+ }
+ if(($config['system']['webgui']['port'] == "") && ($config['system']['webgui']['protocol'] == "https")) {
+ $webgui_port = 443;
+ }
+
+ if (($post['transparent_proxy'] != 'on') && ($port == $webgui_port)) {
+ $input_errors[] = "You can not run squid on the same port as the webgui";
+ }
+
+ if (($post['transparent_proxy'] != 'on') && ($post['private_subnet_proxy_off'] == 'on')) {
+ $input_errors[] = "You can not bypass traffic to private subnets without using the transparent proxy.";
+ }
+
+ if (($post['transparent_proxy'] != 'on') && !empty($post['defined_ip_proxy_off'])) {
+ $input_errors[] = "You can not bypass traffic from specific IPs without using the transparent proxy.";
+ }
+
+ foreach (array('defined_ip_proxy_off') as $hosts) {
+ foreach (explode(";", $post[$hosts]) as $host) {
+ $host = trim($host);
+ if (!empty($host) && !is_ipaddr($host))
+ $input_errors[] = "The entry '$host' is not a valid IP address";
+ }
+ }
+
+ if(!empty($post['dns_nameservers'])) {
+ $altdns = explode(";", ($post['dns_nameservers']));
+ foreach ($altdns as $dnssrv) {
+ if (!is_ipaddr($dnssrv))
+ $input_errors[] = 'You must enter a valid IP address in the \'Alternate DNS servers\' field';
+ }}
+}
+
+function squid_validate_upstream($post, $input_errors) {
+ if ($post['proxy_forwarding'] == 'on') {
+ $addr = trim($post['proxy_addr']);
+ if (empty($addr))
+ $input_errors[] = 'The field \'Hostname\' is required';
+ else {
+ if (!is_ipaddr($addr) && !is_domain($addr))
+ $input_errors[] = 'You must enter a valid IP address or host name in the \'Proxy hostname\' field';
+ }
+
+ foreach (array('proxy_port' => 'TCP port', 'icp_port' => 'ICP port') as $field => $name) {
+ $port = trim($post[$field]);
+ if (empty($port))
+ $input_errors[] = "The field '$name' is required";
+ else {
+ if (!is_port($port))
+ $input_errors[] = "The field '$name' must contain a valid port number, between 0 and 65535";
+ }
+ }
+ }
+}
+
+function squid_validate_cache($post, $input_errors) {
+ $num_fields = array( 'harddisk_cache_size' => 'Hard disk cache size',
+ 'memory_cache_size' => 'Memory cache size',
+ 'maximum_object_size' => 'Maximum object size',
+ );
+ foreach ($num_fields as $field => $name) {
+ $value = trim($post[$field]);
+ if (!is_numeric($value) || ($value < 0))
+ $input_errors[] = "You must enter a valid value for '$field'";
+ }
+
+ $value = trim($post['minimum_object_size']);
+ if (!is_numeric($value) || ($value < 0))
+ $input_errors[] = 'You must enter a valid value for \'Minimum object size\'';
+
+ if (!empty($post['cache_swap_low'])) {
+ $value = trim($post['cache_swap_low']);
+ if (!is_numeric($value) || ($value > 100))
+ $input_errors[] = 'You must enter a valid value for \'Low-water-mark\'';
+ }
+
+ if (!empty($post['cache_swap_high'])) {
+ $value = trim($post['cache_swap_high']);
+ if (!is_numeric($value) || ($value > 100))
+ $input_errors[] = 'You must enter a valid value for \'High-water-mark\'';
+ }
+
+ if ($post['donotcache'] != "") {
+ foreach (split("\n", $post['donotcache']) as $host) {
+ $host = trim($host);
+ if (!is_ipaddr($host) && !is_domain($host))
+ $input_errors[] = "The host '$host' is not a valid IP or host name";
+ }
+ }
+
+ squid_dash_z();
+
+}
+
+function squid_validate_nac($post, $input_errors) {
+ $allowed_subnets = explode("\n", $post['allowed_subnets']);
+ foreach ($allowed_subnets as $subnet) {
+ $subnet = trim($subnet);
+ if (!empty($subnet) && !is_subnet($subnet))
+ $input_errors[] = "The subnet '$subnet' is not a valid CIDR range";
+ }
+
+ foreach (array( 'unrestricted_hosts', 'banned_hosts') as $hosts) {
+ foreach (explode("\n", $post[$hosts]) as $host) {
+ $host = trim($host);
+ if (!empty($host) && !is_ipaddr($host))
+ $input_errors[] = "The host '$host' is not a valid IP address";
+ }
+ }
+
+ foreach (array('unrestricted_macs', 'banned_macs') as $macs) {
+ foreach (explode("\n", $post[$macs]) as $mac) {
+ $mac = trim($mac);
+ if (!empty($mac) && !is_macaddr($mac))
+ $input_errors[] = "The mac '$mac' is not a valid MAC address";
+ }
+ }
+
+ foreach (explode(",", $post['timelist']) as $time) {
+ $time = trim($time);
+ if (!empty($time) && !squid_is_timerange($time))
+ $input_errors[] = "The time range '$time' is not a valid time range";
+ }
+
+ if(!empty($post['ext_cachemanager'])) {
+ $extmgr = explode(";", ($post['ext_cachemanager']));
+ foreach ($extmgr as $mgr) {
+ if (!is_ipaddr($mgr))
+ $input_errors[] = 'You must enter a valid IP address in the \'External Cache Manager\' field';
+ }}
+}
+
+function squid_validate_traffic($post, $input_errors) {
+ $num_fields = array( 'max_download_size' => 'Maximum download size',
+ 'max_upload_size' => 'Maximum upload size',
+ 'perhost_throttling' => 'Per-host bandwidth throttling',
+ 'overall_throttling' => 'Overall bandwidth throttling',
+ );
+ foreach ($num_fields as $field => $name) {
+ $value = trim($post[$field]);
+ if (!is_numeric($value) || ($value < 0))
+ $input_errors[] = "The field '$name' must contain a positive number";
+ }
+
+ if (!empty($post['quick_abort_min'])) {
+ $value = trim($post['quick_abort_min']);
+ if (!is_numeric($value))
+ $input_errors[] = "The field 'Finish when remaining KB' must contain a positive number";
+ }
+
+ if (!empty($post['quick_abort_max'])) {
+ $value = trim($post['quick_abort_max']);
+ if (!is_numeric($value))
+ $input_errors[] = "The field 'Abort when remaining KB' must contain a positive number";
+ }
+
+ if (!empty($post['quick_abort_pct'])) {
+ $value = trim($post['quick_abort_pct']);
+ if (!is_numeric($value) || ($value > 100))
+ $input_errors[] = "The field 'Finish when remaining %' must contain a percentaged value";
+ }
+
+}
+
+function squid_validate_auth($post, $input_errors) {
+ $num_fields = array( array('auth_processes', 'Authentication processes', 1),
+ array('auth_ttl', 'Authentication TTL', 0),
+ );
+ foreach ($num_fields as $field) {
+ $value = trim($post[$field[0]]);
+ if (!empty($value) && (!is_numeric($value) || ($value < $field[2])))
+ $input_errors[] = "The field '{$field[1]}' must contain a valid number greater than {$field[2]}";
+ }
+
+ $auth_method = $post['auth_method'];
+ if (($auth_method != 'none') && ($auth_method != 'local')) {
+ $server = trim($post['auth_server']);
+ if (empty($server))
+ $input_errors[] = 'The field \'Authentication server\' is required';
+ else if (!is_ipaddr($server) && !is_domain($server))
+ $input_errors[] = 'The field \'Authentication server\' must contain a valid IP address or domain name';
+
+ $port = trim($post['auth_server_port']);
+ if (!empty($port) && !is_port($port))
+ $input_errors[] = 'The field \'Authentication server port\' must contain a valid port number';
+
+ switch ($auth_method) {
+ case 'ldap':
+ $user = trim($post['ldap_user']);
+ if (empty($user))
+ $input_errors[] = 'The field \'LDAP server user DN\' is required';
+ else if (!$user)
+ $input_errors[] = 'The field \'LDAP server user DN\' must be a valid domain name';
+ break;
+ case 'radius':
+ $secret = trim($post['radius_secret']);
+ if (empty($secret))
+ $input_errors[] = 'The field \'RADIUS secret\' is required';
+ break;
+ case 'msnt':
+ foreach (explode(",", trim($post['msnt_secondary'])) as $server) {
+ if (!empty($server) && !is_ipaddr($server) && !is_domain($server))
+ $input_errors[] = "The host '$server' is not a valid IP address or domain name";
+ }
+ break;
+ }
+
+ $no_auth = explode("\n", $post['no_auth_hosts']);
+ foreach ($no_auth as $host) {
+ $host = trim($host);
+ if (!empty($host) && !is_subnet($host))
+ $input_errors[] = "The host '$host' is not a valid CIDR range";
+ }
+ }
+}
+
+function squid_install_cron($should_install) {
+ global $config, $g;
+ if($g['booting']==true)
+ return;
+ $is_installed = false;
+ if(!$config['cron']['item'])
+ return;
+ $x=0;
+ foreach($config['cron']['item'] as $item) {
+ if(strstr($item['command'], "/usr/local/sbin/squid")) {
+ $is_installed = true;
+ break;
+ }
+ $x++;
+ }
+ switch($should_install) {
+ case true:
+ if(!$is_installed) {
+ $cron_item = array();
+ $cron_item['minute'] = "0";
+ $cron_item['hour'] = "0";
+ $cron_item['mday'] = "*";
+ $cron_item['month'] = "*";
+ $cron_item['wday'] = "*";
+ $cron_item['who'] = "root";
+ $cron_item['command'] = "/usr/local/sbin/squid -k rotate";
+ $config['cron']['item'][] = $cron_item;
+ parse_config(true);
+ write_config("Squid Log Rotation");
+ configure_cron();
+ }
+ break;
+ case false:
+ if($is_installed == true) {
+ if($x > 0) {
+ unset($config['cron']['item'][$x]);
+ parse_config(true);
+ write_config();
+ }
+ configure_cron();
+ }
+ break;
+ }
+}
+
+function squid_resync_general() {
+ global $g, $config, $valid_acls;
+
+ $settings = $config['installedpackages']['squid']['config'][0];
+ $conf = "# This file is automatically generated by pfSense\n";
+ $conf = "# Do not edit manually !\n";
+
+ $port = ($settings['proxy_port'] ? $settings['proxy_port'] : 3128);
+ $ifaces = ($settings['active_interface'] ? $settings['active_interface'] : 'lan');
+ $real_ifaces = array();
+ foreach (explode(",", $ifaces) as $i => $iface) {
+ $real_ifaces[] = squid_get_real_interface_address($iface);
+ if($real_ifaces[$i][0]) {
+ $conf .= "http_port {$real_ifaces[$i][0]}:$port\n";
+ }
+ }
+ if (($settings['transparent_proxy'] == 'on')) {
+ $conf .= "http_port 127.0.0.1:80 transparent\n";
+ }
+ $icp_port = ($settings['icp_port'] ? $settings['icp_port'] : 0);
+
+ $pidfile = "{$g['varrun_path']}/squid.pid";
+ $language = ($settings['error_language'] ? $settings['error_language'] : 'English');
+ $errordir = SQUID_CONFBASE . '/errors/' . $language;
+ $icondir = SQUID_CONFBASE . '/icons';
+ $hostname = ($settings['visible_hostname'] ? $settings['visible_hostname'] : 'localhost');
+ $email = ($settings['admin_email'] ? $settings['admin_email'] : 'admin@localhost');
+
+ $logdir = ($settings['log_dir'] ? $settings['log_dir'] : '/var/squid/log');
+
+ $logdir_cache = $logdir . '/cache.log';
+ $logdir_access = ($settings['log_enabled'] == 'on' ? $logdir . '/access.log' : '/dev/null');
+
+ $conf .= <<<EOD
+icp_port $icp_port
+
+pid_filename $pidfile
+cache_effective_user proxy
+cache_effective_group proxy
+error_directory $errordir
+icon_directory $icondir
+visible_hostname $hostname
+cache_mgr $email
+access_log $logdir_access
+cache_log $logdir_cache
+cache_store_log none
+
+EOD;
+
+ if (!empty($settings['log_rotate'])) {
+ $conf .= "logfile_rotate {$settings['log_rotate']}\n";
+ squid_install_cron(true);
+ }
+ else {
+ squid_install_cron(false);
+ }
+
+ $conf .= <<<EOD
+shutdown_lifetime 3 seconds
+
+EOD;
+
+ if ($settings['allow_interface'] == 'on') {
+ $src = '';
+ foreach ($real_ifaces as $iface) {
+ list($ip, $mask) = $iface;
+ $ip = long2ip(ip2long($ip) & ip2long($mask));
+ $src .= " $ip/$mask";
+ }
+ $conf .= "# Allow local network(s) on interface(s)\n";
+ $conf .= "acl localnet src $src\n";
+ $valid_acls[] = 'localnet';
+ }
+ if ($settings['disable_xforward']) $conf .= "forwarded_for off\n";
+ if ($settings['disable_via']) $conf .= "via off\n";
+ if ($settings['disable_squidversion']) $conf .= "httpd_suppress_version_string on\n";
+ if (!empty($settings['uri_whitespace'])) $conf .= "uri_whitespace {$settings['uri_whitespace']}\n";
+ else $conf .= "uri_whitespace strip\n"; //only used for first run
+
+ if(!empty($settings['dns_nameservers'])) {
+ $altdns = explode(";", ($settings['dns_nameservers']));
+ $conf .= "dns_nameservers ";
+ foreach ($altdns as $dnssrv) {
+ $conf .= $dnssrv." ";
+ }
+// $conf .= "\n"; //Kill blank line after DNS-Servers
+ }
+
+ return $conf;
+}
+
+
+function squid_resync_cache() {
+ global $config;
+
+ $settings = $config['installedpackages']['squidcache']['config'][0];
+
+ $cachedir =($settings['harddisk_cache_location'] ? $settings['harddisk_cache_location'] : '/var/squid/cache');
+ $disk_cache_size = ($settings['harddisk_cache_size'] ? $settings['harddisk_cache_size'] : 100);
+ $disk_cache_system = ($settings['harddisk_cache_system'] ? $settings['harddisk_cache_system'] : 'aufs');
+ $level1 = ($settings['level1_subdirs'] ? $settings['level1_subdirs'] : 16);
+ $memory_cache_size = ($settings['memory_cache_size'] ? $settings['memory_cache_size'] : 8);
+ $max_objsize = ($settings['maximum_object_size'] ? $settings['maximum_object_size'] : 10);
+ $min_objsize = ($settings['minimum_object_size'] ? $settings['minimum_object_size'] : 0);
+ $cache_policy = ($settings['cache_replacement_policy'] ? $settings['cache_replacement_policy'] : 'heap LFUDA');
+ $memory_policy = ($settings['memory_replacement_policy'] ? $settings['memory_replacement_policy'] : 'heap GDSF');
+ $offline_mode = ($settings['enable_offline'] == 'on' ? 'on' : 'off');
+
+ $conf = <<<EOD
+cache_mem $memory_cache_size MB
+maximum_object_size_in_memory 32 KB
+memory_replacement_policy $memory_policy
+cache_replacement_policy $cache_policy
+cache_dir $disk_cache_system $cachedir $disk_cache_size $level1 256
+minimum_object_size $min_objsize KB
+maximum_object_size $max_objsize KB
+offline_mode $offline_mode
+
+EOD;
+
+ if (!empty($settings['cache_swap_low'])) $conf .= "cache_swap_low {$settings['cache_swap_low']}\n";
+ if (!empty($settings['cache_swap_high'])) $conf .= "cache_swap_high {$settings['cache_swap_high']}\n";
+
+ $donotcache = base64_decode($settings['donotcache']);
+ if (!empty($donotcache)) {
+ file_put_contents(SQUID_ACLDIR . '/donotcache.acl', $donotcache);
+ $conf .= 'acl donotcache dstdomain "' . SQUID_ACLDIR . "/donotcache.acl\"\n";
+ $conf .= 'cache deny donotcache';
+ }
+ elseif (file_exists(SQUID_ACLDIR . '/donotcache.acl')) {
+ unlink(SQUID_ACLDIR . '/donotcache.acl');
+ }
+
+ return $conf;
+}
+
+function squid_resync_upstream() {
+ global $config;
+ $settings = $config['installedpackages']['squidupstream']['config'][0];
+
+ $conf = '';
+ if ($settings['proxy_forwarding'] == 'on') {
+ $conf .= "cache_peer {$settings['proxy_addr']} parent {$settings['proxy_port']} ";
+ if ($settings['icp_port'] == '7')
+ $conf .= "{$settings['icp_port']} no-query";
+ else
+ $conf .= "{$settings['icp_port']}";
+
+ if (!empty($settings['username']))
+ $conf .= " login={$settings['username']}";
+ if (!empty($settings['password']))
+ $conf .= ":{$settings['password']}";
+ }
+
+ return $conf;
+}
+
+function squid_resync_redirector() {
+ global $config;
+
+ $httpav_enabled = ($config['installedpackages']['clamav']['config'][0]['scan_http'] == 'on');
+ if ($httpav_enabled) {
+ $conf = "url_rewrite_program /usr/local/bin/squirm\n";
+ } else {
+ $conf = "# No redirector configured\n";
+ }
+ return $conf;
+}
+
+function squid_resync_nac() {
+ global $config, $valid_acls;
+
+ $port = ($settings['proxy_port'] ? $settings['proxy_port'] : 3128);
+ $settings = $config['installedpackages']['squidnac']['config'][0];
+ $webgui_port = $config['system']['webgui']['port'];
+
+ $conf = <<<EOD
+
+# Setup some default acls
+acl all src 0.0.0.0/0.0.0.0
+acl localhost src 127.0.0.1/255.255.255.255
+acl safeports port 21 70 80 210 280 443 488 563 591 631 777 901 $webgui_port $port 1025-65535
+acl sslports port 443 563 $webgui_port
+acl manager proto cache_object
+acl purge method PURGE
+acl connect method CONNECT
+acl dynamic urlpath_regex cgi-bin \?
+
+EOD;
+
+ $allowed_subnets = explode("\n", base64_decode($settings['allowed_subnets']));
+ $allowed = "";
+ foreach ($allowed_subnets as $subnet) {
+ if(!empty($subnet)) {
+ $subnet = trim($subnet);
+ $allowed .= "$subnet ";
+ }
+ }
+ if (!empty($allowed)) {
+ $conf .= "acl allowed_subnets src $allowed\n";
+ $valid_acls[] = 'allowed_subnets';
+ }
+
+ $options = array( 'unrestricted_hosts' => 'src',
+ 'banned_hosts' => 'src',
+ 'whitelist' => 'dstdom_regex -i',
+ 'blacklist' => 'dstdom_regex -i',
+ );
+ foreach ($options as $option => $directive) {
+ $contents = base64_decode($settings[$option]);
+ if (!empty($contents)) {
+ file_put_contents(SQUID_ACLDIR . "/$option.acl", $contents);
+ $conf .= "acl $option $directive \"" . SQUID_ACLDIR . "/$option.acl\"\n";
+ $valid_acls[] = $option;
+ }
+ elseif (file_exists(SQUID_ACLDIR . "/$option.acl")) {
+ unlink(SQUID_ACLDIR . "/$option.acl");
+ }
+ }
+
+ $conf .= <<<EOD
+cache deny dynamic
+http_access allow manager localhost
+
+EOD;
+
+ if(!empty($settings['ext_cachemanager'])) {
+ $extmgr = explode(";", ($settings['ext_cachemanager']));
+ $count = 1;
+ $conf .= "\n# Allow external cache managers\n";
+// $conf .= "acl ext_manager src ".$settings['ext_cachemanager']."\n";
+ foreach ($extmgr as $mgr) {
+ $conf .= "acl ext_manager_".$count." src ";
+ $conf .= $mgr." ";
+ $conf .= "\n";
+ $conf .= "http_access allow manager ext_manager_".$count."\n";
+ $count += 1;
+ }}
+
+ $conf .= <<<EOD
+
+http_access deny manager
+http_access allow purge localhost
+http_access deny purge
+http_access deny !safeports
+http_access deny CONNECT !sslports
+
+# Always allow localhost connections
+http_access allow localhost
+
+EOD;
+
+ return $conf;
+}
+
+function squid_resync_traffic() {
+ global $config, $valid_acls;
+ if(!is_array($valid_acls))
+ return;
+ $settings = $config['installedpackages']['squidtraffic']['config'][0];
+ $conf = '';
+
+ if (!empty($settings['quick_abort_min']) || ($settings['quick_abort_min']) == "0") $conf .= "quick_abort_min {$settings['quick_abort_min']} KB\n";
+ if (!empty($settings['quick_abort_max']) || ($settings['quick_abort_max']) == "0") $conf .= "quick_abort_max {$settings['quick_abort_max']} KB\n";
+ if (!empty($settings['quick_abort_pct'])) $conf .= "quick_abort_pct {$settings['quick_abort_pct']}\n";
+
+ $up_limit = ($settings['max_upload_size'] ? $settings['max_upload_size'] : 0);
+ $down_limit = ($settings['max_download_size'] ? $settings['max_download_size'] : 0);
+ $conf .= "request_body_max_size $up_limit KB\n";
+ $conf .= 'reply_body_max_size ' . ($down_limit * 1024) . " allow all\n";
+
+ // Only apply throttling past 10MB
+ // XXX: Should this really be hardcoded?
+ $threshold = 10 * 1024 * 1024;
+ $overall = $settings['overall_throttling'];
+ if (!isset($overall) || ($overall == 0))
+ $overall = -1;
+ else
+ $overall *= 1024;
+ $perhost = $settings['perhost_throttling'];
+ if (!isset($perhost) || ($perhost == 0))
+ $perhost = -1;
+ else
+ $perhost *= 1024;
+ $conf .= <<<EOD
+delay_pools 1
+delay_class 1 2
+delay_parameters 1 $overall/$overall $perhost/$perhost
+delay_initial_bucket_level 100
+
+EOD;
+
+ if(! empty($settings['unrestricted_hosts'])) {
+ foreach (array('unrestricted_hosts') as $item) {
+ if (in_array($item, $valid_acls))
+ $conf .= "# Do not throttle unrestricted hosts\n";
+ $conf .= "delay_access 1 deny $item\n";
+ }
+ }
+
+ if ($settings['throttle_specific'] == 'on') {
+ $exts = array();
+ $binaries = 'bin,cab,sea,ar,arj,tar,tgz,gz,tbz,bz2,zip,7z,exe,com';
+ $cdimages = 'iso,bin,mds,nrg,gho,bwt,b5t,pqi';
+ $multimedia = 'aiff?,asf,avi,divx,mov,mp3,mp4,wmv,mpe?g,qt,ra?m';
+ foreach (array( 'throttle_binaries' => $binaries,
+ 'throttle_cdimages' => $cdimages,
+ 'throttle_multimedia' => $multimedia) as $field => $set) {
+ if ($settings[$field] == 'on')
+ $exts = array_merge($exts, explode(",", $set));
+ }
+
+ foreach (explode(",", $settings['throttle_others']) as $ext) {
+ if (!empty($ext)) $exts[] = $ext;
+ }
+
+ $contents = '';
+ foreach ($exts as $ext)
+ $contents .= "\.$ext\$\n";
+ file_put_contents(SQUID_ACLDIR . '/throttle_exts.acl', $contents);
+
+ $conf .= "# Throttle extensions matched in the url\n";
+ $conf .= "acl throttle_exts urlpath_regex -i \"" . SQUID_ACLDIR . "/throttle_exts.acl\"\n";
+ $conf .= "delay_access 1 allow throttle_exts\n";
+ $conf .= "delay_access 1 deny all\n";
+ }
+ else
+ $conf .= "delay_access 1 allow all\n";
+
+ return $conf;
+}
+
+function squid_resync_auth() {
+ global $config, $valid_acls;
+
+ $settings = $config['installedpackages']['squidauth']['config'][0];
+ $settingsnac = $config['installedpackages']['squidnac']['config'][0];
+ $settingsconfig = $config['installedpackages']['squid']['config'][0];
+ $conf = '';
+
+ // Deny the banned guys before allowing the good guys
+ if(! empty($settingsnac['banned_hosts'])) {
+ if (squid_is_valid_acl('banned_hosts')) {
+ $conf .= "# These hosts are banned\n";
+ $conf .= "http_access deny banned_hosts\n";
+ }
+ }
+ if(! empty($settingsnac['banned_macs'])) {
+ if (squid_is_valid_acl('banned_macs')) {
+ $conf .= "# These macs are banned\n";
+ $conf .= "http_access deny banned_macs\n";
+ }
+ }
+
+ // Unrestricted hosts take precendence over blacklist
+ if(! empty($settingsnac['unrestricted_hosts'])) {
+ if (squid_is_valid_acl('unrestricted_hosts')) {
+ $conf .= "# These hosts do not have any restrictions\n";
+ $conf .= "http_access allow unrestricted_hosts\n";
+ }
+ }
+ if(! empty($settingsnac['unrestricted_macs'])) {
+ if (squid_is_valid_acl('unrestricted_macs')) {
+ $conf .= "# These hosts do not have any restrictions\n";
+ $conf .= "http_access allow unrestricted_macs\n";
+ }
+ }
+
+ // Whitelist and blacklist also take precendence over other allow rules
+ if(! empty($settingsnac['whitelist'])) {
+ if (squid_is_valid_acl('whitelist')) {
+ $conf .= "# Always allow access to whitelist domains\n";
+ $conf .= "http_access allow whitelist\n";
+ }
+ }
+ if(! empty($settingsnac['blacklist'])) {
+ if (squid_is_valid_acl('blacklist')) {
+ $conf .= "# Block access to blacklist domains\n";
+ $conf .= "http_access deny blacklist\n";
+ }
+ }
+
+ $transparent_proxy = ($settingsconfig['transparent_proxy'] == 'on');
+ $auth_method = (($settings['auth_method'] && !$transparent_proxy) ? $settings['auth_method'] : 'none');
+ // Allow the remaining ACLs if no authentication is set
+ if ($auth_method == 'none') {
+ if ($settingsconfig['allow_interface'] == 'on') {
+ $conf .= "# Allow local network(s) on interface(s)\n";
+ $allowed = array('localnet', 'allowed_subnets');
+ $allowed = array_filter($allowed, 'squid_is_valid_acl');
+ foreach ($allowed as $acl)
+ $conf .= "http_access allow $acl\n";
+ }
+ }
+ else {
+ $noauth = implode(' ', explode("\n", base64_decode($settings['no_auth_hosts'])));
+ if (!empty($noauth)) {
+ $conf .= "acl noauth src $noauth\n";
+ $valid_acls[] = 'noauth';
+ }
+
+ // Set up the external authentication programs
+ $auth_ttl = ($settings['auth_ttl'] ? $settings['auth_ttl'] : 60);
+ $processes = ($settings['auth_processes'] ? $settings['auth_processes'] : 5);
+ $prompt = ($settings['auth_prompt'] ? $settings['auth_prompt'] : 'Please enter your credentials to access the proxy');
+ switch ($auth_method) {
+ case 'local':
+ $conf .= 'auth_param basic program /usr/local/libexec/squid/ncsa_auth ' . SQUID_PASSWD . "\n";
+ break;
+ case 'ldap':
+ $port = (isset($settings['auth_port']) ? ":{$settings['auth_port']}" : '');
+ $password = (isset($settings['ldap_pass']) ? "-w {$settings['ldap_pass']}" : '');
+ $conf .= "auth_param basic program /usr/local/libexec/squid/squid_ldap_auth -v {$settings['ldap_version']} -b {$settings['ldap_basedomain']} -D {$settings['ldap_user']} $password -f \"{$settings['ldap_filter']}\" -u uid -P {$settings['auth_server']}$port\n";
+ break;
+ case 'radius':
+ $port = (isset($settings['auth_port']) ? "-p {$settings['auth_server_port']}" : '');
+ $conf .= "auth_param basic program /usr/local/libexec/squid/squid_radius_auth -w {$settings['radius_secret']} -h {$settings['auth_server']} $port\n";
+ break;
+ case 'msnt':
+ $conf .= "auth_param basic program /usr/local/libexec/squid/msnt_auth\n";
+ break;
+ }
+ $conf .= <<<EOD
+auth_param basic children $processes
+auth_param basic realm $prompt
+auth_param basic credentialsttl $auth_ttl minutes
+acl password proxy_auth REQUIRED
+
+EOD;
+
+ // Onto the ACLs
+ $password = array('localnet', 'allowed_subnets');
+ $passwordless = array('unrestricted_hosts');
+ if ($settings['unrestricted_auth'] == 'on') {
+ // Even the unrestricted hosts should authenticate
+ $password = array_merge($password, $passwordless);
+ $passwordless = array();
+ }
+ $passwordless[] = 'noauth';
+ $password = array_filter($password, 'squid_is_valid_acl');
+ $passwordless = array_filter($passwordless, 'squid_is_valid_acl');
+
+ // Allow the ACLs that don't need to authenticate
+ foreach ($passwordless as $acl)
+ $conf .= "http_access allow $acl\n";
+
+ // Allow the other ACLs as long as they authenticate
+ foreach ($password as $acl)
+ $conf .= "http_access allow password $acl\n";
+ }
+
+ if(!empty($config['installedpackages']['squid']['config'][0]['custom_options'])) {
+ $custopts = explode(";", ($config['installedpackages']['squid']['config'][0]['custom_options']));
+ $conf .= "# Custom options\n";
+ foreach ($custopts as $custopt) {
+ $conf .= $custopt."\n";
+ }
+ }
+
+ $conf .= "# Default block all to be sure\n";
+ $conf .= "http_access deny all\n";
+
+ return $conf;
+}
+
+function squid_resync_users() {
+ global $config;
+
+ $users = $config['installedpackages']['squidusers']['config'];
+ $contents = '';
+ if (is_array($users)) {
+ foreach ($users as $user)
+ $contents .= $user['username'] . ':' . crypt($user['password'], base64_encode($user['password'])) . "\n";
+ }
+ file_put_contents(SQUID_PASSWD, $contents);
+ chown(SQUID_PASSWD, 'proxy');
+ chmod(SQUID_PASSWD, 0600);
+}
+
+function squid_resync() {
+ global $config;
+ conf_mount_rw();
+ $conf = squid_resync_general() . "\n";
+ $conf .= squid_resync_cache() . "\n";
+ $conf .= squid_resync_redirector() . "\n";
+ $conf .= squid_resync_upstream() . "\n";
+ $conf .= squid_resync_nac() . "\n";
+ $conf .= squid_resync_traffic() . "\n";
+ $conf .= squid_resync_auth();
+ squid_resync_users();
+
+ /* make sure pinger is executable */
+ if(file_exists("/usr/local/libexec/squid/pinger"))
+ exec("chmod a+x /usr/local/libexec/squid/pinger");
+
+ foreach (array( SQUID_CONFBASE,
+ SQUID_ACLDIR,
+ ) as $dir) {
+ make_dirs($dir);
+ squid_chown_recursive($dir, 'proxy', 'proxy');
+ }
+
+ file_put_contents(SQUID_CONFBASE . '/squid.conf', $conf);
+
+ $log_dir = $config['installedpackages']['squid']['config'][0]['log_dir'].'/';
+
+ if(!is_dir($log_dir)) {
+ log_error("Creating squid log dir $log_dir");
+ make_dirs($log_dir);
+ squid_chown_recursive($log_dir, 'proxy', 'proxy');
+ }
+
+ squid_dash_z();
+
+ if (!is_service_running('squid')) {
+ log_error("Starting Squid");
+ mwexec_bg("/usr/local/sbin/squid -D");
+ } else {
+ log_error("Reloading Squid for configuration sync");
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ }
+
+ filter_configure();
+ conf_mount_ro();
+}
+
+function squid_print_javascript_auth() {
+ global $config;
+ $transparent_proxy = ($config['installedpackages']['squid']['config'][0]['transparent_proxy'] == 'on');
+
+ // No authentication for transparent proxy
+ if ($transparent_proxy) {
+ $javascript = <<<EOD
+<script language="JavaScript">
+<!--
+function on_auth_method_changed() {
+ document.iform.auth_method.disabled = 1;
+ document.iform.auth_server.disabled = 1;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 1;
+ document.iform.auth_prompt.disabled = 1;
+ document.iform.auth_processes.disabled = 1;
+ document.iform.auth_ttl.disabled = 1;
+ document.iform.unrestricted_auth.disabled = 1;
+ document.iform.no_auth_hosts.disabled = 1;
+}
+-->
+</script>
+
+EOD;
+ }
+ else {
+ $javascript = <<<EOD
+<script language="JavaScript">
+<!--
+function on_auth_method_changed() {
+ var field = document.iform.auth_method;
+ var auth_method = field.options[field.selectedIndex].value;
+
+ if (auth_method == 'none') {
+ document.iform.auth_server.disabled = 1;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 1;
+ document.iform.auth_prompt.disabled = 1;
+ document.iform.auth_processes.disabled = 1;
+ document.iform.auth_ttl.disabled = 1;
+ document.iform.unrestricted_auth.disabled = 1;
+ document.iform.no_auth_hosts.disabled = 1;
+ }
+ else {
+ document.iform.auth_prompt.disabled = 0;
+ document.iform.auth_processes.disabled = 0;
+ document.iform.auth_ttl.disabled = 0;
+ document.iform.unrestricted_auth.disabled = 0;
+ document.iform.no_auth_hosts.disabled = 0;
+ }
+
+ switch (auth_method) {
+ case 'local':
+ document.iform.auth_server.disabled = 1;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 1;
+ break;
+ case 'ldap':
+ document.iform.auth_server.disabled = 0;
+ document.iform.auth_server_port.disabled = 0;
+ document.iform.ldap_user.disabled = 0;
+ document.iform.ldap_password.disabled = 0;
+ document.iform.ldap_version.disabled = 0;
+ document.iform.ldap_filter.disabled = 0;
+ document.iform.ldap_basedomain.disabled = 0;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 1;
+ break;
+ case 'radius':
+ document.iform.auth_server.disabled = 0;
+ document.iform.auth_server_port.disabled = 0;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 0;
+ document.iform.msnt_secondary.disabled = 1;
+ break;
+ case 'msnt':
+ document.iform.auth_server.disabled = 0;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 0;
+ break;
+ }
+}
+-->
+</script>
+
+EOD;
+ }
+
+ print($javascript);
+}
+
+function squid_print_javascript_auth2() {
+ print("<script language=\"JavaScript\">on_auth_method_changed()</script>\n");
+}
+
+function squid_generate_rules($type) {
+ global $config;
+
+ $squid_conf = $config['installedpackages']['squid']['config'][0];
+ if (!is_service_running('squid')) {
+ log_error("SQUID is installed but not started. Not installing redirect rules.");
+ return;
+ }
+
+ if (($squid_conf['transparent_proxy'] != 'on') || ($squid_conf['allow_interface'] != 'on')) {
+ return;
+ }
+
+ $ifaces = explode(",", $squid_conf['active_interface']);
+ $ifaces = array_map('convert_friendly_interface_to_real_interface_name', $ifaces);
+ $port = ($squid_conf['proxy_port'] ? $squid_conf['proxy_port'] : 3128);
+
+ $fw_aliases = filter_generate_aliases();
+ if(strstr($fw_aliases, "pptp ="))
+ $PPTP_ALIAS = "\$pptp";
+ else
+ $PPTP_ALIAS = "\$PPTP";
+ if(strstr($fw_aliases, "PPPoE ="))
+ $PPPOE_ALIAS = "\$PPPoE";
+ else
+ $PPPOE_ALIAS = "\$pppoe";
+
+ switch($type) {
+ case 'nat':
+ $rules .= "\n# Setup Squid proxy redirect\n";
+ if ($squid_conf['private_subnet_proxy_off'] == 'on') {
+ foreach ($ifaces as $iface) {
+ $rules .= "no rdr on $iface proto tcp from any to { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 } port 80\n";
+ }
+ }
+ if (!empty($squid_conf['defined_ip_proxy_off'])) {
+ $defined_ip_proxy_off = explode(";", $squid_conf['defined_ip_proxy_off']);
+ $exempt_ip = "";
+ foreach ($defined_ip_proxy_off as $ip_proxy_off) {
+ if(!empty($ip_proxy_off)) {
+ $ip_proxy_off = trim($ip_proxy_off);
+ $exempt_ip .= ", $ip_proxy_off";
+ }
+ }
+ $exempt_ip = substr($exempt_ip,2);
+ foreach ($ifaces as $iface) {
+ $rules .= "no rdr on $iface proto tcp from { $exempt_ip } to any port 80\n";
+ }
+ }
+ foreach ($ifaces as $iface) {
+ $rules .= "rdr on $iface proto tcp from any to !($iface) port 80 -> 127.0.0.1 port 80\n";
+ }
+ /* Handle PPPOE case */
+ if($config['pppoe']['mode'] == "server" && $config['pppoe']['localip']) {
+ $rules .= "rdr on $PPPOE_ALIAS proto tcp from any to !127.0.0.1 port 80 -> 127.0.0.1 port 80\n";
+ }
+ /* Handle PPTP case */
+ if($config['pptpd']['mode'] == "server" && $config['pptpd']['localip']) {
+ $rules .= "rdr on $PPTP_ALIAS proto tcp from any to !127.0.0.1 port 80 -> 127.0.0.1 port 80\n";
+ }
+ $rules .= "\n";
+ break;
+ case 'filter':
+ case 'rule':
+ foreach ($ifaces as $iface) {
+ $rules .= "# Setup squid pass rules for proxy\n";
+ $rules .= "pass in quick on $iface proto tcp from any to !($iface) port 80 flags S/SA keep state\n";
+ $rules .= "pass in quick on $iface proto tcp from any to !($iface) port $port flags S/SA keep state\n";
+ $rules .= "\n";
+ };
+ if($config['pppoe']['mode'] == "server" && $config['pppoe']['localip']) {
+ $rules .= "pass in quick on $PPPOE_ALIAS proto tcp from any to !127.0.0.1 port $port flags S/SA keep state\n";
+ }
+ if($config['pptpd']['mode'] == "server" && $config['pptpd']['localip']) {
+ $rules .= "pass in quick on $PPTP_ALIAS proto tcp from any to !127.0.0.1 port $port flags S/SA keep state\n";
+ }
+ break;
+ default:
+ break;
+ }
+
+ return $rules;
+}
+
+?>
diff --git a/config/squid-8/squid.xml b/config/squid-8/squid.xml
new file mode 100644
index 00000000..f79cc8d2
--- /dev/null
+++ b/config/squid-8/squid.xml
@@ -0,0 +1,334 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squid</name>
+ <version>2.6.STABLE18</version>
+ <title>Proxy server: General settings</title>
+ <include_file>/usr/local/pkg/squid.inc</include_file>
+ <menu>
+ <name>Proxy server</name>
+ <tooltiptext>Modify the proxy server's settings</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>squid</name>
+ <rcfile>squid.sh</rcfile>
+ <executable>squid</executable>
+ <description>Proxy server Service</description>
+ </service>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local Users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <!-- Installation -->
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid-8/squid.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid-8/squid_cache.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid-8/squid_nac.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid-8/squid_ng.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid-8/squid_traffic.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid-8/squid_upstream.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid-8/squid_auth.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid-8/squid_users.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/etc/rc.d/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid-8/proxy_monitor.sh</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid-8/squid_cache.xml</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Proxy interface</fielddescr>
+ <fieldname>active_interface</fieldname>
+ <description>The interface(s) the proxy server will bind to.</description>
+ <type>interfaces_selection</type>
+ <required/>
+ <default_value>lan</default_value>
+ <multiple/>
+ </field>
+ <field>
+ <fielddescr>Allow users on interface</fielddescr>
+ <fieldname>allow_interface</fieldname>
+ <description>If this field is checked, the users connected to the interface selected in the 'Proxy interface' field will be allowed to use the proxy, i.e., there will be no need to add the interface's subnet to the list of allowed subnets. This is just a shortcut.</description>
+ <type>checkbox</type>
+ <required/>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Transparent proxy</fielddescr>
+ <fieldname>transparent_proxy</fieldname>
+ <description>If transparent mode is enabled, all requests for destination port 80 will be forwarded to the proxy server without any additional configuration necessary.</description>
+ <type>checkbox</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Bypass proxy for Private Address Space (RFC 1918) destination</fielddescr>
+ <fieldname>private_subnet_proxy_off</fieldname>
+ <description>Do not forward traffic to Private Address Space (RFC 1918) &lt;b&gt;destination&lt;/b&gt; through the proxy server but directly through the firewall.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Bypass proxy for these source IPs</fielddescr>
+ <fieldname>defined_ip_proxy_off</fieldname>
+ <description>Do not forward traffic from these &lt;b&gt;source&lt;/b&gt; IPs through the proxy server but directly through the firewall. Separate by semi-colons (;).</description>
+ <type>input</type>
+ <size>80</size>
+ </field>
+ <field>
+ <fielddescr>Enabled logging</fielddescr>
+ <fieldname>log_enabled</fieldname>
+ <description>This will enable the access log. Don't switch this on if you don't have much disk space left.</description>
+ <type>checkbox</type>
+ <enablefields>log_query_terms,log_user_agents</enablefields>
+ </field>
+ <field>
+ <fielddescr>Log store directory</fielddescr>
+ <fieldname>log_dir</fieldname>
+ <description>The directory where the log will be stored (note: do not end with a / mark)</description>
+ <type>input</type>
+ <size>60</size>
+ <required/>
+ <default_value>/var/squid/log</default_value>
+ </field>
+ <field>
+ <fielddescr>Log rotate</fielddescr>
+ <fieldname>log_rotate</fieldname>
+ <description>Defines how many days of logfiles will be kept. Rotation is disabled if left empty.</description>
+ <type>input</type>
+ <size>5</size>
+ </field>
+ <field>
+ <fielddescr>Proxy port</fielddescr>
+ <fieldname>proxy_port</fieldname>
+ <description>This is the port the proxy server will listen on.</description>
+ <type>input</type>
+ <size>5</size>
+ <required/>
+ <default_value>3128</default_value>
+ </field>
+ <field>
+ <fielddescr>ICP port</fielddescr>
+ <fieldname>icp_port</fieldname>
+ <description>This is the port the Proxy Server will send and receive ICP queries to and from neighbor caches. Leave this blank if you don't want the proxy server to communicate with neighbor caches through ICP.</description>
+ <type>input</type>
+ <size>5</size>
+ </field>
+ <field>
+ <fielddescr>Visible hostname</fielddescr>
+ <fieldname>visible_hostname</fieldname>
+ <description>This is the URL to be displayed in proxy server error messages.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>localhost</default_value>
+ </field>
+ <field>
+ <fielddescr>Administrator email</fielddescr>
+ <fieldname>admin_email</fieldname>
+ <description>This is the email address displayed in error messages to the users.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>admin@localhost</default_value>
+ </field>
+ <field>
+ <fielddescr>Language</fielddescr>
+ <fieldname>error_language</fieldname>
+ <description>Select the language in which the proxy server will display error messages to users.</description>
+ <type>select</type>
+ <default_value>English</default_value>
+ </field>
+ <field>
+ <fielddescr>Disable X-Forward</fielddescr>
+ <fieldname>disable_xforward</fieldname>
+ <description>If not set, Squid will include your system's IP address or name in the HTTP requests it forwards.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Disable VIA</fielddescr>
+ <fieldname>disable_via</fieldname>
+ <description>If not set, Squid will include a Via header in requests and replies as required by RFC2616.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>What to do with requests that have whitespace characters in the URI</fielddescr>
+ <fieldname>uri_whitespace</fieldname>
+ <description>&lt;b&gt; strip:&lt;/b&gt; The whitespace characters are stripped out of the URL. This is the behavior recommended by RFC2396. &lt;p&gt; &lt;b&gt; deny:&lt;/b&gt; The request is denied. The user receives an "Invalid Request" message.&lt;p&gt; &lt;b&gt; allow:&lt;/b&gt; The request is allowed and the URI is not changed. The whitespace characters remain in the URI.&lt;p&gt; &lt;b&gt; encode:&lt;/b&gt; The request is allowed and the whitespace characters are encoded according to RFC1738.&lt;p&gt; &lt;b&gt; chop:&lt;/b&gt; The request is allowed and the URI is chopped at the first whitespace.</description>
+ <type>select</type>
+ <default_value>strip</default_value>
+ <options>
+ <option>
+ <name>strip</name>
+ <value>strip</value>
+ </option>
+ <option>
+ <name>deny</name>
+ <value>deny</value>
+ </option>
+ <option>
+ <name>allow</name>
+ <value>allow</value>
+ </option>
+ <option>
+ <name>encode</name>
+ <value>encode</value>
+ </option>
+ <option>
+ <name>chop</name>
+ <value>chop</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Use alternate DNS-servers for the proxy-server</fielddescr>
+ <fieldname>dns_nameservers</fieldname>
+ <description>If you want to use other DNS-servers than the DNS-forwarder, enter the IPs here, separated by semi-colons (;).</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Suppress Squid Version</fielddescr>
+ <fieldname>disable_squidversion</fieldname>
+ <description>If set, suppress Squid version string info in HTTP headers and HTML error pages.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Custom Options</fielddescr>
+ <fieldname>custom_options</fieldname>
+ <description>You can put your own custom options here, separated by semi-colons (;). They'll be added to the configuration. They need to be squid.conf native options, otherwise squid will NOT work.</description>
+ <type>textarea</type>
+ <cols>65</cols>
+ <rows>5</rows>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ squid_before_form_general(&amp;$pkg);
+ </custom_php_command_before_form>
+ <custom_add_php_command>
+ squid_resync();
+ </custom_add_php_command>
+ <custom_php_validation_command>
+ squid_validate_general($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ exec("/bin/rm -f /usr/local/etc/rc.d/squid");
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ update_status("Checking Squid cache... One moment please...");
+ update_output_window("This operation may take quite some time, please be patient. Do not press stop or attempt to navigate away from this page during this process.");
+ squid_install_command();
+ squid_resync();
+ exec("/bin/rm -f /usr/local/etc/rc.d/squid");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ squid_deinstall_command();
+ exec("/bin/rm -f /usr/local/etc/rc.d/squid*");
+ </custom_php_deinstall_command>
+ <filter_rules_needed>squid_generate_rules</filter_rules_needed>
+</packagegui>
diff --git a/config/squid-8/squid_auth.inc b/config/squid-8/squid_auth.inc
new file mode 100644
index 00000000..7c99a01b
--- /dev/null
+++ b/config/squid-8/squid_auth.inc
@@ -0,0 +1,446 @@
+<?php
+/* $Id$ */
+
+/*
+ squid_auth.inc
+ part of pfSense (www.pfSense.com)
+
+ Copyright (C) 2005 Michael Capp <michael.capp@gmail.com>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+function global_eval_auth_options()
+{
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ switch ($config['installedpackages']['squidauth']['config'][0]['auth_method']) {
+ case "none":
+ dynamic_auth_content("pkg_edit");
+ dynamic_no_auth();
+ break;
+ case "local_auth":
+ dynamic_auth_content("pkg");
+ /* create empty passwd file to prevent stat error with squid reload */
+ touch ("/usr/local/etc/squid/advanced/ncsa/passwd");
+ dynamic_local_auth();
+ break;
+ case "ldap_bind":
+ dynamic_auth_content("pkg_edit");
+ dynamic_ldap_auth();
+ break;
+ case "domain_auth":
+ $filecontents = file("/usr/local/pkg/squid_auth.xml");
+ dynamic_auth_content("pkg_edit");
+ dynamic_domain_auth();
+ break;
+ case "radius_auth":
+ $filecontents = file("/usr/local/pkg/squid_auth.xml");
+ dynamic_auth_content("pkg_edit");
+ dynamic_radius_auth();
+ break;
+ default:
+ $filecontents = file("/usr/local/pkg/squid_auth.xml");
+ dynamic_auth_content("pkg_edit");
+ dynamic_no_auth();
+ break;
+ }
+
+ config_unlock();
+ conf_mount_ro();
+
+} /* end function global_eval_auth_options */
+
+function dynamic_no_auth() {
+ global $config;
+ conf_mount_rw();
+ $fout = fopen("/usr/local/pkg/squid_extauth.xml", "w");
+ fwrite($fout, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+ fwrite($fout, "<packagegui>\n");
+ fwrite($fout, " <name>squidextnoauth</name>\n");
+ fwrite($fout, " <title>Services: Proxy Server -> Extended Authentication Settings</title>\n");
+ fwrite($fout, " <configpath>installedpackages->package->squidextnoauth->configuration->settings</configpath>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <aftersaveredirect>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</aftersaveredirect>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tabs>\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>General Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Upstream Proxy</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Cache Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Network Access Control</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Traffic Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Extended Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ fwrite($fout, " <active/>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </tabs>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <fields>\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>No Authentication Defined</fielddescr>\n");
+ fwrite($fout, " <fieldname>no_auth</fieldname>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, " </fields>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <custom_add_php_command_late>\n");
+ fwrite($fout, " require_once(\"/usr/local/pkg/squid_ng.inc\");");
+ fwrite($fout, "\n");
+ fwrite($fout, " global_write_squid_config();\n");
+ fwrite($fout, " mwexec(\"/usr/local/sbin/squid -k reconfigure\");\n");
+ fwrite($fout, " </custom_add_php_command_late>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "</packagegui>\n");
+ fclose($fout);
+
+ /* mount filesystem read-only */
+ conf_mount_ro();
+}
+
+function dynamic_local_auth() {
+ global $config;
+ conf_mount_rw();
+
+ $fout = fopen("/usr/local/pkg/squid_extauth.xml", "w");
+
+ fwrite($fout, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "<packagegui>\n");
+ fwrite($fout, " <name>squidextlocalauth</name>\n");
+ fwrite($fout, " <title>Services: Proxy Server -> Extended Auth Settings</title>\n");
+ fwrite($fout, " <version>2.5.10_4</version>\n");
+ fwrite($fout, " <configpath>installedpackages->package->squidextlocalauth->configuration->settings</configpath>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <files></files>\n");
+ fwrite($fout, " <menu></menu>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <aftersaveredirect>/pkg.php?xml=squid_extauth.xml&amp;id=0</aftersaveredirect>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tabs>\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>General Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Upstream Proxy</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Cache Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Network Access Control</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Traffic Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Extended Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ fwrite($fout, " <active/>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </tabs>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <adddeleteeditpagefields>\n");
+ fwrite($fout, " <columnitem>\n");
+ fwrite($fout, " <fielddescr>Username</fielddescr>\n");
+ fwrite($fout, " <fieldname>username</fieldname>\n");
+ fwrite($fout, " </columnitem>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <columnitem>\n");
+ fwrite($fout, " <fielddescr>Description</fielddescr>\n");
+ fwrite($fout, " <fieldname>description</fieldname>\n");
+ fwrite($fout, " </columnitem>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <columnitem>\n");
+ fwrite($fout, " <fielddescr>Restriction Group</fielddescr>\n");
+ fwrite($fout, " <fieldname>group</fieldname>\n");
+ fwrite($fout, " </columnitem>\n");
+ fwrite($fout, " </adddeleteeditpagefields>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <fields>\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Username</fielddescr>\n");
+ fwrite($fout, " <fieldname>username</fieldname>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>15</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Password</fielddescr>\n");
+ fwrite($fout, " <fieldname>password</fieldname>\n");
+ fwrite($fout, " <type>password</type>\n");
+ fwrite($fout, " <size>8</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Description (Optional)</fielddescr>\n");
+ fwrite($fout, " <fieldname>description</fieldname>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>30</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Restriction Group</fielddescr>\n");
+ fwrite($fout, " <fieldname>group</fieldname>\n");
+ fwrite($fout, " <type>select</type>\n");
+ fwrite($fout, " <options>\n");
+ fwrite($fout, " <option><name>Standard</name><value>Standard</value></option>\n");
+ fwrite($fout, " <option><name>Extended</name><value>Extended</value></option>\n");
+ fwrite($fout, " </options>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </fields>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <custom_add_php_command_late>\n");
+ fwrite($fout, " require_once(\"/usr/local/pkg/squid_ng.inc\");\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " mod_htpasswd();\n");
+ fwrite($fout, " global_write_squid_config();\n");
+ fwrite($fout, " mwexec(\"/usr/local/sbin/squid -k reconfigure\");\n");
+ fwrite($fout, " </custom_add_php_command_late>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "</packagegui>\n");
+
+ fclose($fout);
+
+ /* mount filesystem read-only */
+ conf_mount_ro();
+}
+
+function dynamic_ldap_auth() {
+ global $config;
+ conf_mount_rw();
+
+ $fout = fopen("/usr/local/pkg/squid_extauth.xml", "w");
+
+ fwrite($fout, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "<packagegui>\n");
+ fwrite($fout, " <name>squidextldapauth</name>\n");
+ fwrite($fout, " <title>Services: Proxy Server -> Extended Auth Settings</title>\n");
+ fwrite($fout, " <version>2.5.11</version>\n");
+ fwrite($fout, " <configpath>installedpackages->package->squidextldapauth->configuration->settings</configpath>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <files></files>\n");
+ fwrite($fout, " <menu></menu>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <aftersaveredirect>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</aftersaveredirect>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tabs>\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>General Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Upstream Proxy</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Cache Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Network Access Control</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Traffic Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Extended Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ fwrite($fout, " <active/>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </tabs>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <fields>\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Base DN</fielddescr>\n");
+ fwrite($fout, " <fieldname>ldap_basedn</fieldname>\n");
+ fwrite($fout, " <description>This is the base where the LDAP search starts. All subsequent organizational units (OUs)will be included. Example: \"ou=users,o=company\" will search for users in and under the specified company.</description>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>50</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>LDAP Server</fielddescr>\n");
+ fwrite($fout, " <fieldname>ldap_server</fieldname>\n");
+ fwrite($fout, " <description>This is the LDAP server that the bind will be attempted against.</description>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>20</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>LDAP Type</fielddescr>\n");
+ fwrite($fout, " <fieldname>ldap_type</fieldname>\n");
+ fwrite($fout, " <description>This specifies the supported LDAP types.</description>\n");
+ fwrite($fout, " <type>select</type>\n");
+ fwrite($fout, " <options>\n");
+ fwrite($fout, " <option><name>Active Directory</name><value>active_directory</value></option>\n");
+ fwrite($fout, " <option><name>Novell eDirectory</name><value>novell_edirectory</value></option>\n");
+ fwrite($fout, " <option><name>LDAP v2</name><value>ldap_v2</value></option>\n");
+ fwrite($fout, " <option><name>LDAP v3</name><value>ldap_v3</value></option>\n");
+ fwrite($fout, " </options>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>LDAP Port</fielddescr>\n");
+ fwrite($fout, " <fieldname>ldap_port</fieldname>\n");
+ fwrite($fout, " <description>This is the port that LDAP bind will attempt on. The default is \"389\".</description>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>5</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Bind DN Username</fielddescr>\n");
+ fwrite($fout, " <fieldname>bind_dn_username</fieldname>\n");
+ fwrite($fout, " <description>If \"anonymous bind\" is not supported, please specify the bind username that can access the Base DN hierarchy.</description>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>30</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Bind DN Password</fielddescr>\n");
+ fwrite($fout, " <fieldname>bind_dn_password</fieldname>\n");
+ fwrite($fout, " <description>This is the associated password with the Bind DN Username previously specified.</description>\n");
+ fwrite($fout, " <type>password</type>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </fields>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <custom_add_php_command_late>\n");
+ fwrite($fout, " require_once(\"/usr/local/pkg/squid_ng.inc\");\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " mod_htpasswd();\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " global_write_squid_config();\n");
+ fwrite($fout, " mwexec(\"/usr/local/sbin/squid -k reconfigure\");\n");
+ fwrite($fout, " </custom_add_php_command_late>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "</packagegui>\n");
+
+ fclose($fout);
+
+ /* mount filesystem read-only */
+ conf_mount_ro();
+}
+
+/* dynamically re-writes all squid xml files to handle adddeletecolumnitems properly */
+function dynamic_auth_content($pkgvar) {
+
+ switch ($pkgvar) {
+ case "pkg":
+ if ($handle = opendir("/usr/local/pkg")) {
+ while (($file = readdir($handle)) != false) {
+ if (stristr($file, "squid_") && stristr($file, ".xml")) {
+ $filecontents = file("/usr/local/pkg/" . $file);
+ $fout = fopen("/usr/local/pkg/" . $file, "w");
+ foreach($filecontents as $line) {
+ if (stristr($line, "<url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>")) {
+ fwrite($fout, " <url>/pkg.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ } else {
+ fwrite($fout, $line);
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case "pkg_edit":
+ if ($handle = opendir("/usr/local/pkg")) {
+ while (($file = readdir($handle)) != false) {
+ if (stristr($file, "squid_") && stristr($file, ".xml")) {
+ $filecontents = file("/usr/local/pkg/" . $file);
+ $fout = fopen("/usr/local/pkg/" . $file,"w");
+ foreach($filecontents as $line) {
+ if (stristr($line, "<url>/pkg.php?xml=squid_extauth.xml&amp;id=0</url>")) {
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ } else {
+ fwrite($fout, $line);
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+
+} /* end function dynamic_auth_content */
+?> \ No newline at end of file
diff --git a/config/squid-8/squid_auth.xml b/config/squid-8/squid_auth.xml
new file mode 100644
index 00000000..33317d4a
--- /dev/null
+++ b/config/squid-8/squid_auth.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidauth</name>
+ <version>none</version>
+ <title>Proxy server: Authentication</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Local Users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Authentication method</fielddescr>
+ <fieldname>auth_method</fieldname>
+ <description>Select an authentication method. This will allow users to be authenticated by local or external services.</description>
+ <type>select</type>
+ <required/>
+ <default_value>none</default_value>
+ <options>
+ <option><name>None</name><value>none</value></option>
+ <option><name>Local</name><value>local</value></option>
+ <option><name>LDAP</name><value>ldap</value></option>
+ <option><name>RADIUS</name><value>radius</value></option>
+ <option><name>NT domain</name><value>msnt</value></option>
+ </options>
+ <onchange>on_auth_method_changed()</onchange>
+ </field>
+ <field>
+ <fielddescr>LDAP version</fielddescr>
+ <fieldname>ldap_version</fieldname>
+ <description>Enter LDAP protocol version (2 or 3).</description>
+ <type>select</type>
+ <default_value>2</default_value>
+ <options>
+ <option><name>2</name><value>2</value></option>
+ <option><name>3</name><value>3</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Authentication server</fielddescr>
+ <fieldname>auth_server</fieldname>
+ <description>Enter here the IP or hostname of the server that will perform the authentication.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Authentication server port</fielddescr>
+ <fieldname>auth_server_port</fieldname>
+ <description>Enter here the port to use to connect to the authentication server. Leave this field blank to use the authentication method's default port.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>LDAP server user DN</fielddescr>
+ <fieldname>ldap_user</fieldname>
+ <description>Enter here the user DN to use to connect to the LDAP server.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>LDAP password</fielddescr>
+ <fieldname>ldap_pass</fieldname>
+ <description>Enter here the password to use to connect to the LDAP server.</description>
+ <type>password</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>LDAP base domain</fielddescr>
+ <fieldname>ldap_basedomain</fieldname>
+ <description>For LDAP authentication, enter here the base domain in the LDAP server.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>LDAP search filter</fielddescr>
+ <fieldname>ldap_filter</fieldname>
+ <description>Enter LDAP search filter.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>(&amp;(objectClass=person)(uid=%s))</default_value>
+ </field>
+ <field>
+ <fielddescr>RADIUS secret</fielddescr>
+ <fieldname>radius_secret</fieldname>
+ <description>The RADIUS secret for RADIUS authentication.</description>
+ <type>password</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Secondary NT servers</fielddescr>
+ <fieldname>msnt_secondary</fieldname>
+ <description>Comma-separated list of secondary servers to be used for NT domain authentication.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Authentication prompt</fielddescr>
+ <fieldname>auth_prompt</fieldname>
+ <description>This string will be displayed at the top of the authentication request window.</description>
+ <type>input</type>
+ <default_value>Please enter your credentials to access the proxy</default_value>
+ </field>
+ <field>
+ <fielddescr>Authentication processes</fielddescr>
+ <fieldname>auth_processes</fieldname>
+ <description>The number of authenticator processes to spawn. If many authentications are expected within a short timeframe, increase this number accordingly.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>5</default_value>
+ </field>
+ <field>
+ <fielddescr>Authentication TTL</fielddescr>
+ <fieldname>auth_ttl</fieldname>
+ <description>This specifies for how long (in minutes) the proxy server assumes an externally validated username and password combination is valid (Time To Live). When the TTL expires, the user will be prompted for credentials again.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>60</default_value>
+ </field>
+ <field>
+ <fielddescr>Requiere authentication for unrestricted hosts</fielddescr>
+ <fieldname>unrestricted_auth</fieldname>
+ <description>If this option is enabled, even users tagged as unrestricted through access control are required to authenticate to use the proxy.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Subnets that don't need authentication</fielddescr>
+ <fieldname>no_auth_hosts</fieldname>
+ <description>Enter each subnet or IP address on a new line (in CIDR format, e.g.: 10.5.0.0/16, 192.168.1.50/32) that should not be asked for authentication to access the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_auth($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_after_form_command>
+ squid_print_javascript_auth2();
+ </custom_php_after_form_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+ <custom_php_before_form_command>
+ squid_print_javascript_auth2();
+ </custom_php_before_form_command>
+ <custom_php_after_head_command>
+ $transparent_proxy = ($config['installedpackages']['squid']['config'][0]['transparent_proxy'] == 'on');
+ if($transparent_proxy)
+ $input_errors[] = "Authentication cannot be enabled while transparent proxy mode is enabled";
+ squid_print_javascript_auth();
+ </custom_php_after_head_command>
+</packagegui>
diff --git a/config/squid-8/squid_cache.xml b/config/squid-8/squid_cache.xml
new file mode 100644
index 00000000..2a4b7e3d
--- /dev/null
+++ b/config/squid-8/squid_cache.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidcache</name>
+ <version>none</version>
+ <title>Proxy server: Cache management</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local Users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Hard disk cache size</fielddescr>
+ <fieldname>harddisk_cache_size</fieldname>
+ <description>This is the amount of disk space (in megabytes) to use for cached objects.</description>
+ <type>input</type>
+ <required/>
+ <default_value>100</default_value>
+ </field>
+ <field>
+ <fielddescr>Hard disk cache system</fielddescr>
+ <fieldname>harddisk_cache_system</fieldname>
+ <description>This specifies the kind of storage system to use. &lt;p&gt; &lt;b&gt; ufs &lt;/b&gt; is the old well-known Squid storage format that has always been there. &lt;p&gt; &lt;b&gt; aufs &lt;/b&gt; uses POSIX-threads to avoid blocking the main Squid process on disk-I/O. (Formerly known as async-io.) &lt;p&gt; &lt;b&gt; diskd &lt;/b&gt; uses a separate process to avoid blocking the main Squid process on disk-I/O. &lt;p&gt; &lt;b&gt; null &lt;/b&gt; Does not use any storage.</description>
+ <type>select</type>
+ <default_value>aufs</default_value>
+ <options>
+ <option><name>ufs</name><value>ufs</value></option>
+ <option><name>aufs</name><value>aufs</value></option>
+ <option><name>diskd</name><value>diskd</value></option>
+ <option><name>null</name><value>null</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Hard disk cache location</fielddescr>
+ <fieldname>harddisk_cache_location</fieldname>
+ <description>This is the directory where the cache will be stored. (note: do not end with a /). If you change this location, squid needs to make a new cache, this could take a while</description>
+ <type>input</type>
+ <size>60</size>
+ <required/>
+ <default_value>/var/squid/cache</default_value>
+ </field>
+ <field>
+ <fielddescr>Memory cache size</fielddescr>
+ <fieldname>memory_cache_size</fieldname>
+ <description>This is the amount of physical RAM (in megabytes) to be used for negative cache and in-transit objects. This value should not exceed more than 50% of the installed RAM. The minimum value is 1MB.</description>
+ <type>input</type>
+ <required/>
+ <default_value>8</default_value>
+ </field>
+ <field>
+ <fielddescr>Minimum object size</fielddescr>
+ <fieldname>minimum_object_size</fieldname>
+ <description>Objects smaller than the size specified (in kilobytes) will not be saved on disk. The default value is 0, meaning there is no minimum.</description>
+ <type>input</type>
+ <required />
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Maximum object size</fielddescr>
+ <fieldname>maximum_object_size</fieldname>
+ <description>Objects larger than the size specified (in kilobytes) will not be saved on disk. If you wish to increase speed more than you want to save bandwidth, this should be set to a low value.</description>
+ <type>input</type>
+ <required/>
+ <default_value>4</default_value>
+ </field>
+ <field>
+ <fielddescr>Level 1 subdirectories</fielddescr>
+ <fieldname>level1_subdirs</fieldname>
+ <description>Each level-1 directory contains 256 subdirectories, so a value of 256 level-1 directories will use a total of 65536 directories for the hard disk cache. This will significantly slow down the startup process of the proxy service, but can speed up the caching under certain conditions.</description>
+ <type>select</type>
+ <default_value>16</default_value>
+ <options>
+ <option><name>4</name><value>4</value></option>
+ <option><name>8</name><value>8</value></option>
+ <option><name>16</name><value>16</value></option>
+ <option><name>32</name><value>32</value></option>
+ <option><name>64</name><value>64</value></option>
+ <option><name>128</name><value>128</value></option>
+ <option><name>256</name><value>256</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Memory replacement policy</fielddescr>
+ <fieldname>memory_replacement_policy</fieldname>
+ <description>The memory replacement policy determines which objects are purged from memory when space is needed. The default policy for memory replacement is GDSF. &lt;p&gt; &lt;b&gt; LRU: Last Recently Used Policy &lt;/b&gt; - The LRU policies keep recently referenced objects. i.e., it replaces the object that has not been accessed for the longest time. &lt;p&gt; &lt;b&gt; Heap GDSF: Greedy-Dual Size Frequency &lt;/b&gt; - The Heap GDSF policy optimizes object-hit rate by keeping smaller, popular objects in cache. It achieves a lower byte hit rate than LFUDA though, since it evicts larger (possibly popular) objects. &lt;p&gt; &lt;b&gt; Heap LFUDA: Least Frequently Used with Dynamic Aging &lt;/b&gt; - The Heap LFUDA policy keeps popular objects in cache regardless of their size and thus optimizes byte hit rate at the expense of hit rate since one large, popular object will prevent many smaller, slightly less popular objects from being cached. &lt;p&gt; &lt;b&gt; Heap LRU: Last Recently Used &lt;/b&gt; - Works like LRU, but uses a heap instead. &lt;p&gt; Note: If using the LFUDA replacement policy, the value of Maximum Object Size should be increased above its default of 12KB to maximize the potential byte hit rate improvement of LFUDA.</description>
+ <type>select</type>
+ <default_value>heap GDSF</default_value>
+ <options>
+ <option><name>LRU</name><value>lru</value></option>
+ <option><name>Heap LFUDA</name><value>heap LFUDA</value></option>
+ <option><name>Heap GDSF</name><value>heap GDSF</value></option>
+ <option><name>Heap LRU</name><value>heap LRU</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Cache replacement policy</fielddescr>
+ <fieldname>cache_replacement_policy</fieldname>
+ <description>The cache replacement policy decides which objects will remain in cache and which objects are replaced to create space for the new objects. The default policy for cache replacement is LFUDA. Please see the type descriptions specified in the memory replacement policy for additional detail.</description>
+ <type>select</type>
+ <default_value>heap LFUDA</default_value>
+ <options>
+ <option><name>LRU</name><value>lru</value></option>
+ <option><name>Heap LFUDA</name><value>heap LFUDA</value></option>
+ <option><name>Heap GDSF</name><value>heap GDSF</value></option>
+ <option><name>Heap LRU</name><value>heap LRU</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Low-water-mark in %</fielddescr>
+ <fieldname>cache_swap_low</fieldname>
+ <description>Cache replacement begins when the swap usage is above the low-low-water mark and attempts to maintain utilisation near the low-water-mark.</description>
+ <type>input</type>
+ <default_value>90</default_value>
+ </field>
+ <field>
+ <fielddescr>High-water-mark in %</fielddescr>
+ <fieldname>cache_swap_high</fieldname>
+ <description>As swap utilisation gets close to the high-water-mark object eviction becomes more aggressive.</description>
+ <type>input</type>
+ <default_value>95</default_value>
+ </field>
+ <field>
+ <fielddescr>Do not cache</fielddescr>
+ <fieldname>donotcache</fieldname>
+ <description>Enter each domain or IP address on a new line that should never be cached.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Enable offline mode</fielddescr>
+ <fieldname>enable_offline</fieldname>
+ <description>Enable this option and the proxy server will never try to validate cached objects. The offline mode gives access to more cached information than the proposed feature would allow (stale cached versions, where the origin server should have been contacted).</description>
+ <type>checkbox</type>
+ <required/>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ if($_POST['harddisk_cache_size'] != $config['installedpackages']['squidcache']['config'][0]['harddisk_cache_size']) {
+ $needs_dash_z = true;
+ }
+ </custom_php_command_before_form>
+ <custom_php_validation_command>
+ squid_validate_cache($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ if($needs_dash_z)
+ squid_dash_z();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid-8/squid_extauth.xml b/config/squid-8/squid_extauth.xml
new file mode 100644
index 00000000..41d9f633
--- /dev/null
+++ b/config/squid-8/squid_extauth.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidextnoauth</name>
+ <version>none</version>
+ <title>Services: Proxy Server -> Extended Authentication Settings</title>
+ <aftersaveredirect>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</aftersaveredirect>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Auth</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Extended Auth</text>
+ <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>
+ <active/>
+ </tab>
+
+ </tabs>
+ <configpath>installedpackages->package->squidextnoauth->configuration->settings</configpath>
+ <fields>
+ <field>
+ <fielddescr>No Authentication Defined</fielddescr>
+ <fieldname>no_auth</fieldname>
+ <type>text</type>
+ </field>
+ </fields>
+
+ <custom_add_php_command_late>
+ require_once("/usr/local/pkg/squid_ng.inc");
+
+ global_write_squid_config();
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ </custom_add_php_command_late>
+
+</packagegui>
diff --git a/config/squid-8/squid_nac.xml b/config/squid-8/squid_nac.xml
new file mode 100644
index 00000000..193a89c6
--- /dev/null
+++ b/config/squid-8/squid_nac.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidnac</name>
+ <version>none</version>
+ <title>Proxy server: Access control</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local Users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Allowed subnets</fielddescr>
+ <fieldname>allowed_subnets</fieldname>
+ <description>Enter each subnet on a new line that is allowed to use the proxy. The subnets must be expressed as CIDR ranges (e.g.: 192.168.1.0/24). Note that the proxy interface subnet is already an allowed subnet. All the other subnets won't be able to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Unrestricted IPs</fielddescr>
+ <fieldname>unrestricted_hosts</fieldname>
+ <description>Enter each unrestricted IP address on a new line that is not to be filtered out by the other access control directives set in this page.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Banned host addresses</fielddescr>
+ <fieldname>banned_hosts</fieldname>
+ <description>Enter each IP address on a new line that is not to be allowed to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Whitelist</fielddescr>
+ <fieldname>whitelist</fieldname>
+ <description>Enter each destination domain on a new line that will be accessable to the users that are allowed to use the proxy. You also can use regular expressions.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Blacklist</fielddescr>
+ <fieldname>blacklist</fieldname>
+ <description>Enter each destination domain on a new line that will be blocked to the users that are allowed to use the proxy. You also can use regular expressions.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>External Cache-Managers</fielddescr>
+ <fieldname>ext_cachemanager</fieldname>
+ <description>Enter the IPs for the external Cache Managers to be allowed here, separated by semi-colons (;).</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_nac($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid-8/squid_ng.inc b/config/squid-8/squid_ng.inc
new file mode 100644
index 00000000..03f6d48c
--- /dev/null
+++ b/config/squid-8/squid_ng.inc
@@ -0,0 +1,1070 @@
+<?php
+/* $Id$ */
+
+/*
+ squid_ng.inc
+ part of pfSense (www.pfSense.com)
+
+ Copyright (C) 2005 Michael Capp <michael.capp@gmail.com>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+if(!function_exists("filter_configure"))
+ require_once("filter.inc");
+
+function global_write_squid_config()
+{
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ /* define squid configuration file in variable for replace function */
+ $squidconfig = "/usr/local/etc/squid/squid.conf";
+
+ /* squid.xml values */
+ $active_interface = $config['installedpackages']['squid']['config'][0]['active_interface'];
+ $transparent_proxy = $config['installedpackages']['squid']['config'][0]['transparent_proxy'];
+ $log_enabled = $config['installedpackages']['squid']['config'][0]['log_enabled'];
+ $urlfier_enable = $config['installedpackages']['squid']['config'][0]['urlfilter_enable'];
+ $accesslog_disabled = $config['installedpackages']['squid']['config'][0]['accesslog_disabled'];
+ $log_query_terms = $config['installedpackages']['squid']['config'][0]['log_query_terms'];
+ $log_user_agents = $config['installedpackages']['squid']['config'][0]['log_user_agents'];
+ $proxy_port = $config['installedpackages']['squid']['config'][0]['proxy_port'];
+ $visible_hostname = $config['installedpackages']['squid']['config'][0]['visible_hostname'];
+ $cache_admin_email = $config['installedpackages']['squid']['config'][0]['cache_admin_email'];
+ $error_language = $config['installedpackages']['squid']['config'][0]['error_language'];
+ $cachemgr_enabled = $config['installedpackages']['squid']['config'][0]['cachemgr_enabled'];
+
+ /* squid_upstream.xml values */
+ $proxy_forwarding = $config['installedpackages']['squidupstream']['config'][0]['proxy_forwarding'];
+ $client_ip_forwarding = $config['installedpackages']['squidupstream']['config'][0]['client_ip_forwarding'];
+ $user_forwarding = $config['installedpackages']['squidupstream']['config'][0]['user_forwarding'];
+ $upstream_proxy = $config['installedpackages']['squidupstream']['config'][0]['upstream_proxy'];
+ $upstream_proxy_port = $config['installedpackages']['squidupstream']['config'][0]['upstream_proxy_port'];
+ $upstream_username = $config['installedpackages']['squidupstream']['config'][0]['upstream_username'];
+ $upstream_password = $config['installedpackages']['squidupstream']['config'][0]['upstream_psasword'];
+
+ /* squid_cache.xml values */
+ $memory_cache_size = $config['installedpackages']['squidcache']['config'][0]['memory_cache_size'];
+ $harddisk_cache_size = $config['installedpackages']['squidcache']['config'][0]['harddisk_cache_size'];
+ $minimum_object_size = $config['installedpackages']['squidcache']['config'][0]['minimum_object_size'];
+ $maximum_object_size = $config['installedpackages']['squidcache']['config'][0]['maximum_object_size'];
+ $level_subdirs = $config['installedpackages']['squidcache']['config'][0]['level_subdirs'];
+ $memory_replacement = $config['installedpackages']['squidcache']['config'][0]['memory_replacement'];
+ $cache_replacement = $config['installedpackages']['squidcache']['config'][0]['cache_replacement'];
+ $domain = $config['installedpackages']['squidcache']['config'][0]['domain'];
+ $enable_offline = $config['installedpackages']['squidcache']['config'][0]['enable_offline'];
+
+ /* squid_nac.xml values */
+ $allowed_subnets = $config['installedpackages']['squidnac']['config'][0]['allowed_subnets'];
+ $unrestricted_ip_addr = $config['installedpackages']['squidnac']['config'][0]['unrestricted_ip_address'];
+ $unrestricted_mac_addr = $config['installedpackages']['squidnac']['config'][0]['unrestricted_mac_addresses'];
+ $banned_ip_addr = $config['installedpackages']['squidnac']['config'][0]['banned_ip_addresses'];
+ $banned_mac_addr = $config['installedpackages']['squidnac']['config'][0]['banned_mac_addresses'];
+ $override_hosts = $config['installedpackages']['squidnac']['config'][0]['override_hosts'];
+
+ /* squid_traffic.xml values */
+ $max_download_size = $config['installedpackages']['squidtraffic']['config'][0]['max_download_size'];
+ $max_upload_size = $config['installedpackages']['squidtraffic']['config'][0]['max_upload_size'];
+ $dl_overall = $config['installedpackages']['squidtraffic']['config'][0]['dl_overall'];
+ $dl_per_host = $config['installedpackages']['squidtraffic']['config'][0]['dl_per_host'];
+ $throttle_binary_files = $config['installedpackages']['squidtraffic']['config'][0]['throttle_binary_files'];
+ $throttle_cd_images = $config['installedpackages']['squidtraffic']['config'][0]['throttle_cd_images'];
+ $throttle_multimedia = $config['installedpackages']['squidtraffic']['config'][0]['throttle_multimedia'];
+
+ /* squid_auth.xml values */
+ $auth_method = $config['installedpackages']['squidauth']['config'][0]['auth_method'];
+ $auth_processes = $config['installedpackages']['squidauth']['config'][0]['auth_processes'];
+ $auth_cache_ttl = $config['installedpackages']['squidauth']['config'][0]['auth_cache_ttl'];
+ $limit_ip_addr = $config['installedpackages']['squidauth']['config'][0]['limit_ip_addr'];
+ $user_ip_cache_ttl = $config['installedpackages']['squidauth']['config'][0]['user_ip_cache_ttl'];
+ $req_unrestricted_auth = $config['installedpackages']['squidauth']['config'][0]['req_unrestricted_auth'];
+ $auth_realm_prompt = $config['installedpackages']['squidauth']['config'][0]['auth_realm_prompt'];
+ $no_domain_auth = $config['installedpackages']['squidauth']['config'][0]['no_domain_auth'];
+ $min_pass_length = $config['installedpackages']['squidauth']['config'][0]['min_pass_length'];
+ $bypass_extended = $config['installedpackages']['squidauth']['config'][0]['bypass_extended'];
+
+ /* squid_extauth.xml (ldap) values */
+ $ldap_basedn = $config['installedpackages']['squidextldapauth']['config'][0]['ldap_basedn'];
+ $ldap_server = $config['installedpackages']['squidextldapauth']['config'][0]['ldap_server'];
+ $ldap_type = $config['installedpackages']['squidextldapauth']['config'][0]['ldap_type'];
+ $ldap_port = $config['installedpackages']['squidextldapauth']['config'][0]['ldap_port'];
+ $bind_dn_username = $config['installedpackages']['squidextldapauth']['config'][0]['bind_dn_username'];
+ $bind_dn_password = $config['installedpackages']['squidextldapauth']['config'][0]['bind_dn_password'];
+
+ /* squid_extauth.xml (radius) values */
+ $radius_server = $config['installedpackages']['squidextradiusauth']['config'][0]['radius_server'];
+ $radius_port = $config['installedpackages']['squidextradiusauth']['config'][0]['radius_port'];
+ $radius_identifier = $config['installedpackages']['squidextradiusauth']['config'][0]['radius_identifier'];
+ $radius_secret = $config['installedpackages']['squidextradiusauth']['config'][0]['radius_secret'];
+
+ /* static variable assignments for directory mapping */
+ $acldir = "/usr/local/etc/squid/advanced/acls";
+ $ncsadir = "/usr/local/etc/squid/advanced/ncsa";
+ $ntlmdir = "/usr/local/etc/squid/advanced/ntlm";
+ $radiusdir = "/usr/local/etc/squid/advanced/radius";
+
+ $fout = fopen($squidconfig, "w");
+
+ $config_array = array('shutdown_lifetime 5 seconds' . "\n\n");
+
+ if (isset($cachemgr_enabled) && ($cachemgr_enabled == "on")) {
+ mwexec("cp /usr/local/libexec/squid/cachemgr.cgi /usr/local/www/cachemgr.cgi");
+ mwexec("chmod a+rx /usr/local/www/cachemgr.cgi");
+ } else {
+ mwexec("rm -f /usr/local/www/cachemgr.cgi");
+ }
+ unset($cachemgr_enabled);
+
+ if (!isset($icp_port) or ($icp_port == "")) {
+ $icp_port = "3130";
+ }
+ $config_array[] = 'icp_port ' . $icp_port . "\n";
+ unset($icp_port);
+
+ if(!isset($proxy_port) or ($proxy_port == "")) {
+ $proxy_port = "3128";
+ }
+
+ if (isset($transparent_proxy) && ($transparent_proxy != "on")) {
+ $int = convert_friendly_interface_to_real_interface_name($active_interface);
+ $listen_ip = find_interface_ip($int);
+
+ $config_array[] = 'http_port ' . $listen_ip . ':' . $proxy_port . "\n\n";
+ $config_array[] = 'acl QUERY urlpath_regex cgi-bin \?' . "\n";
+ $config_array[] = 'no_cache deny QUERY' . "\n\n";
+ }
+ $config_array[] = 'http_port 127.0.0.1:' . $proxy_port . "\n\n";
+ unset($proxy_port);
+
+ if (isset($domain) && ($domain !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/dst_nocache.acl","w");
+
+ $domain_array = split("; ",$domain);
+ foreach ($domain_array as $no_cache_domain) {
+ fwrite($aclout, $no_cache_domain . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl no_cache_domains dstdomain "' . $acldir . '/dst_nocache.acl"' . "\n";
+ $config_array[] = 'no_cache deny no_cache_domains' . "\n\n";
+ }
+ unset($no_cache_domain);
+ unset($domain_array);
+ unset($domain);
+
+ $config_array[] = 'cache_effective_user squid' . "\n";
+ $config_array[] = 'cache_effective_group squid' . "\n\n";
+ $config_array[] = 'pid_filename /var/run/squid.pid' . "\n\n";
+
+ if (!isset($memory_cache_size) or ($memory_cache_size == "")) {
+ $memory_cache_size = "8";
+ }
+ $config_array[] = 'cache_mem ' . $memory_cache_size . ' MB' . "\n";
+ unset($memory_cache_size);
+
+ if (!isset($harddisk_cache_size) or ($harddisk_cache_size == "")) {
+ $harddisk_cache_size = "500";
+ }
+
+ if (!isset($level_subdirs) or ($level_subdirs == "")) {
+ $level_subdirs = "16";
+ }
+
+ $config_array[] = 'cache_dir diskd /var/squid/cache ' . $harddisk_cache_size . ' ' . $level_subdirs . ' 256' . "\n\n";
+ unset($harddisk_cache_size);
+ unset($level_subdirs);
+
+ if (!isset($error_language) or ($error_language == "")) {
+ $error_language = "English";
+ }
+ $config_array[] = 'error_directory /usr/local/etc/squid/errors/' . $error_language . "\n\n";
+ unset($error_language);
+
+ if (isset($offline_mode) && ($offline_mode == "on")) {
+ $config_array[] = 'offline_mode on' . "\n\n";
+ } else {
+ $config_array[] = 'offline_mode off' . "\n\n";
+ }
+
+ if (!isset($memory_replacement) or ($memory_replacement == "")) {
+ $memory_replacement = "heap GDSF";
+ }
+ $config_array[] = 'memory_replacement_policy ' . $memory_replacement . "\n";
+ unset($memory_replacement);
+
+ if (!isset($cache_replacement) or ($cache_replacement == "")) {
+ $cache_replacement="heap GDSF";
+ }
+ $config_array[] = 'cache_replacement_policy ' . $cache_replacement . "\n\n";
+ unset($cache_replacement);
+
+ if (isset($accesslog_disabled) && ($accesslog_disabled == "on")) {
+ $config_array[] = 'cache_access_log none' . "\n";
+ } else {
+ $config_array[] = 'cache_access_log /var/log/access.log' . "\n";
+ }
+ $config_array[] = 'cache_log /var/log/cache.log' . "\n";
+ $config_array[] = 'cache_store_log none' . "\n";
+ unset($accesslog_disabled);
+ unset($log_enabled);
+
+ if (isset($log_query_terms) && ($log_query_terms == "on")) {
+ $config_array[] = 'strip_query_terms off' . "\n";
+ } else {
+ $config_array[] = 'strip_query_terms on' . "\n";
+ }
+ unset($log_query_terms);
+
+ $config_array[] = 'useragent_log /var/log/useragent.log' . "\n\n";
+ unset($log_user_agents);
+
+ $config_array[] = 'log_mime_hdrs off' . "\n";
+ $config_array[] = 'emulate_httpd_log on' . "\n";
+
+ switch ($user_forwarding) {
+ case "on":
+ $config_array[] = 'forwarded_for on' . "\n\n";
+ break;
+ case "off":
+ $config_array[] = 'forwarded_for off' . "\n\n";
+ break;
+ default:
+ $config_array[] = 'forwarded_for off' . "\n\n";
+ break;
+ }
+ unset($user_forwarding);
+
+ switch ($auth_method) {
+ case "none":
+ break;
+ case "local_auth":
+ $config_array[] = 'auth_param basic program /usr/local/libexec/squid/ncsa_auth /usr/local/etc/squid/advanced/ncsa/passwd' . "\n";
+ if (!isset($auth_processes) or ($auth_processes == "")) {
+ $auth_processes = "5";
+ }
+ $config_array[] = 'auth_param basic children ' . $auth_processes . "\n";
+
+ if (!isset($auth_realm_prompt) or ($auth_realm_prompt == "")) {
+ $auth_realm_prompt = "pfSense Advanced Proxy";
+ }
+ $config_array[] = 'auth_param basic realm ' . $auth_realm_prompt . "\n";
+
+ if (!isset($auth_cache_ttl) or ($auth_cache_ttl == "")) {
+ $auth_cache_ttl = "60";
+ }
+ $config_array[] = 'auth_param basic credentialsttl ' . $auth_cache_ttl . ' minutes' . "\n\n";
+ $config_array[] = 'acl for_inetusers proxy_auth REQUIRED' . "\n\n";
+
+ unset($auth_realm_prompt);
+ unset($auth_processes);
+ unset($auth_cache_ttl);
+
+ break;
+ case "radius_auth";
+ $config_array[] = 'auth_param basic program /usr/local/libexec/squid/squid_rad_auth -h ' . $radius_server . ' -p ' . $radius_port . ' -i ' . $radius_identifier . ' -w ' . $radius_secret . "\n";
+ if (!isset($auth_processes) or ($auth_processes == "")) {
+ $auth_processes = "5";
+ }
+ $config_array[] = 'auth_param basic children ' . $auth_processes . "\n";
+
+ if (!isset($auth_realm_prompt) or ($auth_realm_prompt == "")) {
+ $auth_realm_prompt = "pfSense Advanced Proxy";
+ }
+ $config_array[] = 'auth_param basic realm ' . $auth_realm_prompt . "\n";
+
+ if (!isset($auth_cache_ttl) or ($auth_cache_ttl == "")) {
+ $auth_cache_ttl = "60";
+ }
+ $config_array[] = 'auth_param basic credentialsttl ' . $auth_cache_ttl . ' minutes' . "\n\n";
+ $config_array[] = 'acl for_inetusers proxy_auth REQUIRED' . "\n\n";
+
+ unset($auth_realm_prompt);
+ unset($auth_processes);
+ unset($auth_cache_ttl);
+
+ break;
+ case "ldap_bind";
+ $config_array[] = 'auth_param basic program /usr/local/libexec/squid_ldap_auth -b "' . $ldap_basedn . '" -D "' . $bind_dn_username . '" -w "' . $bind_dn_password . '" -f "(&(objectClass=person)(cn=%s))" -u -cn -P "' . $ldap_server . ":" . $ldap_port . "\n";
+ $config_array[] = 'auth_param basic program /usr/local/libexec/squid/squid_ldap_auth';
+ $config_array[] = ' -b "' . $ldap_basedn . '"';
+ $config_array[] = ' -D "' . $bind_dn_username . '"';
+ $config_array[] = " -w " . $bind_dn_password;
+ $config_array[] = ' -f "(&(objectClass=person)(cn=%s))"';
+ $config_array[] = " -u cn -P " . $ldap_server . ":" . $ldap_port . "\n";
+
+ if (!isset($auth_processes) or ($auth_processes == "")) {
+ $auth_processes = "5";
+ }
+ $config_array[] = 'auth_param basic children ' . $auth_processes . "\n";
+
+ if (!isset($auth_realm_prompt) or ($auth_realm_prompt == "")) {
+ $auth_realm_prompt = "pfSense Advanced Proxy";
+ }
+ $config_array[] = 'auth_param basic realm ' . $auth_realm_prompt . "\n";
+
+ if (!isset($auth_cache_ttl) or ($auth_cache_ttl == "")) {
+ $auth_cache_ttl = "60";
+ }
+ $config_array[] = 'auth_param basic credentialsttl ' . $auth_cache_ttl . ' minutes' . "\n\n";
+ $config_array[] = 'acl for_inetusers proxy_auth REQUIRED' . "\n\n";
+
+ unset($auth_realm_prompt);
+ unset($auth_processes);
+ unset($auth_cache_ttl);
+
+ break;
+ case "windows_auth";
+ break;
+ }
+
+ if (isset($throttle_binary_files) && ($throttle_binary_files == "on")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $binary_out = "\.bin$\n\.cab$\n\.gz$\n\.rar$\n\.sea$\n\.tar$\n\.tgz$\n\.zip$\n";
+
+ $throttle_out = fopen($acldir . "/dst_throttle_binary.acl", "w");
+ fwrite($throttle_out, $binary_out);
+ fclose($throttle_out);
+ $config_array[] = 'acl for_throttled_binary url_regex -i "' . $acldir . '/dst_throttle_binary.acl"' . "\n";
+ } else {
+ if (file_exists($acldir . "/dst_throttle_binary.acl")) unlink($acldir . "/dst_throttle_binary.acl");
+ }
+ unset($throttle_binary_files);
+ unset($throttle_out);
+ unset($binary_out);
+
+ if (isset($throttle_cd_images) && ($throttle_cd_images == "on")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $cd_out = "\.b5t$\n\.bin$\n\.bwt$\n\.cdi$\n\.cue$\n\.gho$\n\.img$\n\.iso$\n\.mds$\n\.nrg$\n\.pqi$\n";
+
+ $throttle_out = fopen($acldir . "/dst_throttle_cd.acl","w");
+ fwrite($throttle_out, $cd_out);
+ fclose($throttle_out);
+ $config_array[] = 'acl for_throttled_cd url_regex -i "' . $acldir . '/dst_throttle_cd.acl"' . "\n";
+ } else {
+ if (file_exists($acldir . "/dst_throttle_cd.acl")) {
+ unlink($acldir . "/dst_throttle_cd.acl");
+ }
+ }
+ unset($throttle_cd_images);
+ unset($throttle_out);
+ unset($cd_out);
+
+ if (isset($throttle_multimedia) && ($throttle_multimedia == "on")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $multimedia_out = "\.aiff?$\n\.asf$\n\.avi$\n\.divx$\n\.mov$\n\.mp3$\n\.mpe?g$\n\.qt$\n\.ra?m$\n";
+
+ $throttle_out = fopen($acldir . "/dst_throttle_multimedia.acl","w");
+ fwrite($throttle_out, $multimedia_out);
+ fclose($throttle_out);
+ $config_array[] = 'acl for_throttled_multimedia url_regex -i "' . $acldir . '/dst_throttle_multimedia.acl"' . "\n";
+ } else {
+ if (file_exists($acldir . "/dst_throttle_multimedia.acl")) {
+ unlink($acldir . "/dst_throttle_multimedia.acl");
+ }
+ }
+ unset($throttle_multimedia);
+ unset($multimedia_out);
+ unset($throttle_out);
+
+ $config_array[] = 'acl within_timeframe time MTWHFAS 00:00-24:00' . "\n\n";
+
+ /* obtain interface subnet and address for Squid rules */
+ $lactive_interface = strtolower($active_interface);
+
+ $lancfg = $config['interfaces'][$lactive_interface];
+ $lanif = $lancfg['if'];
+ $lanip = $lancfg['ipaddr'];
+ $lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
+ $lansn = $lancfg['subnet'];
+
+ $config_array[] = 'acl all src 0.0.0.0/0.0.0.0' . "\n";
+ $config_array[] = 'acl localnet src ' . $lansa . '/' . $lansn . "\n";
+ $config_array[] = 'acl localhost src 127.0.0.1/255.255.255.255' . "\n";
+ $config_array[] = 'acl SSL_ports port 443 563 873 # https, snews, rsync' . "\n";
+ $config_array[] = 'acl Safe_ports port 80 # http' . "\n";
+ $config_array[] = 'acl Safe_ports port 21 # ftp' . "\n";
+ $config_array[] = 'acl Safe_ports port 443 563 873 # https, snews, rsync' . "\n";
+ $config_array[] = 'acl Safe_ports port 70 # gopher' . "\n";
+ $config_array[] = 'acl Safe_ports port 210 # wais' . "\n";
+ $config_array[] = 'acl Safe_ports port 1025-65535 # unregistered ports' . "\n";
+ $config_array[] = 'acl Safe_ports port 280 # http-mgmt' . "\n";
+ $config_array[] = 'acl Safe_ports port 488 # gss-http' . "\n";
+ $config_array[] = 'acl Safe_ports port 591 # filemaker' . "\n";
+ $config_array[] = 'acl Safe_ports port 777 # multiling http' . "\n";
+ $config_array[] = 'acl Safe_ports port 800 # Squids port (for icons)' . "\n\n";
+
+ /* allow access through proxy for custom admin port */
+ $custom_port = $config['system']['webgui']['port'];
+ if (isset($custom_port) && ($custom_port !== "")) {
+ $config_array[] = 'acl pf_admin_port port ' . $custom_port . "\n";
+ unset($custom_port);
+ } else {
+ $admin_protocol = $config['system']['webgui']['protocol'];
+ switch ($admin_protocol) {
+ case "http";
+ $config_array[] = 'acl pf_admin_port port 80' ."\n";
+ break;
+ case "https";
+ $config_array[] = 'acl pf_admin_port port 443' . "\n";
+ break;
+ default;
+ $config_array[] = 'acl pf_admin_port port 80' . "\n";
+ break;
+ }
+ unset($admin_protocol);
+ }
+
+ /* define override hosts as specified in squid_nac.xml */
+ if (isset($override_hosts) && ($override_hosts !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_override_hosts.acl", "w");
+
+ $override_hosts_array = split("; ", $override_hosts);
+ foreach ($override_hosts_array as $ind_override_host) {
+ fwrite($aclout, $ind_override_host . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl override_hosts src "/usr/local/etc/squid/advanced/acls/src_override_hosts.acl"' . "\n";
+ }
+ /* clear variables */
+ unset($override_hosts_array);
+ unset($ind_override_host);
+ unset($override_hosts);
+
+ /* define subnets allowed to utilize proxy service */
+ if (isset($allowed_subnets) && ($allowed_subnets !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ mwexec("touch {$acldir}/src_subnets.acl");
+ }
+
+ $aclout = fopen($acldir . "/src_subnets.acl","w");
+
+ $allowed_subnets_array = split("; ",$allowed_subnets);
+ foreach ($allowed_subnets_array as $ind_allowed_subnets) {
+ fwrite($aclout, $ind_allowed_subnets . "\n");
+ }
+
+ fclose($aclout);
+ } else {
+
+ $aclout = fopen($acldir . "/src_subnets.acl","w");
+ fwrite($aclout, $lansa . "/" . $lansn . "\n");
+ fclose($aclout);
+ }
+
+ $config_array[] = 'acl pf_networks src "/usr/local/etc/squid/advanced/acls/src_subnets.acl"' . "\n";
+
+ unset($allowed_subnets_array);
+ unset($ind_allowed_subnets);
+ unset($allowed_subnets);
+
+ /* define ip addresses that have 'unrestricted' access */
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_unrestricted_ip.acl","w");
+
+ $unrestricted_ip_array = split("; ",$unrestricted_ip_addr);
+ foreach ($unrestricted_ip_array as $ind_unrestricted_ip) {
+ fwrite($aclout, $ind_unrestricted_ip . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl pf_unrestricted_ip src "/usr/local/etc/squid/advanced/acls/src_unrestricted_ip.acl"' . "\n";
+ }
+ unset($unrestricted_ip_array);
+ unset($unrestricted_ip_addr);
+ unset($ind_unrestricted_ip);
+
+ /* define mac addresses that have 'unrestricted' access */
+ if (isset($unrestricted_mac_addr) && ($unrestricted_mac_addr !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_unrestricted_mac.acl","w");
+
+ $unrestricted_mac_array = split("; ",$unrestricted_mac_addr);
+ foreach ($unrestricted_mac_array as $ind_unrestricted_mac) {
+ fwrite($aclout, $ind_unrestricted_mac . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl pf_unrestricted_mac src "/usr/local/etc/squid/advanced/acls/src_unrestricted_mac.acl"' . "\n";
+ }
+ unset($unrestricted_mac_array);
+ unset($unrestricted_mac_addr);
+ unset($ind_unrestricted_mac);
+
+ /* define ip addresses that are banned from using the proxy service */
+ if (isset($banned_ip_addr) && ($banned_ip_addr !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_banned_ip.acl","w");
+
+ $banned_ip_array = split("; ",$banned_ip_addr);
+ foreach ($banned_ip_array as $ind_banned_ip) {
+ fwrite($aclout, $ind_banned_ip . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl pf_banned_ip src "/usr/local/etc/squid/advanced/acls/src_banned_ip.acl"' . "\n";
+ }
+ unset($banned_ip_addr);
+ unset($banned_ip_addr);
+ unset($ind_banned_ip);
+
+ /* define mac addresses that are banned from using the proxy service */
+ if (isset($banned_mac_addr) && ($banned_mac_addr !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_banned_mac.acl","w");
+
+ $banned_mac_array = split("; ",$banned_mac_addr);
+ foreach ($banned_mac_array as $ind_banned_mac) {
+ fwrite($aclout, $ind_banned_mac . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl pf_banned_mac src "/usr/local/etc/squid/advanced/acls/src_banned_mac.acl"' . "\n";
+ }
+ unset($banned_mac_array);
+ unset($banned_mac_addr);
+ unset($ind_banned_mac);
+
+ $config_array[] = 'acl pf_ips dst ' . $lanip . "\n";
+ $config_array[] = 'acl CONNECT method CONNECT' . "\n\n";
+
+ if (isset($auth_method) && ($auth_method == "none")) {
+ $config_array[] = 'http_access allow localnet' . "\n";
+ }
+ $config_array[] = 'http_access allow localhost' . "\n";
+
+ if (isset($override_hosts) && ($override_hosts !== "")) {
+ $config_array[] = 'http_access allow override_hosts' . "\n";
+ }
+ $config_array[] = "\n";
+
+ switch ($config['system']['webgui']['protocol']) {
+ case "http":
+ $config_array[] = 'http_access allow pf_ips' . "\n";
+ $config_array[] = 'http_access allow pf_admin_port' . "\n";
+ $config_array[] = 'http_access deny !pf_networks' . "\n\n";
+ break;
+ case "https":
+ $config_array[] = 'http_access allow CONNECT pf_ips' . "\n";
+ $config_array[] = 'http_access allow CONNECT pf_admin_port' . "\n";
+ $config_array[] = 'http_access deny CONNECT !pf_networks' . "\n\n";
+ break;
+ }
+
+ $config_array[] = 'http_access deny !Safe_ports' . "\n";
+ $config_array[] = 'http_access deny CONNECT !SSL_ports' . "\n\n";
+
+ if (isset($auth_method) && ($auth_method != "none")) {
+ $config_array[] = 'http_access allow pf_networks for_inetusers within_timeframe' . "\n";
+ }
+
+ $config_array[] = 'http_access deny all' . "\n\n";
+
+ if (isset($dl_overall) && ($dl_overall !== "") and isset($dl_per_host) && ($dl_per_host == "")) {
+ $config_array[] = 'delay_pools 1' . "\n";
+ $config_array[] = 'delay_class 1 3' . "\n";
+
+ if ($dl_overall == "unlimited") {
+ $config_array[] = 'delay_parameters 1 -1/-1 -1/-1 ' . ($dl_overall * 125) . '/' . ($dl_overall * 250) . "\n";
+ } else {
+ $config_array[] = 'delay_parameters 1 ' . ($dl_overall * 125) . '/' . ($dl_overall * 250) . ' -1/-1 -1/-1' . "\n";
+ }
+
+ /* if no unrestricted ip addresses are defined; this line is ignored */
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr == "")) $config_array[] = 'delay_access 1 deny pf_unrestricted_ip' . "\n";
+
+ /* this will define bandwidth delay restrictions for specified throttles */
+ if (isset($throttle_binary_files) && ($throttle_binary_files == "on")) {
+ $config_array[] = 'delay_access 1 allow all for_throttled_binary' . "\n";
+ }
+ if (isset($throttle_cd_images) && ($throttle_cd_images == "on")) {
+ $config_array[] = 'delay_access 1 allow all for_throttled_cd' . "\n";
+ }
+ if (isset($throttle_multimedia) && ($throttle_multimedia == "on")) {
+ $config_array[] = 'delay_access 1 allow all for_throttled_multimedia' . "\n";
+ } else {
+ $config_array[] = 'delay_access 1 allow all' . "\n";
+ }
+ $config_array[] = 'delay_initial_bucket_level 100%' . "\n\n";
+ }
+
+ if (isset($dl_per_host) && ($dl_per_host !== "") and isset($dl_overall) && ($dl_overall == "")) {
+ $config_array[] = 'delay_pools 1' . "\n";
+ $config_array[] = 'delay_class 1 3' . "\n";
+
+ if ($dl_per_host == "unlimited") {
+ $config_array[] = 'delay_parameters 1 ' . ($dl_per_host * 125) . '/' . ($dl_per_host * 250) . '-1/-1 -1/-1' . "\n";
+ } else {
+ $config_array[] = 'delay_parameters 1 -1/-1 -1/-1 ' . ($dl_per_host * 125) . '/' . ($dl_per_host * 250) . "\n";
+ }
+
+ /* if no unrestricted ip addresses are defined; this line is ignored */
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr !== "")) $config_array[] = 'delay_access 1 deny pf_unrestricted_ip' . "\n";
+
+ /* this will define bandwidth delay restrictions for specified throttles */
+ if ($throttle_binary_files == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_binary' . "\n";
+ }
+ if ($throttle_cd_images == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_cd' . "\n";
+ }
+ if ($throttle_multimedia == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_multimedia' ."\n";
+ } else {
+ $config_array[] = 'delay_access 1 allow all' . "\n";
+ }
+ $config_array[] = 'delay_initial_bucket_level 100%' . "\n\n\n";
+ }
+
+ if (isset($dl_overall) && ($dl_overall !== "") and isset($dl_per_host) && ($dl_per_host !== "")) {
+ /* if no bandwidth restrictions are specified, then these parameters are not necessary */
+ if ($dl_overall !== "unlimited" and $dl_per_host !== "unlimited") {
+
+ if ((isset($dl_overall) && ($dl_overall == "unlimited")) and (isset($dl_per_host) && ($dl_per_host !== ""))) {
+ $config_array[] = 'delay_pools 1' . "\n";
+ $config_array[] = 'delay_class 1 3' . "\n";
+ $config_array[] = 'delay_parameters 1 -1/-1 -1/-1 ' . ($dl_per_host * 125) . '/' . ($dl_overall * 250) . "\n";
+ } elseif (isset($dl_overall) && ($dl_overall !== "") and isset($dl_per_host) && ($dl_per_host == "unlimited")) {
+ $config_array[] = 'delay_pools 1' . "\n";
+ $config_array[] = 'delay_class 1 3' . "\n";
+ $config_array[] = 'delay_parameters 1 ' . ($dl_overall * 125) . '/' . ($dl_overall * 250) . ' -1/-1 -1/-1' . "\n";
+ }
+ }
+
+ if ($dl_overall !== "unlimited" and $dl_per_host !== "unlimited") {
+
+ /* if no unrestricted ip addresses are defined; this line is ignored */
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr !== "")) $config_array[] = 'delay_access 1 deny pf_unrestricted_ip' . "\n";
+
+ /* this will define bandwidth delay restrictions for specified throttles */
+ if ($throttle_binary_files == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_binary' . "\n";
+ }
+ if ($throttle_cd_images == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_cd' . "\n";
+ }
+ if ($throttle_multimedia == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_multimedia' . "\n";
+ } else {
+ $config_array[] = 'delay_access 1 allow all' . "\n";
+ }
+ $config_array[] = 'delay_initial_bucket_level 100%' . "\n\n";
+ }
+ }
+
+ $config_array[] = 'header_access X-Forwarded-For deny all' . "\n";
+ $config_array[] = 'header_access Via deny all' . "\n\n";
+
+ /* TODO: acl customization for snmp support */
+ /* fwrite($fout, "\n"); */
+
+ if (isset($urlfilter_enable) && ($urlfilter_enable == "on")) {
+ $config_array[] = 'redirect_program /usr/sbin/squidGuard' . "\n";
+ $config_array[] = 'redirect_children 5' . "\n\n";
+ }
+
+ if (isset($max_upload_size) && ($max_upload_size != "")) {
+ $config_array[] = 'request_body_max_size ' . $max_download_size . 'KB' . "\n";
+ }
+
+ if (isset($max_download_size) && ($max_download_size != "")) {
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr !== "")) $config_array[] = 'reply_body_max_size 0 allow pf_unrestricted_ip' . "\n";
+ /* fwrite($fout, "#reply_body_max_size 0 allow for_extended_users\n"); */
+ $config_array[] = 'reply_body_max_size ' . $max_download_size * 1024 . ' allow all' . "\n\n";
+ }
+
+ /* set default value for maximum_object_size */
+ if (!isset($maximum_object_size) or ($maximum_object_size == "")) {
+ $maximum_object_size = "4096";
+ }
+
+ /* set default value for minimum_object_size */
+ if (!isset($minimum_object_size) or ($minimum_object_size == "")) {
+ $minimum_object_size = "0";
+ }
+ $config_array[] = 'maximum_object_size ' . $maximum_object_size . ' KB' . "\n";
+ $config_array[] = 'minimum_object_size ' . $minimum_object_size . ' KB' . "\n\n";
+
+ if (isset($proxy_forwarding) && ($proxy_forwarding == "on")) {
+ $config_array[] = 'cache_peer ' . $upstream_proxy . ' parent ' . $upstream_proxy_port . ' 3130 login=' . upstream_username . ':' . upstream_password . ' default no-query' . "\n";
+ $config_array[] = 'never_direct allow all' . "\n";
+ }
+ unset($proxy_forwarding);
+
+
+ /* define default ruleset for transparent proxy operation */
+ if (isset($transparent_proxy) && ($transparent_proxy == "on")) {
+ $config_array[] = 'httpd_accel_host virtual' . "\n";
+ $config_array[] = 'httpd_accel_port 80' . "\n";
+ $config_array[] = 'httpd_accel_with_proxy on' . "\n";
+ $config_array[] = 'httpd_accel_uses_host_header on' . "\n\n";
+ }
+ unset($transparent_proxy);
+
+
+ /* define visible hostname */
+ if (isset($visible_hostname) && ($visible_hostname !== "")) {
+ $config_array[] = 'visible_hostname ' . $visible_hostname . "\n";
+ }
+ unset($visible_hostname);
+
+ /* define cache administrators email address within error messages */
+ if (isset($cache_admin_email) && ($cache_admin_email !== "")) {
+ $config_array[] = 'cache_mgr ' . $cache_admin_email . "\n\n";
+ }
+ unset($cache_admin_email);
+
+ /* write configuration file */
+ foreach ($config_array as $config_item)
+ {
+ fwrite($fout, trim($config_item));
+
+ if (stristr($config_item, "\n"))
+ {
+ for ($i = 1; $i < count(explode("\n", $config_item)); $i++)
+ {
+ fwrite($fout, "\n");
+ }
+ }
+
+ }
+ fclose($fout);
+
+ conf_mount_ro();
+ config_unlock();
+
+ touch($squidconfig);
+} /* end function write_squid_config */
+
+function custom_php_install_command() {
+ /* write initial static config for transparent proxy */
+ write_static_squid_config();
+
+ touch("/tmp/custom_php_install_command");
+
+ /* make sure this all exists, see:
+ * http://forum.pfsense.org/index.php?topic=23.msg2391#msg2391
+ */
+ update_output_window("Setting up Squid environment...");
+ mwexec("mkdir -p /var/squid");
+ mwexec("chown squid:squid /var/squid");
+ mwexec("mkdir -p /var/squid/logs");
+ mwexec("chown squid:squid /var/squid/logs");
+ mwexec("mkdir -p /var/squid/cache");
+ mwexec("chown squid:squid /var/squid/cache");
+ mwexec("mkdir -p /usr/local/etc/squid/advanced");
+ mwexec("chown squid:squid /usr/local/etc/squid/advanced");
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/acls");
+ mwexec("chown squid:squid /usr/local/etc/squid/advanced/acls");
+ mwexec("touch /usr/local/etc/squid/advanced/acls/src_subnets.acl");
+ mwexec("chown squid:squid /usr/local/etc/squid/advanced/acls/src_subnets.acl");
+ mwexec("touch /usr/local/etc/squid/advanced/acls/src_unrestricted_ip.acl");
+ mwexec("chown squid:squid /usr/local/etc/squid/advanced/acls/src_unrestricted_ip.acl");
+ mwexec("cp /usr/local/etc/squid/mime.conf.default /usr/local/etc/squid/mime.conf");
+
+
+ /* set a few extra items noted by regan */
+ update_output_window("Creating logs and setting user information...");
+ $fdsquid = fopen("/usr/local/etc/rc.d/aSquid.sh", "w");
+ fwrite($fdsquid, "#/bin/sh\n");
+ fwrite($fdsquid, "# \n");
+ fwrite($fdsquid, "# This file was created by the pfSense package system\n");
+ fwrite($fdsquid, "# Sets up squid option on each bootup that are not persistent\n");
+ fwrite($fdsquid, "# \n\n");
+ fwrite($fdsquid, "chown squid:wheel /dev/pf\n");
+ fwrite($fdsquid, "chmod ug+rw /dev/pf\n");
+ fwrite($fdsquid, "touch /var/log/useragent.log\n");
+ fwrite($fdsquid, "touch /var/log/access.log\n");
+ fwrite($fdsquid, "touch /var/log/cache.log\n");
+ fwrite($fdsquid, "chown squid:wheel /var/log/cache.log\n");
+ fwrite($fdsquid, "chown squid:wheel /var/log/access.log\n");
+ fwrite($fdsquid, "chown squid:wheel /var/log/useragent.log\n");
+ fwrite($fdsquid, "\n");
+ fclose($fdsquid);
+ mwexec("chmod a+rx /usr/local/etc/rc.d/aSquid.sh");
+ mwexec("/usr/local/etc/rc.d/aSquid.sh");
+
+ update_output_window("Creating Proxy Server initialization scripts...");
+ $start = "touch /tmp/ro_root_mount; /usr/local/sbin/squid -D; touch /tmp/filter_dirty";
+ $stop = "/usr/local/sbin/squid -k shutdown";
+ write_rcfile(array(
+ "file" => "squid.sh",
+ "start" => $start,
+ "stop" => $stop
+ )
+ );
+
+ mwexec("chmod 755 /usr/local/etc/rc.d/squid.sh");
+
+ /* create log directory hierarchies if they don't exist */
+ update_output_window("Creating required directory hierarchies...");
+
+ if (!file_exists("/var/squid/logs")) {
+ mwexec("mkdir -p /var/squid/logs");
+ }
+ mwexec("/usr/sbin/chown squid:squid /var/squid/logs");
+
+
+ if (!file_exists("/var/squid/cache")) {
+ mwexec("mkdir -p /var/squid/cache");
+ }
+ mwexec("/usr/sbin/chown squid:squid /var/squid/cache");
+
+ if (!file_exists("/usr/local/etc/squid/advanced/acls")) {
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/acls");
+ }
+ mwexec("/usr/sbin/chown squid:squid /usr/local/etc/squid/advanced/acls");
+
+ if (!file_exists("/usr/local/etc/squid/advanced/ncsa")) {
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/ncsa");
+ }
+ mwexec("/usr/sbin/chown squid:squid /usr/local/etc/squid/advanced/ncsa");
+
+ if (!file_exists("/usr/local/etc/squid/advanced/ntlm")) {
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/ntlm");
+ }
+ mwexec("/usr/sbin/chown squid:squid /usr/local/etc/squid/advanced/ntlm");
+
+ if (!file_exists("/usr/local/etc/squid/advanced/radius")) {
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/radius");
+ }
+ mwexec("/usr/sbin/chown squid:squid /usr/local/etc/squid/advanced/radius");
+
+ $devfs_file = fopen("/etc/devfs.conf", "a");
+ fwrite($devfs_file, "\n# Allow squid to query the packet filter bymaking is group-accessable. ");
+ fwrite($devfs_file, "own pf root:squid");
+ fwrite($devfs_file, "perm pf 0640");
+ fclose($devfs_file);
+
+ update_output_window("Initializing Cache... This may take a moment...");
+ mwexec("/usr/local/sbin/squid -z");
+
+ update_output_window("Starting Proxy Server...");
+ start_service("squid");
+}
+
+function custom_php_deinstall_command() {
+ update_output_window("Stopping proxy service...");
+ stop_service("squid");
+ sleep(1);
+ /* brute force any remaining squid processes out */
+ mwexec("/usr/bin/killall squid");
+ mwexec("/usr/bin/killall pinger");
+ update_output_window("Recursively removing directories hierarchies. If existant, log files in /var/squid/logs will remain...");
+ mwexec("rm -rf /var/squid/cache");
+ update_output_window("Removing configuration files...");
+ unlink_if_exists("/usr/local/etc/rc.d/squid.sh");
+ unlink_if_exists("/usr/local/libexec/squid");
+ unlink_if_exists("/usr/local/etc/rc.d/aSquid.sh");
+ mwexec("rm -f /usr/local/etc/rc.d/squid*");
+ mwexec("rm -f /usr/local/www/cachemgr.cgi");
+ filter_configure();
+}
+
+function write_static_squid_config() {
+ touch("/tmp/write_static_squid_config");
+ global $config;
+ $lancfg = $config['interfaces']['lan'];
+ $lanif = $lancfg['if'];
+ $lanip = $lancfg['ipaddr'];
+ $lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
+ $lansn = $lancfg['subnet'];
+
+ $fout = fopen("/usr/local/etc/squid/squid.conf","w");
+ fwrite($fout, "#\n");
+ fwrite($fout, "# This file was automatically generated by the pfSense package manager.\n");
+ fwrite($fout, "# This default policy enables transparent proxy with no local disk logging.\n");
+ fwrite($fout, "#\n");
+
+ /* set # of dns children */
+ fwrite($fout, "dns_children 15\n");
+
+ fwrite($fout, "shutdown_lifetime 5 seconds\n");
+ fwrite($fout, "icp_port 0\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "acl QUERY urlpath_regex cgi-bin \?\n");
+ fwrite($fout, "no_cache deny QUERY\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "pid_filename /var/run/squid.pid\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "cache_mem 24 MB\n");
+ fwrite($fout, "cache_dir diskd /var/squid/cache 500 16 256\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "error_directory /usr/local/etc/squid/errors/English\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "memory_replacement_policy heap GDSF\n");
+ fwrite($fout, "cache_replacement_policy heap GDSF\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "cache_access_log none\n");
+ fwrite($fout, "cache_log none\n");
+ fwrite($fout, "cache_store_log none\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "log_mime_hdrs off\n");
+ fwrite($fout, "emulate_httpd_log on\n");
+ fwrite($fout, "forwarded_for off\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "acl within_timeframe time MTWHFAS 00:00-24:00\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "acl all src 0.0.0.0/0.0.0.0\n");
+ fwrite($fout, "acl localnet src " . $lansa . "/" . $lansn . "\n");
+ fwrite($fout, "acl localhost src 127.0.0.1/255.255.255.255\n");
+ fwrite($fout, "acl SSL_ports port 443 563 873 # https, snews, rsync\n");
+ fwrite($fout, "acl Safe_ports port 80 # http\n");
+ fwrite($fout, "acl Safe_ports port 21 # ftp\n");
+ fwrite($fout, "acl Safe_ports port 443 563 873 # https, snews, rsync\n");
+ fwrite($fout, "acl Safe_ports port 70 # gopher\n");
+ fwrite($fout, "acl Safe_ports port 210 # wais\n");
+ fwrite($fout, "acl Safe_ports port 1025-65535 # unregistered ports\n");
+ fwrite($fout, "acl Safe_ports port 280 # http-mgmt\n");
+ fwrite($fout, "acl Safe_ports port 488 # gss-http\n");
+ fwrite($fout, "acl Safe_ports port 591 # filemaker\n");
+ fwrite($fout, "acl Safe_ports port 777 # multiling http\n");
+ fwrite($fout, "acl Safe_ports port 800 # Squids port (for icons)\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "acl CONNECT method CONNECT\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "#access to squid; local machine; no restrictions\n");
+ fwrite($fout, "http_access allow localnet\n");
+ fwrite($fout, "http_access allow localhost\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "#Deny non web services\n");
+ fwrite($fout, "http_access deny !Safe_ports\n");
+ fwrite($fout, "http_access deny CONNECT !SSL_ports\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "#Set custom configured ACLs\n");
+ fwrite($fout, "http_access deny all\n");
+ fwrite($fout, "visible_hostname pfSense\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "cache_effective_user squid\n");
+ fwrite($fout, "cache_effective_group squid\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "maximum_object_size 4096 KB\n");
+ fwrite($fout, "minimum_object_size 0 KB\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "request_body_max_size 0 KB\n");
+ fwrite($fout, "reply_body_max_size 0 allow all\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "httpd_accel_host virtual\n");
+ fwrite($fout, "httpd_accel_port 80\n");
+ fwrite($fout, "httpd_accel_with_proxy on\n");
+ fwrite($fout, "httpd_accel_uses_host_header on\n");
+
+ fclose($fout);
+}
+
+function mod_htpasswd() {
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ if (!file_exists("/usr/local/etc/squid/advanced/ncsa")) mwexec("mkdir -p /usr/local/etc/squid/advanced/ncsa");
+
+ $passfile = fopen("/usr/local/etc/squid/advanced/ncsa/passwd", "w+");
+
+ if (isset($config['installedpackages']['squidextlocalauth']['config']) && $config['installedpackages']['squidextlocalauth']['config'] != "") {
+ foreach($config['installedpackages']['squidextlocalauth']['config'] as $rowhelper) {
+ $encpass = generate_htpasswd($rowhelper['username'], $rowhelper['password']);
+ fwrite($passfile, $rowhelper['username'] . ":" . $encpass . "\n");
+ }
+ }
+
+ fclose($passfile);
+
+ conf_mount_ro();
+ config_unlock();
+}
+
+function generate_htpasswd($username, $password) {
+ $all = explode( " ",
+ "a b c d e f g h i j k l m n o p q r s t u v w x y z "
+ . "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z "
+ . "0 1 2 3 4 5 6 7 8 9");
+
+ for ($i = 0; $i < 9; $i++) {
+ srand((double)microtime()*1000000);
+ $randy = rand(0,61);
+ $seed .= $all[$randy];
+ }
+
+ $crypt = crypt($password, "$1$$seed");
+ return $crypt;
+}
+
+?>
diff --git a/config/squid-8/squid_ng.xml b/config/squid-8/squid_ng.xml
new file mode 100644
index 00000000..5d956387
--- /dev/null
+++ b/config/squid-8/squid_ng.xml
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squid</name>
+ <version>2.5.12_4</version>
+ <title>Services: Proxy Server</title>
+ <category>Security</category>
+ <aftersaveredirect>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/squid_ng.inc</include_file>
+ <menu>
+ <name>Squid</name>
+ <tooltiptext>Modify settings for Proxy Server</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>
+ </menu>
+ <menu>
+ <name>Squid stats</name>
+ <tooltiptext>Show Squid statistics</tooltiptext>
+ <section>Services</section>
+ <url>/cachemgr.cgi</url>
+ </menu>
+ <service>
+ <name>squid</name>
+ <rcfile>squid.sh</rcfile>
+ </service>
+ <tabs>
+ <tab>
+ <text>General Settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Network Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Extended Auth</text>
+ <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->squidng->configuration->settings</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_cache.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_nac.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_ng.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_traffic.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_upstream.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_auth.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_auth.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_extauth.xml</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Proxy Listening Interface</fielddescr>
+ <fieldname>active_interface</fieldname>
+ <description>This defines the active listening interface to which the proxy server will listen for its requests.</description>
+ <type>interfaces_selection</type>
+ </field>
+ <field>
+ <fielddescr>Transparent Proxy</fielddescr>
+ <fieldname>transparent_proxy</fieldname>
+ <description>If transparent mode is enabled; all requests for destination port 80 will be forwarded to the proxy server without any additional configuration necessary.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>URL Filtering Enabled</fielddescr>
+ <fieldname>urlfilter_enable</fieldname>
+ <description>This enables the advanced functionality in conjunction with squidGuard to provide an array of URL filtering options. This squidGuard functionality can be additionally configured from Services -> Advanced Proxy Filtering</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Disable Access Log</fielddescr>
+ <fieldname>accesslog_disabled</fieldname>
+ <description>Disable the access log entirely. By default, Squid keeps a log of all requests it processes in /var/log/access.log. This can grow to be fairly large. If you do not require this logging, check this box to disable.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Log Query Terms</fielddescr>
+ <fieldname>log_query_terms</fieldname>
+ <description>This will log the complete URL rather than the part of the URL containing dynamic queries.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Log User Agents</fielddescr>
+ <fieldname>log_user_agents</fieldname>
+ <description>This will enable the useragent string to be written to a separate log. The results are not shown in the GUI and should only be used for debugging purposes.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Proxy Port</fielddescr>
+ <fieldname>proxy_port</fieldname>
+ <description>This is the port the Proxy Server will listen for client requests on. The default is 3128.</description>
+ <type>input</type>
+ <size>4</size>
+ <combinefieldsend>true</combinefieldsend>
+ </field>
+ <field>
+ <fielddescr>ICP Port</fielddescr>
+ <fieldname>icp_port</fieldname>
+ <description>This is the port the Proxy Server will send and receive ICP queries to and from neighbor caches. The default value is 0, which means this function is disabled.</description>
+ <type>input</type>
+ <size>4</size>
+ </field>
+ <field>
+ <fielddescr>Visible Hostname</fielddescr>
+ <fieldname>visible_hostname</fieldname>
+ <description>This URL is displayed on the Proxy Server error messages.</description>
+ <type>input</type>
+ <size>35</size>
+ </field>
+ <field>
+ <fielddescr>Cache Administrator E-Mail</fielddescr>
+ <fieldname>cache_admin_email</fieldname>
+ <description>This E-Mail address is displayed on the Proxy Server error messages.</description>
+ <type>input</type>
+ <size>35</size>
+ </field>
+ <field>
+ <fielddescr>Error Messages Language</fielddescr>
+ <fieldname>error_language</fieldname>
+ <description>Select the language in which the Proxy Server shall display error messages to users.</description>
+ <type>select</type>
+ <options>
+ <option><name>Bulgarian</name><value>Bulgarian</value></option>
+ <option><name>Catalan</name><value>Catalan</value></option>
+ <option><name>Czech</name><value>Czech</value></option>
+ <option><name>Danish</name><value>Danish</value></option>
+ <option><name>Dutch</name><value>Dutch</value></option>
+ <option><name>English</name><value>English</value></option>
+ <option><name>Estonian</name><value>Estonian</value></option>
+ <option><name>Finnish</name><value>Finnish</value></option>
+ <option><name>French</name><value>French</value></option>
+ <option><name>German</name><value>German</value></option>
+ <option><name>Hebrew</name><value>Hebrew</value></option>
+ <option><name>Hungarian</name><value>Hungarian</value></option>
+ <option><name>Italian</name><value>Italian</value></option>
+ <option><name>Japanese</name><value>Japanese</value></option>
+ <option><name>Korean</name><value>Korean</value></option>
+ <option><name>Lithuanian</name><value>Lithuanian</value></option>
+ <option><name>Polish</name><value>Polish</value></option>
+ <option><name>Portuguese</name><value>Portuguese</value></option>
+ <option><name>Romanian</name><value>Romanian</value></option>
+ <option><name>Russian-1251</name><value>Russian-1251</value></option>
+ <option><name>Russian-koi8-r</name><value>Russian-koi8-r</value></option>
+ <option><name>Serbian</name><value>Serbian</value></option>
+ <option><name>Simplify Chinese</name><value>Simplify Chinese</value></option>
+ <option><name>Slovak</name><value>Slovak</value></option>
+ <option><name>Spanish</name><value>Spanish</value></option>
+ <option><name>Swedish</name><value>Swedish</value></option>
+ <option><name>Traditional Chinese</name><value>Traditional Chinese</value></option>
+ <option><name>Turkish</name><value>Turkish</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Enable cachemgr</fielddescr>
+ <fieldname>cachemgr_enabled</fieldname>
+ <description>Enable Squid's cachemgr.cgi to provide stats. Once enabled you can access this from the pfSense menus. &lt;b&gt;Note:&lt;/b&gt; This page is not secured by pfSense, any user with access to the pfSense admin port can view the stats. The page prompts for a password but it only required for shutting down Squid.</description>
+ <type>checkbox</type>
+ </field>
+
+ </fields>
+ <custom_add_php_command_late>
+ global_write_squid_config();
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ start_service("squid");
+ </custom_add_php_command_late>
+ <custom_php_install_command>
+ custom_php_install_command();
+ write_static_squid_config();
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ start_service("squid");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ custom_php_deinstall_command();
+ stop_service("squid");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/squid-8/squid_traffic.xml b/config/squid-8/squid_traffic.xml
new file mode 100644
index 00000000..d560a7ad
--- /dev/null
+++ b/config/squid-8/squid_traffic.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidtraffic</name>
+ <version>none</version>
+ <title>Proxy server: Traffic management</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local Users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Maximum download size</fielddescr>
+ <fieldname>max_download_size</fieldname>
+ <description>Limit the maximum total download size to the size specified here (in kilobytes). Set to 0 to disable.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Maximum upload size</fielddescr>
+ <fieldname>max_upload_size</fieldname>
+ <description>Limit the maximum total upload size to the size specified here (in kilobytes). Set to 0 to disable.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Overall bandwidth throttling</fielddescr>
+ <fieldname>overall_throttling</fieldname>
+ <description>This value specifies (in kilobytes per second) the bandwidth throttle for downloads. Users will gradually have their download speed increased according to this value. Set to 0 to disable bandwidth throttling.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Per-host throttling</fielddescr>
+ <fieldname>perhost_throttling</fieldname>
+ <description>This value specifies the download throttling per host. Set to 0 to disable this.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Throttle only specific extensions</fielddescr>
+ <fieldname>throttle_specific</fieldname>
+ <description>Leave this checked to be able to choose the extensions that throttling will be applied to. Otherwise, all files will be throttled.</description>
+ <type>checkbox</type>
+ <enablefields>throttle_binaries,throttle_cdimages,throttle_multimedia,throttle_others</enablefields>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Throttle binary files</fielddescr>
+ <fieldname>throttle_binaries</fieldname>
+ <description>Check this to apply bandwidth throttle to binary files. This includes compressed archives and executables.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Throttle CD images</fielddescr>
+ <fieldname>throttle_cdimages</fieldname>
+ <description>Check this to apply bandwidth throttle to CD image files.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Throttle multimedia files</fielddescr>
+ <fieldname>throttle_multimedia</fieldname>
+ <description>Check this to apply bandwidth throttle to multimedia files, such as movies or songs.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Throttle other extensions</fielddescr>
+ <fieldname>throttle_others</fieldname>
+ <description>Comma-separated list of extensions to apply bandwidth throttle to.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Finish transfer if less than x KB remaining</fielddescr>
+ <fieldname>quick_abort_min</fieldname>
+ <description>If the transfer has less than x KB remaining, it will finish the retrieval. Set to 0 to abort the transfer immediately.</description>
+ <type>input</type>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Abort transfer if more than x KB remaining</fielddescr>
+ <fieldname>quick_abort_max</fieldname>
+ <description>If the transfer has more than x KB remaining, it will abort the retrieval. Set to 0 to abort the transfer immediately.</description>
+ <type>input</type>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Finish transfer if more than x % finished</fielddescr>
+ <fieldname>quick_abort_pct</fieldname>
+ <description>If more than x % of the transfer has completed, it will finish the retrieval.</description>
+ <type>input</type>
+ <default_value>0</default_value>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_traffic($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid-8/squid_upstream.xml b/config/squid-8/squid_upstream.xml
new file mode 100644
index 00000000..ad494524
--- /dev/null
+++ b/config/squid-8/squid_upstream.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidupstream</name>
+ <version>none</version>
+ <title>Proxy server: Upstream proxy settings</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local Users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Enable forwarding</fielddescr>
+ <fieldname>proxy_forwarding</fieldname>
+ <description>This option enables the proxy server to forward requests to an upstream server.</description>
+ <type>checkbox</type>
+ <enablefields>proxy_addr,proxy_port,icp_port,username,password</enablefields>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Hostname</fielddescr>
+ <fieldname>proxy_addr</fieldname>
+ <description>Enter here the IP address or host name of the upstream proxy.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>TCP port</fielddescr>
+ <fieldname>proxy_port</fieldname>
+ <description>Enter the port to use to connect to the upstream proxy.</description>
+ <type>input</type>
+ <size>5</size>
+ <default_value>3128</default_value>
+ </field>
+ <field>
+ <fielddescr>ICP port</fielddescr>
+ <fieldname>icp_port</fieldname>
+ <description>Enter the port to connect to the upstream proxy for the ICP protocol. Use port number 7 to disable ICP communication between the proxies.</description>
+ <type>input</type>
+ <size>5</size>
+ <default_value>7</default_value>
+ </field>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>If the upstream proxy requires a username, specify it here.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>If the upstream proxy requires a password, specify it here.</description>
+ <type>password</type>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_upstream($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid-8/squid_users.xml b/config/squid-8/squid_users.xml
new file mode 100644
index 00000000..eef6389f
--- /dev/null
+++ b/config/squid-8/squid_users.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidusers</name>
+ <version>none</version>
+ <title>Proxy server: Local users</title>
+ <include_file>squid.inc</include_file>
+ <delete_string>A proxy server user has been deleted.</delete_string>
+ <addedit_string>A proxy server user has been created/modified.</addedit_string>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local Users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>Enter the username here.</description>
+ <type>input</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the password here.</description>
+ <type>password</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>You may enter a description here for your reference (not parsed).</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_resync_config_command>
+ squid_resync_users();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/tinydns/tinydns.inc b/config/tinydns/tinydns.inc
index b86d7779..5e730156 100644
--- a/config/tinydns/tinydns.inc
+++ b/config/tinydns/tinydns.inc
@@ -89,7 +89,7 @@ name="svscan"
rcvar=`set_rcvar`
command="/usr/local/bin/svscan"
svscan_enable=\${svscan_enable-"YES"}
-svscan_servicedir=\${svscan_servicedir-"/service"}
+svscan_servicedir=\${svscan_servicedir-"{$g['varrun_path']}/service"}
start_cmd="svscan_start"
stop_postcmd="svscan_stop_post"
@@ -99,18 +99,18 @@ load_rc_config \$name
required_dirs="\${svscan_servicedir}"
svscan_start () {
+ global $g;
+
echo "Starting svscan."
/usr/bin/env \
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
/usr/sbin/daemon -f /bin/sh -c "\$command \$svscan_servicedir 2>&1 | /usr/local/bin/readproctitle service errors: ................................................................................................................................................................................................................................................................................................................................................................................................................ &" > /dev/null
- minicron {$refreshinterval} /var/run/ping_hosts.pid "/etc/ping_hosts.sh; cd /etc/tinydns/root && /usr/local/bin/tinydns-data"
+ minicron {$refreshinterval} {$g['varrun_path']}/ping_hosts.pid "/etc/ping_hosts.sh; cd {$g['varetc_path']}/etc/tinydns/root && /usr/local/bin/tinydns-data"
}
svscan_stop_post () {
echo "Stopping svscan."
find -L "\$svscan_servicedir" -mindepth 1 -maxdepth 2 -type d \( \! -path "\$svscan_servicedir/*/*" -or -name 'log' \) -print0 | xargs -0 /usr/local/bin/svc -dx
- PIDTOKILL=`cat /var/run/ping_hosts.pid`
- kill $PIDTOKILL
}
run_rc_command "\$1"
@@ -119,18 +119,48 @@ EOD;
fwrite($fd, $svscan);
fclose($fd);
- conf_mount_ro();
- filter_configure();
+ $filename = "tinydns.sh";
+ $start = "/usr/local/bin/php -q -d auto_prepend_file=config.inc <<ENDPHP
+<?php
+ require_once(\"/usr/local/pkg/tinydns.inc\");
tinydns_custom_php_changeip_command();
+ tinydns_create_zone_file();
+ tinydns_setup_ping_items();
+?>
+ENDPHP\n";
+
+ $stop = "";
+ $interfaces = explode(",", $config['installedpackages']['tinydns']['config'][0]['interface']);
+ foreach ($interfaces as $dnsidx => $dnsif)
+ $stop .= "\t/usr/local/bin/svc -dx {$g['varrun_path']}/service/dnscache{$dnsidx}\n";
+
- exec("/usr/local/etc/rc.d/svscan.sh start");
+ $stop .= <<<ENDSH
+ /usr/local/bin/svc -dx {$g['varrun_path']}/service/tinydns
+ /usr/local/bin/svc -dx {$g['varrun_path']}/service/axfrdns
+ /bin/rm -rf {$g['varrun_path']}/service/tinydns {$g['varetc_path']}/tinydns {$g['varrun_path']}/dnscache* {$g['varetc_path']}/dnscache* {$g['varetc_path']}/axfrdns {$g['varrun_path']}/axfrdns
+ /bin/pkill -F /var/run/ping_hosts.pid
+ENDSH;
+
+ write_rcfile(array(
+ "file" => $filename,
+ "start" => $start,
+ "stop" => $stop
+ )
+ );
+
+ conf_mount_ro();
+ filter_configure();
}
function tinydns_custom_php_deinstall_command() {
global $g, $config;
+
conf_mount_rw();
/* destroy all daemontools items */
+ exec("/usr/local/etc/rc.d/tinydns.sh stop");
+ exec("/usr/local/etc/rc.d/svscan.sh stop");
exec("/usr/bin/killall supervise");
exec("/usr/bin/killall tinydns");
exec("/usr/sbin/pw groupdel Gtinydns");
@@ -143,8 +173,8 @@ function tinydns_custom_php_deinstall_command() {
exec("rm /usr/local/www/*tinydns*");
exec("rm /usr/local/pkg/*tinydns*");
exec("rm /usr/local/pkg/pf/*tinydns*");
- exec("rm -rf /etc/tinydns /service/tinydns");
- exec("rm -rf /etc/dnscache* /service/dnscache*");
+ exec("rm -rf {$g['varetc_path']}/etc/tinydns {$g['varrun_path']}/service/tinydns {$g['varetc_path']}/axfrdns");
+ exec("rm -rf {$g['varetc_path']}/etc/dnscache* {$g['varrun_path']}/service/dnscache*");
filter_configure();
conf_mount_ro();
}
@@ -170,34 +200,34 @@ function tinydns_custom_php_changeip_command() {
$ztipaddress = populate_zt_array();
/* setup daemon tools service area */
- if(!is_dir("/service"))
- exec("/bin/mkdir /service");
+ if(!is_dir("{$g['varrun_path']}/service"))
+ exec("/bin/mkdir -p {$g['varrun_path']}/service");
exec("/usr/sbin/pw useradd Gtinydns");
exec("/usr/sbin/pw useradd Gdnslog");
exec("/usr/sbin/pw useradd Gdnscache");
exec("/usr/sbin/pw useradd Gaxfrdns");
- exec("/bin/rm -r /etc/dnscache*");
- exec("/bin/rm -r /service/dnscache*");
+ exec("/bin/rm -r {$g['varetc_path']}/etc/dnscache*");
+ exec("/bin/rm -r {$g['varrun_path']}/service/dnscache*");
/* TinyDNS Server */
- exec("/usr/local/bin/tinydns-conf Gtinydns Gdnslog /etc/tinydns {$dnsserverip}");
- exec("/bin/ln -s /etc/tinydns /service/");
+ exec("/usr/local/bin/tinydns-conf Gtinydns Gdnslog {$g['varetc_path']}/etc/tinydns {$dnsserverip}");
+ exec("/bin/ln -s {$g['varetc_path']}/etc/tinydns {$g['varrun_path']}/service/");
/* AXFRDNS - Zone transfers */
if(is_array($ztipaddress))
- exec("/usr/local/bin/axfrdns-conf Gaxfrdns Gdnslog /etc/axfrdns /etc/tinydns {$dnsserverip}");
- exec("/bin/ln -s /etc/axfrdns /service/");
+ exec("/usr/local/bin/axfrdns-conf Gaxfrdns Gdnslog {$g['varetc_path']}/etc/axfrdns {$g['varetc_path']}/etc/tinydns {$dnsserverip}");
+ exec("/bin/ln -s {$g['varetc_path']}/etc/axfrdns {$g['varrun_path']}/service/");
- exec("echo {$dnsserverip} > /etc/tinydns/env/IP");
+ exec("echo {$dnsserverip} > {$g['varetc_path']}/etc/tinydns/env/IP");
exec("/usr/bin/killall -9 tinydns");
if($config['installedpackages']['tinydns']['config'][0]['enableforwarding']) {
$interfaces = explode(",", $config['installedpackages']['tinydns']['config'][0]['interface']);
- exec("/bin/cp /var/etc/resolv.conf /var/etc/resolv.conf.original");
- exec("/bin/cp /var/etc/resolv.conf /var/etc/resolv.conf.dnscache");
- exec("echo domain {$config['system']['domain']} > /var/etc/resolv.conf");
- exec("rm -rf /etc/dnscache* /service/dnscache*");
+ exec("/bin/cp {$g['varetc_path']}/resolv.conf {$g['varetc_path']}/resolv.conf.original");
+ exec("/bin/cp {$g['varetc_path']}/resolv.conf {$g['varetc_path']}/resolv.conf.dnscache");
+ exec("echo domain {$config['system']['domain']} > {$g['varetc_path']}/resolv.conf");
+ exec("rm -rf {$g['varetc_path']}/etc/dnscache* {$g['varrun_path']}/service/dnscache*");
foreach ($interfaces as $dnsidx => $dnsif) {
$dnscacheif = convert_friendly_interface_to_real_interface_name($dnsif);
$dnscacheip = find_interface_ip($dnscacheif);
@@ -207,26 +237,26 @@ function tinydns_custom_php_changeip_command() {
$ipmask = $config['interfaces'][$dnsif]['subnet'];
$arr = tinydns_get_ip_subnet_arpa($dnscacheip, $ipmask);
$dnsuserip = $arr[0];
- exec("mkdir /etc/dnscache{$dnsidx}");
- exec("/usr/local/bin/dnscache-conf Gdnscache Gdnslog /etc/dnscache{$dnsidx} {$dnscacheip}");
- exec("/bin/ln -s /etc/dnscache{$dnsidx} /service/");
- if (!is_dir("/etc/dnscache{$dnsidx}/env/IP"))
- exec("mkdir -p /etc/dnscache{$dnsidx}/env");
- exec("echo {$dnscacheip} > /etc/dnscache{$dnsidx}/env/IP");
+ exec("/bin/mkdir -p {$g['varetc_path']}/etc/dnscache{$dnsidx}");
+ exec("/usr/local/bin/dnscache-conf Gdnscache Gdnslog {$g['varetc_path']}/etc/dnscache{$dnsidx} {$dnscacheip}");
+ exec("/bin/ln -s {$g['varetc_path']}/etc/dnscache{$dnsidx} {$g['varrun_path']}/service/");
+ if (!is_dir("{$g['varetc_path']}/etc/dnscache{$dnsidx}/env/IP"))
+ exec("/bin/mkdir -p {$g['varetc_path']}/etc/dnscache{$dnsidx}/env");
+ exec("echo {$dnscacheip} > {$g['varetc_path']}/etc/dnscache{$dnsidx}/env/IP");
tinydns_dnscache_forwarding_servers($dnsidx);
- if (!is_dir("/etc/dnscache{$dnsidx}/root/ip"))
- exec("mkdir -p /etc/dnscache{$dnsidx}/root/ip");
- exec("touch /etc/dnscache{$dnsidx}/root/ip/{$dnsuserip}");
+ if (!is_dir("{$g['varetc_path']}/etc/dnscache{$dnsidx}/root/ip"))
+ exec("/bin/mkdir -p {$g['varetc_path']}/etc/dnscache{$dnsidx}/root/ip");
+ exec("/usr/bin/touch {$g['varetc_path']}/etc/dnscache{$dnsidx}/root/ip/{$dnsuserip}");
tinydns_create_soa_domain_list($dnsserverip, $dnsidx);
- exec("echo nameserver {$dnscacheip} >> /var/etc/resolv.conf");
+ exec("echo nameserver {$dnscacheip} >> {$g['varetc_path']}/resolv.conf");
}
exec("/usr/bin/killall -9 dnscache");
} else {
if(file_exists("/var/etc/resolv.conf.original"))
- exec("/bin/cp /var/etc/resolv.conf.original /var/etc/resolv.conf");
+ exec("/bin/cp {$g['varetc_path']}/resolv.conf.original {$g['varetc_path']}/resolv.conf");
$interfaces = explode(",", $$config['installedpackages']['tinydns']['config'][0]['interface']);
foreach ($interfaces as $dnsidx => $dnsif) {
- if(is_dir("/etc/dnscache{$dnsidx}"))
+ if(is_dir("{$g['varetc_path']}/etc/dnscache{$dnsidx}"))
dnscache_use_root_servers($dnsidx);
}
exec("/usr/bin/killall -9 dnscache");
@@ -252,13 +282,14 @@ function populate_zt_array() {
function tinydns_setup_axfrdns() {
global $g, $config;
+
/* Populate Zone Transfer array */
$ztipaddress = populate_zt_array();
if(!is_array($ztipaddress))
return;
- $fd = fopen("/etc/axfrdns/tcp","w");
+ $fd = fopen("{$g['varetc_path']}/etc/axfrdns/tcp","w");
if(!$fd) {
- log_error("Could not open /etc/axfrdns/tcp for writing");
+ log_error("Could not open {$g['varetc_path']}/etc/axfrdns/tcp for writing");
return;
}
foreach($ztipaddress as $zt) {
@@ -270,7 +301,7 @@ function tinydns_setup_axfrdns() {
}
fclose($fd);
// Recompile database
- exec("cd /service/axfrdns && /usr/local/bin/tinydns-data");
+ exec("cd {$g['varrun_path']}/service/axfrdns && /usr/local/bin/tinydns-data");
}
function tinydns_get_record_status($record, $pingthreshold = "", $wanpingthreshold = "") {
@@ -319,16 +350,17 @@ function tinydns_get_backup_record($record) {
function tinydns_setup_ping_items() {
global $g, $config;
+
if(!$config['installedpackages']['tinydnsdomains'])
return;
$wanif = get_real_wan_interface();
$ip = find_interface_ip($wanif);
- conf_mount_rw();
+
$processed = array();
/* XXX: make this work with other packages */
- $fd = fopen("/var/db/pkgpinghosts", "w");
+ $fd = fopen("{$g['vardb_path']}/pkgpinghosts", "w");
if(!$fd) {
- log_error("Could not open /var/db/pkgpinghosts for writing.");
+ log_error("Could not open {$g['vardb_path']}/pkgpinghosts for writing.");
return;
}
config_lock();
@@ -375,7 +407,6 @@ function tinydns_setup_ping_items() {
}
fclose($fd);
config_unlock();
- conf_mount_ro();
}
function tinydns_create_zone_file() {
@@ -384,13 +415,13 @@ function tinydns_create_zone_file() {
if(file_exists("/tmp/config.cache"))
unlink("/tmp/config.cache");
config_lock();
- if(file_exists("/service/tinydns/root/data"))
- exec("rm -f /service/tinydns/root/data");
- if(!is_dir("/service/tinydns/root"))
+ if(file_exists("{$g['varrun_path']}/service/tinydns/root/data"))
+ exec("rm -f {$g['varrun_path']}/service/tinydns/root/data");
+ if(!is_dir("{$g['varrun_path']}/service/tinydns/root"))
return;
- $fd = fopen("/service/tinydns/root/data", "w");
+ $fd = fopen("{$g['varrun_path']}/service/tinydns/root/data", "w");
if(!$fd) {
- log_error("Could not open /service/tinydns/root/data for writing.");
+ log_error("Could not open {$g['varrun_path']}/service/tinydns/root/data for writing.");
return;
}
@@ -519,7 +550,7 @@ function tinydns_create_zone_file() {
}
fclose($fd);
/* tell tinydns to reload zone file */
- exec("cd /service/tinydns/root && /usr/local/bin/tinydns-data");
+ exec("cd {$g['varrun_path']}/service/tinydns/root && /usr/local/bin/tinydns-data");
config_unlock();
conf_mount_ro();
}
@@ -892,16 +923,16 @@ function tinydns_get_dns_record_type($tinydnsrecord) {
/* This function will be replaced by an auto detect DNS cache servers routine */
/* At the moment there is no tagging of DNSroute to a WAN port. It needs to be added */
function tinydns_dnscache_forwarding_servers($index) {
- global $config;
+ global $g, $config;
- exec("echo 1 > /etc/dnscache{$index}/env/FORWARDONLY");
- if(is_dir("/etc/dnscache{$index}/root/servers/"))
- exec("rm -R /etc/dnscache/root/servers/");
- exec("mkdir -p /etc/dnscache{$index}/root/servers/");
+ exec("echo 1 > {$g['varetc_path']}/etc/dnscache{$index}/env/FORWARDONLY");
+ if(is_dir("{$g['varetc_path']}/etc/dnscache{$index}/root/servers/"))
+ exec("rm -R {$g['varetc_path']}/etc/dnscache/root/servers/");
+ exec("/bin/mkdir -p {$g['varetc_path']}/etc/dnscache{$index}/root/servers/");
if (intval($config['version']) >= 6)
- exec("/bin/cat /var/etc/nameserver_* > /etc/dnscache{$index}/root/servers/@");
+ exec("/bin/cat {$g['varetc_path']}/nameserver_* > {$g['varetc_path']}/etc/dnscache{$index}/root/servers/@");
else {
- $fr = fopen("/var/etc/resolv.conf.dnscache", "r");
+ $fr = fopen("{$g['varetc_path']}/resolv.conf.dnscache", "r");
if (! $fr) {
printf("Error: cannot open resolv.conf.dnscache in tinydns_register_forwarding_servers().\n");
return 1;
@@ -924,9 +955,9 @@ function tinydns_dnscache_forwarding_servers($index) {
}
}
fclose($fr);
- $fr = fopen("/etc/dnscache{$index}/root/servers/@", "w");
+ $fr = fopen("{$g['varetc_path']}/etc/dnscache{$index}/root/servers/@", "w");
if (! $fr) {
- printf("Error: cannot write to /etc/dnscache{$index}/root/servers/@ in tinydns_dnscache_forwarding_servers().\n");
+ printf("Error: cannot write to {$g['varetc_path']}/etc/dnscache{$index}/root/servers/@ in tinydns_dnscache_forwarding_servers().\n");
return 1;
}
if($iprecords)
@@ -935,10 +966,11 @@ function tinydns_dnscache_forwarding_servers($index) {
}
}
-/* This routine adds filenames to /etc/dnscache/root/servers/ with the contents pointing to the tinyDNS server */
+/* This routine adds filenames to {$g['varetc_path']}/etc/dnscache/root/servers/ with the contents pointing to the tinyDNS server */
function tinydns_create_soa_domain_list($dnsserverip, $index = 0) {
- if(file_exists("/service/tinydns/root/data"))
- $tinydns_data = file_get_contents("/service/tinydns/root/data");
+ global $g;
+ if(file_exists("{$g['varrun_path']}/service/tinydns/root/data"))
+ $tinydns_data = file_get_contents("{$g['varrun_path']}/service/tinydns/root/data");
else
$tinydns_data = "";
$datalen = strlen($tinydns_data);
@@ -953,9 +985,9 @@ function tinydns_create_soa_domain_list($dnsserverip, $index = 0) {
if($fqdn) {
$rtypes = tinydns_get_dns_record_type($dnsrecord);
if($rtypes[0] == "SOA") {
- $fr = fopen("/etc/dnscache{$index}/root/servers/{$fqdn}", "w");
+ $fr = fopen("{$g['varetc_path']}/etc/dnscache{$index}/root/servers/{$fqdn}", "w");
if (! $fr) {
- printf("Error: cannot open /etc/dnscache{$index}/root/servers/{$fqdn} in tinydns_create_soa_domain_list().\n");
+ printf("Error: cannot open {$g['varetc_path']}/etc/dnscache{$index}/root/servers/{$fqdn} in tinydns_create_soa_domain_list().\n");
return 1;
}
if($fqdn)fwrite($fr, $dnsserverip);
@@ -968,7 +1000,9 @@ function tinydns_create_soa_domain_list($dnsserverip, $index = 0) {
/* This function is not called */
/* At the moment there is no tagging of DNSroute to a WAN port. It needs to be added */
function tinydns_register_forwarding_servers() {
- $fr = fopen("/var/etc/resolv.conf", "r");
+ global $g;
+
+ $fr = fopen("{$g['varetc_path']}/resolv.conf", "r");
if (! $fr) {
printf("Error: cannot open resolv.conf in tinydns_register_forwarding_servers().\n");
return 1;
@@ -1033,6 +1067,8 @@ EOD;
}
function dnscache_use_root_servers($index = 0) {
+ global $g;
+
$rootservers =<<<EOD
198.41.0.4
192.228.79.201
@@ -1050,13 +1086,13 @@ function dnscache_use_root_servers($index = 0) {
EOD;
- exec("echo 0 > /etc/dnscache{$index}/env/FORWARDONLY");
- if(is_dir("/etc/dnscache{$index}/root/servers/"))
- exec("rm -R /etc/dnscache{$index}/root/servers/");
- exec("mkdir -p /etc/dnscache{$index}/root/servers/");
- $fr = fopen("/etc/dnscache{$index}/root/servers/@", "w");
+ exec("echo 0 > {$g['varetc_path']}/etc/dnscache{$index}/env/FORWARDONLY");
+ if(is_dir("{$g['varetc_path']}/etc/dnscache{$index}/root/servers/"))
+ exec("/bin/rm -R {$g['varetc_path']}/etc/dnscache{$index}/root/servers/");
+ exec("/bin/mkdir -p {$g['varetc_path']}/etc/dnscache{$index}/root/servers/");
+ $fr = fopen("{$g['varetc_path']}/etc/dnscache{$index}/root/servers/@", "w");
if (! $fr) {
- printf("Error: cannot write to /etc/dnscache{$index}/root/servers/@ in dnscache_use_root_servers().\n");
+ printf("Error: cannot write to {$g['varetc_path']}/etc/dnscache{$index}/root/servers/@ in dnscache_use_root_servers().\n");
return 1;
}
fwrite($fr, $rootservers);
diff --git a/config/tinydns/tinydns.xml b/config/tinydns/tinydns.xml
index a6720179..1eb5b1eb 100644
--- a/config/tinydns/tinydns.xml
+++ b/config/tinydns/tinydns.xml
@@ -57,8 +57,14 @@
<url>/tinydns_status.php</url>
</menu>
<service>
- <name>DNS Server</name>
+ <name>svscan</name>
<rcfile>svscan.sh</rcfile>
+ <executable>svscan</executable>
+ <description>Daemontools service directory watcher</description>
+ </service>
+ <service>
+ <name>DNS Server</name>
+ <rcfile>tinydns.sh</rcfile>
<executable>tinydns</executable>
<description>TinyDNS DNS Server</description>
</service>