moved files into cgi-bin and etc/asterisk directories
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 16 Jan 2010 02:58:20 +0000 (02:58 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 16 Jan 2010 02:58:20 +0000 (02:58 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@118 01035d8c-6547-0410-b346-abe4f91aad63

73 files changed:
easy-asterisk-gui/about.sh [deleted file]
easy-asterisk-gui/admin.sh [deleted file]
easy-asterisk-gui/anphone.png [deleted file]
easy-asterisk-gui/at-530.html [deleted file]
easy-asterisk-gui/banner.html [deleted file]
easy-asterisk-gui/cgi-bin/about.sh [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/admin.sh [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/anphone.png [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/at-530.html [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/banner.html [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/check_loggedin.sh [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/cross.png [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/faq.html [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/faq.sh [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/index.html [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/ipphone.png [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/ipphones.js [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/ipphones.pl [new file with mode: 0755]
easy-asterisk-gui/cgi-bin/ipphones.sh [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/login.sh [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/logout.sh [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/menu.html [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/network.js [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/network.sh [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/phoneline.jpg [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/phones.js [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/phones.pl [new file with mode: 0755]
easy-asterisk-gui/cgi-bin/phones.sh [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/prototype.js [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/set_network.sh [new file with mode: 0755]
easy-asterisk-gui/cgi-bin/set_ring.sh [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/set_voiplines.sh [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/tick.png [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/tooltip.css [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/tooltip.js [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/tooltips.html [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/voipline.jpg [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/voiplines.js [new file with mode: 0644]
easy-asterisk-gui/cgi-bin/voiplines.pl [new file with mode: 0755]
easy-asterisk-gui/cgi-bin/voiplines.sh [new file with mode: 0644]
easy-asterisk-gui/check_loggedin.sh [deleted file]
easy-asterisk-gui/cross.png [deleted file]
easy-asterisk-gui/etc/asterisk/sip.conf [new file with mode: 0644]
easy-asterisk-gui/faq.html [deleted file]
easy-asterisk-gui/faq.sh [deleted file]
easy-asterisk-gui/index.html [deleted file]
easy-asterisk-gui/ipphone.png [deleted file]
easy-asterisk-gui/ipphones.js [deleted file]
easy-asterisk-gui/ipphones.pl [deleted file]
easy-asterisk-gui/ipphones.sh [deleted file]
easy-asterisk-gui/login.sh [deleted file]
easy-asterisk-gui/logout.sh [deleted file]
easy-asterisk-gui/menu.html [deleted file]
easy-asterisk-gui/network.js [deleted file]
easy-asterisk-gui/network.sh [deleted file]
easy-asterisk-gui/phoneline.jpg [deleted file]
easy-asterisk-gui/phones.js [deleted file]
easy-asterisk-gui/phones.pl [deleted file]
easy-asterisk-gui/phones.sh [deleted file]
easy-asterisk-gui/prototype.js [deleted file]
easy-asterisk-gui/restart.sh [deleted file]
easy-asterisk-gui/set_network.sh [deleted file]
easy-asterisk-gui/set_ring.sh [deleted file]
easy-asterisk-gui/set_voiplines.sh [deleted file]
easy-asterisk-gui/sip.conf [deleted file]
easy-asterisk-gui/tick.png [deleted file]
easy-asterisk-gui/tooltip.css [deleted file]
easy-asterisk-gui/tooltip.js [deleted file]
easy-asterisk-gui/tooltips.html [deleted file]
easy-asterisk-gui/voipline.jpg [deleted file]
easy-asterisk-gui/voiplines.js [deleted file]
easy-asterisk-gui/voiplines.pl [deleted file]
easy-asterisk-gui/voiplines.sh [deleted file]

diff --git a/easy-asterisk-gui/about.sh b/easy-asterisk-gui/about.sh
deleted file mode 100644 (file)
index 50c92d2..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-#!/bin/sh
-# about.sh
-# David Rowe 7 Jan 2010
-# About screen for Easy Asterisk GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
-    echo "<html>"
-    echo "<head>"
-    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
-    echo "</head>"
-    echo "</html>"
-    exit
-fi
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-
-cat << EOF
-<html>
-<title>Easy Asterisk - About</title>
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800>'
-cat banner.html
-echo "    <tr>"
-cat menu.html    
-cat <<EOF
-
-    <td valign="top">
-
-    <table align="right" width=600>
-      <tr><td align="left" valign="top"><h2>About</h2></td></tr>
-EOF
-echo '      <tr><td><strong>Easy Asterisk</strong> $Revision$</td></tr> ' | sed -n 's/\$//pg'
-echo '      <tr><td>&nbsp;</td></tr>'
-echo '      <tr><td>Brought to you by the <a href="http://rowetel.com/ucasterisk/index.html">Free Telephony Project</a></td></tr>'
-echo '      <tr><td><a href="http://rowetel.com/ucasterisk/ip04.html"><img src="http://rowetel.com/images/ip04/ip04_case.jpg" border="0" /></a></td></tr>'
-
-more=`echo "$QUERY_STRING" | grep -oe "more=[^&?]*" | sed -n "s/more=//p"`
-if  [ $more -eq 1 ]; then
-  echo 
-else
-    echo "      <tr><td>&nbsp;</td></tr>"
-    echo '      <tr><td><a href="about.sh?more=1">More</a></td></tr>';
-cat <<EOF
-    </table>
-    </td>
-    </tr>
-</table>
-</body>
-</html>
-EOF
-exit
-fi
-
-echo "      <tr><td>&nbsp;</td></tr>"
-echo "      <tr><td><h3>cat /proc/version</h3></td></tr>"
-echo "      <tr><td>"
-cat /proc/version
-echo "      </td></tr>"
-
-which ipkg >> /dev/null
-if [ $? -eq 0 ]; then
-    echo "      <tr><td>&nbsp;</td></tr>"
-    echo "      <tr><td><h3>ipkg list_installed</h3></td></tr>"
-    echo "      <tr><td>"
-    ipkg list_installed | tr '\n' '#' | sed -n 's/\#/<br>/pg'
-    echo "      </td></tr>"
-fi
-
-echo "      <tr><td>&nbsp;</td></tr>"
-echo "      <tr><td><h3>cat /proc/loadavg</h3></td></tr>"
-echo "      <tr><td>"
-cat /proc/loadavg
-echo "      </td></tr>"
-
-echo "      <tr><td>&nbsp;</td></tr>"
-echo "      <tr><td><h3>uptime</h3></td></tr>"
-echo "      <tr><td>"
-uptime
-echo "      </td></tr>"
-
-echo "      <tr><td>&nbsp;</td></tr>"
-echo "      <tr><td><h3>cat /proc/meminfo</h3></td></tr>"
-echo "      <tr><td>"
-cat /proc/meminfo | tr '\n' '#' | sed -n 's/\#/<br>/pg'
-echo "      </td></tr>"
-
-echo "      <tr><td>&nbsp;</td></tr>"
-echo "      <tr><td><h3>cat /proc/cmdline</h3></td></tr>"
-echo "      <tr><td>"
-cat /proc/cmdline
-echo "      </td></tr>"
-
-echo "      <tr><td>&nbsp;</td></tr>"
-echo "      <tr><td><h3>cat /proc/cpuinfo</h3></td></tr>"
-echo "      <tr><td>"
-cat /proc/cpuinfo
-echo "      </td></tr>"
-
-if [ -f /proc/mtd ]; then
-    echo "      <tr><td>&nbsp;</td></tr>"
-    echo "      <tr><td><h3>cat /proc/mtd</h3></td></tr>"
-    echo "      <tr><td>"
-    cat /proc/mtd | tr '\n' '#' | sed -n 's/\#/<br>/pg'
-    echo "      </td></tr>"
-fi
-
-if [ -f /proc/yaffs ]; then
-    echo "      <tr><td>&nbsp;</td></tr>"
-    echo "      <tr><td><h3>cat /proc/yaffs</h3></td></tr>"
-    echo "      <tr><td>"
-    cat /proc/yaffs | tr '\n' '#' | sed -n 's/\#/<br>/pg'
-    echo "      </td></tr>"
-fi
-
-echo "      <tr><td>&nbsp;</td></tr>"
-echo '      <tr><td><a href="about.sh">Less</a></td></tr>';
-
-cat <<EOF
-    </table>
-
-    </td>
-
-    </tr>
-
-</table>
-</body>
-</html>
-EOF
-
diff --git a/easy-asterisk-gui/admin.sh b/easy-asterisk-gui/admin.sh
deleted file mode 100644 (file)
index f5c2fdd..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/bin/sh
-# admin.sh
-# David Rowe 7 Jan 2010
-# Admin screen for Easy Asterisk GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
-    echo "<html>"
-    echo "<head>"
-    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
-    echo "</head>"
-    echo "</html>"
-    exit
-fi
-
-# set password CGI
-
-echo "$QUERY_STRING" | grep -oe "pass=" > /dev/null
-if [ $? -eq 0 ]; then
-    pass=`echo "$QUERY_STRING" | grep -oe "pass=[^&?]*" | sed -n "s/pass=//p"`
-    passwd_cmdline $pass
-fi
-
-# restart CGI
-
-echo "$QUERY_STRING" | grep -oe "restart=1" > /dev/null
-if [ $? -eq 0 ]; then
-
-# kill cookie to log out.  This ensures hitting refresh wont run
-# the restart process again
-
-cat <<EOF
-Content-type: text/html
-Set-Cookie: loggedin=1; expires=Thursday, 01-Jan-98 12:00:00 GMT
-
-<head>
-<title>Easy Asterisk - Restart</title>
-</head>
-<body>
-<h2>Restarting...come back in 1 minute</h2>
-</body>
-EOF
-reboot
-fi
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-
-cat << EOF
-<html>
-<title>Easy Asterisk - Admin</title>
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800>'
-cat banner.html
-echo "    <tr>"
-cat menu.html    
-cat <<EOF
-
-    <td valign="top">
-
-    <table align="right" width=600>
-      <tr><td>&nbsp</td></tr>
-      <form action="admin.sh" method="get">
-      <tr><td align="left" valign="top"><h2>Admin</h2></td></tr>
-
-      <tr><td>&nbsp</td></tr>
-      <tr><td colspan="2"><h3>Change Phone System Password</h2></td></tr>
-      <tr><td>New Password:</td><td><input type="password" name="pass" ></td></tr>
-      <tr><td>&nbsp</td></tr>
-      <tr><td></td><td>Default password is uClinux</td>
-      <tr><td><input type="submit" value="Set Password"></td></tr>
-      </form>
-
-      <tr><td>&nbsp</td></tr>
-      <tr><td  colspan="2"><h3>Restart Phone System</h2></td></tr>
-      <form action="admin.sh" method="get">
-      <tr><td><input type="hidden" name="restart" value="1"></td></tr>
-      <tr><td onMouseOver="popUp(event,'admin_restart')" onmouseout="popUp(event,'admin_restart')">
-          <input type="submit" value="Restart"></td></tr>
-      </form>
-
-      <tr><td>&nbsp</td></tr>
-      <tr><td colspan="2"><h3>Reset Phone System Defaults</h2></td></tr>
-      <form action="admin.sh?defaults=1" method="get">
-      <tr><td><input type="submit" value="Reset"></td></tr>
-      </form>
-
-      <tr><td>&nbsp</td></tr>
-      <tr><td colspan="2"><h3>Upgrade Software</h2></td></tr>
-      <form action="admin.sh?upgrade=1" method="get">
-      <tr><td>Software URL:</td><td><input type="text" name="upgrade" ></td></tr>
-      <tr><td><input type="submit" value="Upgrade"></td></tr>
-      </form>
-
-    </table>
-    </form>
-
-    </td>
-
-    </tr>
-
-</table>
-</body>
-</html>
-EOF
-
diff --git a/easy-asterisk-gui/anphone.png b/easy-asterisk-gui/anphone.png
deleted file mode 100644 (file)
index 9783372..0000000
Binary files a/easy-asterisk-gui/anphone.png and /dev/null differ
diff --git a/easy-asterisk-gui/at-530.html b/easy-asterisk-gui/at-530.html
deleted file mode 100644 (file)
index 686fb70..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-<ol>
-<li>Connect the WAN port of the AT-530 to your network, it will boot and obtain an IP via DHCP.  
-<li>Find the <strong>IP</strong> of the phone by pressing the <strong>Sysinfo</strong> button a few times.  
-<li>Open another browser window.  Go to the phones <strong>IP</strong>, for example <strong>http://192.168.1.160</strong>
-<li>Login to the phone using the username/password <strong>admin/admin</strong>.  
-<li>Optional: set a static IP using the WAN menu (I like static IPs for SIP phones).  
-<li>Go to the phone <strong>SIP Config</strong> menu.
-<li>Set <strong>Register Server Address</strong> to your Phone System IP Address.
-<li>Set <strong>Register Username</strong> to the phone number (e.g. 6011).
-<li>Also set </strong>Register Password</strong> to the phone number (e.g. 6011) and
-the </strong>Phone Number</strong> to the phone number (e.g. 6011).
-<li>Check the <strong>Enable Register</strong> box.
-<li>Then click on <strong>Apply</strong>. 
-<li>On your browser refresh this page to see if the phone is connected to your phone system.
-</ol>
diff --git a/easy-asterisk-gui/banner.html b/easy-asterisk-gui/banner.html
deleted file mode 100644 (file)
index 0288909..0000000
+++ /dev/null
@@ -1 +0,0 @@
-    <tr><td colspan="2"><h2>&nbsp;</h2></td></tr>
diff --git a/easy-asterisk-gui/cgi-bin/about.sh b/easy-asterisk-gui/cgi-bin/about.sh
new file mode 100644 (file)
index 0000000..50c92d2
--- /dev/null
@@ -0,0 +1,141 @@
+#!/bin/sh
+# about.sh
+# David Rowe 7 Jan 2010
+# About screen for Easy Asterisk GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+    echo "<html>"
+    echo "<head>"
+    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
+    echo "</head>"
+    echo "</html>"
+    exit
+fi
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+
+cat << EOF
+<html>
+<title>Easy Asterisk - About</title>
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800>'
+cat banner.html
+echo "    <tr>"
+cat menu.html    
+cat <<EOF
+
+    <td valign="top">
+
+    <table align="right" width=600>
+      <tr><td align="left" valign="top"><h2>About</h2></td></tr>
+EOF
+echo '      <tr><td><strong>Easy Asterisk</strong> $Revision$</td></tr> ' | sed -n 's/\$//pg'
+echo '      <tr><td>&nbsp;</td></tr>'
+echo '      <tr><td>Brought to you by the <a href="http://rowetel.com/ucasterisk/index.html">Free Telephony Project</a></td></tr>'
+echo '      <tr><td><a href="http://rowetel.com/ucasterisk/ip04.html"><img src="http://rowetel.com/images/ip04/ip04_case.jpg" border="0" /></a></td></tr>'
+
+more=`echo "$QUERY_STRING" | grep -oe "more=[^&?]*" | sed -n "s/more=//p"`
+if  [ $more -eq 1 ]; then
+  echo 
+else
+    echo "      <tr><td>&nbsp;</td></tr>"
+    echo '      <tr><td><a href="about.sh?more=1">More</a></td></tr>';
+cat <<EOF
+    </table>
+    </td>
+    </tr>
+</table>
+</body>
+</html>
+EOF
+exit
+fi
+
+echo "      <tr><td>&nbsp;</td></tr>"
+echo "      <tr><td><h3>cat /proc/version</h3></td></tr>"
+echo "      <tr><td>"
+cat /proc/version
+echo "      </td></tr>"
+
+which ipkg >> /dev/null
+if [ $? -eq 0 ]; then
+    echo "      <tr><td>&nbsp;</td></tr>"
+    echo "      <tr><td><h3>ipkg list_installed</h3></td></tr>"
+    echo "      <tr><td>"
+    ipkg list_installed | tr '\n' '#' | sed -n 's/\#/<br>/pg'
+    echo "      </td></tr>"
+fi
+
+echo "      <tr><td>&nbsp;</td></tr>"
+echo "      <tr><td><h3>cat /proc/loadavg</h3></td></tr>"
+echo "      <tr><td>"
+cat /proc/loadavg
+echo "      </td></tr>"
+
+echo "      <tr><td>&nbsp;</td></tr>"
+echo "      <tr><td><h3>uptime</h3></td></tr>"
+echo "      <tr><td>"
+uptime
+echo "      </td></tr>"
+
+echo "      <tr><td>&nbsp;</td></tr>"
+echo "      <tr><td><h3>cat /proc/meminfo</h3></td></tr>"
+echo "      <tr><td>"
+cat /proc/meminfo | tr '\n' '#' | sed -n 's/\#/<br>/pg'
+echo "      </td></tr>"
+
+echo "      <tr><td>&nbsp;</td></tr>"
+echo "      <tr><td><h3>cat /proc/cmdline</h3></td></tr>"
+echo "      <tr><td>"
+cat /proc/cmdline
+echo "      </td></tr>"
+
+echo "      <tr><td>&nbsp;</td></tr>"
+echo "      <tr><td><h3>cat /proc/cpuinfo</h3></td></tr>"
+echo "      <tr><td>"
+cat /proc/cpuinfo
+echo "      </td></tr>"
+
+if [ -f /proc/mtd ]; then
+    echo "      <tr><td>&nbsp;</td></tr>"
+    echo "      <tr><td><h3>cat /proc/mtd</h3></td></tr>"
+    echo "      <tr><td>"
+    cat /proc/mtd | tr '\n' '#' | sed -n 's/\#/<br>/pg'
+    echo "      </td></tr>"
+fi
+
+if [ -f /proc/yaffs ]; then
+    echo "      <tr><td>&nbsp;</td></tr>"
+    echo "      <tr><td><h3>cat /proc/yaffs</h3></td></tr>"
+    echo "      <tr><td>"
+    cat /proc/yaffs | tr '\n' '#' | sed -n 's/\#/<br>/pg'
+    echo "      </td></tr>"
+fi
+
+echo "      <tr><td>&nbsp;</td></tr>"
+echo '      <tr><td><a href="about.sh">Less</a></td></tr>';
+
+cat <<EOF
+    </table>
+
+    </td>
+
+    </tr>
+
+</table>
+</body>
+</html>
+EOF
+
diff --git a/easy-asterisk-gui/cgi-bin/admin.sh b/easy-asterisk-gui/cgi-bin/admin.sh
new file mode 100644 (file)
index 0000000..f5c2fdd
--- /dev/null
@@ -0,0 +1,116 @@
+#!/bin/sh
+# admin.sh
+# David Rowe 7 Jan 2010
+# Admin screen for Easy Asterisk GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+    echo "<html>"
+    echo "<head>"
+    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
+    echo "</head>"
+    echo "</html>"
+    exit
+fi
+
+# set password CGI
+
+echo "$QUERY_STRING" | grep -oe "pass=" > /dev/null
+if [ $? -eq 0 ]; then
+    pass=`echo "$QUERY_STRING" | grep -oe "pass=[^&?]*" | sed -n "s/pass=//p"`
+    passwd_cmdline $pass
+fi
+
+# restart CGI
+
+echo "$QUERY_STRING" | grep -oe "restart=1" > /dev/null
+if [ $? -eq 0 ]; then
+
+# kill cookie to log out.  This ensures hitting refresh wont run
+# the restart process again
+
+cat <<EOF
+Content-type: text/html
+Set-Cookie: loggedin=1; expires=Thursday, 01-Jan-98 12:00:00 GMT
+
+<head>
+<title>Easy Asterisk - Restart</title>
+</head>
+<body>
+<h2>Restarting...come back in 1 minute</h2>
+</body>
+EOF
+reboot
+fi
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+
+cat << EOF
+<html>
+<title>Easy Asterisk - Admin</title>
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800>'
+cat banner.html
+echo "    <tr>"
+cat menu.html    
+cat <<EOF
+
+    <td valign="top">
+
+    <table align="right" width=600>
+      <tr><td>&nbsp</td></tr>
+      <form action="admin.sh" method="get">
+      <tr><td align="left" valign="top"><h2>Admin</h2></td></tr>
+
+      <tr><td>&nbsp</td></tr>
+      <tr><td colspan="2"><h3>Change Phone System Password</h2></td></tr>
+      <tr><td>New Password:</td><td><input type="password" name="pass" ></td></tr>
+      <tr><td>&nbsp</td></tr>
+      <tr><td></td><td>Default password is uClinux</td>
+      <tr><td><input type="submit" value="Set Password"></td></tr>
+      </form>
+
+      <tr><td>&nbsp</td></tr>
+      <tr><td  colspan="2"><h3>Restart Phone System</h2></td></tr>
+      <form action="admin.sh" method="get">
+      <tr><td><input type="hidden" name="restart" value="1"></td></tr>
+      <tr><td onMouseOver="popUp(event,'admin_restart')" onmouseout="popUp(event,'admin_restart')">
+          <input type="submit" value="Restart"></td></tr>
+      </form>
+
+      <tr><td>&nbsp</td></tr>
+      <tr><td colspan="2"><h3>Reset Phone System Defaults</h2></td></tr>
+      <form action="admin.sh?defaults=1" method="get">
+      <tr><td><input type="submit" value="Reset"></td></tr>
+      </form>
+
+      <tr><td>&nbsp</td></tr>
+      <tr><td colspan="2"><h3>Upgrade Software</h2></td></tr>
+      <form action="admin.sh?upgrade=1" method="get">
+      <tr><td>Software URL:</td><td><input type="text" name="upgrade" ></td></tr>
+      <tr><td><input type="submit" value="Upgrade"></td></tr>
+      </form>
+
+    </table>
+    </form>
+
+    </td>
+
+    </tr>
+
+</table>
+</body>
+</html>
+EOF
+
diff --git a/easy-asterisk-gui/cgi-bin/anphone.png b/easy-asterisk-gui/cgi-bin/anphone.png
new file mode 100644 (file)
index 0000000..9783372
Binary files /dev/null and b/easy-asterisk-gui/cgi-bin/anphone.png differ
diff --git a/easy-asterisk-gui/cgi-bin/at-530.html b/easy-asterisk-gui/cgi-bin/at-530.html
new file mode 100644 (file)
index 0000000..686fb70
--- /dev/null
@@ -0,0 +1,15 @@
+<ol>
+<li>Connect the WAN port of the AT-530 to your network, it will boot and obtain an IP via DHCP.  
+<li>Find the <strong>IP</strong> of the phone by pressing the <strong>Sysinfo</strong> button a few times.  
+<li>Open another browser window.  Go to the phones <strong>IP</strong>, for example <strong>http://192.168.1.160</strong>
+<li>Login to the phone using the username/password <strong>admin/admin</strong>.  
+<li>Optional: set a static IP using the WAN menu (I like static IPs for SIP phones).  
+<li>Go to the phone <strong>SIP Config</strong> menu.
+<li>Set <strong>Register Server Address</strong> to your Phone System IP Address.
+<li>Set <strong>Register Username</strong> to the phone number (e.g. 6011).
+<li>Also set </strong>Register Password</strong> to the phone number (e.g. 6011) and
+the </strong>Phone Number</strong> to the phone number (e.g. 6011).
+<li>Check the <strong>Enable Register</strong> box.
+<li>Then click on <strong>Apply</strong>. 
+<li>On your browser refresh this page to see if the phone is connected to your phone system.
+</ol>
diff --git a/easy-asterisk-gui/cgi-bin/banner.html b/easy-asterisk-gui/cgi-bin/banner.html
new file mode 100644 (file)
index 0000000..0288909
--- /dev/null
@@ -0,0 +1 @@
+    <tr><td colspan="2"><h2>&nbsp;</h2></td></tr>
diff --git a/easy-asterisk-gui/cgi-bin/check_loggedin.sh b/easy-asterisk-gui/cgi-bin/check_loggedin.sh
new file mode 100644 (file)
index 0000000..3d0f975
--- /dev/null
@@ -0,0 +1,9 @@
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+    echo "<html>"
+    echo "<head>"
+    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
+    echo "</head>"
+    echo "</html>"
+    exit
+fi
diff --git a/easy-asterisk-gui/cgi-bin/cross.png b/easy-asterisk-gui/cgi-bin/cross.png
new file mode 100644 (file)
index 0000000..05baecd
Binary files /dev/null and b/easy-asterisk-gui/cgi-bin/cross.png differ
diff --git a/easy-asterisk-gui/cgi-bin/faq.html b/easy-asterisk-gui/cgi-bin/faq.html
new file mode 100644 (file)
index 0000000..dd6258e
--- /dev/null
@@ -0,0 +1,16 @@
+<ol>
+
+<li><strong>Transfer a Call</strong>
+
+<li><strong>Answer a call on another ringing phone</strong>:  If you hear another phone ringing and
+want to answer the call on your phone, just pick up your phone and
+dial *8.  Note an IP phone can pick up a call on a ringing IP phone
+but not an Analog phone.  An Analog pohone can pick up another
+ringing Analog phone but not an IP phone.
+
+</ol>
+
+<h2>Resources and Links</h2>
+<ol>
+<li>A good book on Asterisk is <a href="http://astbook.asteriskdocs.org">Asterisk - The Future of Telephony</a>
+</ol>
diff --git a/easy-asterisk-gui/cgi-bin/faq.sh b/easy-asterisk-gui/cgi-bin/faq.sh
new file mode 100644 (file)
index 0000000..7713e92
--- /dev/null
@@ -0,0 +1,58 @@
+#!/bin/sh
+# faq.sh
+# David Rowe 7 Jan 2010
+# FAQ screen for Easy Asterisk GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+    echo "<html>"
+    echo "<head>"
+    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
+    echo "</head>"
+    echo "</html>"
+    exit
+fi
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+
+cat << EOF
+<html>
+<title>Easy Asterisk - FAQ</title>
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800>'
+cat banner.html
+echo "    <tr>"
+cat menu.html    
+cat <<EOF
+
+    <td valign="top">
+
+    <table align="right" width=600>
+      <tr><td align="left" valign="top"><h2>FAQ</h2></td></tr>
+      <tr><td>
+EOF
+cat faq.html
+cat <<EOF
+      </td></tr>
+    </table>
+
+    </td>
+
+    </tr>
+
+</table>
+</body>
+</html>
+EOF
+
diff --git a/easy-asterisk-gui/cgi-bin/index.html b/easy-asterisk-gui/cgi-bin/index.html
new file mode 100644 (file)
index 0000000..8514560
--- /dev/null
@@ -0,0 +1,5 @@
+<html>
+<head>
+<meta http-equiv="REFRESH" content="0;url=http:login.sh">
+</head>
+</html>
\ No newline at end of file
diff --git a/easy-asterisk-gui/cgi-bin/ipphone.png b/easy-asterisk-gui/cgi-bin/ipphone.png
new file mode 100644 (file)
index 0000000..f9578db
Binary files /dev/null and b/easy-asterisk-gui/cgi-bin/ipphone.png differ
diff --git a/easy-asterisk-gui/cgi-bin/ipphones.js b/easy-asterisk-gui/cgi-bin/ipphones.js
new file mode 100644 (file)
index 0000000..9c50cea
--- /dev/null
@@ -0,0 +1,3 @@
+function localInit() {
+}
+
diff --git a/easy-asterisk-gui/cgi-bin/ipphones.pl b/easy-asterisk-gui/cgi-bin/ipphones.pl
new file mode 100755 (executable)
index 0000000..4c95095
--- /dev/null
@@ -0,0 +1,88 @@
+#!/sbin/microperl
+# ipphones.pl
+# David Rowe 6 Jan 2010
+#
+# Text processing for the ipphones screen
+
+$ipaddress = $ARGV[0];
+$more = $ARGV[1];
+
+# Slurp up SIP extension (Sip) data from extensions.conf
+
+my %ip = (); # ip extension keyed on sip.conf name
+
+open EXT, "/etc/asterisk/extensions.conf";
+while (<EXT>) { 
+    if (/.*=>[ ]*([0-9]*),1.*SIP\/([0-9]*)\)/) {
+        $ip{$2} = $1;
+       #print "'$1' '$2' $ip{$2}\n";
+    }
+}
+close EXT;
+
+my %sip = ();  # SIP IP phone status keyed on sip.conf names 
+               # if no entry we can't see IP phone device
+my %voip = (); # SIP trunks status keyed on sip.conf names 
+               # if no entry we can't see SIP trunk
+my %ipad = (); # IP address of SIP device keyed on sip.conf names
+
+open SIP, "sipshowpeers.txt";
+while (<SIP>) { 
+    if (/^([0-9]*)[\s\/].*(OK)/) {
+        $sip{$1} = $2;
+       #print "'$1' '$2' $sip{$1}\n";
+       $e = $1;
+       if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
+           $ipad{$e} = $1;
+           #print "'$1'\n";
+       }
+    }
+    if (/^(voip[0-9]*)[\s\/].*(OK)/) {
+        $voip{$1} = $2;
+       #print "'$1' '$2' $voip{$1}\n";
+       $e = $1;
+       if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
+           $ipad{$e} = $1;
+           #print "'$1'\n";
+       }
+    }
+}
+
+close SIP;
+
+# print list of IP phones with connection status
+
+$unconnected = 0;
+foreach $e (sort keys %ip) {
+    if ($sip{$e} eq "OK") {
+       $icon = "<img src=\"tick.png\" alt=\"Connected\" />";
+        $tooltip_status = "onMouseOver=\"popUp(event,'ipphones_connected')\" onmouseout=\"popUp(event,'ipphones_connected')\"";    
+        $comment=$ipad{$e};
+        $tooltip_ext = "onMouseOver=\"popUp(event,'phone_ext')\" onmouseout=\"popUp(event,'phone_ext')\"";
+       $tooltip_ip =  "onMouseOver=\"popUp(event,'phone_ipphone_ip')\" onmouseout=\"popUp(event,'phone_ipphone_ip')\"";
+       $unconnected = 0;
+    }
+    else {
+       $unconnected = $unconnected + 1;
+       $icon = "<img src=\"cross.png\" alt=\"Not Connected\" />";
+        $tooltip_status = "onMouseOver=\"popUp(event,'ipphones_notconnected')\" onmouseout=\"popUp(event,'ipphones_notconnected')\"";
+        $comment="Available";
+       $tooltip_id = "iphones_$e";
+       print "<div id=\"$tooltip_id\" class=\"tip\"> Configure your IP phone with username/password $e/$e, SIP Server IP $ipaddress</div>";
+        $tooltip_ext = "onMouseOver=\"popUp(event,'$tooltip_id')\" onmouseout=\"popUp(event,'$tooltip_id')\"";
+       $tooltip_ip = "";
+    }
+    
+    if ($more == 1 || ($unconnected < 5)) {
+       print "<tr><td $tooltip_ext>$e</td><td></td><td $tooltip_ip>$comment</td><td $tooltip_status>$icon</td></tr>\n";
+    }
+}
+
+if ($more == 0) {
+    print '<tr><td><a href="ipphones.sh?more=1">More</a></td></tr>';
+}
+else {
+    print '<tr><td><a href="ipphones.sh">Less</a></td></tr>';
+}
+
+
diff --git a/easy-asterisk-gui/cgi-bin/ipphones.sh b/easy-asterisk-gui/cgi-bin/ipphones.sh
new file mode 100644 (file)
index 0000000..03d87d3
--- /dev/null
@@ -0,0 +1,77 @@
+#!/bin/sh
+# dashboard.sh
+# David Rowe 6 Jan 2010
+# Dashboard screen for Easy Asterisk GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+    echo "<html>"
+    echo "<head>"
+    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
+    echo "</head>"
+    echo "</html>"
+    exit
+fi
+
+more=`echo "$QUERY_STRING" | grep -oe "more=[^&?]*" | sed -n "s/more=//p"`
+ipaddress=`ifconfig eth0 | sed -n 's/.*inet addr:\(.*\)  Bcast.*/\1/p'`
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+
+echo "<script>"
+echo 'var init_internet="'$internet'";'
+cat ipphones.js
+echo "</script>"
+
+cat << EOF
+<html>
+<title>Easy Asterisk - IP Phones</title>
+<body onload="localInit()">
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800 border=0>'
+cat banner.html
+echo "    <tr>"
+cat menu.html    
+cat <<EOF
+
+    <td valign="top">
+
+    <table align="right" width=600 border=0>
+      <tr><td  onMouseOver="popUp(event,'ipphones_ipphones')" onmouseout="popUp(event,'ipphones_ipphones')" 
+           colspan="4" align="left" valign="top" ><h2>IP Phones</h2></td></tr>
+      <tr onMouseOver="popUp(event,'phone_ipaddress')" onmouseout="popUp(event,'phone_ipaddress')">
+         <td colspan="3">Phone System IP Address:</td>
+EOF
+echo "<td>$ipaddress</td></tr><td>&nbsp;</td><tr></tr>"
+
+    # use perl to construct list of IP phones for us
+    asterisk "-rx sip show peers" 2>/dev/null > sipshowpeers.txt
+    ./ipphones.pl $ipaddress $more
+
+cat <<EOF
+    </table>
+
+    <h2>&nbsp;<br>How to Configure IP Phones</h2>
+    <h3>1. Atcom AT-530</h3>
+EOF
+cat at-530.html
+cat <<EOF
+     </td>
+    </tr>
+
+</table>
+</body>
+</html>
+EOF
+
diff --git a/easy-asterisk-gui/cgi-bin/login.sh b/easy-asterisk-gui/cgi-bin/login.sh
new file mode 100644 (file)
index 0000000..f195f8d
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/sh
+# login.sh
+# David Rowe 4 Jan 2010
+# CGI for Easy Asterisk login GUI
+
+pass=`echo "$QUERY_STRING" | grep -oe "pass=[^&?]*" | sed -n "s/pass=//p"`
+
+echo $QUERY_STRING | grep pass > /dev/null
+if [ $? -eq 1 ]; then
+    # Display form -------------------------------
+
+    cat <<EOF
+    <script src="prototype.js"></script>
+    <link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
+    <script type="text/javascript" src="tooltip.js"></script>
+    <link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+    cat << EOF
+    <html>
+    <title>Easy Asterisk - Login</title>
+    <form action="login.sh" method="get">
+    <table align="center" width=600>
+    <tr><td colspan="2" align="left"><h2>Login</h2></td>
+    <tr>
+      <tr><td>Password:</td><td><input type="password" name="pass" ></td></tr>
+      <tr><td><input type="submit" value="Login"></td></tr>
+    </tr>
+    <tr><td></td><td>Default password is uClinux</td>
+    </table>
+    </form>
+    </html>
+EOF
+else
+    testuser root $pass
+    if [ $? -eq 0 ]; then
+
+       # login sucessful
+        echo "Content-type: text/html"
+        echo "Set-Cookie: loggedin=1"
+        echo ""
+       echo "<head>"
+       echo "<title>Easy Asterisk - Login</title>"
+       echo '<meta http-equiv="REFRESH" content="0;url=http:phones.sh">'
+       echo "</head>"
+       echo "<body>"
+       echo "Please wait a few seconds....."
+       echo "</body>"
+    else
+       # login failed
+       cat <<EOF
+       <html>
+       <head>
+       <title>Easy Asterisk - Login</title>
+       <meta http-equiv="REFRESH" content="0;url=http:login.sh">
+       <body>
+       Please wait a few seconds.....
+       </body>
+       </head>
+       </html>
+EOF
+    fi
+fi
+
diff --git a/easy-asterisk-gui/cgi-bin/logout.sh b/easy-asterisk-gui/cgi-bin/logout.sh
new file mode 100644 (file)
index 0000000..bf8a05d
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+# logout.sh
+# David Rowe 4 Jan 2010
+# CGI for Easy Asterisk logout GUI
+
+cat <<EOF
+Content-type: text/html
+Set-Cookie: loggedin=1; expires=Thursday, 01-Jan-98 12:00:00 GMT
+
+<title>Easy Asterisk - Logout</title>
+<meta http-equiv="REFRESH" content="0;url=http:login.sh"
+EOF
+#echo $HTTP_COOKIE
diff --git a/easy-asterisk-gui/cgi-bin/menu.html b/easy-asterisk-gui/cgi-bin/menu.html
new file mode 100644 (file)
index 0000000..81e4aa8
--- /dev/null
@@ -0,0 +1,37 @@
+    <div id="admin_tip" class="tip">Change your password, Time & time zone, Reset the defaults, Install new software</div>
+    <div id="network_tip" class="tip">Connect the phone system to your network and the Internet</div>
+    <div id="phones_tip" class="tip">Lists your phones and phone lines</div>
+    <div id="ipphones_tip" class="tip">Set up your IP phones</div>
+    <div id="about_tip" class="tip">Boring information like software version numbers</div>
+    <div id="faq_tip" class="tip">Frequently asked questions and links to further information</div>
+    <div id="logout_tip" class="tip">I think you can work this one out....</div>
+    <div id="voipline_tip" class="tip">Set up your VOIP phone line</div>
+    <td valign="top" >
+       <table align="right" width=200>
+       <tr><td><h2>&nbsp;</h2></td></tr>
+       <tr onMouseOver="popUp(event,'about_tip')" onmouseout="popUp(event,'about_tip')">
+         <td><a href="about.sh">About</a></td>
+       </tr>
+       <tr onMouseOver="popUp(event,'admin_tip')" onmouseout="popUp(event,'admin_tip')">
+         <td><a href="admin.sh">Admin</a></td>
+       </tr>
+       <tr onMouseOver="popUp(event,'faq_tip')" onmouseout="popUp(event,'faq_tip')">
+         <td><a href="faq.sh">FAQ</a></td>
+       </tr>
+       <tr onMouseOver="popUp(event,'ipphones_tip')" onmouseout="popUp(event,'ipphones_tip')">
+         <td><a href="ipphones.sh">IP Phones</a></td>
+       </tr>
+       <tr onMouseOver="popUp(event,'logout_tip')" onmouseout="popUp(event,'logout_tip')">
+         <td><a href="logout.sh">Logout</a></td>
+       </tr>
+       <tr onMouseOver="popUp(event,'phones_tip')" onmouseout="popUp(event,'phones_tip')">
+         <td><a href="phones.sh">Phone System</a></td>
+       </tr>
+       <tr onMouseOver="popUp(event,'network_tip')" onmouseout="popUp(event,'network_tip')">
+         <td><a href="network.sh">Network</a></td>
+       </tr>
+       <tr onMouseOver="popUp(event,'voipline_tip')" onmouseout="popUp(event,'voipline_tip')">
+         <td><a href="voiplines.sh">VOIP Line</a></td>
+       </tr>
+       </table>
+    </td>
diff --git a/easy-asterisk-gui/cgi-bin/network.js b/easy-asterisk-gui/cgi-bin/network.js
new file mode 100644 (file)
index 0000000..108bf01
--- /dev/null
@@ -0,0 +1,76 @@
+var script_path = "cgi-bin/";
+
+function doStatic() {    
+    $('ipaddress').disabled = 0;
+    $('netmask').disabled = 0;
+    $('gateway').disabled = 0;
+    $('dns').disabled = 0;
+}
+
+function doDHCP() {
+    $('ipaddress').disabled = 1;
+    $('netmask').disabled = 1;
+    $('gateway').disabled = 1;
+    $('dns').disabled = 1;
+}
+
+// http://moblog.bradleyit.com/2009/06/javascript-ip-address-validation.html
+
+function isIP(obj) {
+    var ary = obj.value.split(".");
+    var ip = true;
+
+    for (var i=0; i<4; i++) { 
+       ip = (!ary[i].match(/^\d{1,3}$/) || (Number(ary[i]) > 255)) ? false : ip; 
+    } 
+  
+    if (ip)
+       ip = (ary.length == 4); 
+
+    if (!ip) {    
+       // the value is NOT a valid IP address
+       obj.style.background = "red";
+       obj.select();
+    } 
+    else { obj.style.background = ""; } // the value IS a valid IP address
+
+    return ip;
+}
+
+function localInit() {
+
+    if (init_dhcp == "yes") {
+       $('dhcp').checked = true;
+       $('ipaddress').disabled = 1;
+       $('netmask').disabled = 1;
+       $('gateway').disabled = 1;
+       $('dns').disabled = 1;
+    }
+    else {
+       $('static').checked = true;
+       $('ipaddress').disabled = 0;
+       $('netmask').disabled = 0;
+       $('gateway').disabled = 0;
+       $('dns').disabled = 0;
+    }
+    $('ipaddress').value = init_ipaddress;
+    $('netmask').value = init_netmask;
+    $('gateway').value = init_gateway;
+    $('dns').value = init_dns;
+    $('backdoor').value = init_backdoor;    
+    if (init_internet == "yes")
+       $('internet').innerHTML = '<img src="tick.png" alt="tick" />';
+    else
+        $('internet').innerHTML = '<img src="cross.png" alt="tick" />';
+
+}
+
+function validate_form(form)
+{
+    var valid = true;
+
+    if ($('dhcp').checked == false)
+       valid = isIP(form.ipaddress) && isIP(form.ipaddress) && isIP(form.gateway) && isIP(form.dns);
+
+    return valid;
+}
diff --git a/easy-asterisk-gui/cgi-bin/network.sh b/easy-asterisk-gui/cgi-bin/network.sh
new file mode 100644 (file)
index 0000000..a32d508
--- /dev/null
@@ -0,0 +1,151 @@
+#!/bin/sh
+# network.sh
+# David Rowe 4 Jan 2010
+# CGI for Easy Asterisk network GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+    echo "<html>"
+    echo "<head>"
+    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
+    echo "</head>"
+    echo "</html>"
+    exit
+fi
+
+grok_network=0
+
+if [ -f /etc/rc.d/S10network ]; then
+  grok_network=1
+  dhcp=yes
+  ipaddress=`ifconfig eth0 | sed -n 's/.*inet addr:\(.*\)  Bcast.*/\1/p'`
+  netmask=`ifconfig eth0 | sed -n 's/.*Mask:\(.*\)\s*/\1/p'`
+  gateway=`route -n | awk '/^0.0.0.0/ {print $2}'`
+  dns=`cat /etc/resolv.conf | awk '/^nameserver/ {print $2}'`
+fi
+
+if [ -f /etc/rc.d/S10network-static ]
+then
+  grok_network=1
+  dhcp=no  
+  ipaddress=`sed -n 's/IPADDRESS="\(.*\)"/\1/p' /etc/init.d/network-static`
+  netmask=`sed -n 's/NETMASK="\(.*\)"/\1/p' /etc/init.d/network-static`
+  gateway=`sed -n 's/GATEWAY="\(.*\)"/\1/p' /etc/init.d/network-static`
+  dns=`sed -n 's/DNS="\(.*\)"/\1/p' /etc/init.d/network-static`
+fi
+
+# if we don't understand this machines network config then bail
+
+if [ $groknetwork -eq 0 ]; then
+cat << EOF
+<html>
+<title>Easy Asterisk - Network</title>
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800 border=0>'
+cat banner.html
+echo "    <tr>"
+cat menu.html    
+cat <<EOF
+
+    <td valign="top">
+    <table align="center" width=600 border=0>
+      <tr><td colspan="2" align="left" valign="top"><h2>Network</h2></td></tr>
+      <tr><td>Sorry - I can't edit the Network configuration on this machine</td></tr>
+    </td>
+    </table>
+    </td>
+    </tr>
+
+</table>
+
+</html>
+EOF
+fi
+if [ -f /etc/rc.d/S05network-backdoor ]; then
+  backdoor=`sed -n 's/IPADDRESS="\(.*\)"/\1/p' /etc/init.d/network-backdoor`
+fi
+
+# See if we have Internet connectivity, first check dns as time outs can be very slow
+
+dns_packet_loss=`ping $dns -c 1 -q | sed -n 's/.*received, \(.*\)% packet loss/\1/p'`
+internet="no";
+if [ $dns_packet_loss == "0" ]; then
+  packet_loss=`ping google.com -c 1 -q | sed -n 's/.*received, \(.*\)% packet loss/\1/p'`
+  if [ $packet_loss == "0" ]; then
+    internet="yes";
+  fi
+fi
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+
+echo "<script>"
+echo 'var init_dhcp="'$dhcp'";'
+echo 'var init_ipaddress="'$ipaddress'";'
+echo 'var init_netmask="'$netmask'";'
+echo 'var init_gateway="'$gateway'";'
+echo 'var init_dns="'$dns'";'
+echo 'var init_backdoor="'$backdoor'";'
+echo 'var init_internet="'$internet'";'
+cat network.js
+echo "</script>"
+
+cat << EOF
+<html>
+<title>Easy Asterisk - Network</title>
+<body onload="localInit()">
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800 border=0>'
+cat banner.html
+echo "    <tr>"
+cat menu.html    
+cat <<EOF
+
+    <td valign="top">
+
+    <form action="set_network.sh" onsubmit="return validate_form(this)" method="get">
+    <table align="center" width=600 border=0>
+      <tr><td colspan="2" align="left" valign="top"><h2>Network</h2></td></tr>
+      <tr>
+        <td><input type="radio" id="static" name="dhcp" value="no" onClick="doStatic()">Static</td>
+        <td><input type="radio" id="dhcp"   name="dhcp" value="yes" onClick="doDHCP()">DHCP</td>
+      </tr>
+      <tr><td>IP Address:</td><td><input type="text" name="ipaddress" id="ipaddress" onBlur="isIP(this)"></td></tr>
+      <tr><td>Netmask:</td><td><input type="text" name="netmask" id="netmask" onBlur="isIP(this)"></td></tr>
+      <tr><td>Gateway:</td><td><input type="text" name="gateway" id="gateway" onBlur="isIP(this)"></td></tr>
+      <tr><td>DNS:</td><td><input type="text" name="dns" id="dns" onBlur="isIP(this)"></td></tr>
+      <tr onMouseOver="popUp(event,'network_backdoor')" onmouseout="popUp(event,'network_backdoor')">
+          <td>Emergency IP:</td><td><input type="text" name="backdoor" id="backdoor" onBlur="isIP(this)"></td>
+      </tr>
+      <tr onMouseOver="popUp(event,'network_internet')" onmouseout="popUp(event,'network_internet')">
+         <td>Internet Connection:</td>
+         <td><div id="internet" >
+         <span style="margin-left: 4px;font-weight:bold">&nbsp;</span></div></td>
+
+      </tr>
+      <tr><td><input id="networkapply" type="submit" value="Apply"></td></tr>
+    </table>
+    </form>
+
+    </td>
+
+    </tr>
+
+</table>
+
+</html>
+EOF
+
diff --git a/easy-asterisk-gui/cgi-bin/phoneline.jpg b/easy-asterisk-gui/cgi-bin/phoneline.jpg
new file mode 100644 (file)
index 0000000..21078c3
Binary files /dev/null and b/easy-asterisk-gui/cgi-bin/phoneline.jpg differ
diff --git a/easy-asterisk-gui/cgi-bin/phones.js b/easy-asterisk-gui/cgi-bin/phones.js
new file mode 100644 (file)
index 0000000..74d6eaf
--- /dev/null
@@ -0,0 +1,7 @@
+function localInit() {
+    if (init_internet == "yes")
+       $('internet').innerHTML = '<img src="tick.png" alt="tick" />';
+    else
+        $('internet').innerHTML = '<img src="cross.png" alt="tick" />';
+}
+
diff --git a/easy-asterisk-gui/cgi-bin/phones.pl b/easy-asterisk-gui/cgi-bin/phones.pl
new file mode 100755 (executable)
index 0000000..98db525
--- /dev/null
@@ -0,0 +1,216 @@
+#!/sbin/microperl
+# phones.pl
+# David Rowe 5 Jan 2010
+#
+# Text processing for the phones screen.
+
+$tool_tip = "onMouseOver=\"popUp(event,'network_internet')\" onmouseout=\"popUp(event,'network_internet')\"";
+
+# Slurp up analog port (Zap) data from extensions.conf
+
+my %analog = (); # analog extension keyed on zap port
+
+open EXT, "/etc/asterisk/extensions.conf";
+while (<EXT>) { 
+    if (/.*=>[ ]*([0-9]*),1.*Zap\/([0-9]*)\)/) {
+        $analog{$2} = $1;
+       #print "'$1' '$2' $analog{$2}\n";
+    }
+}
+close EXT;
+
+# Slurp up data on installed zaptel ports from /etc/zaptel.conf
+
+my %zap = (); # zaptel port type keyed on zap port 
+              # (fxs/fxo or no entry if not live)
+open ZAP, "/etc/zaptel.conf";
+while (<ZAP>) { 
+    if (/fxoks=(.*)/) {
+        @fxs = split(/,/, $1);
+       foreach (@fxs) {
+           $zap{$_} = "fxs";
+       }
+    }
+    if (/fxsks=(.*)/) {
+        @fxo = split(/,/, $1);
+       foreach (@fxo) {
+           $zap{$_} = "fxo";
+       }
+    }
+}
+close ZAP;
+
+# Slurp up SIP extension (Sip) data from extensions.conf
+
+my %ip = (); # ip extension keyed on sip.conf name
+
+open EXT, "/etc/asterisk/extensions.conf";
+while (<EXT>) { 
+    if (/.*=>[ ]*([0-9]*),1.*Sip\/([0-9]*)\)/) {
+        $ip{$2} = $1;
+       #print "'$1' '$2' $ip{$2}\n";
+    }
+}
+close EXT;
+
+# Determine which extenions are "Reception", i.e. set to ring on incoming
+# calls
+
+my %zap_ring = (); # ring flag keyed on Zap port (1,2...)
+my %sip_ring = (); # ring flag keyed on sip.cong ext name (6011,6012 etc)
+
+open EXT, "/etc/asterisk/extensions.conf";
+while (<EXT>) { 
+    if (/s,1,Dial\((.*)\) ;; easy/) {
+        @ring = split(/&/, $1);
+       #print "'$1' '@ring'\n foreach:\n";
+       foreach (@ring) {
+           #print "    $_\n";
+           if (/Zap\/([0-9]*)/) {
+               $zap_ring{$1} = 1;
+               #print "'$_' $1 \n";
+           }
+           if (/SIP\/([0-9]*)/) {
+               $sip_ring{$1} = 1;
+               #print "'$_' $1 \n";
+           }
+       }
+    }
+}
+close EXT;
+
+
+# work out which IP phones are registered -----------------------------------
+
+my %sip = ();  # SIP IP phone status keyed on sip.conf names (6011,6012 etc)
+               # if no entry we can't see IP phone device
+my %ipad = (); # IP address of SIP device keyed on sip.conf names
+
+open SIP, "sipshowpeers.txt";
+while (<SIP>) { 
+    if (/^([0-9]*)[\s\/].*(OK)/) {
+        $sip{$1} = $2;
+       #print "'$1' '$2' $sip{$1}\n";
+       $e = $1;
+       if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
+           $ipad{$e} = $1;
+           #print "'$1'\n";
+       }
+    }
+
+    if (/^(.*)\/.*(OK)/) {
+        #$sip{$1} = $2;
+       #print "'$1' '$2' $sip{$1}\n";
+       $e = $1;
+       if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
+           $ipad{$e} = $1;
+           #print "'$1'\n";
+       }
+    }
+}
+
+close SIP;
+
+# Determine if Asterisk can see current voip line (SIP trunk) 
+# sipshowpeers.txt needs to be generated before calling this perl
+# script
+
+my %voip = (); # SIP trunks status keyed on sip.conf stanza name/username
+               # if no entry we can't see SIP trunk
+
+open SIP, "sipshowregistry.txt";
+while (<SIP>) { 
+    if (/^(.*):.*(Registered)/) {
+        $voip{$1} = $2;
+       #print "'$1' '$2' $voip{$1}\n";
+    }
+}
+
+close SIP;
+
+# start phones ringing form -------------------------------------------
+
+print '<form action="set_ring.sh?" method="get">';
+
+# print list of analog phones
+
+$tooltip_anphone = "onMouseOver=\"popUp(event,'phone_anphone')\" onmouseout=\"popUp(event,'phone_anphone')\"";
+$tooltip_ext = "onMouseOver=\"popUp(event,'phone_ext')\" onmouseout=\"popUp(event,'phone_ext')\"";
+$tooltip_port = "onMouseOver=\"popUp(event,'phone_port_phone')\" onmouseout=\"popUp(event,'phone_port_phone')\"";
+$tooltip_reception = "onMouseOver=\"popUp(event,'phone_reception')\" onmouseout=\"popUp(event,'phone_reception')\"";
+
+foreach $a (sort keys %analog) {
+    if ($zap{$a} eq "fxs") {
+       $icon = "<img src=\"tick.png\" alt=\"Analog Phone OK\" />";
+       print "<tr><td $tooltip_ext>$analog{$a}</td><td $tooltip_anphone>Analog Phone</td><td $tooltip_port>Port $a</td>";
+       if ($zap_ring{$a} == 1) {
+           $checked = "checked";
+       }
+       else {
+           $checked = "";
+       }
+       print "<td $tooltip_reception><input type=\"checkbox\" name=\"Zap_$a\" $checked>Reception</td><td>$icon</td></tr>\n";
+    }
+}
+
+# print list of IP phones
+
+$tooltip_ipphone = "onMouseOver=\"popUp(event,'phone_ipphone')\" onmouseout=\"popUp(event,'phone_ipphone')\"";
+$tooltip_ipphone_ip = "onMouseOver=\"popUp(event,'phone_ipphone_ip')\" onmouseout=\"popUp(event,'phone_ipphone_ip')\"";
+$tooltip_reception = "onMouseOver=\"popUp(event,'phone_reception')\" onmouseout=\"popUp(event,'phone_reception')\"";
+
+foreach $s (sort keys %sip) {
+    if ($sip{$s} eq "OK") {
+       $icon = "<img src=\"tick.png\" alt=\"IP Phone OK\" />";
+       print "<tr><td $tooltip_ext>$s</td><td $tooltip_ipphone>IP Phone</td><td $tooltip_ipphone_ip>$ipad{$s}</td>";
+       if ($sip_ring{$s} == 1) {
+           $checked = "checked";
+       }
+       else {
+           $checked = "";
+       }
+       print "<td $tooltip_reception><input type=\"checkbox\" name=\"SIP_$s\" $checked>Reception</td><td>$icon</td></tr>\n";
+    }
+}
+
+print '<tr><td>&nbsp;</td></tr>';
+print "<tr><td onMouseOver=\"popUp(event,'phone_addipphone')\" onmouseout=\"popUp(event,'phone_addipphone')\">";
+print "<a href=\"ipphones.sh\">Add IP Phone</a></td><td></td><td></td><td><input type=\"submit\" value=\"Update Reception\"></td></tr>";
+
+$tool_tip = "onMouseOver=\"popUp(event,'phone_lines')\" onmouseout=\"popUp(event,'phone_lines')\"";
+
+print '<tr><td>&nbsp</td></tr>';
+print "<tr $tool_tip><td colspan=\"4\" align=\"left\" valign=\"top\" ><h2>Phone Lines</h2></td></tr>
+";
+
+print "</form>";
+
+# print list of analog phone lines
+
+$tooltip_phoneline = "onMouseOver=\"popUp(event,'phone_phoneline')\" onmouseout=\"popUp(event,'phone_phoneline')\"";
+$tooltip_port = "onMouseOver=\"popUp(event,'phone_port_line')\" onmouseout=\"popUp(event,'phone_port_line')\"";
+$tooltip_line_prefix = "onMouseOver=\"popUp(event,'phone_line_prefix')\" onmouseout=\"popUp(event,'phone_line_prefix')\"";
+
+foreach $a (sort keys %analog) {
+    if ($zap{$a} eq "fxo") {
+       $icon = "<img src=\"tick.png\" alt=\"Phone Line OK\" />";
+       print "<tr><td $tooltip_line_prefix>0</td><td $tooltip_phoneline>Analog Line</td><td $tooltip_port>Port $a</td><td></td><td>$icon</td></tr>\n";
+    }
+}
+
+# print list of SIP VOIP trunks
+
+$tooltip_voipline = "onMouseOver=\"popUp(event,'phone_voipline')\" onmouseout=\"popUp(event,'phone_voipline')\"";
+$tooltip_voipline_ip = "onMouseOver=\"popUp(event,'phone_voipline_ip')\" onmouseout=\"popUp(event,'phone_voipline_ip')\"";
+$tooltip_voipline_prefix = "onMouseOver=\"popUp(event,'phone_voipline_prefix')\" onmouseout=\"popUp(event,'phone_voipline_prefix')\"";
+
+foreach $s (sort keys %voip) {
+    if ($voip{$s} eq "Registered") {
+       $icon = "<img src=\"tick.png\" alt=\"VOIP Line OK\" />";
+       print "<tr><td $tooltip_voipline_prefix>1</td><td $tooltip_voipline>VOIP Line</td><td $tooltip_voipline_ip>$ipad{$s}</td><td></td><td>$icon</td></tr>\n";
+    }
+}
+
+print '<tr><td>&nbsp;</td></tr>';
+print "<tr><td colspan=2 onMouseOver=\"popUp(event,'phone_addvoipline')\" onmouseout=\"popUp(event,'phone_addvoipline')\">";
+print "<a href=\"voiplines.sh\">Set Up VOIP Line</a></td></tr>";
diff --git a/easy-asterisk-gui/cgi-bin/phones.sh b/easy-asterisk-gui/cgi-bin/phones.sh
new file mode 100644 (file)
index 0000000..5dba25d
--- /dev/null
@@ -0,0 +1,97 @@
+#!/bin/sh
+# phones.sh
+# David Rowe 4 Jan 2010
+# Phones screen for Easy Asterisk GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+    echo "<html>"
+    echo "<head>"
+    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
+    echo "</head>"
+    echo "</html>"
+    exit
+fi
+
+# See if we have Internet connectivity, first check dns as time outs can be very slow
+
+dns=`cat /etc/resolv.conf | awk '/^nameserver/ {print $2}'`
+dns_packet_loss=`ping $dns -c 1 -q | sed -n 's/.*received, \(.*\)% packet loss/\1/p'`
+internet="no";
+if [ $dns_packet_loss == "0" ]; then
+  packet_loss=`ping google.com -c 1 -q | sed -n 's/.*received, \(.*\)% packet loss/\1/p'`
+  if [ $packet_loss == "0" ]; then
+    internet="yes";
+  fi
+fi
+
+ipaddress=`ifconfig eth0 | sed -n 's/.*inet addr:\(.*\)  Bcast.*/\1/p'`
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+
+echo "<script>"
+echo 'var init_internet="'$internet'";'
+cat phones.js
+echo "</script>"
+
+cat << EOF
+<html>
+<title>Easy Asterisk - Phones</title>
+<body onload="localInit()">
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800>'
+cat banner.html
+echo "    <tr>"
+cat menu.html    
+cat <<EOF
+
+    <td valign="top">
+
+    <table align="right" width=600>
+      <tr>
+          <td onMouseOver="popUp(event,'phone_system')" onmouseout="popUp(event,'phone_system')" colspan="4" align="left" valign="top"><h2>Phone System</h2></td>
+      </tr>
+      <tr>
+         <td colspan="3" onMouseOver="popUp(event,'network_internet')" onmouseout="popUp(event,'network_internet')">Internet Connection:</td>
+         <td></td><td><div id="internet" >&nbsp;</div></td>
+      </tr>
+      <tr onMouseOver="popUp(event,'phone_ipaddress')" onmouseout="popUp(event,'phone_ipaddress')">
+         <td colspan="4">Phone System IP Address:</td>
+EOF
+echo "<td>$ipaddress</td>"
+cat <<EOF
+      </tr>
+      <tr><td>&nbsp</td></tr>
+      <tr>
+          <td onMouseOver="popUp(event,'phone_phones')" onmouseout="popUp(event,'phone_phones')" 
+               colspan="3" align="left" valign="top" ><h2>Phones</h2></td>
+      </tr>
+EOF
+
+# use perl to construct list of phones and phone lines for us
+asterisk "-rx sip show peers" 2>/dev/null > sipshowpeers.txt
+./phones.pl
+
+cat<<EOF
+    </table>
+
+    </td>
+
+    </tr>
+
+</table>
+</body>
+</html>
+EOF
+
diff --git a/easy-asterisk-gui/cgi-bin/prototype.js b/easy-asterisk-gui/cgi-bin/prototype.js
new file mode 100644 (file)
index 0000000..0e85338
--- /dev/null
@@ -0,0 +1,1781 @@
+/*  Prototype JavaScript framework, version 1.4.0
+ *  (c) 2005 Sam Stephenson <sam@conio.net>
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *  For details, see the Prototype web site: http://prototype.conio.net/
+ *
+/*--------------------------------------------------------------------------*/
+
+var Prototype = {
+  Version: '1.4.0',
+  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
+
+  emptyFunction: function() {},
+  K: function(x) {return x}
+}
+
+var Class = {
+  create: function() {
+    return function() {
+      this.initialize.apply(this, arguments);
+    }
+  }
+}
+
+var Abstract = new Object();
+
+Object.extend = function(destination, source) {
+  for (property in source) {
+    destination[property] = source[property];
+  }
+  return destination;
+}
+
+Object.inspect = function(object) {
+  try {
+    if (object == undefined) return 'undefined';
+    if (object == null) return 'null';
+    return object.inspect ? object.inspect() : object.toString();
+  } catch (e) {
+    if (e instanceof RangeError) return '...';
+    throw e;
+  }
+}
+
+Function.prototype.bind = function() {
+  var __method = this, args = $A(arguments), object = args.shift();
+  return function() {
+    return __method.apply(object, args.concat($A(arguments)));
+  }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+  var __method = this;
+  return function(event) {
+    return __method.call(object, event || window.event);
+  }
+}
+
+Object.extend(Number.prototype, {
+  toColorPart: function() {
+    var digits = this.toString(16);
+    if (this < 16) return '0' + digits;
+    return digits;
+  },
+
+  succ: function() {
+    return this + 1;
+  },
+
+  times: function(iterator) {
+    $R(0, this, true).each(iterator);
+    return this;
+  }
+});
+
+var Try = {
+  these: function() {
+    var returnValue;
+
+    for (var i = 0; i < arguments.length; i++) {
+      var lambda = arguments[i];
+      try {
+        returnValue = lambda();
+        break;
+      } catch (e) {}
+    }
+
+    return returnValue;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create();
+PeriodicalExecuter.prototype = {
+  initialize: function(callback, frequency) {
+    this.callback = callback;
+    this.frequency = frequency;
+    this.currentlyExecuting = false;
+
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    if (!this.currentlyExecuting) {
+      try {
+        this.currentlyExecuting = true;
+        this.callback();
+      } finally {
+        this.currentlyExecuting = false;
+      }
+    }
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+function $() {
+  var elements = new Array();
+
+  for (var i = 0; i < arguments.length; i++) {
+    var element = arguments[i];
+    if (typeof element == 'string')
+      element = document.getElementById(element);
+
+    if (arguments.length == 1)
+      return element;
+
+    elements.push(element);
+  }
+
+  return elements;
+}
+Object.extend(String.prototype, {
+  stripTags: function() {
+    return this.replace(/<\/?[^>]+>/gi, '');
+  },
+
+  stripScripts: function() {
+    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+  },
+
+  extractScripts: function() {
+    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+    return (this.match(matchAll) || []).map(function(scriptTag) {
+      return (scriptTag.match(matchOne) || ['', ''])[1];
+    });
+  },
+
+  evalScripts: function() {
+    return this.extractScripts().map(eval);
+  },
+
+  escapeHTML: function() {
+    var div = document.createElement('div');
+    var text = document.createTextNode(this);
+    div.appendChild(text);
+    return div.innerHTML;
+  },
+
+  unescapeHTML: function() {
+    var div = document.createElement('div');
+    div.innerHTML = this.stripTags();
+    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
+  },
+
+  toQueryParams: function() {
+    var pairs = this.match(/^\??(.*)$/)[1].split('&');
+    return pairs.inject({}, function(params, pairString) {
+      var pair = pairString.split('=');
+      params[pair[0]] = pair[1];
+      return params;
+    });
+  },
+
+  toArray: function() {
+    return this.split('');
+  },
+
+  camelize: function() {
+    var oStringList = this.split('-');
+    if (oStringList.length == 1) return oStringList[0];
+
+    var camelizedString = this.indexOf('-') == 0
+      ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
+      : oStringList[0];
+
+    for (var i = 1, len = oStringList.length; i < len; i++) {
+      var s = oStringList[i];
+      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
+    }
+
+    return camelizedString;
+  },
+
+  inspect: function() {
+    return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
+  }
+});
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+var $break    = new Object();
+var $continue = new Object();
+
+var Enumerable = {
+  each: function(iterator) {
+    var index = 0;
+    try {
+      this._each(function(value) {
+        try {
+          iterator(value, index++);
+        } catch (e) {
+          if (e != $continue) throw e;
+        }
+      });
+    } catch (e) {
+      if (e != $break) throw e;
+    }
+  },
+
+  all: function(iterator) {
+    var result = true;
+    this.each(function(value, index) {
+      result = result && !!(iterator || Prototype.K)(value, index);
+      if (!result) throw $break;
+    });
+    return result;
+  },
+
+  any: function(iterator) {
+    var result = true;
+    this.each(function(value, index) {
+      if (result = !!(iterator || Prototype.K)(value, index))
+        throw $break;
+    });
+    return result;
+  },
+
+  collect: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      results.push(iterator(value, index));
+    });
+    return results;
+  },
+
+  detect: function (iterator) {
+    var result;
+    this.each(function(value, index) {
+      if (iterator(value, index)) {
+        result = value;
+        throw $break;
+      }
+    });
+    return result;
+  },
+
+  findAll: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      if (iterator(value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  grep: function(pattern, iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      var stringValue = value.toString();
+      if (stringValue.match(pattern))
+        results.push((iterator || Prototype.K)(value, index));
+    })
+    return results;
+  },
+
+  include: function(object) {
+    var found = false;
+    this.each(function(value) {
+      if (value == object) {
+        found = true;
+        throw $break;
+      }
+    });
+    return found;
+  },
+
+  inject: function(memo, iterator) {
+    this.each(function(value, index) {
+      memo = iterator(memo, value, index);
+    });
+    return memo;
+  },
+
+  invoke: function(method) {
+    var args = $A(arguments).slice(1);
+    return this.collect(function(value) {
+      return value[method].apply(value, args);
+    });
+  },
+
+  max: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      value = (iterator || Prototype.K)(value, index);
+      if (value >= (result || value))
+        result = value;
+    });
+    return result;
+  },
+
+  min: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      value = (iterator || Prototype.K)(value, index);
+      if (value <= (result || value))
+        result = value;
+    });
+    return result;
+  },
+
+  partition: function(iterator) {
+    var trues = [], falses = [];
+    this.each(function(value, index) {
+      ((iterator || Prototype.K)(value, index) ?
+        trues : falses).push(value);
+    });
+    return [trues, falses];
+  },
+
+  pluck: function(property) {
+    var results = [];
+    this.each(function(value, index) {
+      results.push(value[property]);
+    });
+    return results;
+  },
+
+  reject: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      if (!iterator(value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  sortBy: function(iterator) {
+    return this.collect(function(value, index) {
+      return {value: value, criteria: iterator(value, index)};
+    }).sort(function(left, right) {
+      var a = left.criteria, b = right.criteria;
+      return a < b ? -1 : a > b ? 1 : 0;
+    }).pluck('value');
+  },
+
+  toArray: function() {
+    return this.collect(Prototype.K);
+  },
+
+  zip: function() {
+    var iterator = Prototype.K, args = $A(arguments);
+    if (typeof args.last() == 'function')
+      iterator = args.pop();
+
+    var collections = [this].concat(args).map($A);
+    return this.map(function(value, index) {
+      iterator(value = collections.pluck(index));
+      return value;
+    });
+  },
+
+  inspect: function() {
+    return '#<Enumerable:' + this.toArray().inspect() + '>';
+  }
+}
+
+Object.extend(Enumerable, {
+  map:     Enumerable.collect,
+  find:    Enumerable.detect,
+  select:  Enumerable.findAll,
+  member:  Enumerable.include,
+  entries: Enumerable.toArray
+});
+var $A = Array.from = function(iterable) {
+  if (!iterable) return [];
+  if (iterable.toArray) {
+    return iterable.toArray();
+  } else {
+    var results = [];
+    for (var i = 0; i < iterable.length; i++)
+      results.push(iterable[i]);
+    return results;
+  }
+}
+
+Object.extend(Array.prototype, Enumerable);
+
+Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+  _each: function(iterator) {
+    for (var i = 0; i < this.length; i++)
+      iterator(this[i]);
+  },
+
+  clear: function() {
+    this.length = 0;
+    return this;
+  },
+
+  first: function() {
+    return this[0];
+  },
+
+  last: function() {
+    return this[this.length - 1];
+  },
+
+  compact: function() {
+    return this.select(function(value) {
+      return value != undefined || value != null;
+    });
+  },
+
+  flatten: function() {
+    return this.inject([], function(array, value) {
+      return array.concat(value.constructor == Array ?
+        value.flatten() : [value]);
+    });
+  },
+
+  without: function() {
+    var values = $A(arguments);
+    return this.select(function(value) {
+      return !values.include(value);
+    });
+  },
+
+  indexOf: function(object) {
+    for (var i = 0; i < this.length; i++)
+      if (this[i] == object) return i;
+    return -1;
+  },
+
+  reverse: function(inline) {
+    return (inline !== false ? this : this.toArray())._reverse();
+  },
+
+  shift: function() {
+    var result = this[0];
+    for (var i = 0; i < this.length - 1; i++)
+      this[i] = this[i + 1];
+    this.length--;
+    return result;
+  },
+
+  inspect: function() {
+    return '[' + this.map(Object.inspect).join(', ') + ']';
+  }
+});
+var Hash = {
+  _each: function(iterator) {
+    for (key in this) {
+      var value = this[key];
+      if (typeof value == 'function') continue;
+
+      var pair = [key, value];
+      pair.key = key;
+      pair.value = value;
+      iterator(pair);
+    }
+  },
+
+  keys: function() {
+    return this.pluck('key');
+  },
+
+  values: function() {
+    return this.pluck('value');
+  },
+
+  merge: function(hash) {
+    return $H(hash).inject($H(this), function(mergedHash, pair) {
+      mergedHash[pair.key] = pair.value;
+      return mergedHash;
+    });
+  },
+
+  toQueryString: function() {
+    return this.map(function(pair) {
+      return pair.map(encodeURIComponent).join('=');
+    }).join('&');
+  },
+
+  inspect: function() {
+    return '#<Hash:{' + this.map(function(pair) {
+      return pair.map(Object.inspect).join(': ');
+    }).join(', ') + '}>';
+  }
+}
+
+function $H(object) {
+  var hash = Object.extend({}, object || {});
+  Object.extend(hash, Enumerable);
+  Object.extend(hash, Hash);
+  return hash;
+}
+ObjectRange = Class.create();
+Object.extend(ObjectRange.prototype, Enumerable);
+Object.extend(ObjectRange.prototype, {
+  initialize: function(start, end, exclusive) {
+    this.start = start;
+    this.end = end;
+    this.exclusive = exclusive;
+  },
+
+  _each: function(iterator) {
+    var value = this.start;
+    do {
+      iterator(value);
+      value = value.succ();
+    } while (this.include(value));
+  },
+
+  include: function(value) {
+    if (value < this.start)
+      return false;
+    if (this.exclusive)
+      return value < this.end;
+    return value <= this.end;
+  }
+});
+
+var $R = function(start, end, exclusive) {
+  return new ObjectRange(start, end, exclusive);
+}
+
+var Ajax = {
+  getTransport: function() {
+    return Try.these(
+      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
+      function() {return new XMLHttpRequest()}
+    ) || false;
+  },
+
+  activeRequestCount: 0
+}
+
+Ajax.Responders = {
+  responders: [],
+
+  _each: function(iterator) {
+    this.responders._each(iterator);
+  },
+
+  register: function(responderToAdd) {
+    if (!this.include(responderToAdd))
+      this.responders.push(responderToAdd);
+  },
+
+  unregister: function(responderToRemove) {
+    this.responders = this.responders.without(responderToRemove);
+  },
+
+  dispatch: function(callback, request, transport, json) {
+    this.each(function(responder) {
+      if (responder[callback] && typeof responder[callback] == 'function') {
+        try {
+          responder[callback].apply(responder, [request, transport, json]);
+        } catch (e) {}
+      }
+    });
+  }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+  onCreate: function() {
+    Ajax.activeRequestCount++;
+  },
+
+  onComplete: function() {
+    Ajax.activeRequestCount--;
+  }
+});
+
+Ajax.Base = function() {};
+Ajax.Base.prototype = {
+  setOptions: function(options) {
+    this.options = {
+      method:       'post',
+      asynchronous: true,
+      parameters:   ''
+    }
+    Object.extend(this.options, options || {});
+  },
+
+  responseIsSuccess: function() {
+    return this.transport.status == undefined
+        || this.transport.status == 0
+        || (this.transport.status >= 200 && this.transport.status < 300);
+  },
+
+  responseIsFailure: function() {
+    return !this.responseIsSuccess();
+  }
+}
+
+Ajax.Request = Class.create();
+Ajax.Request.Events =
+  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
+  initialize: function(url, options) {
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+    this.request(url);
+  },
+
+  request: function(url) {
+    var parameters = this.options.parameters || '';
+    if (parameters.length > 0) parameters += '&_=';
+
+    try {
+      this.url = url;
+      if (this.options.method == 'get' && parameters.length > 0)
+        this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
+
+      Ajax.Responders.dispatch('onCreate', this, this.transport);
+
+      this.transport.open(this.options.method, this.url,
+        this.options.asynchronous);
+
+      if (this.options.asynchronous) {
+        this.transport.onreadystatechange = this.onStateChange.bind(this);
+        setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
+      }
+
+      this.setRequestHeaders();
+
+      var body = this.options.postBody ? this.options.postBody : parameters;
+      this.transport.send(this.options.method == 'post' ? body : null);
+
+    } catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  setRequestHeaders: function() {
+    var requestHeaders =
+      ['X-Requested-With', 'XMLHttpRequest',
+       'X-Prototype-Version', Prototype.Version];
+
+    if (this.options.method == 'post') {
+      requestHeaders.push('Content-type',
+        'application/x-www-form-urlencoded');
+
+      /* Force "Connection: close" for Mozilla browsers to work around
+       * a bug where XMLHttpReqeuest sends an incorrect Content-length
+       * header. See Mozilla Bugzilla #246651.
+       */
+      if (this.transport.overrideMimeType)
+        requestHeaders.push('Connection', 'close');
+    }
+
+    if (this.options.requestHeaders)
+      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
+
+    for (var i = 0; i < requestHeaders.length; i += 2)
+      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
+  },
+
+  onStateChange: function() {
+    var readyState = this.transport.readyState;
+    if (readyState != 1)
+      this.respondToReadyState(this.transport.readyState);
+  },
+
+  header: function(name) {
+    try {
+      return this.transport.getResponseHeader(name);
+    } catch (e) {}
+  },
+
+  evalJSON: function() {
+    try {
+      return eval(this.header('X-JSON'));
+    } catch (e) {}
+  },
+
+  evalResponse: function() {
+    try {
+      return eval(this.transport.responseText);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  respondToReadyState: function(readyState) {
+    var event = Ajax.Request.Events[readyState];
+    var transport = this.transport, json = this.evalJSON();
+
+    if (event == 'Complete') {
+      try {
+        (this.options['on' + this.transport.status]
+         || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
+         || Prototype.emptyFunction)(transport, json);
+      } catch (e) {
+        this.dispatchException(e);
+      }
+
+      if ((this.header('Content-type') || '').match(/^text\/javascript/i))
+        this.evalResponse();
+    }
+
+    try {
+      (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
+      Ajax.Responders.dispatch('on' + event, this, transport, json);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+
+    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
+    if (event == 'Complete')
+      this.transport.onreadystatechange = Prototype.emptyFunction;
+  },
+
+  dispatchException: function(exception) {
+    (this.options.onException || Prototype.emptyFunction)(this, exception);
+    Ajax.Responders.dispatch('onException', this, exception);
+  }
+});
+
+Ajax.Updater = Class.create();
+
+Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
+  initialize: function(container, url, options) {
+    this.containers = {
+      success: container.success ? $(container.success) : $(container),
+      failure: container.failure ? $(container.failure) :
+        (container.success ? null : $(container))
+    }
+
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+
+    var onComplete = this.options.onComplete || Prototype.emptyFunction;
+    this.options.onComplete = (function(transport, object) {
+      this.updateContent();
+      onComplete(transport, object);
+    }).bind(this);
+
+    this.request(url);
+  },
+
+  updateContent: function() {
+    var receiver = this.responseIsSuccess() ?
+      this.containers.success : this.containers.failure;
+    var response = this.transport.responseText;
+
+    if (!this.options.evalScripts)
+      response = response.stripScripts();
+
+    if (receiver) {
+      if (this.options.insertion) {
+        new this.options.insertion(receiver, response);
+      } else {
+        Element.update(receiver, response);
+      }
+    }
+
+    if (this.responseIsSuccess()) {
+      if (this.onComplete)
+        setTimeout(this.onComplete.bind(this), 10);
+    }
+  }
+});
+
+Ajax.PeriodicalUpdater = Class.create();
+Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
+  initialize: function(container, url, options) {
+    this.setOptions(options);
+    this.onComplete = this.options.onComplete;
+
+    this.frequency = (this.options.frequency || 2);
+    this.decay = (this.options.decay || 1);
+
+    this.updater = {};
+    this.container = container;
+    this.url = url;
+
+    this.start();
+  },
+
+  start: function() {
+    this.options.onComplete = this.updateComplete.bind(this);
+    this.onTimerEvent();
+  },
+
+  stop: function() {
+    this.updater.onComplete = undefined;
+    clearTimeout(this.timer);
+    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+  },
+
+  updateComplete: function(request) {
+    if (this.options.decay) {
+      this.decay = (request.responseText == this.lastText ?
+        this.decay * this.options.decay : 1);
+
+      this.lastText = request.responseText;
+    }
+    this.timer = setTimeout(this.onTimerEvent.bind(this),
+      this.decay * this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    this.updater = new Ajax.Updater(this.container, this.url, this.options);
+  }
+});
+document.getElementsByClassName = function(className, parentElement) {
+  var children = ($(parentElement) || document.body).getElementsByTagName('*');
+  return $A(children).inject([], function(elements, child) {
+    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
+      elements.push(child);
+    return elements;
+  });
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Element) {
+  var Element = new Object();
+}
+
+Object.extend(Element, {
+  visible: function(element) {
+    return $(element).style.display != 'none';
+  },
+
+  toggle: function() {
+    for (var i = 0; i < arguments.length; i++) {
+      var element = $(arguments[i]);
+      Element[Element.visible(element) ? 'hide' : 'show'](element);
+    }
+  },
+
+  hide: function() {
+    for (var i = 0; i < arguments.length; i++) {
+      var element = $(arguments[i]);
+      element.style.display = 'none';
+    }
+  },
+
+  show: function() {
+    for (var i = 0; i < arguments.length; i++) {
+      var element = $(arguments[i]);
+      element.style.display = '';
+    }
+  },
+
+  remove: function(element) {
+    element = $(element);
+    element.parentNode.removeChild(element);
+  },
+
+  update: function(element, html) {
+    $(element).innerHTML = html.stripScripts();
+    setTimeout(function() {html.evalScripts()}, 10);
+  },
+
+  getHeight: function(element) {
+    element = $(element);
+    return element.offsetHeight;
+  },
+
+  classNames: function(element) {
+    return new Element.ClassNames(element);
+  },
+
+  hasClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    return Element.classNames(element).include(className);
+  },
+
+  addClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    return Element.classNames(element).add(className);
+  },
+
+  removeClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    return Element.classNames(element).remove(className);
+  },
+
+  // removes whitespace-only text node children
+  cleanWhitespace: function(element) {
+    element = $(element);
+    for (var i = 0; i < element.childNodes.length; i++) {
+      var node = element.childNodes[i];
+      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+        Element.remove(node);
+    }
+  },
+
+  empty: function(element) {
+    return $(element).innerHTML.match(/^\s*$/);
+  },
+
+  scrollTo: function(element) {
+    element = $(element);
+    var x = element.x ? element.x : element.offsetLeft,
+        y = element.y ? element.y : element.offsetTop;
+    window.scrollTo(x, y);
+  },
+
+  getStyle: function(element, style) {
+    element = $(element);
+    var value = element.style[style.camelize()];
+    if (!value) {
+      if (document.defaultView && document.defaultView.getComputedStyle) {
+        var css = document.defaultView.getComputedStyle(element, null);
+        value = css ? css.getPropertyValue(style) : null;
+      } else if (element.currentStyle) {
+        value = element.currentStyle[style.camelize()];
+      }
+    }
+
+    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
+      if (Element.getStyle(element, 'position') == 'static') value = 'auto';
+
+    return value == 'auto' ? null : value;
+  },
+
+  setStyle: function(element, style) {
+    element = $(element);
+    for (name in style)
+      element.style[name.camelize()] = style[name];
+  },
+
+  getDimensions: function(element) {
+    element = $(element);
+    if (Element.getStyle(element, 'display') != 'none')
+      return {width: element.offsetWidth, height: element.offsetHeight};
+
+    // All *Width and *Height properties give 0 on elements with display none,
+    // so enable the element temporarily
+    var els = element.style;
+    var originalVisibility = els.visibility;
+    var originalPosition = els.position;
+    els.visibility = 'hidden';
+    els.position = 'absolute';
+    els.display = '';
+    var originalWidth = element.clientWidth;
+    var originalHeight = element.clientHeight;
+    els.display = 'none';
+    els.position = originalPosition;
+    els.visibility = originalVisibility;
+    return {width: originalWidth, height: originalHeight};
+  },
+
+  makePositioned: function(element) {
+    element = $(element);
+    var pos = Element.getStyle(element, 'position');
+    if (pos == 'static' || !pos) {
+      element._madePositioned = true;
+      element.style.position = 'relative';
+      // Opera returns the offset relative to the positioning context, when an
+      // element is position relative but top and left have not been defined
+      if (window.opera) {
+        element.style.top = 0;
+        element.style.left = 0;
+      }
+    }
+  },
+
+  undoPositioned: function(element) {
+    element = $(element);
+    if (element._madePositioned) {
+      element._madePositioned = undefined;
+      element.style.position =
+        element.style.top =
+        element.style.left =
+        element.style.bottom =
+        element.style.right = '';
+    }
+  },
+
+  makeClipping: function(element) {
+    element = $(element);
+    if (element._overflow) return;
+    element._overflow = element.style.overflow;
+    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
+      element.style.overflow = 'hidden';
+  },
+
+  undoClipping: function(element) {
+    element = $(element);
+    if (element._overflow) return;
+    element.style.overflow = element._overflow;
+    element._overflow = undefined;
+  }
+});
+
+var Toggle = new Object();
+Toggle.display = Element.toggle;
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.Insertion = function(adjacency) {
+  this.adjacency = adjacency;
+}
+
+Abstract.Insertion.prototype = {
+  initialize: function(element, content) {
+    this.element = $(element);
+    this.content = content.stripScripts();
+
+    if (this.adjacency && this.element.insertAdjacentHTML) {
+      try {
+        this.element.insertAdjacentHTML(this.adjacency, this.content);
+      } catch (e) {
+        if (this.element.tagName.toLowerCase() == 'tbody') {
+          this.insertContent(this.contentFromAnonymousTable());
+        } else {
+          throw e;
+        }
+      }
+    } else {
+      this.range = this.element.ownerDocument.createRange();
+      if (this.initializeRange) this.initializeRange();
+      this.insertContent([this.range.createContextualFragment(this.content)]);
+    }
+
+    setTimeout(function() {content.evalScripts()}, 10);
+  },
+
+  contentFromAnonymousTable: function() {
+    var div = document.createElement('div');
+    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
+    return $A(div.childNodes[0].childNodes[0].childNodes);
+  }
+}
+
+var Insertion = new Object();
+
+Insertion.Before = Class.create();
+Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
+  initializeRange: function() {
+    this.range.setStartBefore(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.parentNode.insertBefore(fragment, this.element);
+    }).bind(this));
+  }
+});
+
+Insertion.Top = Class.create();
+Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(true);
+  },
+
+  insertContent: function(fragments) {
+    fragments.reverse(false).each((function(fragment) {
+      this.element.insertBefore(fragment, this.element.firstChild);
+    }).bind(this));
+  }
+});
+
+Insertion.Bottom = Class.create();
+Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.appendChild(fragment);
+    }).bind(this));
+  }
+});
+
+Insertion.After = Class.create();
+Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
+  initializeRange: function() {
+    this.range.setStartAfter(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.parentNode.insertBefore(fragment,
+        this.element.nextSibling);
+    }).bind(this));
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+  initialize: function(element) {
+    this.element = $(element);
+  },
+
+  _each: function(iterator) {
+    this.element.className.split(/\s+/).select(function(name) {
+      return name.length > 0;
+    })._each(iterator);
+  },
+
+  set: function(className) {
+    this.element.className = className;
+  },
+
+  add: function(classNameToAdd) {
+    if (this.include(classNameToAdd)) return;
+    this.set(this.toArray().concat(classNameToAdd).join(' '));
+  },
+
+  remove: function(classNameToRemove) {
+    if (!this.include(classNameToRemove)) return;
+    this.set(this.select(function(className) {
+      return className != classNameToRemove;
+    }).join(' '));
+  },
+
+  toString: function() {
+    return this.toArray().join(' ');
+  }
+}
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+var Field = {
+  clear: function() {
+    for (var i = 0; i < arguments.length; i++)
+      $(arguments[i]).value = '';
+  },
+
+  focus: function(element) {
+    $(element).focus();
+  },
+
+  present: function() {
+    for (var i = 0; i < arguments.length; i++)
+      if ($(arguments[i]).value == '') return false;
+    return true;
+  },
+
+  select: function(element) {
+    $(element).select();
+  },
+
+  activate: function(element) {
+    element = $(element);
+    element.focus();
+    if (element.select)
+      element.select();
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Form = {
+  serialize: function(form) {
+    var elements = Form.getElements($(form));
+    var queryComponents = new Array();
+
+    for (var i = 0; i < elements.length; i++) {
+      var queryComponent = Form.Element.serialize(elements[i]);
+      if (queryComponent)
+        queryComponents.push(queryComponent);
+    }
+
+    return queryComponents.join('&');
+  },
+
+  getElements: function(form) {
+    form = $(form);
+    var elements = new Array();
+
+    for (tagName in Form.Element.Serializers) {
+      var tagElements = form.getElementsByTagName(tagName);
+      for (var j = 0; j < tagElements.length; j++)
+        elements.push(tagElements[j]);
+    }
+    return elements;
+  },
+
+  getInputs: function(form, typeName, name) {
+    form = $(form);
+    var inputs = form.getElementsByTagName('input');
+
+    if (!typeName && !name)
+      return inputs;
+
+    var matchingInputs = new Array();
+    for (var i = 0; i < inputs.length; i++) {
+      var input = inputs[i];
+      if ((typeName && input.type != typeName) ||
+          (name && input.name != name))
+        continue;
+      matchingInputs.push(input);
+    }
+
+    return matchingInputs;
+  },
+
+  disable: function(form) {
+    var elements = Form.getElements(form);
+    for (var i = 0; i < elements.length; i++) {
+      var element = elements[i];
+      element.blur();
+      element.disabled = 'true';
+    }
+  },
+
+  enable: function(form) {
+    var elements = Form.getElements(form);
+    for (var i = 0; i < elements.length; i++) {
+      var element = elements[i];
+      element.disabled = '';
+    }
+  },
+
+  findFirstElement: function(form) {
+    return Form.getElements(form).find(function(element) {
+      return element.type != 'hidden' && !element.disabled &&
+        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+    });
+  },
+
+  focusFirstElement: function(form) {
+    Field.activate(Form.findFirstElement(form));
+  },
+
+  reset: function(form) {
+    $(form).reset();
+  }
+}
+
+Form.Element = {
+  serialize: function(element) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    var parameter = Form.Element.Serializers[method](element);
+
+    if (parameter) {
+      var key = encodeURIComponent(parameter[0]);
+      if (key.length == 0) return;
+
+      if (parameter[1].constructor != Array)
+        parameter[1] = [parameter[1]];
+
+      return parameter[1].map(function(value) {
+        return key + '=' + encodeURIComponent(value);
+      }).join('&');
+    }
+  },
+
+  getValue: function(element) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    var parameter = Form.Element.Serializers[method](element);
+
+    if (parameter)
+      return parameter[1];
+  }
+}
+
+Form.Element.Serializers = {
+  input: function(element) {
+    switch (element.type.toLowerCase()) {
+      case 'submit':
+      case 'hidden':
+      case 'password':
+      case 'text':
+        return Form.Element.Serializers.textarea(element);
+      case 'checkbox':
+      case 'radio':
+        return Form.Element.Serializers.inputSelector(element);
+    }
+    return false;
+  },
+
+  inputSelector: function(element) {
+    if (element.checked)
+      return [element.name, element.value];
+  },
+
+  textarea: function(element) {
+    return [element.name, element.value];
+  },
+
+  select: function(element) {
+    return Form.Element.Serializers[element.type == 'select-one' ?
+      'selectOne' : 'selectMany'](element);
+  },
+
+  selectOne: function(element) {
+    var value = '', opt, index = element.selectedIndex;
+    if (index >= 0) {
+      opt = element.options[index];
+      value = opt.value;
+      if (!value && !('value' in opt))
+        value = opt.text;
+    }
+    return [element.name, value];
+  },
+
+  selectMany: function(element) {
+    var value = new Array();
+    for (var i = 0; i < element.length; i++) {
+      var opt = element.options[i];
+      if (opt.selected) {
+        var optValue = opt.value;
+        if (!optValue && !('value' in opt))
+          optValue = opt.text;
+        value.push(optValue);
+      }
+    }
+    return [element.name, value];
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var $F = Form.Element.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = function() {}
+Abstract.TimedObserver.prototype = {
+  initialize: function(element, frequency, callback) {
+    this.frequency = frequency;
+    this.element   = $(element);
+    this.callback  = callback;
+
+    this.lastValue = this.getValue();
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  }
+}
+
+Form.Element.Observer = Class.create();
+Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.Observer = Class.create();
+Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = function() {}
+Abstract.EventObserver.prototype = {
+  initialize: function(element, callback) {
+    this.element  = $(element);
+    this.callback = callback;
+
+    this.lastValue = this.getValue();
+    if (this.element.tagName.toLowerCase() == 'form')
+      this.registerFormCallbacks();
+    else
+      this.registerCallback(this.element);
+  },
+
+  onElementEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  },
+
+  registerFormCallbacks: function() {
+    var elements = Form.getElements(this.element);
+    for (var i = 0; i < elements.length; i++)
+      this.registerCallback(elements[i]);
+  },
+
+  registerCallback: function(element) {
+    if (element.type) {
+      switch (element.type.toLowerCase()) {
+        case 'checkbox':
+        case 'radio':
+          Event.observe(element, 'click', this.onElementEvent.bind(this));
+          break;
+        case 'password':
+        case 'text':
+        case 'textarea':
+        case 'select-one':
+        case 'select-multiple':
+          Event.observe(element, 'change', this.onElementEvent.bind(this));
+          break;
+      }
+    }
+  }
+}
+
+Form.Element.EventObserver = Class.create();
+Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.EventObserver = Class.create();
+Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+if (!window.Event) {
+  var Event = new Object();
+}
+
+Object.extend(Event, {
+  KEY_BACKSPACE: 8,
+  KEY_TAB:       9,
+  KEY_RETURN:   13,
+  KEY_ESC:      27,
+  KEY_LEFT:     37,
+  KEY_UP:       38,
+  KEY_RIGHT:    39,
+  KEY_DOWN:     40,
+  KEY_DELETE:   46,
+
+  element: function(event) {
+    return event.target || event.srcElement;
+  },
+
+  isLeftClick: function(event) {
+    return (((event.which) && (event.which == 1)) ||
+            ((event.button) && (event.button == 1)));
+  },
+
+  pointerX: function(event) {
+    return event.pageX || (event.clientX +
+      (document.documentElement.scrollLeft || document.body.scrollLeft));
+  },
+
+  pointerY: function(event) {
+    return event.pageY || (event.clientY +
+      (document.documentElement.scrollTop || document.body.scrollTop));
+  },
+
+  stop: function(event) {
+    if (event.preventDefault) {
+      event.preventDefault();
+      event.stopPropagation();
+    } else {
+      event.returnValue = false;
+      event.cancelBubble = true;
+    }
+  },
+
+  // find the first node with the given tagName, starting from the
+  // node the event was triggered on; traverses the DOM upwards
+  findElement: function(event, tagName) {
+    var element = Event.element(event);
+    while (element.parentNode && (!element.tagName ||
+        (element.tagName.toUpperCase() != tagName.toUpperCase())))
+      element = element.parentNode;
+    return element;
+  },
+
+  observers: false,
+
+  _observeAndCache: function(element, name, observer, useCapture) {
+    if (!this.observers) this.observers = [];
+    if (element.addEventListener) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.addEventListener(name, observer, useCapture);
+    } else if (element.attachEvent) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.attachEvent('on' + name, observer);
+    }
+  },
+
+  unloadCache: function() {
+    if (!Event.observers) return;
+    for (var i = 0; i < Event.observers.length; i++) {
+      Event.stopObserving.apply(this, Event.observers[i]);
+      Event.observers[i][0] = null;
+    }
+    Event.observers = false;
+  },
+
+  observe: function(element, name, observer, useCapture) {
+    var element = $(element);
+    useCapture = useCapture || false;
+
+    if (name == 'keypress' &&
+        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
+        || element.attachEvent))
+      name = 'keydown';
+
+    this._observeAndCache(element, name, observer, useCapture);
+  },
+
+  stopObserving: function(element, name, observer, useCapture) {
+    var element = $(element);
+    useCapture = useCapture || false;
+
+    if (name == 'keypress' &&
+        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
+        || element.detachEvent))
+      name = 'keydown';
+
+    if (element.removeEventListener) {
+      element.removeEventListener(name, observer, useCapture);
+    } else if (element.detachEvent) {
+      element.detachEvent('on' + name, observer);
+    }
+  }
+});
+
+/* prevent memory leaks in IE */
+Event.observe(window, 'unload', Event.unloadCache, false);
+var Position = {
+  // set to true if needed, warning: firefox performance problems
+  // NOT neeeded for page scrolling, only if draggable contained in
+  // scrollable elements
+  includeScrollOffsets: false,
+
+  // must be called before calling withinIncludingScrolloffset, every time the
+  // page is scrolled
+  prepare: function() {
+    this.deltaX =  window.pageXOffset
+                || document.documentElement.scrollLeft
+                || document.body.scrollLeft
+                || 0;
+    this.deltaY =  window.pageYOffset
+                || document.documentElement.scrollTop
+                || document.body.scrollTop
+                || 0;
+  },
+
+  realOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.scrollTop  || 0;
+      valueL += element.scrollLeft || 0;
+      element = element.parentNode;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  cumulativeOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  positionedOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+      if (element) {
+        p = Element.getStyle(element, 'position');
+        if (p == 'relative' || p == 'absolute') break;
+      }
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  offsetParent: function(element) {
+    if (element.offsetParent) return element.offsetParent;
+    if (element == document.body) return element;
+
+    while ((element = element.parentNode) && element != document.body)
+      if (Element.getStyle(element, 'position') != 'static')
+        return element;
+
+    return document.body;
+  },
+
+  // caches x/y coordinate pair to use with overlap
+  within: function(element, x, y) {
+    if (this.includeScrollOffsets)
+      return this.withinIncludingScrolloffsets(element, x, y);
+    this.xcomp = x;
+    this.ycomp = y;
+    this.offset = this.cumulativeOffset(element);
+
+    return (y >= this.offset[1] &&
+            y <  this.offset[1] + element.offsetHeight &&
+            x >= this.offset[0] &&
+            x <  this.offset[0] + element.offsetWidth);
+  },
+
+  withinIncludingScrolloffsets: function(element, x, y) {
+    var offsetcache = this.realOffset(element);
+
+    this.xcomp = x + offsetcache[0] - this.deltaX;
+    this.ycomp = y + offsetcache[1] - this.deltaY;
+    this.offset = this.cumulativeOffset(element);
+
+    return (this.ycomp >= this.offset[1] &&
+            this.ycomp <  this.offset[1] + element.offsetHeight &&
+            this.xcomp >= this.offset[0] &&
+            this.xcomp <  this.offset[0] + element.offsetWidth);
+  },
+
+  // within must be called directly before
+  overlap: function(mode, element) {
+    if (!mode) return 0;
+    if (mode == 'vertical')
+      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+        element.offsetHeight;
+    if (mode == 'horizontal')
+      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+        element.offsetWidth;
+  },
+
+  clone: function(source, target) {
+    source = $(source);
+    target = $(target);
+    target.style.position = 'absolute';
+    var offsets = this.cumulativeOffset(source);
+    target.style.top    = offsets[1] + 'px';
+    target.style.left   = offsets[0] + 'px';
+    target.style.width  = source.offsetWidth + 'px';
+    target.style.height = source.offsetHeight + 'px';
+  },
+
+  page: function(forElement) {
+    var valueT = 0, valueL = 0;
+
+    var element = forElement;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+
+      // Safari fix
+      if (element.offsetParent==document.body)
+        if (Element.getStyle(element,'position')=='absolute') break;
+
+    } while (element = element.offsetParent);
+
+    element = forElement;
+    do {
+      valueT -= element.scrollTop  || 0;
+      valueL -= element.scrollLeft || 0;
+    } while (element = element.parentNode);
+
+    return [valueL, valueT];
+  },
+
+  clone: function(source, target) {
+    var options = Object.extend({
+      setLeft:    true,
+      setTop:     true,
+      setWidth:   true,
+      setHeight:  true,
+      offsetTop:  0,
+      offsetLeft: 0
+    }, arguments[2] || {})
+
+    // find page position of source
+    source = $(source);
+    var p = Position.page(source);
+
+    // find coordinate system to use
+    target = $(target);
+    var delta = [0, 0];
+    var parent = null;
+    // delta [0,0] will do fine with position: fixed elements,
+    // position:absolute needs offsetParent deltas
+    if (Element.getStyle(target,'position') == 'absolute') {
+      parent = Position.offsetParent(target);
+      delta = Position.page(parent);
+    }
+
+    // correct by body offsets (fixes Safari)
+    if (parent == document.body) {
+      delta[0] -= document.body.offsetLeft;
+      delta[1] -= document.body.offsetTop;
+    }
+
+    // set position
+    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
+    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
+    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
+    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
+  },
+
+  absolutize: function(element) {
+    element = $(element);
+    if (element.style.position == 'absolute') return;
+    Position.prepare();
+
+    var offsets = Position.positionedOffset(element);
+    var top     = offsets[1];
+    var left    = offsets[0];
+    var width   = element.clientWidth;
+    var height  = element.clientHeight;
+
+    element._originalLeft   = left - parseFloat(element.style.left  || 0);
+    element._originalTop    = top  - parseFloat(element.style.top || 0);
+    element._originalWidth  = element.style.width;
+    element._originalHeight = element.style.height;
+
+    element.style.position = 'absolute';
+    element.style.top    = top + 'px';;
+    element.style.left   = left + 'px';;
+    element.style.width  = width + 'px';;
+    element.style.height = height + 'px';;
+  },
+
+  relativize: function(element) {
+    element = $(element);
+    if (element.style.position == 'relative') return;
+    Position.prepare();
+
+    element.style.position = 'relative';
+    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
+    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.height = element._originalHeight;
+    element.style.width  = element._originalWidth;
+  }
+}
+
+// Safari returns margins on body which is incorrect if the child is absolutely
+// positioned.  For performance reasons, redefine Position.cumulativeOffset for
+// KHTML/WebKit only.
+if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
+  Position.cumulativeOffset = function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      if (element.offsetParent == document.body)
+        if (Element.getStyle(element, 'position') == 'absolute') break;
+
+      element = element.offsetParent;
+    } while (element);
+
+    return [valueL, valueT];
+  }
+}
\ No newline at end of file
diff --git a/easy-asterisk-gui/cgi-bin/set_network.sh b/easy-asterisk-gui/cgi-bin/set_network.sh
new file mode 100755 (executable)
index 0000000..23c69e7
--- /dev/null
@@ -0,0 +1,64 @@
+#!/bin/sh
+# set_network.sh
+#
+# CGI to set network parameters of an IP0X.
+
+cat <<EOF
+<html>
+<head>
+<title>set_network.sh</title>
+<meta http-equiv="REFRESH" content="0;url=http:network.sh">
+<body>
+Please wait a few seconds.....
+</body>
+</head>
+</html>
+EOF
+
+dhcp=`echo "$QUERY_STRING" | grep -oe "dhcp=[^&?]*" | sed -n "s/dhcp=//p"`
+ipaddress=`echo "$QUERY_STRING" | grep -oe "ipaddress=[^&?]*" | sed -n "s/ipaddress=//p"`
+netmask=`echo "$QUERY_STRING" | grep -oe "netmask=[^&?]*" | sed -n "s/netmask=//p"`
+gateway=`echo "$QUERY_STRING" | grep -oe "gateway=[^&?]*" | sed -n "s/gateway=//p"`
+dns=`echo "$QUERY_STRING" | grep -oe "dns=[^&?]*" | sed -n "s/dns=//p"`
+backdoor=`echo "$QUERY_STRING" | grep -oe "backdoor=[^&?]*" | sed -n "s/backdoor=//p"`
+
+if [ $dhcp == "yes" ]; then
+
+  # DHCP
+
+  if [ -f /etc/rc.d/S10network-static ]; then
+    /etc/init.d/network-static disable
+    /etc/init.d/network-static stop
+    /etc/init.d/network enable
+    /etc/init.d/network start
+  else
+    # if already running restart service
+    /etc/init.d/network stop
+    /etc/init.d/network start
+  fi
+fi
+
+if [ $dhcp == "no" ]; then
+  
+  # Static IP
+
+  if [ -f /etc/rc.d/S10network ]; then
+    /etc/init.d/network stop
+    /etc/init.d/network disable
+    /etc/init.d/network-static enable
+  fi
+  
+  sed -i "s/DHCPD=.*/DHCPD=no/g" /etc/init.d/network-static
+  sed -i "s/IPADDRESS=.*/IPADDRESS=\"$ipaddress\"/g" /etc/init.d/network-static
+  sed -i "s/NETMASK=.*/NETMASK=\"$netmask\"/g" /etc/init.d/network-static
+  sed -i "s/GATEWAY=.*/GATEWAY=\"$gateway\"/g" /etc/init.d/network-static
+  sed -i "s/DNS=.*/DNS=\"$dns\"/g" /etc/init.d/network-static
+  /etc/init.d/network-static stop
+  /etc/init.d/network-static start
+fi
+
+if [ -f /etc/rc.d/S05network-backdoor ]; then
+  sed -i "s/IPADDRESS=.*/IPADDRESS=\"$backdoor\"/g" /etc/init.d/network-backdoor
+  /etc/init.d/network-backdoor stop
+  /etc/init.d/network-backdoor start
+fi
diff --git a/easy-asterisk-gui/cgi-bin/set_ring.sh b/easy-asterisk-gui/cgi-bin/set_ring.sh
new file mode 100644 (file)
index 0000000..c7b559c
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/sh -x
+# set_ring.sh
+# David Rowe 4 Jan 2010
+# CGI to set which extensions ring on uncoming calls
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+    echo "<html>"
+    echo "<head>"
+    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
+    echo "</head>"
+    echo "</html>"
+    exit
+fi
+
+# extract extensions to ring and reload extensions.conf
+
+a=`echo "$QUERY_STRING" | sed -n "s/=on*//pg" | sed -n 's,_,/,pg'`
+
+# escape & if present
+echo "$a" | grep "&" >> /dev/null
+if [ $? -eq 0 ]; then
+  a=`echo $a | sed -n "s/&/\\\\&/pg"`
+fi
+
+sed -i "s_s,1,Dial(.*) ;; easy-asterisk_s,1,Dial($a) ;; easy-asterisk_" /etc/asterisk/extensions.conf
+asterisk -rx "dialplan reload" 2>/dev/null 1 > /dev/null
+
+# bounce us back to Phones screen
+
+cat <<EOF
+<html>
+<head>
+<title>Easy Asterisk - Set Ring</title>
+<meta http-equiv="REFRESH" content="0;url=http:phones.sh">
+<body>
+Please wait a few seconds.....
+EOF
+#echo $QUERY_STRING "<br>"
+#echo "$QUERY_STRING" | sed -n "s/=on*//pg" | sed -n 's,_,/,pg'
+#echo "<br>"
+#echo $a
+
+cat <<EOF
+</body>
+</head>
+</html>
+EOF
+
diff --git a/easy-asterisk-gui/cgi-bin/set_voiplines.sh b/easy-asterisk-gui/cgi-bin/set_voiplines.sh
new file mode 100644 (file)
index 0000000..696d4f4
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/sh
+# set_voipline.sh
+# # David Rowe 12 Jan 2010
+#
+# CGI to set voip line parameters in sip.conf.
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+    echo "<html>"
+    echo "<head>"
+    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
+    echo "</head>"
+    echo "</html>"
+    exit
+fi
+
+user=`echo "$QUERY_STRING" | grep -oe "user=[^&?]*" | sed -n "s/user=//p"`
+pass=`echo "$QUERY_STRING" | grep -oe "pass=[^&?]*" | sed -n "s/pass=//p"`
+host=`echo "$QUERY_STRING" | grep -oe "host=[^&?]*" | sed -n "s/host=//p"`
+stanza=`echo "$QUERY_STRING" | grep -oe "stanza=[^&?]*" | sed -n "s/stanza=//p"`
+
+# create new sip.conf with selected provider uncommented
+
+echo "set_voiplines.sh" $user $pass $host $stanza >> /tmp/log.txt
+./set_voiplines.pl $user $pass $host $stanza > /etc/asterisk/sip.conf.new
+mv /etc/asterisk/sip.conf /etc/asterisk/sip.conf.bak
+mv /etc/asterisk/sip.conf.new /etc/asterisk/sip.conf
+
+# get asterisk to load changes
+
+asterisk -rx "sip reload" 2>/dev/null 1 > /dev/null
+
+cat <<EOF
+<html>
+<head>
+<title>set_voiplines.sh</title>
+<meta http-equiv="REFRESH" content="0;url=http:voiplines.sh">
+<body>
+Please wait a few seconds.....
+</body>
+</head>
+</html>
+EOF
+
diff --git a/easy-asterisk-gui/cgi-bin/tick.png b/easy-asterisk-gui/cgi-bin/tick.png
new file mode 100644 (file)
index 0000000..c155dff
Binary files /dev/null and b/easy-asterisk-gui/cgi-bin/tick.png differ
diff --git a/easy-asterisk-gui/cgi-bin/tooltip.css b/easy-asterisk-gui/cgi-bin/tooltip.css
new file mode 100644 (file)
index 0000000..f426356
--- /dev/null
@@ -0,0 +1,7 @@
+.tip {font:12px/14px
+Arial,Helvetica,sans-serif; border:solid 1px
+#666666; width:270px; padding:1px;
+position:absolute; z-index:100;
+visibility:hidden; color:#333333; top:20px;
+left:90px; background-color:#ffffcc;
+layer-background-color:#ffffcc;}
diff --git a/easy-asterisk-gui/cgi-bin/tooltip.js b/easy-asterisk-gui/cgi-bin/tooltip.js
new file mode 100644 (file)
index 0000000..26142e8
--- /dev/null
@@ -0,0 +1,7 @@
+// Extended Tooltip Javascript
+// copyright 9th August 2002, 3rd July 2005, 24th August 2008
+// by Stephen Chapman, Felgall Pty Ltd
+
+// permission is granted to use this javascript provided that the below code is not altered
+function pw() {return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth}; function mouseX(evt) {return evt.clientX ? evt.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) : evt.pageX;} function mouseY(evt) {return evt.clientY ? evt.clientY + (document.documentElement.scrollTop || document.body.scrollTop) : evt.pageY} function popUp(evt,oi) {if (document.getElementById) {var wp = pw(); dm = document.getElementById(oi); ds = dm.style; st = ds.visibility; if (dm.offsetWidth) ew = dm.offsetWidth; else if (dm.clip.width) ew = dm.clip.width; if (st == "visible" || st == "show") { ds.visibility = "hidden"; } else {tv = mouseY(evt) + 20; lv = mouseX(evt) - (ew/4); if (lv < 2) lv = 2; else if (lv + ew > wp) lv -= ew/2; lv += 'px';tv += 'px';  ds.left = lv; ds.top = tv; ds.visibility = "visible";}}}
+                  
diff --git a/easy-asterisk-gui/cgi-bin/tooltips.html b/easy-asterisk-gui/cgi-bin/tooltips.html
new file mode 100644 (file)
index 0000000..dab4bff
--- /dev/null
@@ -0,0 +1,137 @@
+<div id="network_internet" class="tip">
+                         A tick means your phone system can reach the Internet.  You need the Internet for VOIP calls
+                         and software upgrades.  
+                         If you have a problem reaching the Internet check your Network settings, in 
+                         particular Gateway and DNS.</div>
+
+<div id="network_backdoor" class="tip">
+                         Emergency backdoor IP. Useful if you get locked out of the main network connection, for 
+                         example due to DHCP problems on your network or a configuration mistake.  
+                         Write this number down somewhere!</div>
+
+<div id="phone_reception" class="tip">
+                         If ticked this phone will ring when some one
+                         calls the phone system from an outside Analog
+                         or VOIP Line.  More than one phone can be
+                         ticked.  You can answer a call on another
+                         ringing phone by dialling *8 on your phone -
+                         see FAQ for details.</div>
+
+<div id="phone_anphone" class="tip">
+                         Analog Phone: Normal telephone plugged into a port on your phone system.
+                         </div>
+<div id="phone_ipphone" class="tip">
+                         IP Phone plugged into your network.
+                         </div>
+<div id="phone_line" class="tip">
+                         Analog Phone Line: Analog telephone line plugged into a port on your phone system.
+                         </div>
+<div id="phone_voipline" class="tip">
+                         VOIP  Phone Line: Make and receive phone calls over the Internet.
+                         </div>
+
+<div id="phone_system" class="tip">
+                         Important information about your Phone System.</div>
+
+<div id="phone_ipaddress" class="tip">
+                         The address of your Phone System
+                         on your network.  Use this address to connect
+                         IP Phones to your Phone System.  </div>
+
+<div id="phone_phones" class="tip">
+                         List of phones connected to your Phone
+                         System.  You can connect Analog or IP Phones
+                         to your system.  When IP Phones are
+                         configured correctly, they appear on this
+                         list.  If an IP phone is not configured
+                         correctly, it will not appear on this list.
+                         Analog phones require hardware to be
+                         installed in your Phone system.</div>
+
+<div id="phone_lines" class="tip">
+                         List of phone lines available.  Phone lines
+                         are used to make and receive outside calls.
+                         You can use regular Analog phone lines or
+                         VOIP.  VOIP phone lines require an account
+                         with an Internet Telephone Service Provider.
+                         Analog phone lines require hardware to be
+                         installed in your Phone System.</div>
+
+<div id="phone_ext" class="tip">
+                        Dial this number to call this phone</div>
+
+<div id="phone_port_phone" class="tip">
+                        Port (socket) on the rear of your Phone System.  Plug the phone into this Port.</div>
+
+<div id="phone_port_line" class="tip">
+                        Port (socket) on the rear of your Phone
+                        System.  Plug the phone line into this
+                        Port.</div>
+
+<div id="phone_line_prefix" class="tip">
+                        Dial 0 for an Analog outside line.  For example to call 5551234 dial 05551234</div>
+
+<div id="phone_ipphone_ip" class="tip">
+                        IP Address of this phone on your network</div>
+
+<div id="phone_voipline_ip" class="tip">
+                        IP Address of the VOIP Internet Telephone Service Provider</div>
+
+<div id="phone_voipline_prefix" class="tip">
+                        Dial 1 for a VOIP outside line.  For example to call 5551234 dial 15551234</div>
+
+<div id="phone_addipphone" class="tip">
+                        Instructions and help on adding a new IP phone</div>
+
+<div id="phone_addvoipline" class="tip">
+                        Instructions and help on VOIP Line set up</div>
+
+<div id="ipphones_ipphones" class="tip">
+                        List of possible IP phones.  For a new phone
+                        choose any Available number.  Refresh this
+                        page to update</div>
+
+<div id="ipphones_connected" class="tip">
+                        The IP phone is connected to your phone system and ready to use</div>
+
+<div id="ipphones_notconnected" class="tip">
+                        No IP phone is connected.  Either no IP phone
+                        is present, or the IP phone has not been set
+                        up.</div>
+
+<div id="voiplines_voiplines" class="tip">
+                        A VOIP line allows you to make and receive
+                       phones calls over the Internet.  Normally a
+                       VOIP line is provided by an Internet Telephony
+                       Service Provider (ITSP).  They will give you
+                       an account, which includes the user and
+                       password details that you can fill in below.
+                       Refresh this page on your browser to see if
+                       your VOIP line is working.  </div>
+
+<div id="voiplines_provider" class="tip">
+                        Your Internet Telephony Service Provider.
+                        They will give you an account with a user name
+                        and password.</div>
+
+<div id="voiplines_user" class="tip">
+                        Your account name with your Internet Telephony Service Provider</div>
+
+<div id="voiplines_pass" class="tip">
+                        The password for your Internet Telephony Service Provider account</div>
+
+<div id="voiplines_host" class="tip">
+                        The Internet address of your Internet
+                        Telephony Service Provider.  This will usually
+                        be filled in automatically.</div>
+
+<div id="voiplines_status" class="tip">
+                        A tick means you are connected to your
+                        Internet Telephony Service Provider.  Refresh
+                        your browser to update.</div>
+
+<div id="admin_restart" class="tip">
+                        Press this button to restart your phone
+                        system.  This is the same as turning the power
+                        off and back on. </div>
+
diff --git a/easy-asterisk-gui/cgi-bin/voipline.jpg b/easy-asterisk-gui/cgi-bin/voipline.jpg
new file mode 100644 (file)
index 0000000..d84b105
Binary files /dev/null and b/easy-asterisk-gui/cgi-bin/voipline.jpg differ
diff --git a/easy-asterisk-gui/cgi-bin/voiplines.js b/easy-asterisk-gui/cgi-bin/voiplines.js
new file mode 100644 (file)
index 0000000..083838a
--- /dev/null
@@ -0,0 +1,7 @@
+function changeProvider() {
+       provider = $('provider').value;
+       $('user').value = users[provider];
+       $('pass').value = passwords[provider];
+       $('host').value = hosts[provider];
+       $('stanza').value = stanzas[provider];
+}
diff --git a/easy-asterisk-gui/cgi-bin/voiplines.pl b/easy-asterisk-gui/cgi-bin/voiplines.pl
new file mode 100755 (executable)
index 0000000..64b5a2c
--- /dev/null
@@ -0,0 +1,136 @@
+#!/sbin/microperl
+# voiplines.pl
+# David Rowe 12 Jan 2010
+#
+# Text processing for the voiplines screen
+
+# slurp up list of possible voip line providers --------------------------------
+# one of these will be currently selected
+
+open SIP, "/etc/asterisk/sip.conf";
+my $provider = ""; # current provider bring parsed in sip.conf
+my @providers=();  # list of all providers
+my %stanza = ();   # stanza name keyed on provider
+my %user = ();     # user keyed on provider
+my %pass = ();     # password keyed on provider
+my %host = ();     # host name keyed on provider
+
+while (<SIP>) { 
+
+    # start of any stanza switches off parsing.  It may get switched
+    # back on below if it contains easy-asterisk keyword. This allows
+    # non-easy asterisk SIP devices to be included in sip.conf
+
+    if (/\[/) {
+       $provider = ""; 
+    }
+
+    # currently disabled easy-asterisk provider
+
+    if (/^;\[(.*)\].* \"(.*)\" easy-asterisk/) {
+       push (@providers, $2);
+       $provider = $2;
+       $stanza{$2} = $1;
+       #print "'$1' '$2'\n";   
+    }
+
+    # current easy-asterisk provider
+
+    if (/^\[(.*)\].* \"(.*)\" easy-asterisk/) {
+       push (@providers, $2);
+       $provider = $2;
+       $provider_current = $2;
+       $stanza{$2} = $1;
+       #print "'$1' '$2'\n";
+    }
+
+    if ($provider ne "") {
+       #print $_;
+
+       if (/^;*user=(.*)/) {
+           $user{$provider} = $1;
+       }
+       if (/^;*username=(.*)/) {
+           $user{$provider} = $1;
+       }
+       if (/^;*secret=(.*)/) {
+           $pass{$provider} = $1;
+       }
+       if (/^;*host=(.*)/) {
+           $host{$provider} = $1;
+       }
+    }
+
+    $state = $next_state;
+}
+close SIP;
+
+# Determine if Asterisk can see current voip line (SIP trunk) 
+# sipshowpeers.txt needs to be generated before calling this perl
+# script
+
+my %voip = (); # SIP trunks status keyed on sip.conf stanza name/username
+               # if no entry we can't see SIP trunk
+
+open SIP, "sipshowregistry.txt";
+while (<SIP>) { 
+    if (/^(.*):.*(Registered)/) {
+        $voip{$1} = $2;
+       #print "'$1' '$2' $voip{$1}\n";
+    }
+}
+
+close SIP;
+
+# javascript to handle changing providers
+
+print "<script>\n";
+print "var hosts = new Array();\n";
+print "var users = new Array();\n";
+print "var passwords = new Array();\n";
+print "var stanzas = new Array();\n";
+foreach (@providers) {
+    print "hosts[\'$_\'] = \'$host{$_}\';\n";
+    print "users[\'$_\'] = \'$user{$_}\';\n";
+    print "passwords[\'$_\'] = \'$pass{$_}\';\n";
+    print "stanzas[\'$_\'] = \'$stanza{$_}\';\n";
+}
+print "</script>\n";
+
+# generate form fields -------------------------------------------
+
+$tt_provider = "onMouseOver=\"popUp(event,'voiplines_provider')\" onmouseout=\"popUp(event,'voiplines_provider')\"";
+$tt_user = "onMouseOver=\"popUp(event,'voiplines_user')\" onmouseout=\"popUp(event,'voiplines_user')\"";
+$tt_pass = "onMouseOver=\"popUp(event,'voiplines_pass')\" onmouseout=\"popUp(event,'voiplines_pass')\"";
+$tt_host = "onMouseOver=\"popUp(event,'voiplines_host')\" onmouseout=\"popUp(event,'voiplines_host')\"";
+$tt_status = "onMouseOver=\"popUp(event,'voiplines_status')\" onmouseout=\"popUp(event,'voiplines_status')\"";
+
+print "<tr $tt_provider><td>Provider</td><td>\n";
+print "<select name=\"provider\" id=\"provider\" onchange=\"changeProvider()\">\n";
+foreach (@providers) {
+    if ($_ eq $provider_current) {
+       print "<option selected=\"yes\">$_</option>\n";
+    }
+    else {
+       print "<option>$_</option>\n";
+    }
+}
+print "</select></td></tr>\n";
+
+print "<tr $tt_user><td>User:</td><td><input type=\"text\" name=\"user\" id=\"user\" value=\"$user{$provider_current}\"></td></tr>\n";
+print "<tr $tt_pass><td>Password:</td><td><input type=\"password\" name=\"pass\" id=\"pass\" value=\"$pass{$provider_current}\"></td></tr>\n";
+print "<tr $tt_host><td>Host:</td><td><input type=\"text\" name=\"host\" id=\"host\" value=\"$host{$provider_current}\"></td></tr>\n";
+
+#print "\nXXX $provider_current $stanza{$provider_current} $voip{$stanza{$provider_current}}\n";
+
+if ($voip{$stanza{$provider_current}} eq "Registered") {
+    $icon = "<img src=\"tick.png\" alt=\"OK\" />";
+}
+else {
+    $icon = "<img src=\"cross.png\" alt=\"Not OK\" />";
+}
+print "<tr $tt_status><td>Voip Line Status:</td><td>$icon</td></tr>\n";
+
+# hidden field to pass stanza with form
+
+print "<tr><td><input type=\"hidden\" name=\"stanza\" id=\"stanza\" value=\"$stanza{$provider_current}\"></td></tr>";
diff --git a/easy-asterisk-gui/cgi-bin/voiplines.sh b/easy-asterisk-gui/cgi-bin/voiplines.sh
new file mode 100644 (file)
index 0000000..071408e
--- /dev/null
@@ -0,0 +1,76 @@
+#!/bin/sh
+# voiplines.sh
+# David Rowe 12 Jan 2010
+# VOIP Line screen for Easy Asterisk GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+    echo "<html>"
+    echo "<head>"
+    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
+    echo "</head>"
+    echo "</html>"
+    exit
+fi
+
+# See if we have can reach the VOIP Line provider
+
+asterisk "-rx sip show registry" 2>/dev/null > sipshowregistry.txt
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+<script>
+EOF
+
+cat voiplines.js
+
+cat << EOF
+</script>
+<html>
+<title>Easy Asterisk - VOIP Line</title>
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800>'
+cat banner.html
+echo "    <tr>"
+cat menu.html    
+cat <<EOF
+
+    <td valign="top">
+
+    <table align="right" width=600>
+      <tr><td>&nbsp</td></tr>
+      <form action="set_voiplines.sh" method="get">
+      <tr><td onMouseOver="popUp(event,'voiplines_voiplines')" onmouseout="popUp(event,'voiplines_voiplines')" align="left" valign="top"><h2>VOIP Line</h2></td></tr>
+
+      <tr><td>&nbsp</td></tr>
+EOF
+
+./voiplines.pl
+
+cat <<EOF
+      <tr><td>&nbsp</td></tr>
+      <tr><td><input type="submit" value="OK"></td></tr>
+
+      </form>
+
+    </table>
+    </form>
+
+    </td>
+
+    </tr>
+
+</table>
+</body>
+</html>
+EOF
+
diff --git a/easy-asterisk-gui/check_loggedin.sh b/easy-asterisk-gui/check_loggedin.sh
deleted file mode 100644 (file)
index 3d0f975..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
-    echo "<html>"
-    echo "<head>"
-    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
-    echo "</head>"
-    echo "</html>"
-    exit
-fi
diff --git a/easy-asterisk-gui/cross.png b/easy-asterisk-gui/cross.png
deleted file mode 100644 (file)
index 05baecd..0000000
Binary files a/easy-asterisk-gui/cross.png and /dev/null differ
diff --git a/easy-asterisk-gui/etc/asterisk/sip.conf b/easy-asterisk-gui/etc/asterisk/sip.conf
new file mode 100644 (file)
index 0000000..9ee3f20
--- /dev/null
@@ -0,0 +1,559 @@
+;
+; SIP Configuration example for Asterisk
+;
+; Syntax for specifying a SIP device in extensions.conf is
+; SIP/devicename where devicename is defined in a section below.
+;
+; You may also use 
+; SIP/username@domain to call any SIP user on the Internet
+; (Don't forget to enable DNS SRV records if you want to use this)
+; 
+; If you define a SIP proxy as a peer below, you may call
+; SIP/proxyhostname/user or SIP/user@proxyhostname 
+; where the proxyhostname is defined in a section below 
+; 
+; Useful CLI commands to check peers/users:
+;   sip show peers             Show all SIP peers (including friends)
+;   sip show users             Show all SIP users (including friends)
+;   sip show registry          Show status of hosts we register with
+;
+;   sip debug                  Show all SIP messages
+;
+;   reload chan_sip.so         Reload configuration file
+;                              Active SIP peers will not be reconfigured
+;
+
+[general]
+context=default                        ; Default context for incoming calls
+;allowguest=no                 ; Allow or reject guest calls (default is yes, this can also be set to 'osp'
+                               ; if asterisk was compiled with OSP support.
+;realm=mydomain.tld            ; Realm for digest authentication
+                               ; defaults to "asterisk"
+                               ; Realms MUST be globally unique according to RFC 3261
+                               ; Set this to your host name or domain name
+bindport=5060                  ; UDP Port to bind to (SIP standard port is 5060)
+bindaddr=0.0.0.0               ; IP address to bind to (0.0.0.0 binds to all)
+srvlookup=yes                  ; Enable DNS SRV lookups on outbound calls
+                               ; Note: Asterisk only uses the first host 
+                               ; in SRV records
+                               ; Disabling DNS SRV lookups disables the 
+                               ; ability to place SIP calls based on domain 
+                               ; names to some other SIP users on the Internet
+                               
+;domain=mydomain.tld           ; Set default domain for this host
+                               ; If configured, Asterisk will only allow
+                               ; INVITE and REFER to non-local domains
+                               ; Use "sip show domains" to list local domains
+;domain=mydomain.tld,mydomain-incoming
+                               ; Add domain and configure incoming context
+                               ; for external calls to this domain
+;domain=1.2.3.4                        ; Add IP address as local domain
+                               ; You can have several "domain" settings
+;allowexternalinvites=no       ; Disable INVITE and REFER to non-local domains
+                               ; Default is yes
+;autodomain=yes                        ; Turn this on to have Asterisk add local host
+                               ; name and local IP to domain list.
+;pedantic=yes                  ; Enable slow, pedantic checking for Pingtel
+                               ; and multiline formatted headers for strict
+                               ; SIP compatibility (defaults to "no")
+;tos=184                       ; Set IP QoS to either a keyword or numeric val
+;tos=lowdelay                  ; lowdelay,throughput,reliability,mincost,none
+;maxexpiry=3600                        ; Max length of incoming registration we allow
+;defaultexpiry=120             ; Default length of incoming/outoing registration
+;notifymimetype=text/plain     ; Allow overriding of mime type in MWI NOTIFY
+;checkmwi=10                   ; Default time between mailbox checks for peers
+;vmexten=voicemail      ; dialplan extension to reach mailbox sets the 
+                                               ; Message-Account in the MWI notify message 
+                                               ; defaults to "asterisk"
+;videosupport=yes              ; Turn on support for SIP video
+;recordhistory=yes             ; Record SIP history by default 
+                               ; (see sip history / sip no history)
+
+;disallow=all                  ; First disallow all codecs
+;allow=ulaw                    ; Allow codecs in order of preference
+;allow=ilbc                    ; 
+;musicclass=default            ; Sets the default music on hold class for all SIP calls
+                               ; This may also be set for individual users/peers
+;language=en                   ; Default language setting for all users/peers
+                               ; This may also be set for individual users/peers
+;relaxdtmf=yes                 ; Relax dtmf handling
+;rtptimeout=60                 ; Terminate call if 60 seconds of no RTP activity
+                               ; when we're not on hold
+;rtpholdtimeout=300            ; Terminate call if 300 seconds of no RTP activity
+                               ; when we're on hold (must be > rtptimeout)
+;trustrpid = no                        ; If Remote-Party-ID should be trusted
+;sendrpid = yes                        ; If Remote-Party-ID should be sent
+;progressinband=never          ; If we should generate in-band ringing always
+                               ; use 'never' to never use in-band signalling, even in cases
+                               ; where some buggy devices might not render it
+;useragent=Asterisk PBX                ; Allows you to change the user agent string
+;promiscredir = no             ; If yes, allows 302 or REDIR to non-local SIP address
+                               ; Note that promiscredir when redirects are made to the
+                                       ; local system will cause loops since SIP is incapable
+                                       ; of performing a "hairpin" call.
+;usereqphone = no              ; If yes, ";user=phone" is added to uri that contains
+                               ; a valid phone number
+;dtmfmode = rfc2833            ; Set default dtmfmode for sending DTMF. Default: rfc2833
+                               ; Other options: 
+                               ; info : SIP INFO messages
+                               ; inband : Inband audio (requires 64 kbit codec -alaw, ulaw)
+                               ; auto : Use rfc2833 if offered, inband otherwise
+
+;compactheaders = yes          ; send compact sip headers.
+;sipdebug = yes                        ; Turn on SIP debugging by default, from
+                               ; the moment the channel loads this configuration
+;subscribecontext = default    ; Set a specific context for SUBSCRIBE requests
+                               ; Useful to limit subscriptions to local extensions
+                               ; Settable per peer/user also
+;notifyringing = yes           ; Notify subscriptions on RINGING state
+
+;
+; If regcontext is specified, Asterisk will dynamically create and destroy a
+; NoOp priority 1 extension for a given peer who registers or unregisters with
+; us.  The actual extension is the 'regexten' parameter of the registering
+; peer or its name if 'regexten' is not provided.  More than one regexten may
+; be supplied if they are separated by '&'.  Patterns may be used in regexten.
+;
+;regcontext=sipregistrations
+;
+; Asterisk can register as a SIP user agent to a SIP proxy (provider)
+; Format for the register statement is:
+;       register => user[:secret[:authuser]]@host[:port][/extension]
+;
+; If no extension is given, the 's' extension is used. The extension needs to
+; be defined in extensions.conf to be able to accept calls from this SIP proxy
+; (provider).
+;
+; host is either a host name defined in DNS or the name of a section defined
+; below.
+;
+; Examples:
+;
+;register => 1234:password@mysipprovider.com   
+;
+;     This will pass incoming calls to the 's' extension
+;
+;
+;register => 2345:password@sip_proxy/1234
+;
+;    Register 2345 at sip provider 'sip_proxy'.  Calls from this provider
+;    connect to local extension 1234 in extensions.conf, default context,
+;    unless you configure a [sip_proxy] section below, and configure a
+;    context.
+;    Tip 1: Avoid assigning hostname to a sip.conf section like [provider.com]
+;    Tip 2: Use separate type=peer and type=user sections for SIP providers
+;           (instead of type=friend) if you have calls in both directions
+  
+;registertimeout=20            ; retry registration calls every 20 seconds (default)
+;registerattempts=10           ; Number of registration attempts before we give up
+                               ; 0 = continue forever, hammering the other server until it 
+                               ; accepts the registration
+                               ; Default is 0 tries, continue forever
+;callevents=no                 ; generate manager events when sip ua performs events (e.g. hold)
+
+; register easy-asterisk voip line providers here
+
+register => user@generic ; easy-asterisk - do not change this comment
+;register => user@oeg ; easy-asterisk - do not change this comment
+
+;----------------------------------------- NAT SUPPORT ------------------------
+; The externip, externhost and localnet settings are used if you use Asterisk
+; behind a NAT device to communicate with services on the outside.
+
+;externip = 200.201.202.203    ; Address that we're going to put in outbound SIP messages
+                               ; if we're behind a NAT
+
+                               ; The externip and localnet is used
+                               ; when registering and communicating with other proxies
+                               ; that we're registered with
+;externhost=foo.dyndns.net     ; Alternatively you can specify an 
+                               ; external host, and Asterisk will 
+                               ; perform DNS queries periodically.  Not
+                               ; recommended for production 
+                               ; environments!  Use externip instead
+;externrefresh=10              ; How often to refresh externhost if 
+                               ; used
+                               ; You may add multiple local networks.  A reasonable set of defaults
+                               ; are:
+;localnet=192.168.0.0/255.255.0.0; All RFC 1918 addresses are local networks
+;localnet=10.0.0.0/255.0.0.0   ; Also RFC1918
+;localnet=172.16.0.0/12                ; Another RFC1918 with CIDR notation
+;localnet=169.254.0.0/255.255.0.0 ;Zero conf local network
+
+; The nat= setting is used when Asterisk is on a public IP, communicating with
+; devices hidden behind a NAT device (broadband router).  If you have one-way
+; audio problems, you usually have problems with your NAT configuration or your
+; firewall's support of SIP+RTP ports.  You configure Asterisk choice of RTP
+; ports for incoming audio in rtp.conf
+;
+;nat=no                                ; Global NAT settings  (Affects all peers and users)
+                                ; yes = Always ignore info and assume NAT
+                                ; no = Use NAT mode only according to RFC3581 
+                                ; never = Never attempt NAT mode or RFC3581 support
+                               ; route = Assume NAT, don't send rport 
+                               ; (work around more UNIDEN bugs)
+
+;rtcachefriends=yes            ; Cache realtime friends by adding them to the internal list
+                               ; just like friends added from the config file only on a
+                               ; as-needed basis? (yes|no)
+
+;rtupdate=yes                  ; Send registry updates to database using realtime? (yes|no)
+                               ; If set to yes, when a SIP UA registers successfully, the ip address,
+                               ; the origination port, the registration period, and the username of
+                               ; the UA will be set to database via realtime. If not present, defaults to 'yes'.
+
+;rtautoclear=yes               ; Auto-Expire friends created on the fly on the same schedule
+                               ; as if it had just registered? (yes|no|<seconds>)
+                               ; If set to yes, when the registration expires, the friend will vanish from
+                               ; the configuration until requested again. If set to an integer,
+                               ; friends expire within this number of seconds instead of the
+                               ; registration interval.
+
+;ignoreregexpire=yes           ; Enabling this setting has two functions:
+                               ;
+                               ; For non-realtime peers, when their registration expires, the information
+                               ; will _not_ be removed from memory or the Asterisk database; if you attempt
+                               ; to place a call to the peer, the existing information will be used in spite
+                               ; of it having expired
+                               ;
+                               ; For realtime peers, when the peer is retrieved from realtime storage,
+                               ; the registration information will be used regardless of whether
+                               ; it has expired or not; if it expires while the realtime peer is still in
+                               ; memory (due to caching or other reasons), the information will not be
+                               ; removed from realtime storage
+
+; Incoming INVITE and REFER messages can be matched against a list of 'allowed'
+; domains, each of which can direct the call to a specific context if desired.
+; By default, all domains are accepted and sent to the default context or the
+; context associated with the user/peer placing the call.
+; Domains can be specified using:
+; domain=<domain>[,<context>]
+; Examples:
+; domain=myasterisk.dom
+; domain=customer.com,customer-context
+;
+; In addition, all the 'default' domains associated with a server should be
+; added if incoming request filtering is desired.
+; autodomain=yes
+;
+; To disallow requests for domains not serviced by this server:
+; allowexternaldomains=no
+
+; fromdomain=mydomain.tld ; When making outbound SIP INVITEs to
+                          ; non-peers, use your primary domain "identity"
+                          ; for From: headers instead of just your IP
+                          ; address. This is to be polite and
+                          ; it may be a mandatory requirement for some
+                          ; destinations which do not have a prior
+                          ; account relationship with your server. 
+
+[authentication]
+; Global credentials for outbound calls, i.e. when a proxy challenges your
+; Asterisk server for authentication. These credentials override
+; any credentials in peer/register definition if realm is matched.
+;
+; This way, Asterisk can authenticate for outbound calls to other
+; realms. We match realm on the proxy challenge and pick an set of 
+; credentials from this list
+; Syntax:
+;      auth = <user>:<secret>@<realm>
+;      auth = <user>#<md5secret>@<realm>
+; Example:
+;auth=mark:topsecret@digium.com
+; 
+; You may also add auth= statements to [peer] definitions 
+; Peer auth= override all other authentication settings if we match on realm
+
+;------------------------------------------------------------------------------
+; Users and peers have different settings available. Friends have all settings,
+; since a friend is both a peer and a user
+;
+; User config options:        Peer configuration:
+; --------------------        -------------------
+; context                     context
+; permit                      permit
+; deny                        deny
+; secret                      secret
+; md5secret                   md5secret
+; dtmfmode                    dtmfmode
+; canreinvite                 canreinvite
+; nat                         nat
+; callgroup                   callgroup
+; pickupgroup                 pickupgroup
+; language                    language
+; allow                       allow
+; disallow                    disallow
+; insecure                    insecure
+; trustrpid                   trustrpid
+; progressinband              progressinband
+; promiscredir                promiscredir
+; useclientcode               useclientcode
+; accountcode                 accountcode
+; setvar                      setvar
+; callerid                   callerid
+; amaflags                   amaflags
+; call-limit                 call-limit
+; restrictcid                restrictcid
+; subscribecontext           subscribecontext
+; videosupport               videosupport
+;                             mailbox
+;                             username
+;                             template
+;                             fromdomain
+;                             regexten
+;                             fromuser
+;                             host
+;                             port
+;                             qualify
+;                             defaultip
+;                             rtptimeout
+;                             rtpholdtimeout
+;                             sendrpid
+
+;[sip_proxy]
+; For incoming calls only. Example: FWD (Free World Dialup)
+; We match on IP address of the proxy for incoming calls 
+; since we can not match on username (caller id)
+;type=peer
+;context=from-fwd
+;host=fwd.pulver.com
+
+;[sip_proxy-out]
+;type=peer                     ; we only want to call out, not be called
+;secret=guessit
+;username=yourusername         ; Authentication user for outbound proxies
+;fromuser=yourusername         ; Many SIP providers require this!
+;fromdomain=provider.sip.domain        
+;host=box.provider.com
+;usereqphone=yes               ; This provider requires ";user=phone" on URI
+;call-limit=5                  ; permit only 5 simultaneous outgoing calls to this peer
+
+;------------------------------------------------------------------------------
+; Definitions of locally connected SIP phones
+;
+; type = user  a device that authenticates to us by "from" field to place calls
+; type = peer  a device we place calls to or that calls us and we match by host
+; type = friend two configurations (peer+user) in one
+;
+; For local phones, type=friend works most of the time
+;
+; If you have one-way audio, you propably have NAT problems. 
+; If Asterisk is on a public IP, and the phone is inside of a NAT device
+; you will need to configure nat option for those phones.
+; Also, turn on qualify=yes to keep the nat session open
+
+;[grandstream1]
+;type=friend                   
+;context=from-sip              ; Where to start in the dialplan when this phone calls
+;callerid=John Doe <1234>      ; Full caller ID, to override the phones config
+;host=192.168.0.23             ; we have a static but private IP address
+                               ; No registration allowed
+;nat=no                                ; there is not NAT between phone and Asterisk
+;canreinvite=yes               ; allow RTP voice traffic to bypass Asterisk
+;dtmfmode=info                 ; either RFC2833 or INFO for the BudgeTone
+;call-limit=1                  ; permit only 1 outgoing call and 1 incoming call at a time
+                               ; from the phone to asterisk
+                               ; (1 for the explicit peer, 1 for the explicit user,
+                               ; remember that a friend equals 1 peer and 1 user in
+                               ; memory)
+;mailbox=1234@default          ; mailbox 1234 in voicemail context "default"
+;disallow=all                  ; need to disallow=all before we can use allow=
+;allow=ulaw                    ; Note: In user sections the order of codecs
+                               ; listed with allow= does NOT matter!
+;allow=alaw
+;allow=g723.1                  ; Asterisk only supports g723.1 pass-thru!
+;allow=g729                    ; Pass-thru only unless g729 license obtained
+;astdb=chan2ext/SIP/grandstream1=1234  ; ensures an astDB entry exists
+
+
+;[xlite1]
+; Turn off silence suppression in X-Lite ("Transmit Silence"=YES)!
+; Note that Xlite sends NAT keep-alive packets, so qualify=yes is not needed
+;type=friend
+;regexten=1234                 ; When they register, create extension 1234
+;callerid="Jane Smith" <5678>
+;host=dynamic                  ; This device needs to register
+;nat=yes                       ; X-Lite is behind a NAT router
+;canreinvite=no                        ; Typically set to NO if behind NAT
+;disallow=all
+;allow=gsm                     ; GSM consumes far less bandwidth than ulaw
+;allow=ulaw
+;allow=alaw
+;mailbox=1234@default,1233@default     ; Subscribe to status of multiple mailboxes
+
+
+;[snom]
+;type=friend                   ; Friends place calls and receive calls
+;context=from-sip              ; Context for incoming calls from this user
+;secret=blah
+;subscribecontext=localextensions      ; Only allow SUBSCRIBE for local extensions
+;language=de                   ; Use German prompts for this user 
+;host=dynamic                  ; This peer register with us
+;dtmfmode=inband               ; Choices are inband, rfc2833, or info
+;defaultip=192.168.0.59                ; IP used until peer registers
+;mailbox=1234@context,2345      ; Mailbox(-es) for message waiting indicator
+;vmexten=voicemail      ; dialplan extension to reach mailbox 
+                        ; sets the Message-Account in the MWI notify message
+                        ; defaults to global vmexten which defaults to "asterisk"
+;restrictcid=yes               ; To have the callerid restriced -> sent as ANI
+;disallow=all
+;allow=ulaw                    ; dtmfmode=inband only works with ulaw or alaw!
+
+
+;[polycom]
+;type=friend                   ; Friends place calls and receive calls
+;context=from-sip              ; Context for incoming calls from this user
+;secret=blahpoly
+;host=dynamic                  ; This peer register with us
+;dtmfmode=rfc2833              ; Choices are inband, rfc2833, or info
+;username=polly                        ; Username to use in INVITE until peer registers
+                               ; Normally you do NOT need to set this parameter
+;disallow=all
+;allow=ulaw                     ; dtmfmode=inband only works with ulaw or alaw!
+;progressinband=no             ; Polycom phones don't work properly with "never"
+
+
+;[pingtel]
+;type=friend
+;secret=blah
+;host=dynamic
+;insecure=port                 ; Allow matching of peer by IP address without matching port number
+;insecure=invite               ; Do not require authentication of incoming INVITEs
+;insecure=port,invite          ; (both)
+;qualify=1000                  ; Consider it down if it's 1 second to reply
+                               ; Helps with NAT session
+                               ; qualify=yes uses default value
+;callgroup=1,3-4               ; We are in caller groups 1,3,4
+;pickupgroup=1,3-5             ; We can do call pick-p for call group 1,3,4,5
+;defaultip=192.168.0.60                ; IP address to use if peer has not registred
+
+;[cisco1]
+;type=friend
+;secret=blah
+;qualify=200                   ; Qualify peer is no more than 200ms away
+;nat=yes                       ; This phone may be natted
+                               ; Send SIP and RTP to the IP address that packet is 
+                               ; received from instead of trusting SIP headers 
+;host=dynamic                  ; This device registers with us
+;canreinvite=no                        ; Asterisk by default tries to redirect the
+                               ; RTP media stream (audio) to go directly from
+                               ; the caller to the callee.  Some devices do not
+                               ; support this (especially if one of them is 
+                               ; behind a NAT).
+;defaultip=192.168.0.4         ; IP address to use until registration
+;username=goran                        ; Username to use when calling this device before registration
+                               ; Normally you do NOT need to set this parameter
+;setvar=CUSTID=5678            ; Channel variable to be set for all calls from this device
+
+; Pre-configured SIP extensions
+
+[6011]
+type=friend
+context=default
+host=dynamic
+secret=6011
+canreinvite=no
+callerid=6011
+disallow=all
+allow=ulaw,g729
+qualify=yes
+
+[6012]
+type=friend
+context=default
+host=dynamic
+secret=6012
+canreinvite=no
+callerid=6012
+disallow=all
+allow=ulaw,g729
+
+[6013]
+type=friend
+context=default
+host=dynamic
+secret=6013
+canreinvite=no
+callerid=6013
+disallow=all
+allow=ulaw,g729
+
+[6014]
+type=friend
+context=default
+host=dynamic
+secret=6014
+canreinvite=no
+callerid=6014
+disallow=all
+allow=ulaw,g729
+
+[6015]
+type=friend
+context=default
+host=dynamic
+secret=6015
+canreinvite=no
+callerid=6015
+disallow=all
+allow=ulaw,g729
+
+[6016]
+type=friend
+context=default
+host=dynamic
+secret=6016
+canreinvite=no
+callerid=6016
+disallow=all
+allow=ulaw,g729
+
+[6017]
+type=friend
+context=default
+host=dynamic
+secret=6017
+canreinvite=no
+callerid=6017
+disallow=all
+allow=ulaw,g729
+
+[6018]
+type=friend
+context=default
+host=dynamic
+secret=6018
+canreinvite=no
+callerid=6018
+disallow=all
+allow=ulaw,g729
+
+; Pre-configured easy-asterisk SIP trunks
+
+[generic] ; "Generic" easy-asterisk do not remove this comment
+type=friend
+context=default
+username=user
+secret=password
+host=192.168.1.28
+canreinvite=no
+disallow=all
+allow=ulaw,g729
+qualify=yes
+
+;[oeg] ; "OEG" easy-asterisk do not remove this comment
+;host=voip.oeg.com.au
+;secret=pass
+;username=your user number
+;fromdomain=voip.oeg.com.au
+;fromuser=your user number
+;insecure=port,invite
+;type=friend
+;disallow=all
+;allow=g729,ulaw
+;dtmfmod=rfc2833
+;qualify=yes
+;canreinvite=no
+;nat=yes
+;context=default
+
diff --git a/easy-asterisk-gui/faq.html b/easy-asterisk-gui/faq.html
deleted file mode 100644 (file)
index dd6258e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<ol>
-
-<li><strong>Transfer a Call</strong>
-
-<li><strong>Answer a call on another ringing phone</strong>:  If you hear another phone ringing and
-want to answer the call on your phone, just pick up your phone and
-dial *8.  Note an IP phone can pick up a call on a ringing IP phone
-but not an Analog phone.  An Analog pohone can pick up another
-ringing Analog phone but not an IP phone.
-
-</ol>
-
-<h2>Resources and Links</h2>
-<ol>
-<li>A good book on Asterisk is <a href="http://astbook.asteriskdocs.org">Asterisk - The Future of Telephony</a>
-</ol>
diff --git a/easy-asterisk-gui/faq.sh b/easy-asterisk-gui/faq.sh
deleted file mode 100644 (file)
index 7713e92..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/sh
-# faq.sh
-# David Rowe 7 Jan 2010
-# FAQ screen for Easy Asterisk GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
-    echo "<html>"
-    echo "<head>"
-    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
-    echo "</head>"
-    echo "</html>"
-    exit
-fi
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-
-cat << EOF
-<html>
-<title>Easy Asterisk - FAQ</title>
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800>'
-cat banner.html
-echo "    <tr>"
-cat menu.html    
-cat <<EOF
-
-    <td valign="top">
-
-    <table align="right" width=600>
-      <tr><td align="left" valign="top"><h2>FAQ</h2></td></tr>
-      <tr><td>
-EOF
-cat faq.html
-cat <<EOF
-      </td></tr>
-    </table>
-
-    </td>
-
-    </tr>
-
-</table>
-</body>
-</html>
-EOF
-
diff --git a/easy-asterisk-gui/index.html b/easy-asterisk-gui/index.html
deleted file mode 100644 (file)
index 8514560..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<head>
-<meta http-equiv="REFRESH" content="0;url=http:login.sh">
-</head>
-</html>
\ No newline at end of file
diff --git a/easy-asterisk-gui/ipphone.png b/easy-asterisk-gui/ipphone.png
deleted file mode 100644 (file)
index f9578db..0000000
Binary files a/easy-asterisk-gui/ipphone.png and /dev/null differ
diff --git a/easy-asterisk-gui/ipphones.js b/easy-asterisk-gui/ipphones.js
deleted file mode 100644 (file)
index 9c50cea..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-function localInit() {
-}
-
diff --git a/easy-asterisk-gui/ipphones.pl b/easy-asterisk-gui/ipphones.pl
deleted file mode 100755 (executable)
index 4c95095..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/sbin/microperl
-# ipphones.pl
-# David Rowe 6 Jan 2010
-#
-# Text processing for the ipphones screen
-
-$ipaddress = $ARGV[0];
-$more = $ARGV[1];
-
-# Slurp up SIP extension (Sip) data from extensions.conf
-
-my %ip = (); # ip extension keyed on sip.conf name
-
-open EXT, "/etc/asterisk/extensions.conf";
-while (<EXT>) { 
-    if (/.*=>[ ]*([0-9]*),1.*SIP\/([0-9]*)\)/) {
-        $ip{$2} = $1;
-       #print "'$1' '$2' $ip{$2}\n";
-    }
-}
-close EXT;
-
-my %sip = ();  # SIP IP phone status keyed on sip.conf names 
-               # if no entry we can't see IP phone device
-my %voip = (); # SIP trunks status keyed on sip.conf names 
-               # if no entry we can't see SIP trunk
-my %ipad = (); # IP address of SIP device keyed on sip.conf names
-
-open SIP, "sipshowpeers.txt";
-while (<SIP>) { 
-    if (/^([0-9]*)[\s\/].*(OK)/) {
-        $sip{$1} = $2;
-       #print "'$1' '$2' $sip{$1}\n";
-       $e = $1;
-       if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
-           $ipad{$e} = $1;
-           #print "'$1'\n";
-       }
-    }
-    if (/^(voip[0-9]*)[\s\/].*(OK)/) {
-        $voip{$1} = $2;
-       #print "'$1' '$2' $voip{$1}\n";
-       $e = $1;
-       if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
-           $ipad{$e} = $1;
-           #print "'$1'\n";
-       }
-    }
-}
-
-close SIP;
-
-# print list of IP phones with connection status
-
-$unconnected = 0;
-foreach $e (sort keys %ip) {
-    if ($sip{$e} eq "OK") {
-       $icon = "<img src=\"tick.png\" alt=\"Connected\" />";
-        $tooltip_status = "onMouseOver=\"popUp(event,'ipphones_connected')\" onmouseout=\"popUp(event,'ipphones_connected')\"";    
-        $comment=$ipad{$e};
-        $tooltip_ext = "onMouseOver=\"popUp(event,'phone_ext')\" onmouseout=\"popUp(event,'phone_ext')\"";
-       $tooltip_ip =  "onMouseOver=\"popUp(event,'phone_ipphone_ip')\" onmouseout=\"popUp(event,'phone_ipphone_ip')\"";
-       $unconnected = 0;
-    }
-    else {
-       $unconnected = $unconnected + 1;
-       $icon = "<img src=\"cross.png\" alt=\"Not Connected\" />";
-        $tooltip_status = "onMouseOver=\"popUp(event,'ipphones_notconnected')\" onmouseout=\"popUp(event,'ipphones_notconnected')\"";
-        $comment="Available";
-       $tooltip_id = "iphones_$e";
-       print "<div id=\"$tooltip_id\" class=\"tip\"> Configure your IP phone with username/password $e/$e, SIP Server IP $ipaddress</div>";
-        $tooltip_ext = "onMouseOver=\"popUp(event,'$tooltip_id')\" onmouseout=\"popUp(event,'$tooltip_id')\"";
-       $tooltip_ip = "";
-    }
-    
-    if ($more == 1 || ($unconnected < 5)) {
-       print "<tr><td $tooltip_ext>$e</td><td></td><td $tooltip_ip>$comment</td><td $tooltip_status>$icon</td></tr>\n";
-    }
-}
-
-if ($more == 0) {
-    print '<tr><td><a href="ipphones.sh?more=1">More</a></td></tr>';
-}
-else {
-    print '<tr><td><a href="ipphones.sh">Less</a></td></tr>';
-}
-
-
diff --git a/easy-asterisk-gui/ipphones.sh b/easy-asterisk-gui/ipphones.sh
deleted file mode 100644 (file)
index 03d87d3..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/sh
-# dashboard.sh
-# David Rowe 6 Jan 2010
-# Dashboard screen for Easy Asterisk GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
-    echo "<html>"
-    echo "<head>"
-    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
-    echo "</head>"
-    echo "</html>"
-    exit
-fi
-
-more=`echo "$QUERY_STRING" | grep -oe "more=[^&?]*" | sed -n "s/more=//p"`
-ipaddress=`ifconfig eth0 | sed -n 's/.*inet addr:\(.*\)  Bcast.*/\1/p'`
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-
-echo "<script>"
-echo 'var init_internet="'$internet'";'
-cat ipphones.js
-echo "</script>"
-
-cat << EOF
-<html>
-<title>Easy Asterisk - IP Phones</title>
-<body onload="localInit()">
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800 border=0>'
-cat banner.html
-echo "    <tr>"
-cat menu.html    
-cat <<EOF
-
-    <td valign="top">
-
-    <table align="right" width=600 border=0>
-      <tr><td  onMouseOver="popUp(event,'ipphones_ipphones')" onmouseout="popUp(event,'ipphones_ipphones')" 
-           colspan="4" align="left" valign="top" ><h2>IP Phones</h2></td></tr>
-      <tr onMouseOver="popUp(event,'phone_ipaddress')" onmouseout="popUp(event,'phone_ipaddress')">
-         <td colspan="3">Phone System IP Address:</td>
-EOF
-echo "<td>$ipaddress</td></tr><td>&nbsp;</td><tr></tr>"
-
-    # use perl to construct list of IP phones for us
-    asterisk "-rx sip show peers" 2>/dev/null > sipshowpeers.txt
-    ./ipphones.pl $ipaddress $more
-
-cat <<EOF
-    </table>
-
-    <h2>&nbsp;<br>How to Configure IP Phones</h2>
-    <h3>1. Atcom AT-530</h3>
-EOF
-cat at-530.html
-cat <<EOF
-     </td>
-    </tr>
-
-</table>
-</body>
-</html>
-EOF
-
diff --git a/easy-asterisk-gui/login.sh b/easy-asterisk-gui/login.sh
deleted file mode 100644 (file)
index f195f8d..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/bin/sh
-# login.sh
-# David Rowe 4 Jan 2010
-# CGI for Easy Asterisk login GUI
-
-pass=`echo "$QUERY_STRING" | grep -oe "pass=[^&?]*" | sed -n "s/pass=//p"`
-
-echo $QUERY_STRING | grep pass > /dev/null
-if [ $? -eq 1 ]; then
-    # Display form -------------------------------
-
-    cat <<EOF
-    <script src="prototype.js"></script>
-    <link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
-    <script type="text/javascript" src="tooltip.js"></script>
-    <link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-    cat << EOF
-    <html>
-    <title>Easy Asterisk - Login</title>
-    <form action="login.sh" method="get">
-    <table align="center" width=600>
-    <tr><td colspan="2" align="left"><h2>Login</h2></td>
-    <tr>
-      <tr><td>Password:</td><td><input type="password" name="pass" ></td></tr>
-      <tr><td><input type="submit" value="Login"></td></tr>
-    </tr>
-    <tr><td></td><td>Default password is uClinux</td>
-    </table>
-    </form>
-    </html>
-EOF
-else
-    testuser root $pass
-    if [ $? -eq 0 ]; then
-
-       # login sucessful
-        echo "Content-type: text/html"
-        echo "Set-Cookie: loggedin=1"
-        echo ""
-       echo "<head>"
-       echo "<title>Easy Asterisk - Login</title>"
-       echo '<meta http-equiv="REFRESH" content="0;url=http:phones.sh">'
-       echo "</head>"
-       echo "<body>"
-       echo "Please wait a few seconds....."
-       echo "</body>"
-    else
-       # login failed
-       cat <<EOF
-       <html>
-       <head>
-       <title>Easy Asterisk - Login</title>
-       <meta http-equiv="REFRESH" content="0;url=http:login.sh">
-       <body>
-       Please wait a few seconds.....
-       </body>
-       </head>
-       </html>
-EOF
-    fi
-fi
-
diff --git a/easy-asterisk-gui/logout.sh b/easy-asterisk-gui/logout.sh
deleted file mode 100644 (file)
index bf8a05d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-# logout.sh
-# David Rowe 4 Jan 2010
-# CGI for Easy Asterisk logout GUI
-
-cat <<EOF
-Content-type: text/html
-Set-Cookie: loggedin=1; expires=Thursday, 01-Jan-98 12:00:00 GMT
-
-<title>Easy Asterisk - Logout</title>
-<meta http-equiv="REFRESH" content="0;url=http:login.sh"
-EOF
-#echo $HTTP_COOKIE
diff --git a/easy-asterisk-gui/menu.html b/easy-asterisk-gui/menu.html
deleted file mode 100644 (file)
index 81e4aa8..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-    <div id="admin_tip" class="tip">Change your password, Time & time zone, Reset the defaults, Install new software</div>
-    <div id="network_tip" class="tip">Connect the phone system to your network and the Internet</div>
-    <div id="phones_tip" class="tip">Lists your phones and phone lines</div>
-    <div id="ipphones_tip" class="tip">Set up your IP phones</div>
-    <div id="about_tip" class="tip">Boring information like software version numbers</div>
-    <div id="faq_tip" class="tip">Frequently asked questions and links to further information</div>
-    <div id="logout_tip" class="tip">I think you can work this one out....</div>
-    <div id="voipline_tip" class="tip">Set up your VOIP phone line</div>
-    <td valign="top" >
-       <table align="right" width=200>
-       <tr><td><h2>&nbsp;</h2></td></tr>
-       <tr onMouseOver="popUp(event,'about_tip')" onmouseout="popUp(event,'about_tip')">
-         <td><a href="about.sh">About</a></td>
-       </tr>
-       <tr onMouseOver="popUp(event,'admin_tip')" onmouseout="popUp(event,'admin_tip')">
-         <td><a href="admin.sh">Admin</a></td>
-       </tr>
-       <tr onMouseOver="popUp(event,'faq_tip')" onmouseout="popUp(event,'faq_tip')">
-         <td><a href="faq.sh">FAQ</a></td>
-       </tr>
-       <tr onMouseOver="popUp(event,'ipphones_tip')" onmouseout="popUp(event,'ipphones_tip')">
-         <td><a href="ipphones.sh">IP Phones</a></td>
-       </tr>
-       <tr onMouseOver="popUp(event,'logout_tip')" onmouseout="popUp(event,'logout_tip')">
-         <td><a href="logout.sh">Logout</a></td>
-       </tr>
-       <tr onMouseOver="popUp(event,'phones_tip')" onmouseout="popUp(event,'phones_tip')">
-         <td><a href="phones.sh">Phone System</a></td>
-       </tr>
-       <tr onMouseOver="popUp(event,'network_tip')" onmouseout="popUp(event,'network_tip')">
-         <td><a href="network.sh">Network</a></td>
-       </tr>
-       <tr onMouseOver="popUp(event,'voipline_tip')" onmouseout="popUp(event,'voipline_tip')">
-         <td><a href="voiplines.sh">VOIP Line</a></td>
-       </tr>
-       </table>
-    </td>
diff --git a/easy-asterisk-gui/network.js b/easy-asterisk-gui/network.js
deleted file mode 100644 (file)
index 108bf01..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-var script_path = "cgi-bin/";
-
-function doStatic() {    
-    $('ipaddress').disabled = 0;
-    $('netmask').disabled = 0;
-    $('gateway').disabled = 0;
-    $('dns').disabled = 0;
-}
-
-function doDHCP() {
-    $('ipaddress').disabled = 1;
-    $('netmask').disabled = 1;
-    $('gateway').disabled = 1;
-    $('dns').disabled = 1;
-}
-
-// http://moblog.bradleyit.com/2009/06/javascript-ip-address-validation.html
-
-function isIP(obj) {
-    var ary = obj.value.split(".");
-    var ip = true;
-
-    for (var i=0; i<4; i++) { 
-       ip = (!ary[i].match(/^\d{1,3}$/) || (Number(ary[i]) > 255)) ? false : ip; 
-    } 
-  
-    if (ip)
-       ip = (ary.length == 4); 
-
-    if (!ip) {    
-       // the value is NOT a valid IP address
-       obj.style.background = "red";
-       obj.select();
-    } 
-    else { obj.style.background = ""; } // the value IS a valid IP address
-
-    return ip;
-}
-
-function localInit() {
-
-    if (init_dhcp == "yes") {
-       $('dhcp').checked = true;
-       $('ipaddress').disabled = 1;
-       $('netmask').disabled = 1;
-       $('gateway').disabled = 1;
-       $('dns').disabled = 1;
-    }
-    else {
-       $('static').checked = true;
-       $('ipaddress').disabled = 0;
-       $('netmask').disabled = 0;
-       $('gateway').disabled = 0;
-       $('dns').disabled = 0;
-    }
-    $('ipaddress').value = init_ipaddress;
-    $('netmask').value = init_netmask;
-    $('gateway').value = init_gateway;
-    $('dns').value = init_dns;
-    $('backdoor').value = init_backdoor;    
-    if (init_internet == "yes")
-       $('internet').innerHTML = '<img src="tick.png" alt="tick" />';
-    else
-        $('internet').innerHTML = '<img src="cross.png" alt="tick" />';
-
-}
-
-function validate_form(form)
-{
-    var valid = true;
-
-    if ($('dhcp').checked == false)
-       valid = isIP(form.ipaddress) && isIP(form.ipaddress) && isIP(form.gateway) && isIP(form.dns);
-
-    return valid;
-}
diff --git a/easy-asterisk-gui/network.sh b/easy-asterisk-gui/network.sh
deleted file mode 100644 (file)
index a32d508..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-#!/bin/sh
-# network.sh
-# David Rowe 4 Jan 2010
-# CGI for Easy Asterisk network GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
-    echo "<html>"
-    echo "<head>"
-    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
-    echo "</head>"
-    echo "</html>"
-    exit
-fi
-
-grok_network=0
-
-if [ -f /etc/rc.d/S10network ]; then
-  grok_network=1
-  dhcp=yes
-  ipaddress=`ifconfig eth0 | sed -n 's/.*inet addr:\(.*\)  Bcast.*/\1/p'`
-  netmask=`ifconfig eth0 | sed -n 's/.*Mask:\(.*\)\s*/\1/p'`
-  gateway=`route -n | awk '/^0.0.0.0/ {print $2}'`
-  dns=`cat /etc/resolv.conf | awk '/^nameserver/ {print $2}'`
-fi
-
-if [ -f /etc/rc.d/S10network-static ]
-then
-  grok_network=1
-  dhcp=no  
-  ipaddress=`sed -n 's/IPADDRESS="\(.*\)"/\1/p' /etc/init.d/network-static`
-  netmask=`sed -n 's/NETMASK="\(.*\)"/\1/p' /etc/init.d/network-static`
-  gateway=`sed -n 's/GATEWAY="\(.*\)"/\1/p' /etc/init.d/network-static`
-  dns=`sed -n 's/DNS="\(.*\)"/\1/p' /etc/init.d/network-static`
-fi
-
-# if we don't understand this machines network config then bail
-
-if [ $groknetwork -eq 0 ]; then
-cat << EOF
-<html>
-<title>Easy Asterisk - Network</title>
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800 border=0>'
-cat banner.html
-echo "    <tr>"
-cat menu.html    
-cat <<EOF
-
-    <td valign="top">
-    <table align="center" width=600 border=0>
-      <tr><td colspan="2" align="left" valign="top"><h2>Network</h2></td></tr>
-      <tr><td>Sorry - I can't edit the Network configuration on this machine</td></tr>
-    </td>
-    </table>
-    </td>
-    </tr>
-
-</table>
-
-</html>
-EOF
-fi
-if [ -f /etc/rc.d/S05network-backdoor ]; then
-  backdoor=`sed -n 's/IPADDRESS="\(.*\)"/\1/p' /etc/init.d/network-backdoor`
-fi
-
-# See if we have Internet connectivity, first check dns as time outs can be very slow
-
-dns_packet_loss=`ping $dns -c 1 -q | sed -n 's/.*received, \(.*\)% packet loss/\1/p'`
-internet="no";
-if [ $dns_packet_loss == "0" ]; then
-  packet_loss=`ping google.com -c 1 -q | sed -n 's/.*received, \(.*\)% packet loss/\1/p'`
-  if [ $packet_loss == "0" ]; then
-    internet="yes";
-  fi
-fi
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-
-echo "<script>"
-echo 'var init_dhcp="'$dhcp'";'
-echo 'var init_ipaddress="'$ipaddress'";'
-echo 'var init_netmask="'$netmask'";'
-echo 'var init_gateway="'$gateway'";'
-echo 'var init_dns="'$dns'";'
-echo 'var init_backdoor="'$backdoor'";'
-echo 'var init_internet="'$internet'";'
-cat network.js
-echo "</script>"
-
-cat << EOF
-<html>
-<title>Easy Asterisk - Network</title>
-<body onload="localInit()">
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800 border=0>'
-cat banner.html
-echo "    <tr>"
-cat menu.html    
-cat <<EOF
-
-    <td valign="top">
-
-    <form action="set_network.sh" onsubmit="return validate_form(this)" method="get">
-    <table align="center" width=600 border=0>
-      <tr><td colspan="2" align="left" valign="top"><h2>Network</h2></td></tr>
-      <tr>
-        <td><input type="radio" id="static" name="dhcp" value="no" onClick="doStatic()">Static</td>
-        <td><input type="radio" id="dhcp"   name="dhcp" value="yes" onClick="doDHCP()">DHCP</td>
-      </tr>
-      <tr><td>IP Address:</td><td><input type="text" name="ipaddress" id="ipaddress" onBlur="isIP(this)"></td></tr>
-      <tr><td>Netmask:</td><td><input type="text" name="netmask" id="netmask" onBlur="isIP(this)"></td></tr>
-      <tr><td>Gateway:</td><td><input type="text" name="gateway" id="gateway" onBlur="isIP(this)"></td></tr>
-      <tr><td>DNS:</td><td><input type="text" name="dns" id="dns" onBlur="isIP(this)"></td></tr>
-      <tr onMouseOver="popUp(event,'network_backdoor')" onmouseout="popUp(event,'network_backdoor')">
-          <td>Emergency IP:</td><td><input type="text" name="backdoor" id="backdoor" onBlur="isIP(this)"></td>
-      </tr>
-      <tr onMouseOver="popUp(event,'network_internet')" onmouseout="popUp(event,'network_internet')">
-         <td>Internet Connection:</td>
-         <td><div id="internet" >
-         <span style="margin-left: 4px;font-weight:bold">&nbsp;</span></div></td>
-
-      </tr>
-      <tr><td><input id="networkapply" type="submit" value="Apply"></td></tr>
-    </table>
-    </form>
-
-    </td>
-
-    </tr>
-
-</table>
-
-</html>
-EOF
-
diff --git a/easy-asterisk-gui/phoneline.jpg b/easy-asterisk-gui/phoneline.jpg
deleted file mode 100644 (file)
index 21078c3..0000000
Binary files a/easy-asterisk-gui/phoneline.jpg and /dev/null differ
diff --git a/easy-asterisk-gui/phones.js b/easy-asterisk-gui/phones.js
deleted file mode 100644 (file)
index 74d6eaf..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-function localInit() {
-    if (init_internet == "yes")
-       $('internet').innerHTML = '<img src="tick.png" alt="tick" />';
-    else
-        $('internet').innerHTML = '<img src="cross.png" alt="tick" />';
-}
-
diff --git a/easy-asterisk-gui/phones.pl b/easy-asterisk-gui/phones.pl
deleted file mode 100755 (executable)
index 98db525..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-#!/sbin/microperl
-# phones.pl
-# David Rowe 5 Jan 2010
-#
-# Text processing for the phones screen.
-
-$tool_tip = "onMouseOver=\"popUp(event,'network_internet')\" onmouseout=\"popUp(event,'network_internet')\"";
-
-# Slurp up analog port (Zap) data from extensions.conf
-
-my %analog = (); # analog extension keyed on zap port
-
-open EXT, "/etc/asterisk/extensions.conf";
-while (<EXT>) { 
-    if (/.*=>[ ]*([0-9]*),1.*Zap\/([0-9]*)\)/) {
-        $analog{$2} = $1;
-       #print "'$1' '$2' $analog{$2}\n";
-    }
-}
-close EXT;
-
-# Slurp up data on installed zaptel ports from /etc/zaptel.conf
-
-my %zap = (); # zaptel port type keyed on zap port 
-              # (fxs/fxo or no entry if not live)
-open ZAP, "/etc/zaptel.conf";
-while (<ZAP>) { 
-    if (/fxoks=(.*)/) {
-        @fxs = split(/,/, $1);
-       foreach (@fxs) {
-           $zap{$_} = "fxs";
-       }
-    }
-    if (/fxsks=(.*)/) {
-        @fxo = split(/,/, $1);
-       foreach (@fxo) {
-           $zap{$_} = "fxo";
-       }
-    }
-}
-close ZAP;
-
-# Slurp up SIP extension (Sip) data from extensions.conf
-
-my %ip = (); # ip extension keyed on sip.conf name
-
-open EXT, "/etc/asterisk/extensions.conf";
-while (<EXT>) { 
-    if (/.*=>[ ]*([0-9]*),1.*Sip\/([0-9]*)\)/) {
-        $ip{$2} = $1;
-       #print "'$1' '$2' $ip{$2}\n";
-    }
-}
-close EXT;
-
-# Determine which extenions are "Reception", i.e. set to ring on incoming
-# calls
-
-my %zap_ring = (); # ring flag keyed on Zap port (1,2...)
-my %sip_ring = (); # ring flag keyed on sip.cong ext name (6011,6012 etc)
-
-open EXT, "/etc/asterisk/extensions.conf";
-while (<EXT>) { 
-    if (/s,1,Dial\((.*)\) ;; easy/) {
-        @ring = split(/&/, $1);
-       #print "'$1' '@ring'\n foreach:\n";
-       foreach (@ring) {
-           #print "    $_\n";
-           if (/Zap\/([0-9]*)/) {
-               $zap_ring{$1} = 1;
-               #print "'$_' $1 \n";
-           }
-           if (/SIP\/([0-9]*)/) {
-               $sip_ring{$1} = 1;
-               #print "'$_' $1 \n";
-           }
-       }
-    }
-}
-close EXT;
-
-
-# work out which IP phones are registered -----------------------------------
-
-my %sip = ();  # SIP IP phone status keyed on sip.conf names (6011,6012 etc)
-               # if no entry we can't see IP phone device
-my %ipad = (); # IP address of SIP device keyed on sip.conf names
-
-open SIP, "sipshowpeers.txt";
-while (<SIP>) { 
-    if (/^([0-9]*)[\s\/].*(OK)/) {
-        $sip{$1} = $2;
-       #print "'$1' '$2' $sip{$1}\n";
-       $e = $1;
-       if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
-           $ipad{$e} = $1;
-           #print "'$1'\n";
-       }
-    }
-
-    if (/^(.*)\/.*(OK)/) {
-        #$sip{$1} = $2;
-       #print "'$1' '$2' $sip{$1}\n";
-       $e = $1;
-       if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
-           $ipad{$e} = $1;
-           #print "'$1'\n";
-       }
-    }
-}
-
-close SIP;
-
-# Determine if Asterisk can see current voip line (SIP trunk) 
-# sipshowpeers.txt needs to be generated before calling this perl
-# script
-
-my %voip = (); # SIP trunks status keyed on sip.conf stanza name/username
-               # if no entry we can't see SIP trunk
-
-open SIP, "sipshowregistry.txt";
-while (<SIP>) { 
-    if (/^(.*):.*(Registered)/) {
-        $voip{$1} = $2;
-       #print "'$1' '$2' $voip{$1}\n";
-    }
-}
-
-close SIP;
-
-# start phones ringing form -------------------------------------------
-
-print '<form action="set_ring.sh?" method="get">';
-
-# print list of analog phones
-
-$tooltip_anphone = "onMouseOver=\"popUp(event,'phone_anphone')\" onmouseout=\"popUp(event,'phone_anphone')\"";
-$tooltip_ext = "onMouseOver=\"popUp(event,'phone_ext')\" onmouseout=\"popUp(event,'phone_ext')\"";
-$tooltip_port = "onMouseOver=\"popUp(event,'phone_port_phone')\" onmouseout=\"popUp(event,'phone_port_phone')\"";
-$tooltip_reception = "onMouseOver=\"popUp(event,'phone_reception')\" onmouseout=\"popUp(event,'phone_reception')\"";
-
-foreach $a (sort keys %analog) {
-    if ($zap{$a} eq "fxs") {
-       $icon = "<img src=\"tick.png\" alt=\"Analog Phone OK\" />";
-       print "<tr><td $tooltip_ext>$analog{$a}</td><td $tooltip_anphone>Analog Phone</td><td $tooltip_port>Port $a</td>";
-       if ($zap_ring{$a} == 1) {
-           $checked = "checked";
-       }
-       else {
-           $checked = "";
-       }
-       print "<td $tooltip_reception><input type=\"checkbox\" name=\"Zap_$a\" $checked>Reception</td><td>$icon</td></tr>\n";
-    }
-}
-
-# print list of IP phones
-
-$tooltip_ipphone = "onMouseOver=\"popUp(event,'phone_ipphone')\" onmouseout=\"popUp(event,'phone_ipphone')\"";
-$tooltip_ipphone_ip = "onMouseOver=\"popUp(event,'phone_ipphone_ip')\" onmouseout=\"popUp(event,'phone_ipphone_ip')\"";
-$tooltip_reception = "onMouseOver=\"popUp(event,'phone_reception')\" onmouseout=\"popUp(event,'phone_reception')\"";
-
-foreach $s (sort keys %sip) {
-    if ($sip{$s} eq "OK") {
-       $icon = "<img src=\"tick.png\" alt=\"IP Phone OK\" />";
-       print "<tr><td $tooltip_ext>$s</td><td $tooltip_ipphone>IP Phone</td><td $tooltip_ipphone_ip>$ipad{$s}</td>";
-       if ($sip_ring{$s} == 1) {
-           $checked = "checked";
-       }
-       else {
-           $checked = "";
-       }
-       print "<td $tooltip_reception><input type=\"checkbox\" name=\"SIP_$s\" $checked>Reception</td><td>$icon</td></tr>\n";
-    }
-}
-
-print '<tr><td>&nbsp;</td></tr>';
-print "<tr><td onMouseOver=\"popUp(event,'phone_addipphone')\" onmouseout=\"popUp(event,'phone_addipphone')\">";
-print "<a href=\"ipphones.sh\">Add IP Phone</a></td><td></td><td></td><td><input type=\"submit\" value=\"Update Reception\"></td></tr>";
-
-$tool_tip = "onMouseOver=\"popUp(event,'phone_lines')\" onmouseout=\"popUp(event,'phone_lines')\"";
-
-print '<tr><td>&nbsp</td></tr>';
-print "<tr $tool_tip><td colspan=\"4\" align=\"left\" valign=\"top\" ><h2>Phone Lines</h2></td></tr>
-";
-
-print "</form>";
-
-# print list of analog phone lines
-
-$tooltip_phoneline = "onMouseOver=\"popUp(event,'phone_phoneline')\" onmouseout=\"popUp(event,'phone_phoneline')\"";
-$tooltip_port = "onMouseOver=\"popUp(event,'phone_port_line')\" onmouseout=\"popUp(event,'phone_port_line')\"";
-$tooltip_line_prefix = "onMouseOver=\"popUp(event,'phone_line_prefix')\" onmouseout=\"popUp(event,'phone_line_prefix')\"";
-
-foreach $a (sort keys %analog) {
-    if ($zap{$a} eq "fxo") {
-       $icon = "<img src=\"tick.png\" alt=\"Phone Line OK\" />";
-       print "<tr><td $tooltip_line_prefix>0</td><td $tooltip_phoneline>Analog Line</td><td $tooltip_port>Port $a</td><td></td><td>$icon</td></tr>\n";
-    }
-}
-
-# print list of SIP VOIP trunks
-
-$tooltip_voipline = "onMouseOver=\"popUp(event,'phone_voipline')\" onmouseout=\"popUp(event,'phone_voipline')\"";
-$tooltip_voipline_ip = "onMouseOver=\"popUp(event,'phone_voipline_ip')\" onmouseout=\"popUp(event,'phone_voipline_ip')\"";
-$tooltip_voipline_prefix = "onMouseOver=\"popUp(event,'phone_voipline_prefix')\" onmouseout=\"popUp(event,'phone_voipline_prefix')\"";
-
-foreach $s (sort keys %voip) {
-    if ($voip{$s} eq "Registered") {
-       $icon = "<img src=\"tick.png\" alt=\"VOIP Line OK\" />";
-       print "<tr><td $tooltip_voipline_prefix>1</td><td $tooltip_voipline>VOIP Line</td><td $tooltip_voipline_ip>$ipad{$s}</td><td></td><td>$icon</td></tr>\n";
-    }
-}
-
-print '<tr><td>&nbsp;</td></tr>';
-print "<tr><td colspan=2 onMouseOver=\"popUp(event,'phone_addvoipline')\" onmouseout=\"popUp(event,'phone_addvoipline')\">";
-print "<a href=\"voiplines.sh\">Set Up VOIP Line</a></td></tr>";
diff --git a/easy-asterisk-gui/phones.sh b/easy-asterisk-gui/phones.sh
deleted file mode 100644 (file)
index 5dba25d..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/bin/sh
-# phones.sh
-# David Rowe 4 Jan 2010
-# Phones screen for Easy Asterisk GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
-    echo "<html>"
-    echo "<head>"
-    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
-    echo "</head>"
-    echo "</html>"
-    exit
-fi
-
-# See if we have Internet connectivity, first check dns as time outs can be very slow
-
-dns=`cat /etc/resolv.conf | awk '/^nameserver/ {print $2}'`
-dns_packet_loss=`ping $dns -c 1 -q | sed -n 's/.*received, \(.*\)% packet loss/\1/p'`
-internet="no";
-if [ $dns_packet_loss == "0" ]; then
-  packet_loss=`ping google.com -c 1 -q | sed -n 's/.*received, \(.*\)% packet loss/\1/p'`
-  if [ $packet_loss == "0" ]; then
-    internet="yes";
-  fi
-fi
-
-ipaddress=`ifconfig eth0 | sed -n 's/.*inet addr:\(.*\)  Bcast.*/\1/p'`
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-
-echo "<script>"
-echo 'var init_internet="'$internet'";'
-cat phones.js
-echo "</script>"
-
-cat << EOF
-<html>
-<title>Easy Asterisk - Phones</title>
-<body onload="localInit()">
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800>'
-cat banner.html
-echo "    <tr>"
-cat menu.html    
-cat <<EOF
-
-    <td valign="top">
-
-    <table align="right" width=600>
-      <tr>
-          <td onMouseOver="popUp(event,'phone_system')" onmouseout="popUp(event,'phone_system')" colspan="4" align="left" valign="top"><h2>Phone System</h2></td>
-      </tr>
-      <tr>
-         <td colspan="3" onMouseOver="popUp(event,'network_internet')" onmouseout="popUp(event,'network_internet')">Internet Connection:</td>
-         <td></td><td><div id="internet" >&nbsp;</div></td>
-      </tr>
-      <tr onMouseOver="popUp(event,'phone_ipaddress')" onmouseout="popUp(event,'phone_ipaddress')">
-         <td colspan="4">Phone System IP Address:</td>
-EOF
-echo "<td>$ipaddress</td>"
-cat <<EOF
-      </tr>
-      <tr><td>&nbsp</td></tr>
-      <tr>
-          <td onMouseOver="popUp(event,'phone_phones')" onmouseout="popUp(event,'phone_phones')" 
-               colspan="3" align="left" valign="top" ><h2>Phones</h2></td>
-      </tr>
-EOF
-
-# use perl to construct list of phones and phone lines for us
-asterisk "-rx sip show peers" 2>/dev/null > sipshowpeers.txt
-./phones.pl
-
-cat<<EOF
-    </table>
-
-    </td>
-
-    </tr>
-
-</table>
-</body>
-</html>
-EOF
-
diff --git a/easy-asterisk-gui/prototype.js b/easy-asterisk-gui/prototype.js
deleted file mode 100644 (file)
index 0e85338..0000000
+++ /dev/null
@@ -1,1781 +0,0 @@
-/*  Prototype JavaScript framework, version 1.4.0
- *  (c) 2005 Sam Stephenson <sam@conio.net>
- *
- *  Prototype is freely distributable under the terms of an MIT-style license.
- *  For details, see the Prototype web site: http://prototype.conio.net/
- *
-/*--------------------------------------------------------------------------*/
-
-var Prototype = {
-  Version: '1.4.0',
-  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
-
-  emptyFunction: function() {},
-  K: function(x) {return x}
-}
-
-var Class = {
-  create: function() {
-    return function() {
-      this.initialize.apply(this, arguments);
-    }
-  }
-}
-
-var Abstract = new Object();
-
-Object.extend = function(destination, source) {
-  for (property in source) {
-    destination[property] = source[property];
-  }
-  return destination;
-}
-
-Object.inspect = function(object) {
-  try {
-    if (object == undefined) return 'undefined';
-    if (object == null) return 'null';
-    return object.inspect ? object.inspect() : object.toString();
-  } catch (e) {
-    if (e instanceof RangeError) return '...';
-    throw e;
-  }
-}
-
-Function.prototype.bind = function() {
-  var __method = this, args = $A(arguments), object = args.shift();
-  return function() {
-    return __method.apply(object, args.concat($A(arguments)));
-  }
-}
-
-Function.prototype.bindAsEventListener = function(object) {
-  var __method = this;
-  return function(event) {
-    return __method.call(object, event || window.event);
-  }
-}
-
-Object.extend(Number.prototype, {
-  toColorPart: function() {
-    var digits = this.toString(16);
-    if (this < 16) return '0' + digits;
-    return digits;
-  },
-
-  succ: function() {
-    return this + 1;
-  },
-
-  times: function(iterator) {
-    $R(0, this, true).each(iterator);
-    return this;
-  }
-});
-
-var Try = {
-  these: function() {
-    var returnValue;
-
-    for (var i = 0; i < arguments.length; i++) {
-      var lambda = arguments[i];
-      try {
-        returnValue = lambda();
-        break;
-      } catch (e) {}
-    }
-
-    return returnValue;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var PeriodicalExecuter = Class.create();
-PeriodicalExecuter.prototype = {
-  initialize: function(callback, frequency) {
-    this.callback = callback;
-    this.frequency = frequency;
-    this.currentlyExecuting = false;
-
-    this.registerCallback();
-  },
-
-  registerCallback: function() {
-    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
-  },
-
-  onTimerEvent: function() {
-    if (!this.currentlyExecuting) {
-      try {
-        this.currentlyExecuting = true;
-        this.callback();
-      } finally {
-        this.currentlyExecuting = false;
-      }
-    }
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-function $() {
-  var elements = new Array();
-
-  for (var i = 0; i < arguments.length; i++) {
-    var element = arguments[i];
-    if (typeof element == 'string')
-      element = document.getElementById(element);
-
-    if (arguments.length == 1)
-      return element;
-
-    elements.push(element);
-  }
-
-  return elements;
-}
-Object.extend(String.prototype, {
-  stripTags: function() {
-    return this.replace(/<\/?[^>]+>/gi, '');
-  },
-
-  stripScripts: function() {
-    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
-  },
-
-  extractScripts: function() {
-    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
-    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
-    return (this.match(matchAll) || []).map(function(scriptTag) {
-      return (scriptTag.match(matchOne) || ['', ''])[1];
-    });
-  },
-
-  evalScripts: function() {
-    return this.extractScripts().map(eval);
-  },
-
-  escapeHTML: function() {
-    var div = document.createElement('div');
-    var text = document.createTextNode(this);
-    div.appendChild(text);
-    return div.innerHTML;
-  },
-
-  unescapeHTML: function() {
-    var div = document.createElement('div');
-    div.innerHTML = this.stripTags();
-    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
-  },
-
-  toQueryParams: function() {
-    var pairs = this.match(/^\??(.*)$/)[1].split('&');
-    return pairs.inject({}, function(params, pairString) {
-      var pair = pairString.split('=');
-      params[pair[0]] = pair[1];
-      return params;
-    });
-  },
-
-  toArray: function() {
-    return this.split('');
-  },
-
-  camelize: function() {
-    var oStringList = this.split('-');
-    if (oStringList.length == 1) return oStringList[0];
-
-    var camelizedString = this.indexOf('-') == 0
-      ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
-      : oStringList[0];
-
-    for (var i = 1, len = oStringList.length; i < len; i++) {
-      var s = oStringList[i];
-      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
-    }
-
-    return camelizedString;
-  },
-
-  inspect: function() {
-    return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
-  }
-});
-
-String.prototype.parseQuery = String.prototype.toQueryParams;
-
-var $break    = new Object();
-var $continue = new Object();
-
-var Enumerable = {
-  each: function(iterator) {
-    var index = 0;
-    try {
-      this._each(function(value) {
-        try {
-          iterator(value, index++);
-        } catch (e) {
-          if (e != $continue) throw e;
-        }
-      });
-    } catch (e) {
-      if (e != $break) throw e;
-    }
-  },
-
-  all: function(iterator) {
-    var result = true;
-    this.each(function(value, index) {
-      result = result && !!(iterator || Prototype.K)(value, index);
-      if (!result) throw $break;
-    });
-    return result;
-  },
-
-  any: function(iterator) {
-    var result = true;
-    this.each(function(value, index) {
-      if (result = !!(iterator || Prototype.K)(value, index))
-        throw $break;
-    });
-    return result;
-  },
-
-  collect: function(iterator) {
-    var results = [];
-    this.each(function(value, index) {
-      results.push(iterator(value, index));
-    });
-    return results;
-  },
-
-  detect: function (iterator) {
-    var result;
-    this.each(function(value, index) {
-      if (iterator(value, index)) {
-        result = value;
-        throw $break;
-      }
-    });
-    return result;
-  },
-
-  findAll: function(iterator) {
-    var results = [];
-    this.each(function(value, index) {
-      if (iterator(value, index))
-        results.push(value);
-    });
-    return results;
-  },
-
-  grep: function(pattern, iterator) {
-    var results = [];
-    this.each(function(value, index) {
-      var stringValue = value.toString();
-      if (stringValue.match(pattern))
-        results.push((iterator || Prototype.K)(value, index));
-    })
-    return results;
-  },
-
-  include: function(object) {
-    var found = false;
-    this.each(function(value) {
-      if (value == object) {
-        found = true;
-        throw $break;
-      }
-    });
-    return found;
-  },
-
-  inject: function(memo, iterator) {
-    this.each(function(value, index) {
-      memo = iterator(memo, value, index);
-    });
-    return memo;
-  },
-
-  invoke: function(method) {
-    var args = $A(arguments).slice(1);
-    return this.collect(function(value) {
-      return value[method].apply(value, args);
-    });
-  },
-
-  max: function(iterator) {
-    var result;
-    this.each(function(value, index) {
-      value = (iterator || Prototype.K)(value, index);
-      if (value >= (result || value))
-        result = value;
-    });
-    return result;
-  },
-
-  min: function(iterator) {
-    var result;
-    this.each(function(value, index) {
-      value = (iterator || Prototype.K)(value, index);
-      if (value <= (result || value))
-        result = value;
-    });
-    return result;
-  },
-
-  partition: function(iterator) {
-    var trues = [], falses = [];
-    this.each(function(value, index) {
-      ((iterator || Prototype.K)(value, index) ?
-        trues : falses).push(value);
-    });
-    return [trues, falses];
-  },
-
-  pluck: function(property) {
-    var results = [];
-    this.each(function(value, index) {
-      results.push(value[property]);
-    });
-    return results;
-  },
-
-  reject: function(iterator) {
-    var results = [];
-    this.each(function(value, index) {
-      if (!iterator(value, index))
-        results.push(value);
-    });
-    return results;
-  },
-
-  sortBy: function(iterator) {
-    return this.collect(function(value, index) {
-      return {value: value, criteria: iterator(value, index)};
-    }).sort(function(left, right) {
-      var a = left.criteria, b = right.criteria;
-      return a < b ? -1 : a > b ? 1 : 0;
-    }).pluck('value');
-  },
-
-  toArray: function() {
-    return this.collect(Prototype.K);
-  },
-
-  zip: function() {
-    var iterator = Prototype.K, args = $A(arguments);
-    if (typeof args.last() == 'function')
-      iterator = args.pop();
-
-    var collections = [this].concat(args).map($A);
-    return this.map(function(value, index) {
-      iterator(value = collections.pluck(index));
-      return value;
-    });
-  },
-
-  inspect: function() {
-    return '#<Enumerable:' + this.toArray().inspect() + '>';
-  }
-}
-
-Object.extend(Enumerable, {
-  map:     Enumerable.collect,
-  find:    Enumerable.detect,
-  select:  Enumerable.findAll,
-  member:  Enumerable.include,
-  entries: Enumerable.toArray
-});
-var $A = Array.from = function(iterable) {
-  if (!iterable) return [];
-  if (iterable.toArray) {
-    return iterable.toArray();
-  } else {
-    var results = [];
-    for (var i = 0; i < iterable.length; i++)
-      results.push(iterable[i]);
-    return results;
-  }
-}
-
-Object.extend(Array.prototype, Enumerable);
-
-Array.prototype._reverse = Array.prototype.reverse;
-
-Object.extend(Array.prototype, {
-  _each: function(iterator) {
-    for (var i = 0; i < this.length; i++)
-      iterator(this[i]);
-  },
-
-  clear: function() {
-    this.length = 0;
-    return this;
-  },
-
-  first: function() {
-    return this[0];
-  },
-
-  last: function() {
-    return this[this.length - 1];
-  },
-
-  compact: function() {
-    return this.select(function(value) {
-      return value != undefined || value != null;
-    });
-  },
-
-  flatten: function() {
-    return this.inject([], function(array, value) {
-      return array.concat(value.constructor == Array ?
-        value.flatten() : [value]);
-    });
-  },
-
-  without: function() {
-    var values = $A(arguments);
-    return this.select(function(value) {
-      return !values.include(value);
-    });
-  },
-
-  indexOf: function(object) {
-    for (var i = 0; i < this.length; i++)
-      if (this[i] == object) return i;
-    return -1;
-  },
-
-  reverse: function(inline) {
-    return (inline !== false ? this : this.toArray())._reverse();
-  },
-
-  shift: function() {
-    var result = this[0];
-    for (var i = 0; i < this.length - 1; i++)
-      this[i] = this[i + 1];
-    this.length--;
-    return result;
-  },
-
-  inspect: function() {
-    return '[' + this.map(Object.inspect).join(', ') + ']';
-  }
-});
-var Hash = {
-  _each: function(iterator) {
-    for (key in this) {
-      var value = this[key];
-      if (typeof value == 'function') continue;
-
-      var pair = [key, value];
-      pair.key = key;
-      pair.value = value;
-      iterator(pair);
-    }
-  },
-
-  keys: function() {
-    return this.pluck('key');
-  },
-
-  values: function() {
-    return this.pluck('value');
-  },
-
-  merge: function(hash) {
-    return $H(hash).inject($H(this), function(mergedHash, pair) {
-      mergedHash[pair.key] = pair.value;
-      return mergedHash;
-    });
-  },
-
-  toQueryString: function() {
-    return this.map(function(pair) {
-      return pair.map(encodeURIComponent).join('=');
-    }).join('&');
-  },
-
-  inspect: function() {
-    return '#<Hash:{' + this.map(function(pair) {
-      return pair.map(Object.inspect).join(': ');
-    }).join(', ') + '}>';
-  }
-}
-
-function $H(object) {
-  var hash = Object.extend({}, object || {});
-  Object.extend(hash, Enumerable);
-  Object.extend(hash, Hash);
-  return hash;
-}
-ObjectRange = Class.create();
-Object.extend(ObjectRange.prototype, Enumerable);
-Object.extend(ObjectRange.prototype, {
-  initialize: function(start, end, exclusive) {
-    this.start = start;
-    this.end = end;
-    this.exclusive = exclusive;
-  },
-
-  _each: function(iterator) {
-    var value = this.start;
-    do {
-      iterator(value);
-      value = value.succ();
-    } while (this.include(value));
-  },
-
-  include: function(value) {
-    if (value < this.start)
-      return false;
-    if (this.exclusive)
-      return value < this.end;
-    return value <= this.end;
-  }
-});
-
-var $R = function(start, end, exclusive) {
-  return new ObjectRange(start, end, exclusive);
-}
-
-var Ajax = {
-  getTransport: function() {
-    return Try.these(
-      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
-      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
-      function() {return new XMLHttpRequest()}
-    ) || false;
-  },
-
-  activeRequestCount: 0
-}
-
-Ajax.Responders = {
-  responders: [],
-
-  _each: function(iterator) {
-    this.responders._each(iterator);
-  },
-
-  register: function(responderToAdd) {
-    if (!this.include(responderToAdd))
-      this.responders.push(responderToAdd);
-  },
-
-  unregister: function(responderToRemove) {
-    this.responders = this.responders.without(responderToRemove);
-  },
-
-  dispatch: function(callback, request, transport, json) {
-    this.each(function(responder) {
-      if (responder[callback] && typeof responder[callback] == 'function') {
-        try {
-          responder[callback].apply(responder, [request, transport, json]);
-        } catch (e) {}
-      }
-    });
-  }
-};
-
-Object.extend(Ajax.Responders, Enumerable);
-
-Ajax.Responders.register({
-  onCreate: function() {
-    Ajax.activeRequestCount++;
-  },
-
-  onComplete: function() {
-    Ajax.activeRequestCount--;
-  }
-});
-
-Ajax.Base = function() {};
-Ajax.Base.prototype = {
-  setOptions: function(options) {
-    this.options = {
-      method:       'post',
-      asynchronous: true,
-      parameters:   ''
-    }
-    Object.extend(this.options, options || {});
-  },
-
-  responseIsSuccess: function() {
-    return this.transport.status == undefined
-        || this.transport.status == 0
-        || (this.transport.status >= 200 && this.transport.status < 300);
-  },
-
-  responseIsFailure: function() {
-    return !this.responseIsSuccess();
-  }
-}
-
-Ajax.Request = Class.create();
-Ajax.Request.Events =
-  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
-
-Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
-  initialize: function(url, options) {
-    this.transport = Ajax.getTransport();
-    this.setOptions(options);
-    this.request(url);
-  },
-
-  request: function(url) {
-    var parameters = this.options.parameters || '';
-    if (parameters.length > 0) parameters += '&_=';
-
-    try {
-      this.url = url;
-      if (this.options.method == 'get' && parameters.length > 0)
-        this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
-
-      Ajax.Responders.dispatch('onCreate', this, this.transport);
-
-      this.transport.open(this.options.method, this.url,
-        this.options.asynchronous);
-
-      if (this.options.asynchronous) {
-        this.transport.onreadystatechange = this.onStateChange.bind(this);
-        setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
-      }
-
-      this.setRequestHeaders();
-
-      var body = this.options.postBody ? this.options.postBody : parameters;
-      this.transport.send(this.options.method == 'post' ? body : null);
-
-    } catch (e) {
-      this.dispatchException(e);
-    }
-  },
-
-  setRequestHeaders: function() {
-    var requestHeaders =
-      ['X-Requested-With', 'XMLHttpRequest',
-       'X-Prototype-Version', Prototype.Version];
-
-    if (this.options.method == 'post') {
-      requestHeaders.push('Content-type',
-        'application/x-www-form-urlencoded');
-
-      /* Force "Connection: close" for Mozilla browsers to work around
-       * a bug where XMLHttpReqeuest sends an incorrect Content-length
-       * header. See Mozilla Bugzilla #246651.
-       */
-      if (this.transport.overrideMimeType)
-        requestHeaders.push('Connection', 'close');
-    }
-
-    if (this.options.requestHeaders)
-      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
-
-    for (var i = 0; i < requestHeaders.length; i += 2)
-      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
-  },
-
-  onStateChange: function() {
-    var readyState = this.transport.readyState;
-    if (readyState != 1)
-      this.respondToReadyState(this.transport.readyState);
-  },
-
-  header: function(name) {
-    try {
-      return this.transport.getResponseHeader(name);
-    } catch (e) {}
-  },
-
-  evalJSON: function() {
-    try {
-      return eval(this.header('X-JSON'));
-    } catch (e) {}
-  },
-
-  evalResponse: function() {
-    try {
-      return eval(this.transport.responseText);
-    } catch (e) {
-      this.dispatchException(e);
-    }
-  },
-
-  respondToReadyState: function(readyState) {
-    var event = Ajax.Request.Events[readyState];
-    var transport = this.transport, json = this.evalJSON();
-
-    if (event == 'Complete') {
-      try {
-        (this.options['on' + this.transport.status]
-         || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
-         || Prototype.emptyFunction)(transport, json);
-      } catch (e) {
-        this.dispatchException(e);
-      }
-
-      if ((this.header('Content-type') || '').match(/^text\/javascript/i))
-        this.evalResponse();
-    }
-
-    try {
-      (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
-      Ajax.Responders.dispatch('on' + event, this, transport, json);
-    } catch (e) {
-      this.dispatchException(e);
-    }
-
-    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
-    if (event == 'Complete')
-      this.transport.onreadystatechange = Prototype.emptyFunction;
-  },
-
-  dispatchException: function(exception) {
-    (this.options.onException || Prototype.emptyFunction)(this, exception);
-    Ajax.Responders.dispatch('onException', this, exception);
-  }
-});
-
-Ajax.Updater = Class.create();
-
-Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
-  initialize: function(container, url, options) {
-    this.containers = {
-      success: container.success ? $(container.success) : $(container),
-      failure: container.failure ? $(container.failure) :
-        (container.success ? null : $(container))
-    }
-
-    this.transport = Ajax.getTransport();
-    this.setOptions(options);
-
-    var onComplete = this.options.onComplete || Prototype.emptyFunction;
-    this.options.onComplete = (function(transport, object) {
-      this.updateContent();
-      onComplete(transport, object);
-    }).bind(this);
-
-    this.request(url);
-  },
-
-  updateContent: function() {
-    var receiver = this.responseIsSuccess() ?
-      this.containers.success : this.containers.failure;
-    var response = this.transport.responseText;
-
-    if (!this.options.evalScripts)
-      response = response.stripScripts();
-
-    if (receiver) {
-      if (this.options.insertion) {
-        new this.options.insertion(receiver, response);
-      } else {
-        Element.update(receiver, response);
-      }
-    }
-
-    if (this.responseIsSuccess()) {
-      if (this.onComplete)
-        setTimeout(this.onComplete.bind(this), 10);
-    }
-  }
-});
-
-Ajax.PeriodicalUpdater = Class.create();
-Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
-  initialize: function(container, url, options) {
-    this.setOptions(options);
-    this.onComplete = this.options.onComplete;
-
-    this.frequency = (this.options.frequency || 2);
-    this.decay = (this.options.decay || 1);
-
-    this.updater = {};
-    this.container = container;
-    this.url = url;
-
-    this.start();
-  },
-
-  start: function() {
-    this.options.onComplete = this.updateComplete.bind(this);
-    this.onTimerEvent();
-  },
-
-  stop: function() {
-    this.updater.onComplete = undefined;
-    clearTimeout(this.timer);
-    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
-  },
-
-  updateComplete: function(request) {
-    if (this.options.decay) {
-      this.decay = (request.responseText == this.lastText ?
-        this.decay * this.options.decay : 1);
-
-      this.lastText = request.responseText;
-    }
-    this.timer = setTimeout(this.onTimerEvent.bind(this),
-      this.decay * this.frequency * 1000);
-  },
-
-  onTimerEvent: function() {
-    this.updater = new Ajax.Updater(this.container, this.url, this.options);
-  }
-});
-document.getElementsByClassName = function(className, parentElement) {
-  var children = ($(parentElement) || document.body).getElementsByTagName('*');
-  return $A(children).inject([], function(elements, child) {
-    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
-      elements.push(child);
-    return elements;
-  });
-}
-
-/*--------------------------------------------------------------------------*/
-
-if (!window.Element) {
-  var Element = new Object();
-}
-
-Object.extend(Element, {
-  visible: function(element) {
-    return $(element).style.display != 'none';
-  },
-
-  toggle: function() {
-    for (var i = 0; i < arguments.length; i++) {
-      var element = $(arguments[i]);
-      Element[Element.visible(element) ? 'hide' : 'show'](element);
-    }
-  },
-
-  hide: function() {
-    for (var i = 0; i < arguments.length; i++) {
-      var element = $(arguments[i]);
-      element.style.display = 'none';
-    }
-  },
-
-  show: function() {
-    for (var i = 0; i < arguments.length; i++) {
-      var element = $(arguments[i]);
-      element.style.display = '';
-    }
-  },
-
-  remove: function(element) {
-    element = $(element);
-    element.parentNode.removeChild(element);
-  },
-
-  update: function(element, html) {
-    $(element).innerHTML = html.stripScripts();
-    setTimeout(function() {html.evalScripts()}, 10);
-  },
-
-  getHeight: function(element) {
-    element = $(element);
-    return element.offsetHeight;
-  },
-
-  classNames: function(element) {
-    return new Element.ClassNames(element);
-  },
-
-  hasClassName: function(element, className) {
-    if (!(element = $(element))) return;
-    return Element.classNames(element).include(className);
-  },
-
-  addClassName: function(element, className) {
-    if (!(element = $(element))) return;
-    return Element.classNames(element).add(className);
-  },
-
-  removeClassName: function(element, className) {
-    if (!(element = $(element))) return;
-    return Element.classNames(element).remove(className);
-  },
-
-  // removes whitespace-only text node children
-  cleanWhitespace: function(element) {
-    element = $(element);
-    for (var i = 0; i < element.childNodes.length; i++) {
-      var node = element.childNodes[i];
-      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
-        Element.remove(node);
-    }
-  },
-
-  empty: function(element) {
-    return $(element).innerHTML.match(/^\s*$/);
-  },
-
-  scrollTo: function(element) {
-    element = $(element);
-    var x = element.x ? element.x : element.offsetLeft,
-        y = element.y ? element.y : element.offsetTop;
-    window.scrollTo(x, y);
-  },
-
-  getStyle: function(element, style) {
-    element = $(element);
-    var value = element.style[style.camelize()];
-    if (!value) {
-      if (document.defaultView && document.defaultView.getComputedStyle) {
-        var css = document.defaultView.getComputedStyle(element, null);
-        value = css ? css.getPropertyValue(style) : null;
-      } else if (element.currentStyle) {
-        value = element.currentStyle[style.camelize()];
-      }
-    }
-
-    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
-      if (Element.getStyle(element, 'position') == 'static') value = 'auto';
-
-    return value == 'auto' ? null : value;
-  },
-
-  setStyle: function(element, style) {
-    element = $(element);
-    for (name in style)
-      element.style[name.camelize()] = style[name];
-  },
-
-  getDimensions: function(element) {
-    element = $(element);
-    if (Element.getStyle(element, 'display') != 'none')
-      return {width: element.offsetWidth, height: element.offsetHeight};
-
-    // All *Width and *Height properties give 0 on elements with display none,
-    // so enable the element temporarily
-    var els = element.style;
-    var originalVisibility = els.visibility;
-    var originalPosition = els.position;
-    els.visibility = 'hidden';
-    els.position = 'absolute';
-    els.display = '';
-    var originalWidth = element.clientWidth;
-    var originalHeight = element.clientHeight;
-    els.display = 'none';
-    els.position = originalPosition;
-    els.visibility = originalVisibility;
-    return {width: originalWidth, height: originalHeight};
-  },
-
-  makePositioned: function(element) {
-    element = $(element);
-    var pos = Element.getStyle(element, 'position');
-    if (pos == 'static' || !pos) {
-      element._madePositioned = true;
-      element.style.position = 'relative';
-      // Opera returns the offset relative to the positioning context, when an
-      // element is position relative but top and left have not been defined
-      if (window.opera) {
-        element.style.top = 0;
-        element.style.left = 0;
-      }
-    }
-  },
-
-  undoPositioned: function(element) {
-    element = $(element);
-    if (element._madePositioned) {
-      element._madePositioned = undefined;
-      element.style.position =
-        element.style.top =
-        element.style.left =
-        element.style.bottom =
-        element.style.right = '';
-    }
-  },
-
-  makeClipping: function(element) {
-    element = $(element);
-    if (element._overflow) return;
-    element._overflow = element.style.overflow;
-    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
-      element.style.overflow = 'hidden';
-  },
-
-  undoClipping: function(element) {
-    element = $(element);
-    if (element._overflow) return;
-    element.style.overflow = element._overflow;
-    element._overflow = undefined;
-  }
-});
-
-var Toggle = new Object();
-Toggle.display = Element.toggle;
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.Insertion = function(adjacency) {
-  this.adjacency = adjacency;
-}
-
-Abstract.Insertion.prototype = {
-  initialize: function(element, content) {
-    this.element = $(element);
-    this.content = content.stripScripts();
-
-    if (this.adjacency && this.element.insertAdjacentHTML) {
-      try {
-        this.element.insertAdjacentHTML(this.adjacency, this.content);
-      } catch (e) {
-        if (this.element.tagName.toLowerCase() == 'tbody') {
-          this.insertContent(this.contentFromAnonymousTable());
-        } else {
-          throw e;
-        }
-      }
-    } else {
-      this.range = this.element.ownerDocument.createRange();
-      if (this.initializeRange) this.initializeRange();
-      this.insertContent([this.range.createContextualFragment(this.content)]);
-    }
-
-    setTimeout(function() {content.evalScripts()}, 10);
-  },
-
-  contentFromAnonymousTable: function() {
-    var div = document.createElement('div');
-    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
-    return $A(div.childNodes[0].childNodes[0].childNodes);
-  }
-}
-
-var Insertion = new Object();
-
-Insertion.Before = Class.create();
-Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
-  initializeRange: function() {
-    this.range.setStartBefore(this.element);
-  },
-
-  insertContent: function(fragments) {
-    fragments.each((function(fragment) {
-      this.element.parentNode.insertBefore(fragment, this.element);
-    }).bind(this));
-  }
-});
-
-Insertion.Top = Class.create();
-Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
-  initializeRange: function() {
-    this.range.selectNodeContents(this.element);
-    this.range.collapse(true);
-  },
-
-  insertContent: function(fragments) {
-    fragments.reverse(false).each((function(fragment) {
-      this.element.insertBefore(fragment, this.element.firstChild);
-    }).bind(this));
-  }
-});
-
-Insertion.Bottom = Class.create();
-Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
-  initializeRange: function() {
-    this.range.selectNodeContents(this.element);
-    this.range.collapse(this.element);
-  },
-
-  insertContent: function(fragments) {
-    fragments.each((function(fragment) {
-      this.element.appendChild(fragment);
-    }).bind(this));
-  }
-});
-
-Insertion.After = Class.create();
-Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
-  initializeRange: function() {
-    this.range.setStartAfter(this.element);
-  },
-
-  insertContent: function(fragments) {
-    fragments.each((function(fragment) {
-      this.element.parentNode.insertBefore(fragment,
-        this.element.nextSibling);
-    }).bind(this));
-  }
-});
-
-/*--------------------------------------------------------------------------*/
-
-Element.ClassNames = Class.create();
-Element.ClassNames.prototype = {
-  initialize: function(element) {
-    this.element = $(element);
-  },
-
-  _each: function(iterator) {
-    this.element.className.split(/\s+/).select(function(name) {
-      return name.length > 0;
-    })._each(iterator);
-  },
-
-  set: function(className) {
-    this.element.className = className;
-  },
-
-  add: function(classNameToAdd) {
-    if (this.include(classNameToAdd)) return;
-    this.set(this.toArray().concat(classNameToAdd).join(' '));
-  },
-
-  remove: function(classNameToRemove) {
-    if (!this.include(classNameToRemove)) return;
-    this.set(this.select(function(className) {
-      return className != classNameToRemove;
-    }).join(' '));
-  },
-
-  toString: function() {
-    return this.toArray().join(' ');
-  }
-}
-
-Object.extend(Element.ClassNames.prototype, Enumerable);
-var Field = {
-  clear: function() {
-    for (var i = 0; i < arguments.length; i++)
-      $(arguments[i]).value = '';
-  },
-
-  focus: function(element) {
-    $(element).focus();
-  },
-
-  present: function() {
-    for (var i = 0; i < arguments.length; i++)
-      if ($(arguments[i]).value == '') return false;
-    return true;
-  },
-
-  select: function(element) {
-    $(element).select();
-  },
-
-  activate: function(element) {
-    element = $(element);
-    element.focus();
-    if (element.select)
-      element.select();
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var Form = {
-  serialize: function(form) {
-    var elements = Form.getElements($(form));
-    var queryComponents = new Array();
-
-    for (var i = 0; i < elements.length; i++) {
-      var queryComponent = Form.Element.serialize(elements[i]);
-      if (queryComponent)
-        queryComponents.push(queryComponent);
-    }
-
-    return queryComponents.join('&');
-  },
-
-  getElements: function(form) {
-    form = $(form);
-    var elements = new Array();
-
-    for (tagName in Form.Element.Serializers) {
-      var tagElements = form.getElementsByTagName(tagName);
-      for (var j = 0; j < tagElements.length; j++)
-        elements.push(tagElements[j]);
-    }
-    return elements;
-  },
-
-  getInputs: function(form, typeName, name) {
-    form = $(form);
-    var inputs = form.getElementsByTagName('input');
-
-    if (!typeName && !name)
-      return inputs;
-
-    var matchingInputs = new Array();
-    for (var i = 0; i < inputs.length; i++) {
-      var input = inputs[i];
-      if ((typeName && input.type != typeName) ||
-          (name && input.name != name))
-        continue;
-      matchingInputs.push(input);
-    }
-
-    return matchingInputs;
-  },
-
-  disable: function(form) {
-    var elements = Form.getElements(form);
-    for (var i = 0; i < elements.length; i++) {
-      var element = elements[i];
-      element.blur();
-      element.disabled = 'true';
-    }
-  },
-
-  enable: function(form) {
-    var elements = Form.getElements(form);
-    for (var i = 0; i < elements.length; i++) {
-      var element = elements[i];
-      element.disabled = '';
-    }
-  },
-
-  findFirstElement: function(form) {
-    return Form.getElements(form).find(function(element) {
-      return element.type != 'hidden' && !element.disabled &&
-        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
-    });
-  },
-
-  focusFirstElement: function(form) {
-    Field.activate(Form.findFirstElement(form));
-  },
-
-  reset: function(form) {
-    $(form).reset();
-  }
-}
-
-Form.Element = {
-  serialize: function(element) {
-    element = $(element);
-    var method = element.tagName.toLowerCase();
-    var parameter = Form.Element.Serializers[method](element);
-
-    if (parameter) {
-      var key = encodeURIComponent(parameter[0]);
-      if (key.length == 0) return;
-
-      if (parameter[1].constructor != Array)
-        parameter[1] = [parameter[1]];
-
-      return parameter[1].map(function(value) {
-        return key + '=' + encodeURIComponent(value);
-      }).join('&');
-    }
-  },
-
-  getValue: function(element) {
-    element = $(element);
-    var method = element.tagName.toLowerCase();
-    var parameter = Form.Element.Serializers[method](element);
-
-    if (parameter)
-      return parameter[1];
-  }
-}
-
-Form.Element.Serializers = {
-  input: function(element) {
-    switch (element.type.toLowerCase()) {
-      case 'submit':
-      case 'hidden':
-      case 'password':
-      case 'text':
-        return Form.Element.Serializers.textarea(element);
-      case 'checkbox':
-      case 'radio':
-        return Form.Element.Serializers.inputSelector(element);
-    }
-    return false;
-  },
-
-  inputSelector: function(element) {
-    if (element.checked)
-      return [element.name, element.value];
-  },
-
-  textarea: function(element) {
-    return [element.name, element.value];
-  },
-
-  select: function(element) {
-    return Form.Element.Serializers[element.type == 'select-one' ?
-      'selectOne' : 'selectMany'](element);
-  },
-
-  selectOne: function(element) {
-    var value = '', opt, index = element.selectedIndex;
-    if (index >= 0) {
-      opt = element.options[index];
-      value = opt.value;
-      if (!value && !('value' in opt))
-        value = opt.text;
-    }
-    return [element.name, value];
-  },
-
-  selectMany: function(element) {
-    var value = new Array();
-    for (var i = 0; i < element.length; i++) {
-      var opt = element.options[i];
-      if (opt.selected) {
-        var optValue = opt.value;
-        if (!optValue && !('value' in opt))
-          optValue = opt.text;
-        value.push(optValue);
-      }
-    }
-    return [element.name, value];
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var $F = Form.Element.getValue;
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.TimedObserver = function() {}
-Abstract.TimedObserver.prototype = {
-  initialize: function(element, frequency, callback) {
-    this.frequency = frequency;
-    this.element   = $(element);
-    this.callback  = callback;
-
-    this.lastValue = this.getValue();
-    this.registerCallback();
-  },
-
-  registerCallback: function() {
-    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
-  },
-
-  onTimerEvent: function() {
-    var value = this.getValue();
-    if (this.lastValue != value) {
-      this.callback(this.element, value);
-      this.lastValue = value;
-    }
-  }
-}
-
-Form.Element.Observer = Class.create();
-Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
-  getValue: function() {
-    return Form.Element.getValue(this.element);
-  }
-});
-
-Form.Observer = Class.create();
-Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
-  getValue: function() {
-    return Form.serialize(this.element);
-  }
-});
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.EventObserver = function() {}
-Abstract.EventObserver.prototype = {
-  initialize: function(element, callback) {
-    this.element  = $(element);
-    this.callback = callback;
-
-    this.lastValue = this.getValue();
-    if (this.element.tagName.toLowerCase() == 'form')
-      this.registerFormCallbacks();
-    else
-      this.registerCallback(this.element);
-  },
-
-  onElementEvent: function() {
-    var value = this.getValue();
-    if (this.lastValue != value) {
-      this.callback(this.element, value);
-      this.lastValue = value;
-    }
-  },
-
-  registerFormCallbacks: function() {
-    var elements = Form.getElements(this.element);
-    for (var i = 0; i < elements.length; i++)
-      this.registerCallback(elements[i]);
-  },
-
-  registerCallback: function(element) {
-    if (element.type) {
-      switch (element.type.toLowerCase()) {
-        case 'checkbox':
-        case 'radio':
-          Event.observe(element, 'click', this.onElementEvent.bind(this));
-          break;
-        case 'password':
-        case 'text':
-        case 'textarea':
-        case 'select-one':
-        case 'select-multiple':
-          Event.observe(element, 'change', this.onElementEvent.bind(this));
-          break;
-      }
-    }
-  }
-}
-
-Form.Element.EventObserver = Class.create();
-Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
-  getValue: function() {
-    return Form.Element.getValue(this.element);
-  }
-});
-
-Form.EventObserver = Class.create();
-Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
-  getValue: function() {
-    return Form.serialize(this.element);
-  }
-});
-if (!window.Event) {
-  var Event = new Object();
-}
-
-Object.extend(Event, {
-  KEY_BACKSPACE: 8,
-  KEY_TAB:       9,
-  KEY_RETURN:   13,
-  KEY_ESC:      27,
-  KEY_LEFT:     37,
-  KEY_UP:       38,
-  KEY_RIGHT:    39,
-  KEY_DOWN:     40,
-  KEY_DELETE:   46,
-
-  element: function(event) {
-    return event.target || event.srcElement;
-  },
-
-  isLeftClick: function(event) {
-    return (((event.which) && (event.which == 1)) ||
-            ((event.button) && (event.button == 1)));
-  },
-
-  pointerX: function(event) {
-    return event.pageX || (event.clientX +
-      (document.documentElement.scrollLeft || document.body.scrollLeft));
-  },
-
-  pointerY: function(event) {
-    return event.pageY || (event.clientY +
-      (document.documentElement.scrollTop || document.body.scrollTop));
-  },
-
-  stop: function(event) {
-    if (event.preventDefault) {
-      event.preventDefault();
-      event.stopPropagation();
-    } else {
-      event.returnValue = false;
-      event.cancelBubble = true;
-    }
-  },
-
-  // find the first node with the given tagName, starting from the
-  // node the event was triggered on; traverses the DOM upwards
-  findElement: function(event, tagName) {
-    var element = Event.element(event);
-    while (element.parentNode && (!element.tagName ||
-        (element.tagName.toUpperCase() != tagName.toUpperCase())))
-      element = element.parentNode;
-    return element;
-  },
-
-  observers: false,
-
-  _observeAndCache: function(element, name, observer, useCapture) {
-    if (!this.observers) this.observers = [];
-    if (element.addEventListener) {
-      this.observers.push([element, name, observer, useCapture]);
-      element.addEventListener(name, observer, useCapture);
-    } else if (element.attachEvent) {
-      this.observers.push([element, name, observer, useCapture]);
-      element.attachEvent('on' + name, observer);
-    }
-  },
-
-  unloadCache: function() {
-    if (!Event.observers) return;
-    for (var i = 0; i < Event.observers.length; i++) {
-      Event.stopObserving.apply(this, Event.observers[i]);
-      Event.observers[i][0] = null;
-    }
-    Event.observers = false;
-  },
-
-  observe: function(element, name, observer, useCapture) {
-    var element = $(element);
-    useCapture = useCapture || false;
-
-    if (name == 'keypress' &&
-        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
-        || element.attachEvent))
-      name = 'keydown';
-
-    this._observeAndCache(element, name, observer, useCapture);
-  },
-
-  stopObserving: function(element, name, observer, useCapture) {
-    var element = $(element);
-    useCapture = useCapture || false;
-
-    if (name == 'keypress' &&
-        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
-        || element.detachEvent))
-      name = 'keydown';
-
-    if (element.removeEventListener) {
-      element.removeEventListener(name, observer, useCapture);
-    } else if (element.detachEvent) {
-      element.detachEvent('on' + name, observer);
-    }
-  }
-});
-
-/* prevent memory leaks in IE */
-Event.observe(window, 'unload', Event.unloadCache, false);
-var Position = {
-  // set to true if needed, warning: firefox performance problems
-  // NOT neeeded for page scrolling, only if draggable contained in
-  // scrollable elements
-  includeScrollOffsets: false,
-
-  // must be called before calling withinIncludingScrolloffset, every time the
-  // page is scrolled
-  prepare: function() {
-    this.deltaX =  window.pageXOffset
-                || document.documentElement.scrollLeft
-                || document.body.scrollLeft
-                || 0;
-    this.deltaY =  window.pageYOffset
-                || document.documentElement.scrollTop
-                || document.body.scrollTop
-                || 0;
-  },
-
-  realOffset: function(element) {
-    var valueT = 0, valueL = 0;
-    do {
-      valueT += element.scrollTop  || 0;
-      valueL += element.scrollLeft || 0;
-      element = element.parentNode;
-    } while (element);
-    return [valueL, valueT];
-  },
-
-  cumulativeOffset: function(element) {
-    var valueT = 0, valueL = 0;
-    do {
-      valueT += element.offsetTop  || 0;
-      valueL += element.offsetLeft || 0;
-      element = element.offsetParent;
-    } while (element);
-    return [valueL, valueT];
-  },
-
-  positionedOffset: function(element) {
-    var valueT = 0, valueL = 0;
-    do {
-      valueT += element.offsetTop  || 0;
-      valueL += element.offsetLeft || 0;
-      element = element.offsetParent;
-      if (element) {
-        p = Element.getStyle(element, 'position');
-        if (p == 'relative' || p == 'absolute') break;
-      }
-    } while (element);
-    return [valueL, valueT];
-  },
-
-  offsetParent: function(element) {
-    if (element.offsetParent) return element.offsetParent;
-    if (element == document.body) return element;
-
-    while ((element = element.parentNode) && element != document.body)
-      if (Element.getStyle(element, 'position') != 'static')
-        return element;
-
-    return document.body;
-  },
-
-  // caches x/y coordinate pair to use with overlap
-  within: function(element, x, y) {
-    if (this.includeScrollOffsets)
-      return this.withinIncludingScrolloffsets(element, x, y);
-    this.xcomp = x;
-    this.ycomp = y;
-    this.offset = this.cumulativeOffset(element);
-
-    return (y >= this.offset[1] &&
-            y <  this.offset[1] + element.offsetHeight &&
-            x >= this.offset[0] &&
-            x <  this.offset[0] + element.offsetWidth);
-  },
-
-  withinIncludingScrolloffsets: function(element, x, y) {
-    var offsetcache = this.realOffset(element);
-
-    this.xcomp = x + offsetcache[0] - this.deltaX;
-    this.ycomp = y + offsetcache[1] - this.deltaY;
-    this.offset = this.cumulativeOffset(element);
-
-    return (this.ycomp >= this.offset[1] &&
-            this.ycomp <  this.offset[1] + element.offsetHeight &&
-            this.xcomp >= this.offset[0] &&
-            this.xcomp <  this.offset[0] + element.offsetWidth);
-  },
-
-  // within must be called directly before
-  overlap: function(mode, element) {
-    if (!mode) return 0;
-    if (mode == 'vertical')
-      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
-        element.offsetHeight;
-    if (mode == 'horizontal')
-      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
-        element.offsetWidth;
-  },
-
-  clone: function(source, target) {
-    source = $(source);
-    target = $(target);
-    target.style.position = 'absolute';
-    var offsets = this.cumulativeOffset(source);
-    target.style.top    = offsets[1] + 'px';
-    target.style.left   = offsets[0] + 'px';
-    target.style.width  = source.offsetWidth + 'px';
-    target.style.height = source.offsetHeight + 'px';
-  },
-
-  page: function(forElement) {
-    var valueT = 0, valueL = 0;
-
-    var element = forElement;
-    do {
-      valueT += element.offsetTop  || 0;
-      valueL += element.offsetLeft || 0;
-
-      // Safari fix
-      if (element.offsetParent==document.body)
-        if (Element.getStyle(element,'position')=='absolute') break;
-
-    } while (element = element.offsetParent);
-
-    element = forElement;
-    do {
-      valueT -= element.scrollTop  || 0;
-      valueL -= element.scrollLeft || 0;
-    } while (element = element.parentNode);
-
-    return [valueL, valueT];
-  },
-
-  clone: function(source, target) {
-    var options = Object.extend({
-      setLeft:    true,
-      setTop:     true,
-      setWidth:   true,
-      setHeight:  true,
-      offsetTop:  0,
-      offsetLeft: 0
-    }, arguments[2] || {})
-
-    // find page position of source
-    source = $(source);
-    var p = Position.page(source);
-
-    // find coordinate system to use
-    target = $(target);
-    var delta = [0, 0];
-    var parent = null;
-    // delta [0,0] will do fine with position: fixed elements,
-    // position:absolute needs offsetParent deltas
-    if (Element.getStyle(target,'position') == 'absolute') {
-      parent = Position.offsetParent(target);
-      delta = Position.page(parent);
-    }
-
-    // correct by body offsets (fixes Safari)
-    if (parent == document.body) {
-      delta[0] -= document.body.offsetLeft;
-      delta[1] -= document.body.offsetTop;
-    }
-
-    // set position
-    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
-    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
-    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
-    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
-  },
-
-  absolutize: function(element) {
-    element = $(element);
-    if (element.style.position == 'absolute') return;
-    Position.prepare();
-
-    var offsets = Position.positionedOffset(element);
-    var top     = offsets[1];
-    var left    = offsets[0];
-    var width   = element.clientWidth;
-    var height  = element.clientHeight;
-
-    element._originalLeft   = left - parseFloat(element.style.left  || 0);
-    element._originalTop    = top  - parseFloat(element.style.top || 0);
-    element._originalWidth  = element.style.width;
-    element._originalHeight = element.style.height;
-
-    element.style.position = 'absolute';
-    element.style.top    = top + 'px';;
-    element.style.left   = left + 'px';;
-    element.style.width  = width + 'px';;
-    element.style.height = height + 'px';;
-  },
-
-  relativize: function(element) {
-    element = $(element);
-    if (element.style.position == 'relative') return;
-    Position.prepare();
-
-    element.style.position = 'relative';
-    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
-    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
-
-    element.style.top    = top + 'px';
-    element.style.left   = left + 'px';
-    element.style.height = element._originalHeight;
-    element.style.width  = element._originalWidth;
-  }
-}
-
-// Safari returns margins on body which is incorrect if the child is absolutely
-// positioned.  For performance reasons, redefine Position.cumulativeOffset for
-// KHTML/WebKit only.
-if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
-  Position.cumulativeOffset = function(element) {
-    var valueT = 0, valueL = 0;
-    do {
-      valueT += element.offsetTop  || 0;
-      valueL += element.offsetLeft || 0;
-      if (element.offsetParent == document.body)
-        if (Element.getStyle(element, 'position') == 'absolute') break;
-
-      element = element.offsetParent;
-    } while (element);
-
-    return [valueL, valueT];
-  }
-}
\ No newline at end of file
diff --git a/easy-asterisk-gui/restart.sh b/easy-asterisk-gui/restart.sh
deleted file mode 100644 (file)
index 027dcf2..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-# restart.sh
-# David Rowe 15 Jan 2010
-# Restart script for Easy Asterisk GUI
-
-cat <<EOF    
-<html>
-<title>Easy Asterisk - Restart</title>
-<meta http-equiv="REFRESH" content="2;url=http:login.sh"
-<h2>Restarting...come back in 1 minute</h2>
-</html>
-EOF
-reboot
-
diff --git a/easy-asterisk-gui/set_network.sh b/easy-asterisk-gui/set_network.sh
deleted file mode 100755 (executable)
index 23c69e7..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/bin/sh
-# set_network.sh
-#
-# CGI to set network parameters of an IP0X.
-
-cat <<EOF
-<html>
-<head>
-<title>set_network.sh</title>
-<meta http-equiv="REFRESH" content="0;url=http:network.sh">
-<body>
-Please wait a few seconds.....
-</body>
-</head>
-</html>
-EOF
-
-dhcp=`echo "$QUERY_STRING" | grep -oe "dhcp=[^&?]*" | sed -n "s/dhcp=//p"`
-ipaddress=`echo "$QUERY_STRING" | grep -oe "ipaddress=[^&?]*" | sed -n "s/ipaddress=//p"`
-netmask=`echo "$QUERY_STRING" | grep -oe "netmask=[^&?]*" | sed -n "s/netmask=//p"`
-gateway=`echo "$QUERY_STRING" | grep -oe "gateway=[^&?]*" | sed -n "s/gateway=//p"`
-dns=`echo "$QUERY_STRING" | grep -oe "dns=[^&?]*" | sed -n "s/dns=//p"`
-backdoor=`echo "$QUERY_STRING" | grep -oe "backdoor=[^&?]*" | sed -n "s/backdoor=//p"`
-
-if [ $dhcp == "yes" ]; then
-
-  # DHCP
-
-  if [ -f /etc/rc.d/S10network-static ]; then
-    /etc/init.d/network-static disable
-    /etc/init.d/network-static stop
-    /etc/init.d/network enable
-    /etc/init.d/network start
-  else
-    # if already running restart service
-    /etc/init.d/network stop
-    /etc/init.d/network start
-  fi
-fi
-
-if [ $dhcp == "no" ]; then
-  
-  # Static IP
-
-  if [ -f /etc/rc.d/S10network ]; then
-    /etc/init.d/network stop
-    /etc/init.d/network disable
-    /etc/init.d/network-static enable
-  fi
-  
-  sed -i "s/DHCPD=.*/DHCPD=no/g" /etc/init.d/network-static
-  sed -i "s/IPADDRESS=.*/IPADDRESS=\"$ipaddress\"/g" /etc/init.d/network-static
-  sed -i "s/NETMASK=.*/NETMASK=\"$netmask\"/g" /etc/init.d/network-static
-  sed -i "s/GATEWAY=.*/GATEWAY=\"$gateway\"/g" /etc/init.d/network-static
-  sed -i "s/DNS=.*/DNS=\"$dns\"/g" /etc/init.d/network-static
-  /etc/init.d/network-static stop
-  /etc/init.d/network-static start
-fi
-
-if [ -f /etc/rc.d/S05network-backdoor ]; then
-  sed -i "s/IPADDRESS=.*/IPADDRESS=\"$backdoor\"/g" /etc/init.d/network-backdoor
-  /etc/init.d/network-backdoor stop
-  /etc/init.d/network-backdoor start
-fi
diff --git a/easy-asterisk-gui/set_ring.sh b/easy-asterisk-gui/set_ring.sh
deleted file mode 100644 (file)
index c7b559c..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/sh -x
-# set_ring.sh
-# David Rowe 4 Jan 2010
-# CGI to set which extensions ring on uncoming calls
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
-    echo "<html>"
-    echo "<head>"
-    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
-    echo "</head>"
-    echo "</html>"
-    exit
-fi
-
-# extract extensions to ring and reload extensions.conf
-
-a=`echo "$QUERY_STRING" | sed -n "s/=on*//pg" | sed -n 's,_,/,pg'`
-
-# escape & if present
-echo "$a" | grep "&" >> /dev/null
-if [ $? -eq 0 ]; then
-  a=`echo $a | sed -n "s/&/\\\\&/pg"`
-fi
-
-sed -i "s_s,1,Dial(.*) ;; easy-asterisk_s,1,Dial($a) ;; easy-asterisk_" /etc/asterisk/extensions.conf
-asterisk -rx "dialplan reload" 2>/dev/null 1 > /dev/null
-
-# bounce us back to Phones screen
-
-cat <<EOF
-<html>
-<head>
-<title>Easy Asterisk - Set Ring</title>
-<meta http-equiv="REFRESH" content="0;url=http:phones.sh">
-<body>
-Please wait a few seconds.....
-EOF
-#echo $QUERY_STRING "<br>"
-#echo "$QUERY_STRING" | sed -n "s/=on*//pg" | sed -n 's,_,/,pg'
-#echo "<br>"
-#echo $a
-
-cat <<EOF
-</body>
-</head>
-</html>
-EOF
-
diff --git a/easy-asterisk-gui/set_voiplines.sh b/easy-asterisk-gui/set_voiplines.sh
deleted file mode 100644 (file)
index 696d4f4..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/sh
-# set_voipline.sh
-# # David Rowe 12 Jan 2010
-#
-# CGI to set voip line parameters in sip.conf.
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
-    echo "<html>"
-    echo "<head>"
-    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
-    echo "</head>"
-    echo "</html>"
-    exit
-fi
-
-user=`echo "$QUERY_STRING" | grep -oe "user=[^&?]*" | sed -n "s/user=//p"`
-pass=`echo "$QUERY_STRING" | grep -oe "pass=[^&?]*" | sed -n "s/pass=//p"`
-host=`echo "$QUERY_STRING" | grep -oe "host=[^&?]*" | sed -n "s/host=//p"`
-stanza=`echo "$QUERY_STRING" | grep -oe "stanza=[^&?]*" | sed -n "s/stanza=//p"`
-
-# create new sip.conf with selected provider uncommented
-
-echo "set_voiplines.sh" $user $pass $host $stanza >> /tmp/log.txt
-./set_voiplines.pl $user $pass $host $stanza > /etc/asterisk/sip.conf.new
-mv /etc/asterisk/sip.conf /etc/asterisk/sip.conf.bak
-mv /etc/asterisk/sip.conf.new /etc/asterisk/sip.conf
-
-# get asterisk to load changes
-
-asterisk -rx "sip reload" 2>/dev/null 1 > /dev/null
-
-cat <<EOF
-<html>
-<head>
-<title>set_voiplines.sh</title>
-<meta http-equiv="REFRESH" content="0;url=http:voiplines.sh">
-<body>
-Please wait a few seconds.....
-</body>
-</head>
-</html>
-EOF
-
diff --git a/easy-asterisk-gui/sip.conf b/easy-asterisk-gui/sip.conf
deleted file mode 100644 (file)
index 9ee3f20..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-;
-; SIP Configuration example for Asterisk
-;
-; Syntax for specifying a SIP device in extensions.conf is
-; SIP/devicename where devicename is defined in a section below.
-;
-; You may also use 
-; SIP/username@domain to call any SIP user on the Internet
-; (Don't forget to enable DNS SRV records if you want to use this)
-; 
-; If you define a SIP proxy as a peer below, you may call
-; SIP/proxyhostname/user or SIP/user@proxyhostname 
-; where the proxyhostname is defined in a section below 
-; 
-; Useful CLI commands to check peers/users:
-;   sip show peers             Show all SIP peers (including friends)
-;   sip show users             Show all SIP users (including friends)
-;   sip show registry          Show status of hosts we register with
-;
-;   sip debug                  Show all SIP messages
-;
-;   reload chan_sip.so         Reload configuration file
-;                              Active SIP peers will not be reconfigured
-;
-
-[general]
-context=default                        ; Default context for incoming calls
-;allowguest=no                 ; Allow or reject guest calls (default is yes, this can also be set to 'osp'
-                               ; if asterisk was compiled with OSP support.
-;realm=mydomain.tld            ; Realm for digest authentication
-                               ; defaults to "asterisk"
-                               ; Realms MUST be globally unique according to RFC 3261
-                               ; Set this to your host name or domain name
-bindport=5060                  ; UDP Port to bind to (SIP standard port is 5060)
-bindaddr=0.0.0.0               ; IP address to bind to (0.0.0.0 binds to all)
-srvlookup=yes                  ; Enable DNS SRV lookups on outbound calls
-                               ; Note: Asterisk only uses the first host 
-                               ; in SRV records
-                               ; Disabling DNS SRV lookups disables the 
-                               ; ability to place SIP calls based on domain 
-                               ; names to some other SIP users on the Internet
-                               
-;domain=mydomain.tld           ; Set default domain for this host
-                               ; If configured, Asterisk will only allow
-                               ; INVITE and REFER to non-local domains
-                               ; Use "sip show domains" to list local domains
-;domain=mydomain.tld,mydomain-incoming
-                               ; Add domain and configure incoming context
-                               ; for external calls to this domain
-;domain=1.2.3.4                        ; Add IP address as local domain
-                               ; You can have several "domain" settings
-;allowexternalinvites=no       ; Disable INVITE and REFER to non-local domains
-                               ; Default is yes
-;autodomain=yes                        ; Turn this on to have Asterisk add local host
-                               ; name and local IP to domain list.
-;pedantic=yes                  ; Enable slow, pedantic checking for Pingtel
-                               ; and multiline formatted headers for strict
-                               ; SIP compatibility (defaults to "no")
-;tos=184                       ; Set IP QoS to either a keyword or numeric val
-;tos=lowdelay                  ; lowdelay,throughput,reliability,mincost,none
-;maxexpiry=3600                        ; Max length of incoming registration we allow
-;defaultexpiry=120             ; Default length of incoming/outoing registration
-;notifymimetype=text/plain     ; Allow overriding of mime type in MWI NOTIFY
-;checkmwi=10                   ; Default time between mailbox checks for peers
-;vmexten=voicemail      ; dialplan extension to reach mailbox sets the 
-                                               ; Message-Account in the MWI notify message 
-                                               ; defaults to "asterisk"
-;videosupport=yes              ; Turn on support for SIP video
-;recordhistory=yes             ; Record SIP history by default 
-                               ; (see sip history / sip no history)
-
-;disallow=all                  ; First disallow all codecs
-;allow=ulaw                    ; Allow codecs in order of preference
-;allow=ilbc                    ; 
-;musicclass=default            ; Sets the default music on hold class for all SIP calls
-                               ; This may also be set for individual users/peers
-;language=en                   ; Default language setting for all users/peers
-                               ; This may also be set for individual users/peers
-;relaxdtmf=yes                 ; Relax dtmf handling
-;rtptimeout=60                 ; Terminate call if 60 seconds of no RTP activity
-                               ; when we're not on hold
-;rtpholdtimeout=300            ; Terminate call if 300 seconds of no RTP activity
-                               ; when we're on hold (must be > rtptimeout)
-;trustrpid = no                        ; If Remote-Party-ID should be trusted
-;sendrpid = yes                        ; If Remote-Party-ID should be sent
-;progressinband=never          ; If we should generate in-band ringing always
-                               ; use 'never' to never use in-band signalling, even in cases
-                               ; where some buggy devices might not render it
-;useragent=Asterisk PBX                ; Allows you to change the user agent string
-;promiscredir = no             ; If yes, allows 302 or REDIR to non-local SIP address
-                               ; Note that promiscredir when redirects are made to the
-                                       ; local system will cause loops since SIP is incapable
-                                       ; of performing a "hairpin" call.
-;usereqphone = no              ; If yes, ";user=phone" is added to uri that contains
-                               ; a valid phone number
-;dtmfmode = rfc2833            ; Set default dtmfmode for sending DTMF. Default: rfc2833
-                               ; Other options: 
-                               ; info : SIP INFO messages
-                               ; inband : Inband audio (requires 64 kbit codec -alaw, ulaw)
-                               ; auto : Use rfc2833 if offered, inband otherwise
-
-;compactheaders = yes          ; send compact sip headers.
-;sipdebug = yes                        ; Turn on SIP debugging by default, from
-                               ; the moment the channel loads this configuration
-;subscribecontext = default    ; Set a specific context for SUBSCRIBE requests
-                               ; Useful to limit subscriptions to local extensions
-                               ; Settable per peer/user also
-;notifyringing = yes           ; Notify subscriptions on RINGING state
-
-;
-; If regcontext is specified, Asterisk will dynamically create and destroy a
-; NoOp priority 1 extension for a given peer who registers or unregisters with
-; us.  The actual extension is the 'regexten' parameter of the registering
-; peer or its name if 'regexten' is not provided.  More than one regexten may
-; be supplied if they are separated by '&'.  Patterns may be used in regexten.
-;
-;regcontext=sipregistrations
-;
-; Asterisk can register as a SIP user agent to a SIP proxy (provider)
-; Format for the register statement is:
-;       register => user[:secret[:authuser]]@host[:port][/extension]
-;
-; If no extension is given, the 's' extension is used. The extension needs to
-; be defined in extensions.conf to be able to accept calls from this SIP proxy
-; (provider).
-;
-; host is either a host name defined in DNS or the name of a section defined
-; below.
-;
-; Examples:
-;
-;register => 1234:password@mysipprovider.com   
-;
-;     This will pass incoming calls to the 's' extension
-;
-;
-;register => 2345:password@sip_proxy/1234
-;
-;    Register 2345 at sip provider 'sip_proxy'.  Calls from this provider
-;    connect to local extension 1234 in extensions.conf, default context,
-;    unless you configure a [sip_proxy] section below, and configure a
-;    context.
-;    Tip 1: Avoid assigning hostname to a sip.conf section like [provider.com]
-;    Tip 2: Use separate type=peer and type=user sections for SIP providers
-;           (instead of type=friend) if you have calls in both directions
-  
-;registertimeout=20            ; retry registration calls every 20 seconds (default)
-;registerattempts=10           ; Number of registration attempts before we give up
-                               ; 0 = continue forever, hammering the other server until it 
-                               ; accepts the registration
-                               ; Default is 0 tries, continue forever
-;callevents=no                 ; generate manager events when sip ua performs events (e.g. hold)
-
-; register easy-asterisk voip line providers here
-
-register => user@generic ; easy-asterisk - do not change this comment
-;register => user@oeg ; easy-asterisk - do not change this comment
-
-;----------------------------------------- NAT SUPPORT ------------------------
-; The externip, externhost and localnet settings are used if you use Asterisk
-; behind a NAT device to communicate with services on the outside.
-
-;externip = 200.201.202.203    ; Address that we're going to put in outbound SIP messages
-                               ; if we're behind a NAT
-
-                               ; The externip and localnet is used
-                               ; when registering and communicating with other proxies
-                               ; that we're registered with
-;externhost=foo.dyndns.net     ; Alternatively you can specify an 
-                               ; external host, and Asterisk will 
-                               ; perform DNS queries periodically.  Not
-                               ; recommended for production 
-                               ; environments!  Use externip instead
-;externrefresh=10              ; How often to refresh externhost if 
-                               ; used
-                               ; You may add multiple local networks.  A reasonable set of defaults
-                               ; are:
-;localnet=192.168.0.0/255.255.0.0; All RFC 1918 addresses are local networks
-;localnet=10.0.0.0/255.0.0.0   ; Also RFC1918
-;localnet=172.16.0.0/12                ; Another RFC1918 with CIDR notation
-;localnet=169.254.0.0/255.255.0.0 ;Zero conf local network
-
-; The nat= setting is used when Asterisk is on a public IP, communicating with
-; devices hidden behind a NAT device (broadband router).  If you have one-way
-; audio problems, you usually have problems with your NAT configuration or your
-; firewall's support of SIP+RTP ports.  You configure Asterisk choice of RTP
-; ports for incoming audio in rtp.conf
-;
-;nat=no                                ; Global NAT settings  (Affects all peers and users)
-                                ; yes = Always ignore info and assume NAT
-                                ; no = Use NAT mode only according to RFC3581 
-                                ; never = Never attempt NAT mode or RFC3581 support
-                               ; route = Assume NAT, don't send rport 
-                               ; (work around more UNIDEN bugs)
-
-;rtcachefriends=yes            ; Cache realtime friends by adding them to the internal list
-                               ; just like friends added from the config file only on a
-                               ; as-needed basis? (yes|no)
-
-;rtupdate=yes                  ; Send registry updates to database using realtime? (yes|no)
-                               ; If set to yes, when a SIP UA registers successfully, the ip address,
-                               ; the origination port, the registration period, and the username of
-                               ; the UA will be set to database via realtime. If not present, defaults to 'yes'.
-
-;rtautoclear=yes               ; Auto-Expire friends created on the fly on the same schedule
-                               ; as if it had just registered? (yes|no|<seconds>)
-                               ; If set to yes, when the registration expires, the friend will vanish from
-                               ; the configuration until requested again. If set to an integer,
-                               ; friends expire within this number of seconds instead of the
-                               ; registration interval.
-
-;ignoreregexpire=yes           ; Enabling this setting has two functions:
-                               ;
-                               ; For non-realtime peers, when their registration expires, the information
-                               ; will _not_ be removed from memory or the Asterisk database; if you attempt
-                               ; to place a call to the peer, the existing information will be used in spite
-                               ; of it having expired
-                               ;
-                               ; For realtime peers, when the peer is retrieved from realtime storage,
-                               ; the registration information will be used regardless of whether
-                               ; it has expired or not; if it expires while the realtime peer is still in
-                               ; memory (due to caching or other reasons), the information will not be
-                               ; removed from realtime storage
-
-; Incoming INVITE and REFER messages can be matched against a list of 'allowed'
-; domains, each of which can direct the call to a specific context if desired.
-; By default, all domains are accepted and sent to the default context or the
-; context associated with the user/peer placing the call.
-; Domains can be specified using:
-; domain=<domain>[,<context>]
-; Examples:
-; domain=myasterisk.dom
-; domain=customer.com,customer-context
-;
-; In addition, all the 'default' domains associated with a server should be
-; added if incoming request filtering is desired.
-; autodomain=yes
-;
-; To disallow requests for domains not serviced by this server:
-; allowexternaldomains=no
-
-; fromdomain=mydomain.tld ; When making outbound SIP INVITEs to
-                          ; non-peers, use your primary domain "identity"
-                          ; for From: headers instead of just your IP
-                          ; address. This is to be polite and
-                          ; it may be a mandatory requirement for some
-                          ; destinations which do not have a prior
-                          ; account relationship with your server. 
-
-[authentication]
-; Global credentials for outbound calls, i.e. when a proxy challenges your
-; Asterisk server for authentication. These credentials override
-; any credentials in peer/register definition if realm is matched.
-;
-; This way, Asterisk can authenticate for outbound calls to other
-; realms. We match realm on the proxy challenge and pick an set of 
-; credentials from this list
-; Syntax:
-;      auth = <user>:<secret>@<realm>
-;      auth = <user>#<md5secret>@<realm>
-; Example:
-;auth=mark:topsecret@digium.com
-; 
-; You may also add auth= statements to [peer] definitions 
-; Peer auth= override all other authentication settings if we match on realm
-
-;------------------------------------------------------------------------------
-; Users and peers have different settings available. Friends have all settings,
-; since a friend is both a peer and a user
-;
-; User config options:        Peer configuration:
-; --------------------        -------------------
-; context                     context
-; permit                      permit
-; deny                        deny
-; secret                      secret
-; md5secret                   md5secret
-; dtmfmode                    dtmfmode
-; canreinvite                 canreinvite
-; nat                         nat
-; callgroup                   callgroup
-; pickupgroup                 pickupgroup
-; language                    language
-; allow                       allow
-; disallow                    disallow
-; insecure                    insecure
-; trustrpid                   trustrpid
-; progressinband              progressinband
-; promiscredir                promiscredir
-; useclientcode               useclientcode
-; accountcode                 accountcode
-; setvar                      setvar
-; callerid                   callerid
-; amaflags                   amaflags
-; call-limit                 call-limit
-; restrictcid                restrictcid
-; subscribecontext           subscribecontext
-; videosupport               videosupport
-;                             mailbox
-;                             username
-;                             template
-;                             fromdomain
-;                             regexten
-;                             fromuser
-;                             host
-;                             port
-;                             qualify
-;                             defaultip
-;                             rtptimeout
-;                             rtpholdtimeout
-;                             sendrpid
-
-;[sip_proxy]
-; For incoming calls only. Example: FWD (Free World Dialup)
-; We match on IP address of the proxy for incoming calls 
-; since we can not match on username (caller id)
-;type=peer
-;context=from-fwd
-;host=fwd.pulver.com
-
-;[sip_proxy-out]
-;type=peer                     ; we only want to call out, not be called
-;secret=guessit
-;username=yourusername         ; Authentication user for outbound proxies
-;fromuser=yourusername         ; Many SIP providers require this!
-;fromdomain=provider.sip.domain        
-;host=box.provider.com
-;usereqphone=yes               ; This provider requires ";user=phone" on URI
-;call-limit=5                  ; permit only 5 simultaneous outgoing calls to this peer
-
-;------------------------------------------------------------------------------
-; Definitions of locally connected SIP phones
-;
-; type = user  a device that authenticates to us by "from" field to place calls
-; type = peer  a device we place calls to or that calls us and we match by host
-; type = friend two configurations (peer+user) in one
-;
-; For local phones, type=friend works most of the time
-;
-; If you have one-way audio, you propably have NAT problems. 
-; If Asterisk is on a public IP, and the phone is inside of a NAT device
-; you will need to configure nat option for those phones.
-; Also, turn on qualify=yes to keep the nat session open
-
-;[grandstream1]
-;type=friend                   
-;context=from-sip              ; Where to start in the dialplan when this phone calls
-;callerid=John Doe <1234>      ; Full caller ID, to override the phones config
-;host=192.168.0.23             ; we have a static but private IP address
-                               ; No registration allowed
-;nat=no                                ; there is not NAT between phone and Asterisk
-;canreinvite=yes               ; allow RTP voice traffic to bypass Asterisk
-;dtmfmode=info                 ; either RFC2833 or INFO for the BudgeTone
-;call-limit=1                  ; permit only 1 outgoing call and 1 incoming call at a time
-                               ; from the phone to asterisk
-                               ; (1 for the explicit peer, 1 for the explicit user,
-                               ; remember that a friend equals 1 peer and 1 user in
-                               ; memory)
-;mailbox=1234@default          ; mailbox 1234 in voicemail context "default"
-;disallow=all                  ; need to disallow=all before we can use allow=
-;allow=ulaw                    ; Note: In user sections the order of codecs
-                               ; listed with allow= does NOT matter!
-;allow=alaw
-;allow=g723.1                  ; Asterisk only supports g723.1 pass-thru!
-;allow=g729                    ; Pass-thru only unless g729 license obtained
-;astdb=chan2ext/SIP/grandstream1=1234  ; ensures an astDB entry exists
-
-
-;[xlite1]
-; Turn off silence suppression in X-Lite ("Transmit Silence"=YES)!
-; Note that Xlite sends NAT keep-alive packets, so qualify=yes is not needed
-;type=friend
-;regexten=1234                 ; When they register, create extension 1234
-;callerid="Jane Smith" <5678>
-;host=dynamic                  ; This device needs to register
-;nat=yes                       ; X-Lite is behind a NAT router
-;canreinvite=no                        ; Typically set to NO if behind NAT
-;disallow=all
-;allow=gsm                     ; GSM consumes far less bandwidth than ulaw
-;allow=ulaw
-;allow=alaw
-;mailbox=1234@default,1233@default     ; Subscribe to status of multiple mailboxes
-
-
-;[snom]
-;type=friend                   ; Friends place calls and receive calls
-;context=from-sip              ; Context for incoming calls from this user
-;secret=blah
-;subscribecontext=localextensions      ; Only allow SUBSCRIBE for local extensions
-;language=de                   ; Use German prompts for this user 
-;host=dynamic                  ; This peer register with us
-;dtmfmode=inband               ; Choices are inband, rfc2833, or info
-;defaultip=192.168.0.59                ; IP used until peer registers
-;mailbox=1234@context,2345      ; Mailbox(-es) for message waiting indicator
-;vmexten=voicemail      ; dialplan extension to reach mailbox 
-                        ; sets the Message-Account in the MWI notify message
-                        ; defaults to global vmexten which defaults to "asterisk"
-;restrictcid=yes               ; To have the callerid restriced -> sent as ANI
-;disallow=all
-;allow=ulaw                    ; dtmfmode=inband only works with ulaw or alaw!
-
-
-;[polycom]
-;type=friend                   ; Friends place calls and receive calls
-;context=from-sip              ; Context for incoming calls from this user
-;secret=blahpoly
-;host=dynamic                  ; This peer register with us
-;dtmfmode=rfc2833              ; Choices are inband, rfc2833, or info
-;username=polly                        ; Username to use in INVITE until peer registers
-                               ; Normally you do NOT need to set this parameter
-;disallow=all
-;allow=ulaw                     ; dtmfmode=inband only works with ulaw or alaw!
-;progressinband=no             ; Polycom phones don't work properly with "never"
-
-
-;[pingtel]
-;type=friend
-;secret=blah
-;host=dynamic
-;insecure=port                 ; Allow matching of peer by IP address without matching port number
-;insecure=invite               ; Do not require authentication of incoming INVITEs
-;insecure=port,invite          ; (both)
-;qualify=1000                  ; Consider it down if it's 1 second to reply
-                               ; Helps with NAT session
-                               ; qualify=yes uses default value
-;callgroup=1,3-4               ; We are in caller groups 1,3,4
-;pickupgroup=1,3-5             ; We can do call pick-p for call group 1,3,4,5
-;defaultip=192.168.0.60                ; IP address to use if peer has not registred
-
-;[cisco1]
-;type=friend
-;secret=blah
-;qualify=200                   ; Qualify peer is no more than 200ms away
-;nat=yes                       ; This phone may be natted
-                               ; Send SIP and RTP to the IP address that packet is 
-                               ; received from instead of trusting SIP headers 
-;host=dynamic                  ; This device registers with us
-;canreinvite=no                        ; Asterisk by default tries to redirect the
-                               ; RTP media stream (audio) to go directly from
-                               ; the caller to the callee.  Some devices do not
-                               ; support this (especially if one of them is 
-                               ; behind a NAT).
-;defaultip=192.168.0.4         ; IP address to use until registration
-;username=goran                        ; Username to use when calling this device before registration
-                               ; Normally you do NOT need to set this parameter
-;setvar=CUSTID=5678            ; Channel variable to be set for all calls from this device
-
-; Pre-configured SIP extensions
-
-[6011]
-type=friend
-context=default
-host=dynamic
-secret=6011
-canreinvite=no
-callerid=6011
-disallow=all
-allow=ulaw,g729
-qualify=yes
-
-[6012]
-type=friend
-context=default
-host=dynamic
-secret=6012
-canreinvite=no
-callerid=6012
-disallow=all
-allow=ulaw,g729
-
-[6013]
-type=friend
-context=default
-host=dynamic
-secret=6013
-canreinvite=no
-callerid=6013
-disallow=all
-allow=ulaw,g729
-
-[6014]
-type=friend
-context=default
-host=dynamic
-secret=6014
-canreinvite=no
-callerid=6014
-disallow=all
-allow=ulaw,g729
-
-[6015]
-type=friend
-context=default
-host=dynamic
-secret=6015
-canreinvite=no
-callerid=6015
-disallow=all
-allow=ulaw,g729
-
-[6016]
-type=friend
-context=default
-host=dynamic
-secret=6016
-canreinvite=no
-callerid=6016
-disallow=all
-allow=ulaw,g729
-
-[6017]
-type=friend
-context=default
-host=dynamic
-secret=6017
-canreinvite=no
-callerid=6017
-disallow=all
-allow=ulaw,g729
-
-[6018]
-type=friend
-context=default
-host=dynamic
-secret=6018
-canreinvite=no
-callerid=6018
-disallow=all
-allow=ulaw,g729
-
-; Pre-configured easy-asterisk SIP trunks
-
-[generic] ; "Generic" easy-asterisk do not remove this comment
-type=friend
-context=default
-username=user
-secret=password
-host=192.168.1.28
-canreinvite=no
-disallow=all
-allow=ulaw,g729
-qualify=yes
-
-;[oeg] ; "OEG" easy-asterisk do not remove this comment
-;host=voip.oeg.com.au
-;secret=pass
-;username=your user number
-;fromdomain=voip.oeg.com.au
-;fromuser=your user number
-;insecure=port,invite
-;type=friend
-;disallow=all
-;allow=g729,ulaw
-;dtmfmod=rfc2833
-;qualify=yes
-;canreinvite=no
-;nat=yes
-;context=default
-
diff --git a/easy-asterisk-gui/tick.png b/easy-asterisk-gui/tick.png
deleted file mode 100644 (file)
index c155dff..0000000
Binary files a/easy-asterisk-gui/tick.png and /dev/null differ
diff --git a/easy-asterisk-gui/tooltip.css b/easy-asterisk-gui/tooltip.css
deleted file mode 100644 (file)
index f426356..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-.tip {font:12px/14px
-Arial,Helvetica,sans-serif; border:solid 1px
-#666666; width:270px; padding:1px;
-position:absolute; z-index:100;
-visibility:hidden; color:#333333; top:20px;
-left:90px; background-color:#ffffcc;
-layer-background-color:#ffffcc;}
diff --git a/easy-asterisk-gui/tooltip.js b/easy-asterisk-gui/tooltip.js
deleted file mode 100644 (file)
index 26142e8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Extended Tooltip Javascript
-// copyright 9th August 2002, 3rd July 2005, 24th August 2008
-// by Stephen Chapman, Felgall Pty Ltd
-
-// permission is granted to use this javascript provided that the below code is not altered
-function pw() {return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth}; function mouseX(evt) {return evt.clientX ? evt.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) : evt.pageX;} function mouseY(evt) {return evt.clientY ? evt.clientY + (document.documentElement.scrollTop || document.body.scrollTop) : evt.pageY} function popUp(evt,oi) {if (document.getElementById) {var wp = pw(); dm = document.getElementById(oi); ds = dm.style; st = ds.visibility; if (dm.offsetWidth) ew = dm.offsetWidth; else if (dm.clip.width) ew = dm.clip.width; if (st == "visible" || st == "show") { ds.visibility = "hidden"; } else {tv = mouseY(evt) + 20; lv = mouseX(evt) - (ew/4); if (lv < 2) lv = 2; else if (lv + ew > wp) lv -= ew/2; lv += 'px';tv += 'px';  ds.left = lv; ds.top = tv; ds.visibility = "visible";}}}
-                  
diff --git a/easy-asterisk-gui/tooltips.html b/easy-asterisk-gui/tooltips.html
deleted file mode 100644 (file)
index dab4bff..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-<div id="network_internet" class="tip">
-                         A tick means your phone system can reach the Internet.  You need the Internet for VOIP calls
-                         and software upgrades.  
-                         If you have a problem reaching the Internet check your Network settings, in 
-                         particular Gateway and DNS.</div>
-
-<div id="network_backdoor" class="tip">
-                         Emergency backdoor IP. Useful if you get locked out of the main network connection, for 
-                         example due to DHCP problems on your network or a configuration mistake.  
-                         Write this number down somewhere!</div>
-
-<div id="phone_reception" class="tip">
-                         If ticked this phone will ring when some one
-                         calls the phone system from an outside Analog
-                         or VOIP Line.  More than one phone can be
-                         ticked.  You can answer a call on another
-                         ringing phone by dialling *8 on your phone -
-                         see FAQ for details.</div>
-
-<div id="phone_anphone" class="tip">
-                         Analog Phone: Normal telephone plugged into a port on your phone system.
-                         </div>
-<div id="phone_ipphone" class="tip">
-                         IP Phone plugged into your network.
-                         </div>
-<div id="phone_line" class="tip">
-                         Analog Phone Line: Analog telephone line plugged into a port on your phone system.
-                         </div>
-<div id="phone_voipline" class="tip">
-                         VOIP  Phone Line: Make and receive phone calls over the Internet.
-                         </div>
-
-<div id="phone_system" class="tip">
-                         Important information about your Phone System.</div>
-
-<div id="phone_ipaddress" class="tip">
-                         The address of your Phone System
-                         on your network.  Use this address to connect
-                         IP Phones to your Phone System.  </div>
-
-<div id="phone_phones" class="tip">
-                         List of phones connected to your Phone
-                         System.  You can connect Analog or IP Phones
-                         to your system.  When IP Phones are
-                         configured correctly, they appear on this
-                         list.  If an IP phone is not configured
-                         correctly, it will not appear on this list.
-                         Analog phones require hardware to be
-                         installed in your Phone system.</div>
-
-<div id="phone_lines" class="tip">
-                         List of phone lines available.  Phone lines
-                         are used to make and receive outside calls.
-                         You can use regular Analog phone lines or
-                         VOIP.  VOIP phone lines require an account
-                         with an Internet Telephone Service Provider.
-                         Analog phone lines require hardware to be
-                         installed in your Phone System.</div>
-
-<div id="phone_ext" class="tip">
-                        Dial this number to call this phone</div>
-
-<div id="phone_port_phone" class="tip">
-                        Port (socket) on the rear of your Phone System.  Plug the phone into this Port.</div>
-
-<div id="phone_port_line" class="tip">
-                        Port (socket) on the rear of your Phone
-                        System.  Plug the phone line into this
-                        Port.</div>
-
-<div id="phone_line_prefix" class="tip">
-                        Dial 0 for an Analog outside line.  For example to call 5551234 dial 05551234</div>
-
-<div id="phone_ipphone_ip" class="tip">
-                        IP Address of this phone on your network</div>
-
-<div id="phone_voipline_ip" class="tip">
-                        IP Address of the VOIP Internet Telephone Service Provider</div>
-
-<div id="phone_voipline_prefix" class="tip">
-                        Dial 1 for a VOIP outside line.  For example to call 5551234 dial 15551234</div>
-
-<div id="phone_addipphone" class="tip">
-                        Instructions and help on adding a new IP phone</div>
-
-<div id="phone_addvoipline" class="tip">
-                        Instructions and help on VOIP Line set up</div>
-
-<div id="ipphones_ipphones" class="tip">
-                        List of possible IP phones.  For a new phone
-                        choose any Available number.  Refresh this
-                        page to update</div>
-
-<div id="ipphones_connected" class="tip">
-                        The IP phone is connected to your phone system and ready to use</div>
-
-<div id="ipphones_notconnected" class="tip">
-                        No IP phone is connected.  Either no IP phone
-                        is present, or the IP phone has not been set
-                        up.</div>
-
-<div id="voiplines_voiplines" class="tip">
-                        A VOIP line allows you to make and receive
-                       phones calls over the Internet.  Normally a
-                       VOIP line is provided by an Internet Telephony
-                       Service Provider (ITSP).  They will give you
-                       an account, which includes the user and
-                       password details that you can fill in below.
-                       Refresh this page on your browser to see if
-                       your VOIP line is working.  </div>
-
-<div id="voiplines_provider" class="tip">
-                        Your Internet Telephony Service Provider.
-                        They will give you an account with a user name
-                        and password.</div>
-
-<div id="voiplines_user" class="tip">
-                        Your account name with your Internet Telephony Service Provider</div>
-
-<div id="voiplines_pass" class="tip">
-                        The password for your Internet Telephony Service Provider account</div>
-
-<div id="voiplines_host" class="tip">
-                        The Internet address of your Internet
-                        Telephony Service Provider.  This will usually
-                        be filled in automatically.</div>
-
-<div id="voiplines_status" class="tip">
-                        A tick means you are connected to your
-                        Internet Telephony Service Provider.  Refresh
-                        your browser to update.</div>
-
-<div id="admin_restart" class="tip">
-                        Press this button to restart your phone
-                        system.  This is the same as turning the power
-                        off and back on. </div>
-
diff --git a/easy-asterisk-gui/voipline.jpg b/easy-asterisk-gui/voipline.jpg
deleted file mode 100644 (file)
index d84b105..0000000
Binary files a/easy-asterisk-gui/voipline.jpg and /dev/null differ
diff --git a/easy-asterisk-gui/voiplines.js b/easy-asterisk-gui/voiplines.js
deleted file mode 100644 (file)
index 083838a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-function changeProvider() {
-       provider = $('provider').value;
-       $('user').value = users[provider];
-       $('pass').value = passwords[provider];
-       $('host').value = hosts[provider];
-       $('stanza').value = stanzas[provider];
-}
diff --git a/easy-asterisk-gui/voiplines.pl b/easy-asterisk-gui/voiplines.pl
deleted file mode 100755 (executable)
index 64b5a2c..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/sbin/microperl
-# voiplines.pl
-# David Rowe 12 Jan 2010
-#
-# Text processing for the voiplines screen
-
-# slurp up list of possible voip line providers --------------------------------
-# one of these will be currently selected
-
-open SIP, "/etc/asterisk/sip.conf";
-my $provider = ""; # current provider bring parsed in sip.conf
-my @providers=();  # list of all providers
-my %stanza = ();   # stanza name keyed on provider
-my %user = ();     # user keyed on provider
-my %pass = ();     # password keyed on provider
-my %host = ();     # host name keyed on provider
-
-while (<SIP>) { 
-
-    # start of any stanza switches off parsing.  It may get switched
-    # back on below if it contains easy-asterisk keyword. This allows
-    # non-easy asterisk SIP devices to be included in sip.conf
-
-    if (/\[/) {
-       $provider = ""; 
-    }
-
-    # currently disabled easy-asterisk provider
-
-    if (/^;\[(.*)\].* \"(.*)\" easy-asterisk/) {
-       push (@providers, $2);
-       $provider = $2;
-       $stanza{$2} = $1;
-       #print "'$1' '$2'\n";   
-    }
-
-    # current easy-asterisk provider
-
-    if (/^\[(.*)\].* \"(.*)\" easy-asterisk/) {
-       push (@providers, $2);
-       $provider = $2;
-       $provider_current = $2;
-       $stanza{$2} = $1;
-       #print "'$1' '$2'\n";
-    }
-
-    if ($provider ne "") {
-       #print $_;
-
-       if (/^;*user=(.*)/) {
-           $user{$provider} = $1;
-       }
-       if (/^;*username=(.*)/) {
-           $user{$provider} = $1;
-       }
-       if (/^;*secret=(.*)/) {
-           $pass{$provider} = $1;
-       }
-       if (/^;*host=(.*)/) {
-           $host{$provider} = $1;
-       }
-    }
-
-    $state = $next_state;
-}
-close SIP;
-
-# Determine if Asterisk can see current voip line (SIP trunk) 
-# sipshowpeers.txt needs to be generated before calling this perl
-# script
-
-my %voip = (); # SIP trunks status keyed on sip.conf stanza name/username
-               # if no entry we can't see SIP trunk
-
-open SIP, "sipshowregistry.txt";
-while (<SIP>) { 
-    if (/^(.*):.*(Registered)/) {
-        $voip{$1} = $2;
-       #print "'$1' '$2' $voip{$1}\n";
-    }
-}
-
-close SIP;
-
-# javascript to handle changing providers
-
-print "<script>\n";
-print "var hosts = new Array();\n";
-print "var users = new Array();\n";
-print "var passwords = new Array();\n";
-print "var stanzas = new Array();\n";
-foreach (@providers) {
-    print "hosts[\'$_\'] = \'$host{$_}\';\n";
-    print "users[\'$_\'] = \'$user{$_}\';\n";
-    print "passwords[\'$_\'] = \'$pass{$_}\';\n";
-    print "stanzas[\'$_\'] = \'$stanza{$_}\';\n";
-}
-print "</script>\n";
-
-# generate form fields -------------------------------------------
-
-$tt_provider = "onMouseOver=\"popUp(event,'voiplines_provider')\" onmouseout=\"popUp(event,'voiplines_provider')\"";
-$tt_user = "onMouseOver=\"popUp(event,'voiplines_user')\" onmouseout=\"popUp(event,'voiplines_user')\"";
-$tt_pass = "onMouseOver=\"popUp(event,'voiplines_pass')\" onmouseout=\"popUp(event,'voiplines_pass')\"";
-$tt_host = "onMouseOver=\"popUp(event,'voiplines_host')\" onmouseout=\"popUp(event,'voiplines_host')\"";
-$tt_status = "onMouseOver=\"popUp(event,'voiplines_status')\" onmouseout=\"popUp(event,'voiplines_status')\"";
-
-print "<tr $tt_provider><td>Provider</td><td>\n";
-print "<select name=\"provider\" id=\"provider\" onchange=\"changeProvider()\">\n";
-foreach (@providers) {
-    if ($_ eq $provider_current) {
-       print "<option selected=\"yes\">$_</option>\n";
-    }
-    else {
-       print "<option>$_</option>\n";
-    }
-}
-print "</select></td></tr>\n";
-
-print "<tr $tt_user><td>User:</td><td><input type=\"text\" name=\"user\" id=\"user\" value=\"$user{$provider_current}\"></td></tr>\n";
-print "<tr $tt_pass><td>Password:</td><td><input type=\"password\" name=\"pass\" id=\"pass\" value=\"$pass{$provider_current}\"></td></tr>\n";
-print "<tr $tt_host><td>Host:</td><td><input type=\"text\" name=\"host\" id=\"host\" value=\"$host{$provider_current}\"></td></tr>\n";
-
-#print "\nXXX $provider_current $stanza{$provider_current} $voip{$stanza{$provider_current}}\n";
-
-if ($voip{$stanza{$provider_current}} eq "Registered") {
-    $icon = "<img src=\"tick.png\" alt=\"OK\" />";
-}
-else {
-    $icon = "<img src=\"cross.png\" alt=\"Not OK\" />";
-}
-print "<tr $tt_status><td>Voip Line Status:</td><td>$icon</td></tr>\n";
-
-# hidden field to pass stanza with form
-
-print "<tr><td><input type=\"hidden\" name=\"stanza\" id=\"stanza\" value=\"$stanza{$provider_current}\"></td></tr>";
diff --git a/easy-asterisk-gui/voiplines.sh b/easy-asterisk-gui/voiplines.sh
deleted file mode 100644 (file)
index 071408e..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/bin/sh
-# voiplines.sh
-# David Rowe 12 Jan 2010
-# VOIP Line screen for Easy Asterisk GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
-    echo "<html>"
-    echo "<head>"
-    echo '<meta http-equiv="REFRESH" content="0;url=http:login.sh">'
-    echo "</head>"
-    echo "</html>"
-    exit
-fi
-
-# See if we have can reach the VOIP Line provider
-
-asterisk "-rx sip show registry" 2>/dev/null > sipshowregistry.txt
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<link href="astman.css" media="all" rel="Stylesheet" type="text/css" />
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-<script>
-EOF
-
-cat voiplines.js
-
-cat << EOF
-</script>
-<html>
-<title>Easy Asterisk - VOIP Line</title>
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800>'
-cat banner.html
-echo "    <tr>"
-cat menu.html    
-cat <<EOF
-
-    <td valign="top">
-
-    <table align="right" width=600>
-      <tr><td>&nbsp</td></tr>
-      <form action="set_voiplines.sh" method="get">
-      <tr><td onMouseOver="popUp(event,'voiplines_voiplines')" onmouseout="popUp(event,'voiplines_voiplines')" align="left" valign="top"><h2>VOIP Line</h2></td></tr>
-
-      <tr><td>&nbsp</td></tr>
-EOF
-
-./voiplines.pl
-
-cat <<EOF
-      <tr><td>&nbsp</td></tr>
-      <tr><td><input type="submit" value="OK"></td></tr>
-
-      </form>
-
-    </table>
-    </form>
-
-    </td>
-
-    </tr>
-
-</table>
-</body>
-</html>
-EOF
-