aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/contrib/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/contrib/scripts')
-rw-r--r--trunk/contrib/scripts/README.messages-expire20
-rw-r--r--trunk/contrib/scripts/agents.php73
-rw-r--r--trunk/contrib/scripts/ast_grab_core70
-rw-r--r--trunk/contrib/scripts/astgenkey61
-rw-r--r--trunk/contrib/scripts/astgenkey.8129
-rw-r--r--trunk/contrib/scripts/autosupport163
-rw-r--r--trunk/contrib/scripts/autosupport.841
-rw-r--r--trunk/contrib/scripts/iax-friends.sql15
-rw-r--r--trunk/contrib/scripts/loadtest.tcl148
-rw-r--r--trunk/contrib/scripts/lookup.agi90
-rw-r--r--trunk/contrib/scripts/managerproxy.pl242
-rw-r--r--trunk/contrib/scripts/meetme.sql12
-rw-r--r--trunk/contrib/scripts/messages-expire.pl96
-rw-r--r--trunk/contrib/scripts/postgres_cdr.sql33
-rw-r--r--trunk/contrib/scripts/qview.pl100
-rw-r--r--trunk/contrib/scripts/realtime_pgsql.sql141
-rw-r--r--trunk/contrib/scripts/retrieve_extensions_from_mysql.pl113
-rw-r--r--trunk/contrib/scripts/retrieve_extensions_from_sql.pl158
-rw-r--r--trunk/contrib/scripts/retrieve_sip_conf_from_mysql.pl93
-rw-r--r--trunk/contrib/scripts/safe_asterisk184
-rw-r--r--trunk/contrib/scripts/safe_asterisk.869
-rw-r--r--trunk/contrib/scripts/safe_asterisk_restart110
-rw-r--r--trunk/contrib/scripts/sip-friends.sql14
-rw-r--r--trunk/contrib/scripts/vmail.cgi1099
-rw-r--r--trunk/contrib/scripts/vmdb.sql66
25 files changed, 3340 insertions, 0 deletions
diff --git a/trunk/contrib/scripts/README.messages-expire b/trunk/contrib/scripts/README.messages-expire
new file mode 100644
index 000000000..12f2b0e9c
--- /dev/null
+++ b/trunk/contrib/scripts/README.messages-expire
@@ -0,0 +1,20 @@
+messages-expire.pl
+
+messages-expire finds messages more than X days old and deletes them.
+Because the older messages will be the lower numbers in the folder (msg0000
+will be older than msg0005), just deleting msg0000 will not work.
+expire-messages then runs a routine that goes into every folder in every
+mailbox to reorganize. If the folder contains msg0000, no action is taken.
+If the folder does not, the rename routine takes the oldest message and
+names it msg0000, the next oldest message and names it msg0001 and so on.
+
+The file deletion is done by the -exec parameter to 'find'. It would be far
+more efficient to take the output from 'find' and just reorganize the
+directories from which we deleted a file. Something for the future...
+
+Keep in mind that messages are deleted at the beginning of the script you
+will have mailbox trouble if you check messages before the script
+reorganizes your mailbox.
+
+To use it, make sure the paths are right. Adjust $age (originally set to
+31) if necessary.
diff --git a/trunk/contrib/scripts/agents.php b/trunk/contrib/scripts/agents.php
new file mode 100644
index 000000000..51f8bdee3
--- /dev/null
+++ b/trunk/contrib/scripts/agents.php
@@ -0,0 +1,73 @@
+<?php
+
+ob_implicit_flush(false);
+
+$username = "drmac";
+$secret = "secret";
+
+$socket = fsockopen("127.0.0.1","5038", $errornum, $errorstr);
+
+$agents = array();
+$curr_agent = "";
+$better_status = array( 'AGENT_UNKNOWN' => 'Unknown',
+ 'AGENT_IDLE' => 'Idle',
+ 'AGENT_ONCALL' => 'On Call',
+ 'AGENT_LOGGEDOFF' => 'Not Logged In' );
+
+if(!$socket) {
+ print "Couldn't open socket. Error #" . $errornum . ": " . $errorstr;
+} else {
+ fputs($socket, "Action: Login\r\n");
+ fputs($socket, "UserName: $username\r\n");
+ fputs($socket, "Secret: $secret\r\n\r\n");
+ fputs($socket, "Action: Agents\r\n\r\n");
+ fputs($socket, "Action: Logoff\r\n\r\n");
+
+ while(!feof($socket)) {
+ $info = fscanf($socket, "%s\t%s\r\n");
+ switch($info[0]) {
+ case "Agent:":
+ $curr_agent = $info[1];
+ $agents[$curr_agent] = array();
+ break;
+ case "Name:":
+ $agents[$curr_agent]['Name'] = $info[1];
+ break;
+ case "Status:":
+ $agents[$curr_agent]['Status'] = $better_status[$info[1]];
+ break;
+ case "LoggedInChan:":
+ $agents[$curr_agent]['LoggedInChan'] = $info[1];
+ break;
+ case "LoggedInTime:":
+ if($info[1] != "0") {
+ $agents[$curr_agent]['LoggedInTime'] = date("D, M d Y g:ia", $info[1]);
+ } else {
+ $agents[$curr_agent]['LoggedInTime'] = "n/a";
+ }
+ break;
+ case "TalkingTo:":
+ $agents[$curr_agent]['TalkingTo'] = $info[1];
+ break;
+ default:
+ break;
+ }
+ }
+ fclose($socket);
+
+ print "<html><head><title>Agents Status</title></head>\n<body>\n";
+ print "<table width=\"800px\" border=\"1\">\n";
+ print " <tr><th>Agent #</th><th>Agent Name</th><th>Agent Location</th><th>Agent Status</th><th>Agent Talking To</th><th>Agent Login Time</th></tr>\n";
+
+ foreach( $agents as $agent=>$curr ) {
+ print " <tr>\n <td>" . $agent . "</td>\n";
+ print " <td>" . $curr['Name'] . "</td>\n";
+ print " <td>" . $curr['LoggedInChan'] . "</td>\n";
+ print " <td>" . $curr['Status'] . "</td>\n";
+ print " <td>" . $curr['TalkingTo'] . "</td>\n";
+ print " <td>" . $curr['LoggedInTime'] . "</td>\n </tr>\n";
+ }
+
+ print "</table>\n</body>\n</html>\n";
+}
+?>
diff --git a/trunk/contrib/scripts/ast_grab_core b/trunk/contrib/scripts/ast_grab_core
new file mode 100644
index 000000000..b2bd7b2ed
--- /dev/null
+++ b/trunk/contrib/scripts/ast_grab_core
@@ -0,0 +1,70 @@
+#!/bin/sh
+# $Id$
+# lame quickie script to snarf a core of a hung asterisk process.
+# bugs to ast_grab_core, blinky-lights.org (derrick daugherty)
+
+# we have found that gcore doesn't yield as useful a core file
+# as that yielded by a signal-caused core dump. So we are going to change
+# the strategy to sending a SEGV signal to the asterisk process,
+# and have it 'burn to the ground', leaving behind a core file.
+# the main difference is that you cannot control where the
+# core file will end up. We will assume that safe_asterisk was
+# used to start asterisk, and the core file should therefore end
+# up in /tmp (because safe_asterisk cd's there before starting asterisk).
+# if this is not the case, set DUMPDIR to the place where the core
+# file can be found.
+
+DATE=`date +%Y%m%d%H%M`
+DUMPDIR=/tmp
+HOSTNAME=`hostname`
+ADMINEMAIL="root@localhost"
+
+#the following should be improved
+if [ -e /etc/asterisk/asterisk.conf ]; then
+ RUNDIR=`awk -F"=>" '/astrundir/ {print $2}' /etc/asterisk/asterisk.conf`
+ PID=`cat ${RUNDIR}/asterisk.pid`
+elif [ -e /var/run/asterisk.pid ] ; then
+ PID=`cat /var/run/asterisk.pid`
+else
+ echo Could not find an asterisk.conf definition for astrundir, using \'ps\'
+ echo to try and determine process ID. This is not reliable.
+ PID=`ps auxwf|grep asterisk|grep vv|head -1|awk '{print $2}'`
+fi
+
+echo Snarfing asterisk core, this could take a few seconds depending
+echo on how much memory is in use.
+echo
+echo \*\*\* WARNING \*\*\* If the system is not already locked this will cause the
+echo \*\*\* WARNING \*\*\* process to STOP while memory is dumped to disk.
+echo
+
+/bin/kill -11 ${PID}
+
+echo Snarfed! ${DUMPDIR}/core.${PID}
+echo
+
+
+echo Trying for a backtrace of the captured core.
+/usr/bin/gdb /usr/sbin/asterisk ${DUMPDIR}/core.${PID} > ${DUMPDIR}/gdb_dump.${PID}.txt 2> /dev/null << EOF
+set prompt \n
+set print pretty\n
+echo --------------------------------------------------------------------------------\n
+echo INFO THREAD
+info thread
+echo --------------------------------------------------------------------------------\n
+echo THREAD APPLY ALL BT
+thread apply all bt
+echo --------------------------------------------------------------------------------\n
+echo THREAD APPLY ALL BT FULL
+thread apply all bt full
+quit
+EOF
+echo Done trying for a bt.
+
+
+echo Notifying admins of the core.
+/usr/bin/mail -s "${HOSTNAME} core dumped at ${DUMPDIR}/core.${PID}" ${ADMINEMAIL} < ${DUMPDIR}/gdb_dump.${PID}.txt
+echo Done.
+echo
+echo Reproducible deadlocks should be posted with a full backtrace and instructions
+echo to reproduce the issue at http://bugs.digium.com/ Thanks!
diff --git a/trunk/contrib/scripts/astgenkey b/trunk/contrib/scripts/astgenkey
new file mode 100644
index 000000000..637604896
--- /dev/null
+++ b/trunk/contrib/scripts/astgenkey
@@ -0,0 +1,61 @@
+#!/bin/sh
+#
+# Usage: astgenkey [ -q ] [ -n ] [keyname]
+#
+DES3=-des3
+if [ "$1" = "-q" ]; then
+ QUIET='y'
+ if [ "$2" = "-n" ]; then
+ DES3=
+ KEY=$3
+ else
+ KEY=$2
+ fi
+elif [ "$1" = "-n" ]; then
+ DES3=
+ if [ "$2" = "-q" ]; then
+ QUIET='y'
+ KEY=$3
+ else
+ KEY=$2
+ fi
+else
+ KEY=$1
+fi
+
+if [ "$QUIET" != 'y' ]; then
+ echo ""
+ echo "This script generates an RSA private and public key pair"
+ echo "in PEM format for use by Asterisk. You will be asked to"
+ echo "enter a passcode for your key multiple times. Please"
+ echo "enter the same code each time. The resulting files will"
+ echo "need to be moved to /var/lib/asterisk/keys if you want"
+ echo "to use them, and any private keys (.key files) will"
+ echo "need to be initialized at runtime either by running"
+ echo "Asterisk with the '-i' option, or with the 'init keys'"
+ echo "command once Asterisk is running."
+ echo ""
+ echo "Press ENTER to continue or ^C to cancel."
+ read BLAH
+fi
+
+while [ "$KEY" = "" ]; do
+ echo -n "Enter key name: "
+ read KEY
+done
+
+rm -f ${KEY}.key ${KEY}.pub
+
+echo "Generating SSL key '$KEY': "
+openssl genrsa -out ${KEY}.key ${DES3} 1024
+openssl rsa -in ${KEY}.key -pubout -out ${KEY}.pub
+
+if [ -f "${KEY}.key" ] && [ -f "${KEY}.pub" ]; then
+ if [ "$QUIET" != 'y' ]; then
+ echo "Key creation successful."
+ echo "Public key: ${KEY}.pub"
+ echo "Private key: ${KEY}.key"
+ fi
+else
+ echo "Unknown error creating keys."
+fi
diff --git a/trunk/contrib/scripts/astgenkey.8 b/trunk/contrib/scripts/astgenkey.8
new file mode 100644
index 000000000..8f8325982
--- /dev/null
+++ b/trunk/contrib/scripts/astgenkey.8
@@ -0,0 +1,129 @@
+.\" $Header$
+.\"
+.\" transcript compatibility for postscript use.
+.\"
+.\" synopsis: .P! <file.ps>
+.\"
+.de P!
+.fl
+\!!1 setgray
+.fl
+\\&.\"
+.fl
+\!!0 setgray
+.fl \" force out current output buffer
+\!!save /psv exch def currentpoint translate 0 0 moveto
+\!!/showpage{}def
+.fl \" prolog
+.sy sed \-e 's/^/!/' \\$1\" bring in postscript file
+\!!psv restore
+.
+.de pF
+.ie \\*(f1 .ds f1 \\n(.f
+.el .ie \\*(f2 .ds f2 \\n(.f
+.el .ie \\*(f3 .ds f3 \\n(.f
+.el .ie \\*(f4 .ds f4 \\n(.f
+.el .tm ? font overflow
+.ft \\$1
+..
+.de fP
+.ie !\\*(f4 \{\
+. ft \\*(f4
+. ds f4\"
+' br \}
+.el .ie !\\*(f3 \{\
+. ft \\*(f3
+. ds f3\"
+' br \}
+.el .ie !\\*(f2 \{\
+. ft \\*(f2
+. ds f2\"
+' br \}
+.el .ie !\\*(f1 \{\
+. ft \\*(f1
+. ds f1\"
+' br \}
+.el .tm ? font underflow
+..
+.ds f1\"
+.ds f2\"
+.ds f3\"
+.ds f4\"
+'\" t
+.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n
+.TH ASTGENKEY 8 "May 14th, 2005" "Asterisk" "Linux Programmer's Manual"
+.SH NAME
+.B astgenkey
+-- generates keys for for Asterisk IAX2 RSA authentication
+.SH SYNOPSIS
+.PP
+.B astgenkey
+[ -q ] [ -n ] [ \fIkeyname\fP ]
+
+.SH DESCRIPTION
+.B astgenkey
+This script generates an RSA private and public key pair in PEM format
+for use by Asterisk. The private key should be kept a secret, as it can
+be used to fake your system's identity. Thus by default (without the
+option
+.I -n
+) the script will create a passphrase-encrypted copy of your secret key:
+without entering the passphrase you won't be able to use it.
+
+However if you want to use such a key with Asterisk, you'll have to start
+it interactively, because the scripts that start asterisk can't use that
+encrypted key.
+
+The key is identified by a name. If you don't write the name on the
+command-line you'll be prompted for one. The outputs of the script are:
+
+.I name\fB.pub
+.RS
+The public key: not secret. Send this to the other side.
+.RE
+
+.I name\fB.key
+.RS
+The private key: secret.
+.RE
+
+Those files should be copied to
+.I /var/lib/asterisk/keys
+
+(The private key: on your system. The public key: on other systems)
+
+To see the currently-installed keys from the asterisk CLI, use the command
+
+.RS
+show keys
+.RE
+
+.SH OPTIONS
+.B -q
+.RS
+Run quietly.
+.RE
+
+.B -n
+.RS
+Don't encrypt the private key.
+.RE
+
+.SH FILES
+.I /var/lib/asterisk/keys
+.RS
+.RE
+
+.SH "SEE ALSO"
+asterisk(8), genrsa(1), rsa(1),
+
+http://www.voip-info.org/wiki-Asterisk+iax+rsa+auth
+
+.SH "AUTHOR"
+This manual page was written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the GNU General Public License, Version 2 any
+later version published by the Free Software Foundation.
+
+On Debian systems, the complete text of the GNU General Public
+License can be found in /usr/share/common-licenses/GPL.
diff --git a/trunk/contrib/scripts/autosupport b/trunk/contrib/scripts/autosupport
new file mode 100644
index 000000000..557ca6ce2
--- /dev/null
+++ b/trunk/contrib/scripts/autosupport
@@ -0,0 +1,163 @@
+#!/bin/sh
+#
+# Collect support information
+#
+# Copyright (C) 2005, Digium, Inc.
+#
+# Written by John Bigelow (support@digium.com)
+#
+# Distributed under the terms of the GNU General Public
+# License
+#
+
+OUTPUT=$HOME/digiuminfo
+
+if [ $UID -ne 0 ]; then
+
+ echo "You must be root to run this."
+
+exit 1
+fi
+
+echo
+echo "This will gather information about your system such as:"
+echo "pci listing, dmesg, running processes, and kernel version"
+echo "This may take up to half a minute to run. Please be patient."
+echo "To continue press 'y', to quit press any other key"
+read ans
+
+if [ "$ans" = "y" ]; then
+
+ rm -f $OUTPUT
+
+ echo "------------------" >> $OUTPUT;
+ echo "PCI LIST " >> $OUTPUT;
+ echo "------------------" >> $OUTPUT;
+ lspci -vb >> $OUTPUT;
+ echo >> $OUTPUT;
+ echo >> $OUTPUT;
+
+ echo "------------------" >> $OUTPUT;
+ echo "INTERRUPTS" >> $OUTPUT;
+ echo "------------------" >> $OUTPUT;
+ cat /proc/interrupts >> $OUTPUT;
+ echo >> $OUTPUT;
+ echo >> $OUTPUT;
+
+ echo "------------------" >> $OUTPUT;
+ echo "DMESG OUTPUT" >> $OUTPUT;
+ echo "------------------" >> $OUTPUT;
+ dmesg >> $OUTPUT;
+ echo >> $OUTPUT;
+ echo >> $OUTPUT;
+
+ echo "------------------" >> $OUTPUT;
+ echo "RUNNING PROCESSES" >> $OUTPUT;
+ echo "------------------" >> $OUTPUT;
+ ps aux >> $OUTPUT;
+ echo >> $OUTPUT;
+ echo >> $OUTPUT;
+
+ echo "------------------" >> $OUTPUT;
+ echo "KERNEL VERSION" >> $OUTPUT;
+ echo "------------------" >> $OUTPUT;
+ uname -a >> $OUTPUT;
+ echo >> $OUTPUT;
+ echo >> $OUTPUT;
+
+ echo "------------------" >> $OUTPUT;
+ echo "CPU INFO" >> $OUTPUT;
+ echo "------------------" >> $OUTPUT;
+ cat /proc/cpuinfo >> $OUTPUT;
+ echo >> $OUTPUT;
+ echo >> $OUTPUT;
+
+ echo "------------------" >> $OUTPUT;
+ echo "HDPARM STATUS" >> $OUTPUT;
+ echo "------------------" >> $OUTPUT;
+ hdparm /dev/hda >> $OUTPUT;
+ hdparm -i /dev/hda >> $OUTPUT;
+ echo >> $OUTPUT;
+ echo >> $OUTPUT;
+
+ echo "------------------" >> $OUTPUT;
+ echo "ZAPTEL CONFIG" >> $OUTPUT;
+ echo "------------------" >> $OUTPUT;
+ grep -v '^#' /etc/zaptel.conf >> $OUTPUT;
+ echo >> $OUTPUT;
+ echo >> $OUTPUT;
+
+ echo "------------------" >> $OUTPUT;
+ echo "ZAPATA CONFIG" >> $OUTPUT;
+ echo "------------------" >> $OUTPUT;
+ grep -v '^;' /etc/asterisk/zapata.conf >> $OUTPUT;
+ echo >> $OUTPUT;
+ echo >> $OUTPUT;
+
+ echo "------------------" >> $OUTPUT;
+ echo "EXTENSIONS CONFIG" >> $OUTPUT;
+ echo "------------------" >> $OUTPUT;
+ grep -v '^;' /etc/asterisk/extensions.conf >> $OUTPUT;
+ echo >> $OUTPUT;
+ echo >> $OUTPUT;
+
+ echo "------------------" >> $OUTPUT;
+ echo "ZTTEST" >> $OUTPUT;
+ echo "------------------" >> $OUTPUT;
+ /usr/src/zaptel/zttest -c 20 >> $OUTPUT;
+ echo >> $OUTPUT;
+ echo >> $OUTPUT;
+
+else
+ echo "terminated";
+exit
+fi
+
+echo
+echo "Digium may require root level access to the system to help debug";
+echo "the problem you are experiencing. Do you want to provide login";
+echo "information at this time?";
+echo "Press 'y' for yes and any other key to exit and save the previous info collected"
+read login
+
+if [ "$login" = "y" ]; then
+
+ echo "------------------" >> $OUTPUT;
+ echo "LOGIN INFORMATION" >> $OUTPUT;
+ echo "------------------" >> $OUTPUT;
+
+ echo
+ echo "What is your root password?"
+ read rootpass
+
+ echo
+ echo "Root pass: "$rootpass >> $OUTPUT
+
+ echo
+ echo "What is your PUBLIC IP address?"
+ read ip
+
+ echo "IP address: "$ip >> $OUTPUT
+
+ echo
+ echo "Please provide any other login information that the technician"
+ echo "may need to know to login to the system'(press enter if not)'"
+ read adinfo
+
+ echo "Additional login info: "$adinfo >> $OUTPUT
+
+ echo
+ echo "All information has been stored in $OUTPUT,"
+ echo "Please attach this file to an email ticket you already"
+ echo "have open with Digium Tech Support."
+
+else
+ echo
+ echo "All information except login info has been stored in $OUTPUT,"
+ echo "Please send this file to an email ticket you already"
+ echo "have open with Digium Tech Support."
+exit
+fi
+
+
+
diff --git a/trunk/contrib/scripts/autosupport.8 b/trunk/contrib/scripts/autosupport.8
new file mode 100644
index 000000000..e356fcdbb
--- /dev/null
+++ b/trunk/contrib/scripts/autosupport.8
@@ -0,0 +1,41 @@
+.TH AUTOSUPPORT 8 "Jul 5th, 2005" "Asterisk" "Linux Programmer's Manual"
+.SH NAME
+.B autosupport
+\(em interactive script to provide Digium[tm]'s support with information
+.SH SYNOPSIS
+.PP
+.B autosupport
+
+.SH DESCRIPTION
+.B autoasupport
+is a script that is normally run by a user contacting Digium's support
+to automate gathering support information.
+
+It will probe the system for some configuration and run-time information,
+and will also prompt the user for some optional access information (IP
+address, login and password).
+
+The information is written to /root/digiuminfo which the user is expected
+to attach to a support ticket to Digium.
+
+The script must be run as root as it reads Asterisk's configuration and
+the disk information using hdparm(8).
+
+.SH FILES
+.B /root/digiuminfo
+.RS
+The output of the script goes there
+.RE
+
+.SH SEE ALSO
+asterisk(8)
+
+.SH "AUTHOR"
+autosupport was written by John Bigelow <support@digium.com>.
+This manual page was written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the GNU General Public License, Version 2 any
+later version published by the Free Software Foundation.
+
+On Debian systems, the complete text of the GNU General Public
+License can be found in /usr/share/common-licenses/GPL.
diff --git a/trunk/contrib/scripts/iax-friends.sql b/trunk/contrib/scripts/iax-friends.sql
new file mode 100644
index 000000000..717a27d07
--- /dev/null
+++ b/trunk/contrib/scripts/iax-friends.sql
@@ -0,0 +1,15 @@
+#
+# Table structure for table `iaxfriends`
+#
+
+CREATE TABLE `iaxfriends` (
+ `name` varchar(40) NOT NULL default '',
+ `secret` varchar(40) NOT NULL default '',
+ `context` varchar(40) NOT NULL default '',
+ `ipaddr` varchar(20) NOT NULL default '',
+ `port` int(6) NOT NULL default '0',
+ `regseconds` int(11) NOT NULL default '0',
+ `accountcode` varchar(20) NOT NULL default '',
+ PRIMARY KEY (`name`)
+) TYPE=MyISAM;
+
diff --git a/trunk/contrib/scripts/loadtest.tcl b/trunk/contrib/scripts/loadtest.tcl
new file mode 100644
index 000000000..9c50be338
--- /dev/null
+++ b/trunk/contrib/scripts/loadtest.tcl
@@ -0,0 +1,148 @@
+#!/usr/bin/tclsh
+#
+# Usage (as root):
+#
+# $ tclsh loadtest.tcl
+#
+# Copyleft 2005 by Chris Maj <cmaj_at_freedomcorpse_dot_com>
+#
+# Create a (huge) bunch of call files to dial via pbx_spool.
+# Defaults are selected with 'Enter' and, if all defaults
+# are selected, you'll dial Zap/1/s into default|s|1
+#
+
+
+# where Asterisk's pbx/pbx_spool.c will be looking for work
+set SPOOLDIR /var/spool/asterisk/outgoing
+# pbx_spool is fairly aggresive, so make files here first
+set TEMPDIR /tmp
+
+if { ![file writable $SPOOLDIR] } {
+ puts "Do you need to be root to write to $SPOOLDIR ?"
+ exit
+}
+
+if { ![file readable $TEMPDIR] } {
+ puts "Do you need to be root to read from $TEMPDIR ?"
+ exit
+}
+
+if { ![file writable $TEMPDIR] } {
+ puts "Do you need to be root to write to $TEMPDIR ?"
+ exit
+}
+
+# gets some input from the user
+proc get {var_ default_ prompt_} {
+ global $var_
+ puts $prompt_
+ if { $default_ != "" } {
+ puts -nonewline "(default: $default_) ? "
+ } else {
+ puts -nonewline "? "
+ }
+ flush stdout
+ gets stdin $var_
+ if { [set $var_] == "" && $default_ != "" } {
+ set $var_ $default_
+ }
+}
+
+# puts the user requested channels into a neat, ordered list
+proc splitchans {inch_} {
+ global changroup
+ set outch [list]
+ foreach range [split $inch_ {, }] {
+ set start [lindex [split $range -] 0]
+ set stop [lindex [split $range -] end]
+ if { [string is digit $start] && [string is digit $stop] } {
+ set ::changroup "channel"
+ for {set ch $start} {$ch <= $stop} {incr ch} {
+ if { [lsearch $outch $ch] == -1 } {
+ lappend outch $ch
+ }
+ }
+ } else {
+ set ::changroup "group"
+ foreach ch [split $range -] {
+ lappend outch $ch
+ }
+ }
+ }
+ return [lsort -dictionary $outch]
+}
+
+# writes out a file in the temporary directory,
+# then changes the mtime of the file before
+# sticking it into the outgoing spool directory
+# (where pbx_spool will be looking)
+proc spool {channel_ callcnt_ when_} {
+ set callstr "
+Channel: $::technology/$channel_/$::destination
+Context: $::context
+Extension: $::extension
+Priority: $::priority
+WaitTime: $::timeout
+RetryTime: $::retrytime
+MaxRetries: $::maxretries
+Callerid: $::clid
+SetVar: $::astvar
+Account: $::account
+"
+ set fn "loadtest.call$callcnt_.ch$channel_"
+ set fd [open $::TEMPDIR/$fn w]
+ puts $fd $callstr
+ close $fd
+ file mtime $::TEMPDIR/$fn $when_
+ file rename -force $::TEMPDIR/$fn $::SPOOLDIR/$fn
+}
+
+# prompt the user for some info
+get technology "Zap" "\nEnter technology type
+Zap, IAX, SIP, etc."
+get chans "1" "\nEnter channel(s) or group to test in formats like
+2\n1-4\n3 5 7 9\n1-23,25-47,49-71,73-95\ng4\ng2,g1"
+set channels [splitchans $chans]
+
+get destination "s" "\nEnter destination number"
+get context "default" "\nEnter context"
+get extension "s" "\nEnter extension"
+get priority "1" "\nEnter priority"
+get timeout "45" "\nEnter timeout for call to be answered in seconds"
+get maxretries "0" "\nEnter maximum number of retries"
+
+if { $maxretries > 0 } {
+ get retrytime "300" "\nEnter time between retries in seconds"
+} else {
+ set retrytime 300
+}
+
+get clid "" "\nEnter callerid"
+get astvar "" "\nEnter some extra variables"
+get account "loadtest" "\nEnter account code"
+get calls "1" "\nEnter number of test calls per $changroup"
+get period "60" "\nEnter period between placing calls on a particular $changroup in seconds"
+
+if { [llength $channels] > 1 } {
+ get rate "0" "\nEnter period between placing each call in seconds
+0 will send a call on each $changroup every $period seconds
+1 will send a call on $changroup [lindex $channels 0] at [expr {$period + 0}]s, [lindex $channels 1] at [expr {$period + 1 }]s, etc.
+5 will send a call on $changroup [lindex $channels 0] at [expr {$period + 0}]s, [lindex $channels 1] at [expr {$period + 5 }]s, etc."
+} else {
+ set rate 0
+}
+
+puts -nonewline "\nCreating spooled call files... "
+set now [clock seconds]
+set spoolcnt 0
+set spinner [list / - \\ |]
+for {set i 0} {$i < $calls} {incr i} {
+ foreach ch $channels {
+ set chidx [lsearch $channels $ch]
+ spool $ch [incr spoolcnt] [expr {$now + ($i * $period) + ($rate * $chidx)}]
+ puts -nonewline "\b"
+ puts -nonewline [lindex $spinner [expr {$spoolcnt % 4}]]
+ flush stdout
+ }
+}
+puts "\b$spoolcnt calls placed into $SPOOLDIR !"
diff --git a/trunk/contrib/scripts/lookup.agi b/trunk/contrib/scripts/lookup.agi
new file mode 100644
index 000000000..4b682b837
--- /dev/null
+++ b/trunk/contrib/scripts/lookup.agi
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+#
+# Use Reverse Lookups to populate valuable information
+#
+# Copyright (C) 2005 Digium, Inc.
+#
+# Mark Spencer <markster@digium.com>
+#
+# Based on work of Joe Fratantoni - BrakeDanceJ - Joe@UnrealDestination.com.
+#
+# This program is Free Software distributed under the terms of the GNU
+# General Public License version 2. See LICENSE for details.
+#
+#
+use LWP::UserAgent;
+my %AGI;
+my $debug = 0;
+$|=1;
+sub url_decode {
+ my @args = @_;
+ s/%([0-9A-F]{2})/chr hex $1/egios for @args;
+ s/\"//egios for @args;
+ return wantarray ? @args : $args[0];
+}
+
+while(<STDIN>) {
+ chomp;
+ last unless length($_);
+ if (/^agi_(\w+)\:\s+(.*)$/) {
+ $AGI{$1} = $2;
+ }
+}
+
+alarm(4);
+my $number = $AGI{'callerid'};
+$number =~ /(\d+)/;
+$number = $1;
+die("You must specify a number") unless $number;
+my $ua = LWP::UserAgent->new;
+$ua->agent("Asterisk");
+my $req = HTTP::Request->new(POST => 'http://www.411.com/10668/search/Reverse_Phone');
+$req->content_type('application/x-www-form-urlencoded');
+$req->content("phone=$number");
+my $res = $ua->request($req);
+if ($res->is_success) {
+ my $first, $last, $address, $street, $house, $city, $state, $zip, $phone;
+ if ($res->content =~ /PAGE: PHONE_NOT_FOUND/) {
+ # Limited Information
+ $res->content =~ /is a \s+([A-Za-z -]*), ([A-Z]{2}) \s+based phone number and the registered carrier is (.*)\.\s+/;
+ ($city, $state, $last) =
+ map { url_decode($_) } ($1, $2, $3);
+ $cidname = "$city, $state";
+ } else {
+ # Full Information
+ $res->content =~ /RM_HTML_FIRST_ESC_=(.*)&_RM_HTML_LAST_ESC_=(.*)&_RM_HTML_ADDRESS_ESC_=(.*)&_RM_HTML_STREET_ESC_=(.*)&_RM_HTML_HOUSE_ESC_=(.*)&_RM_HTML_CITY_ESC_=(.*)&_RM_HTML_STATE_ESC_=(.*)&_RM_HTML_ZIP_ESC_=(.*)&_RM_HTML_PHONE_ESC_=(.*)&CITY=(.*)&STATE=(.*)/;
+ ($first, $last, $address, $street, $house, $city, $state, $zip, $phone) =
+ map { url_decode($_) } ($1, $2, $3, $4, $5, $6, $7, $8, $9);
+ my $cidname = $last;
+ if ($first) {
+ $cidname = $first . " " . $last;
+ } else {
+ $cidname = $last;
+ }
+ }
+ print STDOUT "SET VARIABLE CALLERID(name) \"$cidname\"\n";
+ <STDIN>;
+ print STDOUT "SET VARIABLE CALLER_ZIP \"$zip\"\n";
+ <STDIN>;
+ print STDOUT "SET VARIABLE CALLER_STATE \"$state\"\n";
+ <STDIN>;
+ print STDOUT "SET VARIABLE CALLER_CITY \"$city\"\n";
+ <STDIN>;
+ print STDOUT "SET VARIABLE CALLER_ADDRESS \"$address\"\n";
+ <STDIN>;
+ print STDOUT "SET VARIABLE CALLER_LAST \"$last\"\n";
+ <STDIN>;
+ print STDOUT "SET VARIABLE CALLER_FIRST \"$first\"\n";
+ <STDIN>;
+ print STDERR "First: $first\n" .
+ "Last: $last\n" .
+ "Address: $address\n" .
+ "Street: $street\n" .
+ "House: $house\n" .
+ "City: $city\n" .
+ "State: $state\n" .
+ "Zip: $zip\n" .
+ "Phone: $phone\n" if $debug;
+} else {
+ print STDERR $res->status_line . "\n";
+}
diff --git a/trunk/contrib/scripts/managerproxy.pl b/trunk/contrib/scripts/managerproxy.pl
new file mode 100644
index 000000000..cdf79a239
--- /dev/null
+++ b/trunk/contrib/scripts/managerproxy.pl
@@ -0,0 +1,242 @@
+#!/usr/bin/perl -w
+#
+# Simple Asterisk Manager Proxy, Version 1.01
+# 2004-09-26
+# Copyright (c) 2004 David C. Troy <dave@popvox.com>
+#
+# This code is based on Flash Operator Panel 'op_server.pl'
+# by Nicolas Gudino
+#  Copyright (C) 2004.
+#
+# David C. Troy <dave@popvox.com>
+# Nicolas Gudino <nicolas@house.com.ar>
+#
+# This program is free software, distributed under the terms of
+# the GNU General Public License.
+#
+# Security consideration: This script will open your manager port
+# for unauthenticated logins. Be careful out there :-)
+#############################
+
+#############################
+# Perl Prerequisites
+#############################
+use strict;
+use IO::Socket;
+use IO::Select;
+use POSIX qw(setsid);
+
+#############################
+# User Configurable Options
+#############################
+# Configuration for logging in to your asterisk server
+# Check you Asterisk config file "manager.conf" for details
+my $manager_host = '127.0.0.1';
+my $manager_port = 5038;
+my $manager_user = 'your_username';
+my $manager_secret = 'your_secret';
+# Port For this proxy
+my $listen_port = 1234;
+my $manager_pid = "/var/run/asterisk_managerproxy.pid";
+
+#############################
+# Declarations
+#############################
+my %proxy_clients;
+my $O;
+my $p;
+my @S;
+my %blocks;
+my $debug = 0;
+
+$SIG{PIPE} = 'IGNORE';
+$SIG{INT} = 'close_all';
+$SIG{USR1} = 'list_clients';
+
+if (defined($ARGV[0]))
+{
+ if ($ARGV[0] eq "-d")
+ {
+ defined(my $pid = fork) or die "Can't Fork: $!";
+ exit if $pid;
+ setsid or die "Can't start a new session: $!";
+ open MYPIDFILE, ">$manager_pid";
+ print MYPIDFILE $$;
+ close MYPIDFILE;
+ }
+} else {
+ $debug = 1;
+}
+
+
+# Connect to manager
+$p =
+ new IO::Socket::INET->new(
+ PeerAddr => $manager_host,
+ PeerPort => $manager_port,
+ Proto => "tcp",
+ Type => SOCK_STREAM
+ )
+ or die "\nCould not connect to Asterisk Manager Port at $manager_host\n";
+
+$p->autoflush(1);
+
+# Login to Manager
+send_command_to_manager( "Action: Login\r\nUsername: $manager_user\r\nSecret: $manager_secret\r\n\r\n" );
+
+# Start up listener for new connections
+my $m =
+ new IO::Socket::INET(Listen => 1, LocalPort => $listen_port, ReuseAddr => 1)
+ or die "\nCan't listen to port $listen_port\n";
+$O = new IO::Select();
+$O->add($m);
+$O->add($p);
+$/ = "\0";
+
+sub manager_reconnect()
+{
+ my $attempt = 1;
+ my $total_attempts = 60;
+
+ do
+ {
+ log_debug("** Attempt reconnection to manager port # $attempt", 16);
+ $p =
+ new IO::Socket::INET->new(
+ PeerAddr => $manager_host,
+ PeerPort => $manager_port,
+ Proto => "tcp",
+ Type => SOCK_STREAM
+ );
+ $attempt++;
+ if ($attempt > $total_attempts)
+ {
+ die("!! Could not reconnect to Asterisk Manager port");
+ }
+ sleep(10); # wait 10 seconds before trying to reconnect
+ } until $p;
+ $O->add($p);
+ send_command_to_manager(
+ "Action: Login\r\nUsername: $manager_user\r\nSecret: $manager_secret\r\n\r\n"
+ );
+}
+
+# Loop, continuously processing new connections, input from those connections, and input from Manager conn
+while (1)
+{
+ while (@S = $O->can_read)
+ {
+ foreach (@S)
+ {
+ if ($_ == $m)
+ {
+ log_debug("** New client connection", 16);
+ my $C = $m->accept;
+ $proxy_clients{$C} = \$C;
+ print "New Connection: $C\n" if $debug;
+ $O->add($C);
+ } else {
+ # It's not a new client connection
+ my $i;
+ my $R = sysread($_, $i, 2); # 2048; interleave every two bytes?
+ if (defined($R) && $R == 0)
+ {
+ # Confirm it's really dead by trying to write to it?
+ my $T = syswrite($_, ' ', 2); # 2048
+ if (!defined($T))
+ {
+ # connection went away...
+ $O->remove($_);
+ $_->close;
+
+ # If we lost the socket for the Asterisk Mgr, then reconnect
+ if ($_ == $p)
+ {
+ log_debug(
+ "** Asterisk Manager connection lost!!!!!",
+ 16);
+ manager_reconnect();
+ } else {
+ # Remove handle from proxy_clients hash
+ print "Closed Connection: $_\n" if $debug;
+ delete $proxy_clients{$_};
+ }
+ }
+ }
+ else # Socket is active and we are ready to read something from it
+ {
+ $blocks{$_} .= $i;
+ next if ($blocks{$_} !~ /\r\n\r\n$/);
+ # do a 'next' unless we have completed a block; we are not ready to continue
+
+ # Process the completed block
+ # If block is from asterisk, send to clients
+ if ($_ == $p) {
+ # block is from asterisk, send to clients
+ print "asterisk: $_\n$blocks{$_}" if $debug;
+ my $cnt = 0;
+ foreach my $client (values %proxy_clients) {
+ print "writing to $$client...\n" if $debug;
+ syswrite($$client, $blocks{$_});
+ $cnt++;
+ }
+ print "sent block to $cnt clients\n" if $debug;
+ } else {
+ # Blocks are from clients, send to asterisk
+ syswrite($p, $blocks{$_});
+ print "client: $_\n$blocks{$_}\n" if $debug;
+ }
+ delete $blocks{$_};
+
+ } # end if read succeeded
+ } # end if new client connection
+ } # end foreach @S -> can read
+ } # while can read
+} # endless loop
+
+sub close_all
+{
+ log_debug("Exiting...", 0);
+
+ foreach my $hd ($O->handles)
+ {
+ $O->remove($hd);
+ close($hd);
+ }
+
+ exit(0);
+}
+
+sub send_command_to_manager
+{
+ my $comando = shift;
+ if (defined $p)
+ {
+ my @lineas = split("\r\n", $comando);
+ foreach my $linea (@lineas)
+ {
+ syswrite($p, "$linea\r\n");
+ log_debug("-> $linea", 2);
+ }
+ log_debug(" ", 2);
+ syswrite($p, "\r\n");
+ }
+}
+
+sub log_debug
+{
+ my $texto = shift;
+ $texto =~ s/\0//g;
+ print "$texto\n" if $debug;
+}
+
+sub list_clients()
+{
+ my $cnt = 0;
+ foreach my $client (values %proxy_clients) {
+ print "client: $$client\n";
+ $cnt++;
+ }
+ print "$cnt clients.\n\n";
+}
+
diff --git a/trunk/contrib/scripts/meetme.sql b/trunk/contrib/scripts/meetme.sql
new file mode 100644
index 000000000..19c4ed745
--- /dev/null
+++ b/trunk/contrib/scripts/meetme.sql
@@ -0,0 +1,12 @@
+--
+-- Table structure for Realtime meetme
+--
+
+CREATE TABLE meetme (
+ confno char(80) DEFAULT '0' NOT NULL,
+ pin char(20) NULL,
+ adminpin char(20) NULL,
+ members integer DEFAULT 0 NOT NULL,
+ PRIMARY KEY (confno)
+);
+
diff --git a/trunk/contrib/scripts/messages-expire.pl b/trunk/contrib/scripts/messages-expire.pl
new file mode 100644
index 000000000..993997899
--- /dev/null
+++ b/trunk/contrib/scripts/messages-expire.pl
@@ -0,0 +1,96 @@
+#!/usr/bin/perl
+#
+# Script to expire voicemail after a specified number of days
+# by Steve Creel <screel@turbs.com>
+#
+
+# Directory housing the voicemail spool for asterisk
+$dir = "/var/spool/asterisk/voicemail";
+
+# Context for which the script should be running
+$context = "default";
+
+# Age (Delete files older than $age days old)
+$age = 31;
+
+# Age for unheard messages (Defaults to same age for all messages)
+# Set to 0 to not delete unheard messages
+$unheardage = $age;
+
+
+# Delete all files older than $age and $unheardage
+# (named msg????.??? to get the audio and txt files,
+# but we don't delete greetings or the user's name)
+
+if($age==$unheardage) {
+
+ # Save time by doing one find if we're treating everything the same
+ system('find '.$dir.'/'.$context.' -name msg????.??? -mtime +'.$age.' -exec rm {} \; -exec echo Deleted {} \;');
+
+} else {
+
+ # Find everything not in a folder called 'INBOX' and delete it after $age days
+ system('find '.$dir.'/'.$context.' -path \'*INBOX*\' -prune -o -name msg????.??? -mtime +'.$age.' -exec rm {} \; -exec echo Deleted {} \;');
+
+ # If unheardage is set to 0, we won't delete any unheard messages
+ if($unheardage > 0) {
+
+ # Delete things that are in a folder called INBOX after $unheardage days
+ system('find '.$dir.'/'.$context.' -path \'*INBOX*\' -name msg????.??? -mtime +'.$unheardage.' -exec rm {} \; -exec echo Deleted {} \;');
+
+ }
+}
+
+# For testing - what number to we start when we renumber?
+$start = "0";
+
+# Rename to msg and a 4 digit number, 0 padded.
+$fnbase = sprintf "msg%04d", $start;
+
+# Make $dir include the context too
+$dir.="/".$context;
+
+( -d $dir ) || die "Can't read list of mailboxes ($dir): $!\n";
+@mailboxes = `ls -A1 $dir`;
+chomp(@mailboxes);
+
+$save_fnbase = $fnbase;
+
+foreach $mailbox (@mailboxes) {
+
+ ( -d $dir."/".$mailbox) || die "Can't read list of folders (".$dir."/".$mailbox."): $!\n";
+ @folders = `ls -A1 $dir/$mailbox`;
+ chomp(@folders);
+
+ foreach $folder (@folders) {
+ if (-d $dir."/".$mailbox."/".$folder) {
+ ( -d $dir."/".$mailbox."/".$folder) || die "Can't read list of messages (".$dir."/".$mailbox."/".$folder.") $!\n";
+ @files = `ls -A1 $dir/$mailbox/$folder/`;
+
+ # Sort so everything is in proper order.
+ @files = sort @files;
+ chomp(@files);
+
+ # If there is still (after deleting old files earlier in the
+ # script) a msg0000.txt, we don't need to shuffle anything
+ # in this folder.
+ if (-f $dir."/".$mailbox."/".$folder."/msg0000.txt") { next; }
+
+ foreach $ext (("WAV", "wav", "gsm", "txt")) {
+ # Reset the fnbase for each file type
+ $fnbase = $save_fnbase;
+
+ foreach $file (@files) {
+ if ( $file =~ /$ext/ ) {
+ chdir($dir."/".$mailbox."/".$folder."/") || die "Can't change folder: $!";
+ print "Renaming: ".$dir."/".$mailbox."/".$folder."/".$file." to ".$fnbase.".".$ext."\n";
+ rename($file, $fnbase.".".$ext) || die "Cannot rename: $!";
+ $fnbase++;
+ }
+ }
+ }
+ }
+ }
+}
+
+__END__ \ No newline at end of file
diff --git a/trunk/contrib/scripts/postgres_cdr.sql b/trunk/contrib/scripts/postgres_cdr.sql
new file mode 100644
index 000000000..a4701bd77
--- /dev/null
+++ b/trunk/contrib/scripts/postgres_cdr.sql
@@ -0,0 +1,33 @@
+
+/*
+ * Id: postgres_cdr.sql,v 1.8.2.11 2003/10/10 11:15:43 pnixon Exp $
+ *
+ * --- Peter Nixon [ codemonkey@peternixon.net ]
+ *
+ * This is a PostgreSQL schema for doing CDR accounting with Asterisk
+ *
+ * The calls will automatically be logged as long as the module is loaded.
+ *
+ */
+
+
+CREATE TABLE cdr (
+ AcctId BIGSERIAL PRIMARY KEY,
+ calldate TIMESTAMP with time zone NOT NULL DEFAULT now(),
+ clid VARCHAR(80) NOT NULL default '',
+ src VARCHAR(80) NOT NULL default '',
+ dst VARCHAR(80) NOT NULL default '',
+ dcontext VARCHAR(80) NOT NULL default '',
+ channel VARCHAR(80) NOT NULL default '',
+ dstchannel VARCHAR(80) NOT NULL default '',
+ lastapp VARCHAR(80) NOT NULL default '',
+ lastdata VARCHAR(80) NOT NULL default '',
+ duration INTEGER NOT NULL default '0',
+ billsec INTEGER NOT NULL default '0',
+ disposition VARCHAR(45) NOT NULL default '',
+ amaflags INTEGER NOT NULL default '0',
+ accountcode VARCHAR(20) NOT NULL default '',
+ uniqueid VARCHAR(32) NOT NULL default '',
+ userfield VARCHAR(255) NOT NULL default ''
+);
+
diff --git a/trunk/contrib/scripts/qview.pl b/trunk/contrib/scripts/qview.pl
new file mode 100644
index 000000000..940e474f7
--- /dev/null
+++ b/trunk/contrib/scripts/qview.pl
@@ -0,0 +1,100 @@
+#!/usr/bin/perl
+#
+# Asterisk Queue Viewer
+# Uses management interface to query call queues on a machine
+# (C) 2003 David C. Troy -- dave@toad.net
+#
+# This program is free software, distributed under the terms of the
+# GNU General Public License
+#
+
+use IO::Socket;
+use CGI qw(:standard);
+use CGI::Carp qw/fatalsToBrowser/;
+
+$host = "asterisk.yourdomain.com";
+$port = 5038;
+$user = "manager_user";
+$secret = "Manager_secret";
+$EOL = "\015\012";
+$BLANK = $EOL x 2;
+$queue = param('queue');
+
+$remote = IO::Socket::INET->new(
+ Proto => 'tcp', # protocol
+ PeerAddr=> $host, # Address of server
+ PeerPort=> $port, # port of server
+ Reuse => 1
+ ) or die "$!";
+
+$remote->autoflush(1); # Send immediately
+
+# Login and get our booty from Asterisk
+$logres = send_cmd("Action: Login${EOL}Username: $user${EOL}Secret: $secret$BLANK");
+$qinfo = send_cmd("Action: queues$BLANK$EOL");
+$logres = send_cmd("Action: Logoff$BLANK");
+close $remote; # Close socket
+
+my %qcalls = map { /(\S+)\s+has (\d+) calls.*?\n\n/sg; } $qinfo;
+my %qmax = map { /(\S+)\s+has \d+ calls \(max (\S+)\).*?\n\n/sg; } $qinfo;
+my %qstrat = map { /(\S+)\s+has \d+ calls \(max \S+\) in (\S+) strategy.*?\n\n/sg; } $qinfo;
+my %qmems = map { /(\S+)\s+has \d+ calls.*?Members:.*?\s{6}(.*?)\s{3}\S*?\s*?Callers/sg; } $qinfo;
+my %qcallers = map { /(\S+)\s+has \d+ calls.*?([No ]*Callers.*?)\n\n/sg; } $qinfo;
+
+print header();
+print start_html(-head=>meta({-http_equiv=>'Refresh', -content=>'120'}),
+ -title=>"PBX Queue Viewer",
+ -style=>{'src'=>'/pbxinfo.css'});
+print "<table width=850><tr>";
+
+$col = 0;
+
+foreach $q (keys %qcalls) {
+
+ $mems = $qmems{$q};
+ $mems =~ s/ //g;
+ $mems =~ s/\n/<br>\n/g;
+ $callers = $qcallers{$q};
+ $callers =~ s/ //g;
+ $callers =~ s/Callers:.*\n//g;
+ $callers =~ s/\n/<br>/g;
+
+ print qq{<td valign=top width=48%><table width=100%>
+<tr><th colspan=2><A HREF=/mrtg/qmon-$q.html>$q</A>&nbsp;&nbsp;$qcalls{$q} calls (max $qmax{$q}), $qstrat{$q} strategy</th></tr>
+<tr><td valign=top width=55%>$mems</td><td valign=top width=45%>$callers</td></tr>
+</table></td>
+};
+
+ print "</tr><tr>" if $col;
+ $col = 0 if $col++;
+
+}
+
+print "</table>";
+
+print end_html();
+
+exit(0);
+
+sub read_conn {
+
+ my $buf="";
+ while (<$remote>) {
+ last if $_ eq $EOL;
+ s/$EOL/\n/g;
+ $buf .= $_;
+ }
+
+ return $buf
+}
+
+sub send_cmd {
+ my $cmd = @_[0];
+
+ my $buf="";
+ print $remote $cmd;
+
+ $buf = read_conn();
+
+ return $buf;
+}
diff --git a/trunk/contrib/scripts/realtime_pgsql.sql b/trunk/contrib/scripts/realtime_pgsql.sql
new file mode 100644
index 000000000..c0de544ab
--- /dev/null
+++ b/trunk/contrib/scripts/realtime_pgsql.sql
@@ -0,0 +1,141 @@
+drop table extensions_conf;
+
+CREATE TABLE extensions_conf (
+id serial NOT NULL,
+context character varying(20) DEFAULT '' NOT NULL,
+exten character varying(20) DEFAULT '' NOT NULL,
+priority smallint DEFAULT 0 NOT NULL,
+app character varying(20) DEFAULT '' NOT NULL,
+appdata character varying(128)
+);
+
+drop table cdr;
+CREATE TABLE cdr (
+calldate timestamp with time zone DEFAULT now() NOT NULL,
+clid character varying(80) DEFAULT '' NOT NULL,
+src character varying(80) DEFAULT '' NOT NULL,
+dst character varying(80) DEFAULT '' NOT NULL,
+dcontext character varying(80) DEFAULT '' NOT NULL,
+channel character varying(80) DEFAULT '' NOT NULL,
+dstchannel character varying(80) DEFAULT '' NOT NULL,
+lastapp character varying(80) DEFAULT '' NOT NULL,
+lastdata character varying(80) DEFAULT '' NOT NULL,
+duration bigint DEFAULT 0::bigint NOT NULL,
+billsec bigint DEFAULT 0::bigint NOT NULL,
+disposition character varying(45) DEFAULT '' NOT NULL,
+amaflags bigint DEFAULT 0::bigint NOT NULL,
+accountcode character varying(20) DEFAULT '' NOT NULL,
+uniqueid character varying(32) DEFAULT '' NOT NULL,
+userfield character varying(255) DEFAULT '' NOT NULL
+);
+
+drop table sip_conf;
+CREATE TABLE sip_conf (
+id serial NOT NULL,
+name character varying(80) DEFAULT '' NOT NULL,
+accountcode character varying(20),
+amaflags character varying(7),
+callgroup character varying(10),
+callerid character varying(80),
+canreinvite character varying(3) DEFAULT 'yes',
+context character varying(80),
+defaultip character varying(15),
+dtmfmode character varying(7),
+fromuser character varying(80),
+fromdomain character varying(80),
+host character varying(31) DEFAULT '' NOT NULL,
+insecure character varying(4),
+"language" character varying(2),
+mailbox character varying(50),
+md5secret character varying(80),
+nat character varying(5) DEFAULT 'no' NOT NULL,
+permit character varying(95),
+deny character varying(95),
+mask character varying(95),
+pickupgroup character varying(10),
+port character varying(5) DEFAULT '' NOT NULL,
+qualify character varying(3),
+restrictcid character varying(1),
+rtptimeout character varying(3),
+rtpholdtimeout character varying(3),
+secret character varying(80),
+"type" character varying DEFAULT 'friend' NOT NULL,
+username character varying(80) DEFAULT '' NOT NULL,
+disallow character varying(100) DEFAULT 'all',
+allow character varying(100) DEFAULT 'g729;ilbc;gsm;ulaw;alaw',
+musiconhold character varying(100),
+regseconds bigint DEFAULT 0::bigint NOT NULL,
+ipaddr character varying(15) DEFAULT '' NOT NULL,
+regexten character varying(80) DEFAULT '' NOT NULL,
+cancallforward character varying(3) DEFAULT 'yes'
+);
+
+drop table voicemail_users;
+CREATE TABLE voicemail_users (
+id serial NOT NULL,
+customer_id bigint DEFAULT (0)::bigint NOT NULL,
+context character varying(50) DEFAULT '' NOT NULL,
+mailbox bigint DEFAULT (0)::bigint NOT NULL,
+"password" character varying(4) DEFAULT '0' NOT NULL,
+fullname character varying(50) DEFAULT '' NOT NULL,
+email character varying(50) DEFAULT '' NOT NULL,
+pager character varying(50) DEFAULT '' NOT NULL,
+stamp timestamp(6) without time zone NOT NULL
+);
+
+drop table queue_table;
+CREATE TABLE queue_table (
+name varchar(128),
+musiconhold varchar(128),
+announce varchar(128),
+context varchar(128),
+timeout int8,
+monitor_join bool,
+monitor_format varchar(128),
+queue_youarenext varchar(128),
+queue_thereare varchar(128),
+queue_callswaiting varchar(128),
+queue_holdtime varchar(128),
+queue_minutes varchar(128),
+queue_seconds varchar(128),
+queue_lessthan varchar(128),
+queue_thankyou varchar(128),
+queue_reporthold varchar(128),
+announce_frequency int8,
+announce_round_seconds int8,
+announce_holdtime varchar(128),
+retry int8,
+wrapuptime int8,
+maxlen int8,
+servicelevel int8,
+strategy varchar(128),
+joinempty varchar(128),
+leavewhenempty varchar(128),
+eventmemberstatus bool,
+eventwhencalled bool,
+reportholdtime bool,
+memberdelay int8,
+weight int8,
+timeoutrestart bool,
+PRIMARY KEY (name)
+) WITHOUT OIDS;
+ALTER TABLE queue_table OWNER TO asterisk;
+
+drop table queue_member_table;
+CREATE TABLE queue_member_table
+(
+queue_name varchar(128),
+interface varchar(128),
+penalty int8,
+PRIMARY KEY (queue_name, interface)
+) WITHOUT OIDS;
+
+GRANT ALL ON TABLE cdr TO asterisk;
+GRANT ALL ON TABLE extensions_conf TO asterisk;
+GRANT ALL ON TABLE sip_conf TO asterisk;
+GRANT ALL ON TABLE voicemail_users TO asterisk;
+GRANT ALL ON TABLE queue_member_table TO asterisk;
+GRANT ALL ON TABLE queue_table TO asterisk;
+
+
+
diff --git a/trunk/contrib/scripts/retrieve_extensions_from_mysql.pl b/trunk/contrib/scripts/retrieve_extensions_from_mysql.pl
new file mode 100644
index 000000000..ca195cfe5
--- /dev/null
+++ b/trunk/contrib/scripts/retrieve_extensions_from_mysql.pl
@@ -0,0 +1,113 @@
+#!/usr/bin/perl -Tw
+# Use these commands to create the appropriate tables in MySQL
+# If flags is 1 then this record is not included in the output extensions file
+#
+#CREATE TABLE extensions (
+# context CHAR(20) DEFAULT 'default' NOT NULL,
+# extension CHAR(20) NOT NULL,
+# priority INT(2) DEFAULT '1' NOT NULL,
+# application CHAR(20) NOT NULL,
+# args CHAR(50),
+# descr TEXT,
+# flags INT(1) DEFAULT '0' NOT NULL,
+# PRIMARY KEY(context, extension, priority)
+#);
+#
+#CREATE TABLE globals (
+# variable CHAR(20) NOT NULL,
+# value CHAR(50) NOT NULL,
+# PRIMARY KEY(variable, value)
+#);
+
+use DBI;
+################### BEGIN OF CONFIGURATION ####################
+
+# the name of the extensions table
+$table_name = "extensions";
+# the name of the globals table
+$global_table_name = "globals";
+# the path to the extensions.conf file
+# WARNING: this file will be substituted by the output of this program
+$extensions_conf = "/etc/asterisk/extensions.conf";
+# the name of the box the MySQL database is running on
+$hostname = "localhost";
+# the name of the database our tables are kept
+$database = "user";
+# username to connect to the database
+$username = "";
+# password to connect to the database
+$password = "";
+
+################### END OF CONFIGURATION #######################
+
+open EXTEN, ">$extensions_conf" || die "Cannot create/overwrite extensions file: $extensions_conf\n";
+
+$dbh = DBI->connect("dbi:mysql:dbname=$database;host=$hostname", "$username", "$password");
+$statement = "SELECT * from $global_table_name order by variable";
+my $result = $dbh->selectall_arrayref($statement);
+unless ($result) {
+ # check for errors after every single database call
+ print "dbh->selectall_arrayref($statement) failed!\n";
+ print "DBI::err=[$DBI::err]\n";
+ print "DBI::errstr=[$DBI::errstr]\n";
+ exit;
+}
+my @resultSet = @{$result};
+if ( $#resultSet > -1 ) {
+ print EXTEN "[globals]\n";
+ foreach $row (@{ $result }) {
+ my @result = @{ $row };
+ print EXTEN "$result[0] = $result[1]\n";
+ }
+ print EXTEN "\n";
+}
+
+$statement = "SELECT context from $table_name group by context";
+
+$result = $dbh->selectall_arrayref($statement);
+unless ($result) {
+ # check for errors after every single database call
+ print "dbh->selectall_arrayref($statement) failed!\n";
+ print "DBI::err=[$DBI::err]\n";
+ print "DBI::errstr=[$DBI::errstr]\n";
+}
+
+@resultSet = @{$result};
+if ( $#resultSet == -1 ) {
+ print "No extensions defined in $table_name\n";
+ exit;
+}
+
+foreach my $row ( @{ $result } ) {
+ my $context = @{ $row }[0];
+ print EXTEN "[$context]\n";
+ $statement = "SELECT * from $table_name where context='$context' order by extension, priority";
+ my $result = $dbh->selectall_arrayref($statement);
+ unless ($result) {
+ # check for errors after every single database call
+ print "dbh->selectall_arrayref($statement) failed!\n";
+ print "DBI::err=[$DBI::err]\n";
+ print "DBI::errstr=[$DBI::errstr]\n";
+ exit;
+ }
+
+ my @resSet = @{$result};
+ if ( $#resSet == -1 ) {
+ print "no results\n";
+ exit;
+ }
+ foreach my $row ( @{ $result } ) {
+ my @result = @{ $row };
+ if ($result[6] == 0) {
+ print EXTEN "exten => $result[1],$result[2],$result[3]";
+ print EXTEN "($result[4])" if defined $result[4];
+ print EXTEN "\t" if not defined $result[4];
+ print EXTEN "\t; $result[5]" if defined $result[5];
+ print EXTEN "\n";
+ }
+ }
+ print EXTEN "\n";
+}
+
+exit 0;
+
diff --git a/trunk/contrib/scripts/retrieve_extensions_from_sql.pl b/trunk/contrib/scripts/retrieve_extensions_from_sql.pl
new file mode 100644
index 000000000..cf17d0351
--- /dev/null
+++ b/trunk/contrib/scripts/retrieve_extensions_from_sql.pl
@@ -0,0 +1,158 @@
+#!/usr/bin/perl -Tw
+# Author: Peter Nixon <codemonkey@peternixon.net>
+# Date: April 2004
+# Copy Policy: GNU Public Licence Version 2 or later
+# URL: http://www.peternixon.net/code/
+# Supported: PostgreSQL, Oracle, MySQL
+# Copyright: 2004 Peter Nixon <codemonkey@petenixon.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# $Id$
+#
+# Use these commands to create the appropriate SQL tables
+# If flags is 1 then the record is not included in the output extensions file
+#
+#CREATE TABLE extensions (
+# context VARCHAR(20) DEFAULT 'default' NOT NULL,
+# extension VARCHAR(20) NOT NULL,
+# priority INTEGER DEFAULT '1' NOT NULL,
+# application VARCHAR(20) NOT NULL,
+# args VARCHAR(50),
+# descr TEXT,
+# flags BOOLEAN DEFAULT '0' NOT NULL,
+# PRIMARY KEY(context, extension, priority)
+#);
+
+#CREATE TABLE globals (
+# variable VARCHAR(20) NOT NULL,
+# value VARCHAR(50) NOT NULL,
+# PRIMARY KEY(variable, value)
+#);
+
+use strict; # Make sure we write decent perl code
+
+require DBI; # We need database drivers for this thing to work
+
+################### BEGIN OF CONFIGURATION ####################
+
+my $table_name = "extensions"; # name of the extensions table
+my $global_table_name = "globals"; # name of the globals table
+my $extensions_conf = "/etc/asterisk/extensions.conf"; # path to extensions.conf
+# WARNING: this file will be substituted by the output of this program
+my $dbbrand = "Pg"; # Hint: "mysql" or any other Perl DBI driver.
+my $hostname = "localhost"; # The SQL server's hostname or IP
+my $database = "peter"; # the name of the database our tables are kept
+my $username = "peter"; # username to connect to the database
+my $password = ""; # password to connect to the database
+my $verbose = 1; # Verbosity Level (0 - 2)
+
+################### END OF CONFIGURATION #######################
+
+# You should not need to edit anything below here
+my $dbh;
+
+sub db_connect {
+ if ($verbose > 1) { print "DEBUG: Connecting to Database Host: $hostname\n" }
+ if ($hostname eq 'localhost') {
+ if ($verbose > 1) { print "DEBUG: SQL server is on localhost so using UNIX socket instead of network socket.\n" }
+ $dbh = DBI->connect("DBI:$dbbrand:dbname=$database", "$username", "$password")
+ or die "Couldn't connect to database: " . DBI->errstr;
+ }
+ else {
+ $dbh = DBI->connect("DBI:$dbbrand:dbname=$database;host=$hostname", "$username", "$password")
+ or die "Couldn't connect to database: " . DBI->errstr;
+ }
+}
+
+sub db_disconnect {
+ if ($verbose > 1) { print "DEBUG: Disconnecting from Database Host: $hostname\n" }
+ $dbh->disconnect
+ or warn "Disconnection failed: $DBI::errstr\n";
+}
+
+sub get_globals {
+ if ($verbose > 0) { print "Checking Database for [global] variables\n"; }
+ my $sth = $dbh->prepare("SELECT variable, value FROM $global_table_name ORDER BY variable")
+ or die "Couldn't prepare statement: " . $dbh->errstr;
+
+ $sth->execute() # Execute the query
+ or die "Couldn't execute SELECT statement: " . $sth->errstr;
+
+ if ($sth->rows > 0) {
+ print EXTEN "[globals]\n";
+ while (my @global = $sth->fetchrow_array()) {
+ print EXTEN "$global[0] = $global[1]\n";
+ }
+ print EXTEN "\n";
+ } else {
+ print "WARNING: You have no global variables set\n";
+ }
+ $sth->finish;
+}
+
+sub get_contexts {
+ if ($verbose > 0) { print "Checking Database for contexts\n"; }
+ my $sth = $dbh->prepare("SELECT context FROM $table_name GROUP BY context")
+ or die "Couldn't prepare statement: " . $dbh->errstr;
+
+ $sth->execute() # Execute the query
+ or die "Couldn't execute SELECT statement: " . $sth->errstr;
+
+ if ($sth->rows > 0) {
+ while (my @context = $sth->fetchrow_array()) {
+ print EXTEN "[$context[0]]\n";
+ &get_extensions($context[0]);
+ print EXTEN "\n";
+ }
+ print EXTEN "\n";
+ } else {
+ print "WARNING: You have no contexts defined in the $table_name table\n";
+ }
+ $sth->finish;
+}
+
+sub get_extensions {
+ my $context = $_[0]; my @extension;
+ if ($verbose > 0) { print " Checking Database for [$context] extensions\n"; }
+ my $sth = $dbh->prepare("SELECT extension, priority, application, args, descr FROM $table_name WHERE context='$context' AND flags = '0' ORDER BY extension, priority")
+ or die "Couldn't prepare statement: " . $dbh->errstr;
+
+ $sth->execute() # Execute the query
+ or die "Couldn't execute SELECT statement: " . $sth->errstr;
+
+ if ($sth->rows > 0) {
+ while (@extension = $sth->fetchrow_array()) {
+ print EXTEN "exten => $extension[0],$extension[1],$extension[2]";
+ print EXTEN "($extension[3])" if defined $extension[3];
+ print EXTEN " ; $extension[4]" if defined $extension[4];
+ print EXTEN "\n";
+ }
+ } else {
+ print "WARNING: You have no extensions for [$context]\n";
+ }
+ $sth->finish;
+}
+
+
+sub main {
+ open EXTEN, ">$extensions_conf" || die "Cannot create/overwrite extensions file: $extensions_conf\n";
+ &db_connect;
+ &get_globals;
+ &get_contexts;
+ &db_disconnect;
+ close EXTEN; # Close the file handle
+ if ($verbose > 0) { print "New $extensions_conf successfully written.\n"; }
+ return 1;
+}
+
+
+exit &main();
diff --git a/trunk/contrib/scripts/retrieve_sip_conf_from_mysql.pl b/trunk/contrib/scripts/retrieve_sip_conf_from_mysql.pl
new file mode 100644
index 000000000..03395a125
--- /dev/null
+++ b/trunk/contrib/scripts/retrieve_sip_conf_from_mysql.pl
@@ -0,0 +1,93 @@
+#!/usr/bin/perl -Tw
+# Retrieves the sip user/peer entries from the database
+# Use these commands to create the appropriate tables in MySQL
+#
+#CREATE TABLE sip (id INT(11) DEFAULT -1 NOT NULL,keyword VARCHAR(20) NOT NULL,data VARCHAR(50) NOT NULL, flags INT(1) DEFAULT 0 NOT NULL,PRIMARY KEY (id,keyword));
+#
+# if flags = 1 then the records are not included in the output file
+
+use DBI;
+################### BEGIN OF CONFIGURATION ####################
+
+# the name of the extensions table
+$table_name = "sip";
+# the path to the extensions.conf file
+# WARNING: this file will be substituted by the output of this program
+$sip_conf = "/etc/asterisk/sip_additional.conf";
+# the name of the box the MySQL database is running on
+$hostname = "localhost";
+# the name of the database our tables are kept
+$database = "sip";
+# username to connect to the database
+$username = "root";
+# password to connect to the database
+$password = "";
+
+################### END OF CONFIGURATION #######################
+
+$additional = "";
+
+open EXTEN, ">$sip_conf" || die "Cannot create/overwrite extensions file: $sip_conf\n";
+
+$dbh = DBI->connect("dbi:mysql:dbname=$database;host=$hostname", "$username", "$password");
+$statement = "SELECT keyword,data from $table_name where id=0 and keyword <> 'account' and flags <> 1";
+my $result = $dbh->selectall_arrayref($statement);
+unless ($result) {
+ # check for errors after every single database call
+ print "dbh->selectall_arrayref($statement) failed!\n";
+ print "DBI::err=[$DBI::err]\n";
+ print "DBI::errstr=[$DBI::errstr]\n";
+ exit;
+}
+my @resultSet = @{$result};
+if ( $#resultSet > -1 ) {
+ foreach $row (@{ $result }) {
+ my @result = @{ $row };
+ $additional .= $result[0]."=".$result[1]."\n";
+ }
+}
+
+$statement = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
+
+$result = $dbh->selectall_arrayref($statement);
+unless ($result) {
+ # check for errors after every single database call
+ print "dbh->selectall_arrayref($statement) failed!\n";
+ print "DBI::err=[$DBI::err]\n";
+ print "DBI::errstr=[$DBI::errstr]\n";
+}
+
+@resultSet = @{$result};
+if ( $#resultSet == -1 ) {
+ print "No sip accounts defined in $table_name\n";
+ exit;
+}
+
+foreach my $row ( @{ $result } ) {
+ my $account = @{ $row }[0];
+ my $id = @{ $row }[1];
+ print EXTEN "[$account]\n";
+ $statement = "SELECT keyword,data from $table_name where id=$id and keyword <> 'account' and flags <> 1 order by keyword";
+ my $result = $dbh->selectall_arrayref($statement);
+ unless ($result) {
+ # check for errors after every single database call
+ print "dbh->selectall_arrayref($statement) failed!\n";
+ print "DBI::err=[$DBI::err]\n";
+ print "DBI::errstr=[$DBI::errstr]\n";
+ exit;
+ }
+
+ my @resSet = @{$result};
+ if ( $#resSet == -1 ) {
+ print "no results\n";
+ exit;
+ }
+ foreach my $row ( @{ $result } ) {
+ my @result = @{ $row };
+ print EXTEN "$result[0]=$result[1]\n";
+ }
+ print EXTEN "$additional\n";
+}
+
+exit 0;
+
diff --git a/trunk/contrib/scripts/safe_asterisk b/trunk/contrib/scripts/safe_asterisk
new file mode 100644
index 000000000..05e44d895
--- /dev/null
+++ b/trunk/contrib/scripts/safe_asterisk
@@ -0,0 +1,184 @@
+#!/bin/bash
+# vim:textwidth=80:tabstop=4:shiftwidth=4:smartindent:autoindent
+
+CLIARGS="$*" # Grab any args passed to safe_asterisk
+TTY=9 # TTY (if you want one) for Asterisk to run on
+CONSOLE=yes # Whether or not you want a console
+#NOTIFY=ben@alkaloid.net # Who to notify about crashes
+#EXEC=/path/to/somescript # Run this command if Asterisk crashes
+#LOGFILE=/path/to/logfile # Where to place the normal logfile (disabled if blank)
+#SYSLOG=local0 # Which syslog facility to use (disabled if blank)
+MACHINE=`hostname` # To specify which machine has crashed when getting the mail
+DUMPDROP=/tmp
+SLEEPSECS=4
+ASTSBINDIR=__ASTERISK_SBIN_DIR__
+ASTPIDFILE=__ASTERISK_VARRUN_DIR__/asterisk.pid
+
+# comment this line out to have this script _not_ kill all mpg123 processes when
+# asterisk exits
+KILLALLMPG123=1
+
+# run asterisk with this priority
+PRIORITY=0
+
+# set system filemax on supported OSes if this variable is set
+# SYSMAXFILES=262144
+
+# set max files open with ulimit. On linux systems, this will be automatically
+# set to the system's maximum files open devided by two, if not set here.
+# MAXFILES=32768
+
+function message() {
+ echo "$1" >&2
+ if [ "$SYSLOG" != "" ]; then
+ logger -p "${SYSLOG}.warn" -t safe_asterisk[$$] "$1"
+ fi
+ if [ "$LOGFILE" != "" ]; then
+ echo "safe_asterisk[$$]: $1" >> "$LOGFILE"
+ fi
+}
+
+# since we're going to change priority and open files limits, we need to be
+# root. if running asterisk as other users, pass that to asterisk on the command
+# line.
+# if we're not root, fall back to standard everything.
+if [ `id -u` != 0 ]
+then
+ echo "Oops. I'm not root. Falling back to standard prio and file max." >&2
+ echo "This is NOT suitable for large systems." >&2
+ PRIORITY=0
+ message "safe_asterisk was started by `id -n` (uid `id -u`)."
+else
+ if `echo $OSTYPE | grep linux 2>&1 > /dev/null `
+ then
+ # maximum number of open files is set to the system maximum divided by two if
+ # MAXFILES is not set.
+ if [ "$MAXFILES" = "" ]
+ then
+ # just check if file-max is readable
+ if [ -r /proc/sys/fs/file-max ]
+ then
+ MAXFILES=$(( `cat /proc/sys/fs/file-max` / 2 ))
+ fi
+ fi
+ SYSCTL_MAXFILES="fs.file-max"
+ elif `echo $OSTYPE | grep darwin 2>&1 > /dev/null `
+ then
+ SYSCTL_MAXFILES="kern.maxfiles"
+ fi
+
+
+ if [ "$SYSMAXFILES" != "" ]
+ then
+ if [ "$SYSCTL_MAXFILES" != "" ]
+ then
+ sysctl -w $SYSCTL_MAXFILES=$SYSMAXFILES
+ fi
+ fi
+
+ # set the process's filemax to whatever set above
+ ulimit -n $MAXFILES
+
+fi
+
+#
+# Let Asterisk dump core
+#
+ulimit -c unlimited
+
+#
+# Don't fork when running "safely"
+#
+ASTARGS=""
+if [ "$TTY" != "" ]; then
+ if [ -c /dev/tty${TTY} ]; then
+ TTY=tty${TTY}
+ elif [ -c /dev/vc/${TTY} ]; then
+ TTY=vc/${TTY}
+ else
+ message "Cannot find specified TTY (${TTY})"
+ exit 1
+ fi
+ ASTARGS="${ASTARGS} -vvvg"
+ if [ "$CONSOLE" != "no" ]; then
+ ASTARGS="${ASTARGS} -c"
+ fi
+fi
+if [ ! -w ${DUMPDROP} ]; then
+ message "Cannot write to ${DUMPDROP}"
+ exit 1
+fi
+
+#
+# Don't die if stdout/stderr can't be written to
+#
+trap '' PIPE
+
+#
+# Run scripts to set any environment variables or do any other system-specific setup needed
+#
+
+if [ -d /etc/asterisk/startup.d ]; then
+ for script in /etc/asterisk/startup.d/*.sh; do
+ if [ -x ${script} ]; then
+ source ${script}
+ fi
+ done
+fi
+
+run_asterisk()
+{
+ while :; do
+
+ if [ "$TTY" != "" ]; then
+ cd /tmp
+ stty sane < /dev/${TTY}
+ nice -n $PRIORITY ${ASTSBINDIR}/asterisk -f ${CLIARGS} ${ASTARGS} >& /dev/${TTY} < /dev/${TTY}
+ else
+ cd /tmp
+ nice -n $PRIORITY ${ASTSBINDIR}/asterisk -f ${CLIARGS} ${ASTARGS}
+ fi
+ EXITSTATUS=$?
+ message "Asterisk ended with exit status $EXITSTATUS"
+ if [ "$EXITSTATUS" = "0" ]; then
+ # Properly shutdown....
+ message "Asterisk shutdown normally."
+ exit 0
+ elif [ $EXITSTATUS -gt 128 ]; then
+ let EXITSIGNAL=EXITSTATUS-128
+ echo "Asterisk exited on signal $EXITSIGNAL."
+ if [ "$NOTIFY" != "" ]; then
+ echo "Asterisk on $MACHINE exited on signal $EXITSIGNAL. Might want to take a peek." | \
+ mail -s "Asterisk Died" $NOTIFY
+ message "Exited on signal $EXITSIGNAL"
+ fi
+ if [ "$EXEC" != "" ]; then
+ $EXEC
+ fi
+
+ PID=`cat ${ASTPIDFILE}`
+ if [ -f /tmp/core.${PID} ]; then
+ mv /tmp/core.${PID} ${DUMPDROP}/core.`hostname`-`date -Iseconds` &
+ elif [ -f /tmp/core ]; then
+ mv /tmp/core ${DUMPDROP}/core.`hostname`-`date -Iseconds` &
+ fi
+ else
+ message "Asterisk died with code $EXITSTATUS."
+
+ PID=`cat ${ASTPIDFILE}`
+ if [ -f /tmp/core.${PID} ]; then
+ mv /tmp/core.${PID} ${DUMPDROP}/core.`hostname`-`date -Iseconds` &
+ elif [ -f /tmp/core ]; then
+ mv /tmp/core ${DUMPDROP}/core.`hostname`-`date -Iseconds` &
+ fi
+ fi
+ message "Automatically restarting Asterisk."
+ sleep $SLEEPSECS
+ if [ $KILLALLMPG123 ]
+ then
+ killall -9 mpg123
+ fi
+ done
+}
+
+run_asterisk &
diff --git a/trunk/contrib/scripts/safe_asterisk.8 b/trunk/contrib/scripts/safe_asterisk.8
new file mode 100644
index 000000000..ebd95142a
--- /dev/null
+++ b/trunk/contrib/scripts/safe_asterisk.8
@@ -0,0 +1,69 @@
+.TH SAFE_ASTERISK 8 "Jun 30th, 2005" "Asterisk" "Linux Programmer's Manual"
+.SH NAME
+.B safe_asterisk
+\(em A wrapper to run the asterisk executable in a loop
+.SH SYNOPSIS
+.PP
+.B safe_asterisk
+.I [ asterisk_params ]
+
+.SH DESCRIPTION
+.B safe_asterisk
+is a script that runs asterisk in a loop, which can be useful if you
+fear asterisk may crash.
+
+The script does not run in the background like a standard service. Rather,
+it runs in its own linux virtual console (9, by default).
+It also uses the option '-c' of asterisk(8) to avoid detaching asterisk
+from that terminal.
+
+safe_asterisk also runs asterisk with unlimited core file size, and thus
+asterisk will dump core in case of a crash.
+
+To get a "picture" of console 9, from another terminal (e.g: from a
+remote shell session) you can use:
+
+ screendump 9
+
+The init script of the Debian package should be able to run safe_asterisk
+as the asterisk service, if so configured. See coments in
+/etc/default/asterisk
+
+.SH FILES
+.B /tmp
+.RS
+safe_asterisk runs in that directory, rather than in / as usual.
+.RE
+
+.B /tmp/core
+.RS
+If core files were generated there, they may be
+.RE
+
+.B /etc/asterisk/startup.d
+.RS
+Files in this directory will be 'source'd by the safe_asterisk script before
+it starts Asterisk proper, allowing them to set additional environment variables
+or run any other steps that are needed for your system.
+.RE
+
+.SH BUGS
+While showing the output on a console is useful, using screen(1) as
+the terminal may be better.
+
+The script does not read configuration from standard location under /etc
+
+It uses fixed locations under /tmp , and thus may be exposed to a
+symlink attacks.
+
+.SH SEE ALSO
+asterisk(8), screendump(9)
+
+.SH "AUTHOR"
+This manual page was written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the GNU General Public License, Version 2 any
+later version published by the Free Software Foundation.
+
+On Debian systems, the complete text of the GNU General Public
+License can be found in /usr/share/common-licenses/GPL.
diff --git a/trunk/contrib/scripts/safe_asterisk_restart b/trunk/contrib/scripts/safe_asterisk_restart
new file mode 100644
index 000000000..81783149a
--- /dev/null
+++ b/trunk/contrib/scripts/safe_asterisk_restart
@@ -0,0 +1,110 @@
+#!/bin/bash
+# vim:textwidth=80:tabstop=4:shiftwidth=4:smartindent
+#
+# this scripts prompts the user thrice, then tells asterisk to please shut down,
+# then kills asterisk and related processes with SIGTERM, then kills asterisk
+# and related processes with SIGKILL, and then starts asterisk with
+# safe_asterisk. Three arguments are currently supported, --no-countdown,
+# --no-prompt and --no-stop-now-first
+
+LOGFILE=/var/log/asterisk/safe_asterisk_restart.log
+ASTERISK=/usr/sbin/asterisk
+SAFE_ASTERISK=/usr/sbin/safe_asterisk
+
+DELAY=1 # Seconds between steps in countdown
+COUNTDOWN_FROM=5 # Steps to count down
+DO_COUNTDOWN=1 # Should I do a countdown before restarting asterisk?
+DO_PROMPT=1 # Should I prompt the user?
+TRY_STOP_NOW_FIRST=1 # Attempt a 'stop now' before killing processes. Note
+ # that this might make this script hang if asterisk
+ # can't respond to the command.
+
+# processes to kill. Please list all AGI scripts here as well as the asterisk
+# processes, since asterisk may leave them unkilled.
+PROCVICTIMS="safe_asterisk asterisk mpg123"
+
+# helper functions
+# die ["string to print"]
+function die {
+ if [[ "$1" != "" ]]; then
+ echo $1
+ else
+ echo "ok. no harm done..."
+ fi
+ exit
+}
+
+# docmd "string to print" "cmd"
+function docmd {
+ printf "$1..."
+ `$2 >> $LOGFILE 2>&1`
+ RETCODE=$?
+ sleep $DELAY
+ if [[ "$RETCODE" == "0" ]]; then
+ echo " OK"
+ else
+ echo " FAILED"
+ fi
+}
+
+# prompt "string" "positive answer"
+function prompt {
+ printf "$1"
+ read answer
+ if [[ "$answer" != "$2" ]]; then
+ die
+ fi
+}
+
+# countdown secs
+function countdown {
+ echo -n "$1 "
+ if [[ $1 > 0 ]]; then
+ sleep 1
+ countdown $[ $1 - 1 ]
+ else
+ echo "boom!"
+ fi
+}
+
+# am I really root?
+if [[ "$UID" != "0" ]]; then
+ echo "Sorry, only root can do this." >&2
+ exit;
+fi
+
+echo "`date`: $0 invoked" >> $LOGFILE
+
+# bash
+for i
+do
+ if [[ "$i" == "--no-countdown" ]]
+ then
+ unset DO_COUNTDOWN
+ fi
+ if [[ "$i" == "--no-prompt" ]]
+ then
+ unset DO_PROMPT
+ fi
+ if [[ "$i" == "--no-stop-now-first" ]]
+ then
+ unset TRY_STOP_NOW_FIRST
+ fi
+done
+
+[[ $DO_PROMPT ]] && prompt "Are you sure you want to restart asterisk? (yes/no)? " "yes"
+[[ $DO_PROMPT ]] && prompt "Really sure? (yes/no)? " "yes"
+[[ $DO_PROMPT ]] && prompt "Absolutely positive? (YES/no)? " "YES"
+
+[[ $DO_COUNTDOWN ]] && echo "OK, I'll do it, but if you're not sure about this, press ctrl+c now."
+[[ $DO_COUNTDOWN ]] && countdown $COUNTDOWN_FROM
+
+# doing the dirty work
+[[ $TRY_STOP_NOW_FIRST ]] && docmd "Asking asterisk kindly to shutdown" "$ASTERISK -rx 'stop now'"
+docmd "Sending asterisk processes the TERM signal" "killall -15 $PROCVICTIMS"
+docmd "Sending asterisk processes KILL signal" "killall -9 $PROCVICTIMS"
+docmd "Starting safe_asterisk" "$SAFE_ASTERISK"
+for i in $PROCVICTIMS
+do
+ ps axf | grep -w $i | grep -v grep
+done
diff --git a/trunk/contrib/scripts/sip-friends.sql b/trunk/contrib/scripts/sip-friends.sql
new file mode 100644
index 000000000..15d7cb393
--- /dev/null
+++ b/trunk/contrib/scripts/sip-friends.sql
@@ -0,0 +1,14 @@
+#
+# Table structure for table `sipfriends`
+#
+
+CREATE TABLE `sipfriends` (
+ `name` varchar(40) NOT NULL default '',
+ `secret` varchar(40) NOT NULL default '',
+ `context` varchar(40) NOT NULL default '',
+ `username` varchar(40) default '',
+ `ipaddr` varchar(20) NOT NULL default '',
+ `port` int(6) NOT NULL default '0',
+ `regseconds` int(11) NOT NULL default '0',
+ PRIMARY KEY (`name`)
+) TYPE=MyISAM;
diff --git a/trunk/contrib/scripts/vmail.cgi b/trunk/contrib/scripts/vmail.cgi
new file mode 100644
index 000000000..a87fc1e84
--- /dev/null
+++ b/trunk/contrib/scripts/vmail.cgi
@@ -0,0 +1,1099 @@
+#!/usr/bin/perl
+#
+# Web based Voicemail for Asterisk
+#
+# Copyright (C) 2002, Linux Support Services, Inc.
+#
+# Distributed under the terms of the GNU General Public License
+#
+# Written by Mark Spencer <markster@linux-support.net>
+#
+# (icky, I know.... if you know better perl please help!)
+#
+#
+# Synchronization added by GDS Partners (www.gdspartners.com)
+# Stojan Sljivic (stojan.sljivic@gdspartners.com)
+#
+use CGI qw/:standard/;
+use Carp::Heavy;
+use CGI::Carp qw(fatalsToBrowser);
+use DBI;
+use Fcntl qw ( O_WRONLY O_CREAT O_EXCL );
+use Time::HiRes qw ( usleep );
+
+$context=""; # Define here your by default context (so you dont need to put voicemail@context in the login
+
+@validfolders = ( "INBOX", "Old", "Work", "Family", "Friends", "Cust1", "Cust2", "Cust3", "Cust4", "Cust5" );
+
+%formats = (
+ "wav" => {
+ name => "Uncompressed WAV",
+ mime => "audio/x-wav",
+ pref => 1
+ },
+ "WAV" => {
+ name => "GSM Compressed WAV",
+ mime => "audio/x-wav",
+ pref => 2
+ },
+ "gsm" => {
+ name => "Raw GSM Audio",
+ mime => "audio/x-gsm",
+ pref => 3
+ }
+);
+
+$astpath = "/_asterisk";
+
+$stdcontainerstart = "<table align=center width=600><tr><td>\n";
+$footer = "<hr><font size=-1><a href=\"http://www.asterisk.org\">The Asterisk Open Source PBX</a> Copyright 2004, <a href=\"http://www.digium.com\">Digium, Inc.</a></a>";
+$stdcontainerend = "</td></tr><tr><td align=right>$footer</td></tr></table>\n";
+
+sub lock_path() {
+
+ my($path) = @_;
+ my $rand;
+ my $rfile;
+ my $start;
+ my $res;
+
+ $rand = rand 99999999;
+ $rfile = "$path/.lock-$rand";
+
+ sysopen(RFILE, $rfile, O_WRONLY | O_CREAT | O_EXCL, 0666) or return -1;
+ close(RFILE);
+
+ $res = link($rfile, "$path/.lock");
+ $start = time;
+ if ($res == 0) {
+ while (($res == 0) && (time - $start <= 5)) {
+ $res = link($rfile, "$path/.lock");
+ usleep(1);
+ }
+ }
+ unlink($rfile);
+
+ if ($res == 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+sub unlock_path() {
+
+ my($path) = @_;
+
+ unlink("$path/.lock");
+}
+
+sub untaint() {
+
+ my($data) = @_;
+
+ if ($data =~ /^([-\@\w.]+)$/) {
+ $data = $1;
+ } else {
+ die "Security violation.";
+ }
+
+ return $data;
+}
+
+sub login_screen() {
+ print header;
+ my ($message) = @_;
+ print <<_EOH;
+
+<TITLE>Asterisk Web-Voicemail</TITLE>
+<BODY BGCOLOR="white">
+$stdcontainerstart
+<FORM METHOD="post">
+<input type=hidden name="action" value="login">
+<table align=center>
+<tr><td valign=top align=center rowspan=6><img align=center src="$astpath/animlogo.gif"></td></tr>
+<tr><td align=center colspan=2><font size=+2>Comedian Mail Login</font></td></tr>
+<tr><td align=center colspan=2><font size=+1>$message</font></td></tr>
+<tr><td>Mailbox:</td><td><input type=text name="mailbox"></td></tr>
+<tr><td>Password:</td><td><input type=password name="password"></td></tr>
+<tr><td align=right colspan=2><input value="Login" type=submit></td></tr>
+<input type=hidden name="context" value="$context">
+</table>
+</FORM>
+$stdcontainerend
+</BODY>\n
+_EOH
+
+}
+
+sub check_login()
+{
+ local ($filename, $startcat) = @_;
+ local ($mbox, $context) = split(/\@/, param('mailbox'));
+ local $pass = param('password');
+ local $category = $startcat;
+ local @fields;
+ local $tmp;
+ local (*VMAIL);
+ if (!$category) {
+ $category = "general";
+ }
+ if (!$context) {
+ $context = param('context');
+ }
+ if (!$context) {
+ $context = "default";
+ }
+ if (!$filename) {
+ $filename = "/etc/asterisk/voicemail.conf";
+ }
+# print header;
+# print "Including <h2>$filename</h2> while in <h2>$category</h2>...\n";
+ open(VMAIL, "<$filename") || die("Bleh, no $filename");
+ while(<VMAIL>) {
+ chomp;
+ if (/include\s\"([^\"]+)\"$/) {
+ ($tmp, $category) = &check_login("/etc/asterisk/$1", $category);
+ if (length($tmp)) {
+# print "Got '$tmp'\n";
+ return ($tmp, $category);
+ }
+ } elsif (/\[(.*)\]/) {
+ $category = $1;
+ } elsif ($category eq "general") {
+ if (/([^\s]+)\s*\=\s*(.*)/) {
+ if ($1 eq "dbname") {
+ $dbname = $2;
+ } elsif ($1 eq "dbpass") {
+ $dbpass = $2;
+ } elsif ($1 eq "dbhost") {
+ $dbhost = $2;
+ } elsif ($1 eq "dbuser") {
+ $dbuser = $2;
+ }
+ }
+ if ($dbname and $dbpass and $dbhost and $dbuser) {
+
+ # db variables are present. Use db for authentication.
+ my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
+ my $sth = $dbh->prepare(qq{select fullname,context from voicemail where mailbox='$mbox' and password='$pass' and context='$context'});
+ $sth->execute();
+ if (($fullname, $category) = $sth->fetchrow_array()) {;
+ return ($fullname ? $fullname : "Extension $mbox in $context",$category);
+ }
+ }
+ } elsif (($category ne "general") && ($category ne "zonemessages")) {
+ if (/([^\s]+)\s*\=\>?\s*(.*)/) {
+ @fields = split(/\,\s*/, $2);
+# print "<p>Mailbox is $1\n";
+ if (($mbox eq $1) && (($pass eq $fields[0]) || ("-${pass}" eq $fields[0])) && ($context eq $category)) {
+ return ($fields[1] ? $fields[1] : "Extension $mbox in $context", $category);
+ }
+ }
+ }
+ }
+ close(VMAIL);
+ return ("", $category);
+}
+
+sub validmailbox()
+{
+ local ($context, $mbox, $filename, $startcat) = @_;
+ local $category = $startcat;
+ local @fields;
+ local (*VMAIL);
+ if (!$context) {
+ $context = param('context');
+ }
+ if (!$context) {
+ $context = "default";
+ }
+ if (!$filename) {
+ $filename = "/etc/asterisk/voicemail.conf";
+ }
+ if (!$category) {
+ $category = "general";
+ }
+ open(VMAIL, "<$filename") || die("Bleh, no $filename");
+ while(<VMAIL>) {
+ chomp;
+ if (/include\s\"([^\"]+)\"$/) {
+ ($tmp, $category) = &validmailbox($mbox, $context, "/etc/asterisk/$1");
+ if ($tmp) {
+ return ($tmp, $category);
+ }
+ } elsif (/\[(.*)\]/) {
+ $category = $1;
+ } elsif ($category eq "general") {
+ if (/([^\s]+)\s*\=\s*(.*)/) {
+ if ($1 eq "dbname") {
+ $dbname = $2;
+ } elsif ($1 eq "dbpass") {
+ $dbpass = $2;
+ } elsif ($1 eq "dbhost") {
+ $dbhost = $2;
+ } elsif ($1 eq "dbuser") {
+ $dbuser = $2;
+ }
+ }
+ if ($dbname and $dbpass and $dbhost and $dbuser) {
+
+ # db variables are present. Use db for authentication.
+ my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
+ my $sth = $dbh->prepare(qq{select fullname,context from voicemail where mailbox='$mbox' and password='$pass' and context='$context'});
+ $sth->execute();
+ if (($fullname, $context) = $sth->fetchrow_array()) {;
+ return ($fullname ? $fullname : "unknown", $category);
+ }
+ }
+ } elsif (($category ne "general") && ($category ne "zonemessages") && ($category eq $context)) {
+ if (/([^\s]+)\s*\=\>?\s*(.*)/) {
+ @fields = split(/\,\s*/, $2);
+ if (($mbox eq $1) && ($context eq $category)) {
+ return ($fields[2] ? $fields[2] : "unknown", $category);
+ }
+ }
+ }
+ }
+ return ("", $category);
+}
+
+sub mailbox_options()
+{
+ local($context, $current, $filename, $category) = @_;
+ local (*VMAIL);
+ local $tmp2;
+ local $tmp;
+ if (!$filename) {
+ $filename = "/etc/asterisk/voicemail.conf";
+ }
+ if (!$category) {
+ $category = "general";
+ }
+# print header;
+# print "Including <h2>$filename</h2> while in <h2>$category</h2>...\n";
+ open(VMAIL, "<$filename") || die("Bleh, no voicemail.conf");
+ while(<VMAIL>) {
+ chomp;
+ s/\;.*$//;
+ if (/include\s\"([^\"]+)\"$/) {
+ ($tmp2, $category) = &mailbox_options($context, $current, "/etc/asterisk/$1", $category);
+# print "Got '$tmp2'...\n";
+ $tmp .= $tmp2;
+ } elsif (/\[(.*)\]/) {
+ $category = $1;
+ } elsif ($category eq "general") {
+ if (/([^\s]+)\s*\=\s*(.*)/) {
+ if ($1 eq "dbname") {
+ $dbname = $2;
+ } elsif ($1 eq "dbpass") {
+ $dbpass = $2;
+ } elsif ($1 eq "dbhost") {
+ $dbhost = $2;
+ } elsif ($1 eq "dbuser") {
+ $dbuser = $2;
+ }
+ }
+ if ($dbname and $dbpass and $dbhost and $dbuser) {
+
+ # db variables are present. Use db for authentication.
+ my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
+ my $sth = $dbh->prepare(qq{select mailbox,fullname,context from voicemail where context='$context' order by mailbox});
+ $sth->execute();
+ while (($mailbox, $fullname, $category) = $sth->fetchrow_array()) {
+ $text = $mailbox;
+ if ($fullname) {
+ $text .= " (".$fullname.")";
+ }
+ if ($mailbox eq $current) {
+ $tmp .= "<OPTION SELECTED>$text</OPTION>\n";
+ } else {
+ $tmp .= "<OPTION>$text</OPTION>\n";
+ }
+ }
+ return ($tmp, $category);
+ }
+ } elsif (($category ne "general") && ($category ne "zonemessages")) {
+ if (/([^\s]+)\s*\=\>?\s*(.*)/) {
+ @fields = split(/\,\s*/, $2);
+ $text = "$1";
+ if ($fields[1]) {
+ $text .= " ($fields[1])";
+ }
+ if ($1 eq $current) {
+ $tmp .= "<OPTION SELECTED>$text</OPTION>\n";
+ } else {
+ $tmp .= "<OPTION>$text</OPTION>\n";
+ }
+
+ }
+ }
+ }
+ close(VMAIL);
+ return ($tmp, $category);
+}
+
+sub mailbox_list()
+{
+ local ($name, $context, $current) = @_;
+ local $tmp;
+ local $text;
+ local $tmp;
+ local $opts;
+ if (!$context) {
+ $context = "default";
+ }
+ $tmp = "<SELECT name=\"$name\">\n";
+ ($opts) = &mailbox_options($context, $current);
+ $tmp .= $opts;
+ $tmp .= "</SELECT>\n";
+
+}
+
+sub msgcount()
+{
+ my ($context, $mailbox, $folder) = @_;
+ my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder";
+ if (opendir(DIR, $path)) {
+ my @msgs = grep(/^msg....\.txt$/, readdir(DIR));
+ closedir(DIR);
+ return sprintf "%d", $#msgs + 1;
+ }
+ return "0";
+}
+
+sub msgcountstr()
+{
+ my ($context, $mailbox, $folder) = @_;
+ my $count = &msgcount($context, $mailbox, $folder);
+ if ($count > 1) {
+ "$count messages";
+ } elsif ($count > 0) {
+ "$count message";
+ } else {
+ "no messages";
+ }
+}
+sub messages()
+{
+ my ($context, $mailbox, $folder) = @_;
+ my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder";
+ if (opendir(DIR, $path)) {
+ my @msgs = sort grep(/^msg....\.txt$/, readdir(DIR));
+ closedir(DIR);
+ return map { s/^msg(....)\.txt$/$1/; $_ } @msgs;
+ }
+ return ();
+}
+
+sub getcookie()
+{
+ my ($var) = @_;
+ return cookie($var);
+}
+
+sub makecookie()
+{
+ my ($format) = @_;
+ cookie(-name => "format", -value =>["$format"], -expires=>"+1y");
+}
+
+sub getfields()
+{
+ my ($context, $mailbox, $folder, $msg) = @_;
+ my $fields;
+ if (open(MSG, "</var/spool/asterisk/voicemail/$context/$mailbox/$folder/msg${msg}.txt")) {
+ while(<MSG>) {
+ s/\#.*$//g;
+ if (/^(\w+)\s*\=\s*(.*)$/) {
+ $fields->{$1} = $2;
+ }
+ }
+ close(MSG);
+ $fields->{'msgid'} = $msg;
+ } else { print "<BR>Unable to open '$msg' in '$mailbox', '$folder'\n<B>"; }
+ $fields;
+}
+
+sub message_prefs()
+{
+ my ($nextaction, $msgid) = @_;
+ my $folder = param('folder');
+ my $mbox = param('mailbox');
+ my $context = param('context');
+ my $passwd = param('password');
+ my $format = param('format');
+ if (!$format) {
+ $format = &getcookie('format');
+ }
+ print header;
+ print <<_EOH;
+
+<TITLE>Asterisk Web-Voicemail: Preferences</TITLE>
+<BODY BGCOLOR="white">
+$stdcontainerstart
+<FORM METHOD="post">
+<table width=100% align=center>
+<tr><td align=right colspan=3><font size=+2>Web Voicemail Preferences</font></td></tr>
+<tr><td align=left><font size=+1>Preferred&nbsp;Audio&nbsp;Format:</font></td><td colspan=2></td></tr>
+_EOH
+
+foreach $fmt (sort { $formats{$a}->{'pref'} <=> $formats{$b}->{'pref'} } keys %formats) {
+ my $clicked = "checked" if $fmt eq $format;
+ print "<tr><td></td><td align=left><input type=radio name=\"format\" $clicked value=\"$fmt\"></td><td width=100%>&nbsp;$formats{$fmt}->{name}</td></tr>\n";
+}
+
+print <<_EOH;
+<tr><td align=right colspan=3><input type=submit value="save settings..."></td></tr>
+</table>
+<input type=hidden name="action" value="$nextaction">
+<input type=hidden name="folder" value="$folder">
+<input type=hidden name="mailbox" value="$mbox">
+<input type=hidden name="context" value="$context">
+<input type=hidden name="password" value="$passwd">
+<input type=hidden name="msgid" value="$msgid">
+$stdcontainerend
+</BODY>\n
+_EOH
+
+}
+
+sub message_play()
+{
+ my ($message, $msgid) = @_;
+ my $folder = param('folder');
+ my ($mbox, $context) = split(/\@/, param('mailbox'));
+ my $passwd = param('password');
+ my $format = param('format');
+
+ my $fields;
+ if (!$context) {
+ $context = param('context');
+ }
+ if (!$context) {
+ $context = "default";
+ }
+
+ my $folders = &folder_list('newfolder', $context, $mbox, $folder);
+ my $mailboxes = &mailbox_list('forwardto', $context, $mbox);
+ if (!$format) {
+ $format = &getcookie('format');
+ }
+ if (!$format) {
+ &message_prefs("play", $msgid);
+ } else {
+ print header(-cookie => &makecookie($format));
+ $fields = &getfields($context, $mbox, $folder, $msgid);
+ if (!$fields) {
+ print "<BR>Bah!\n";
+ return;
+ }
+ my $duration = $fields->{'duration'};
+ if ($duration) {
+ $duration = sprintf "%d:%02d", $duration/60, $duration % 60;
+ } else {
+ $duration = "<i>Unknown</i>";
+ }
+ print <<_EOH;
+
+<TITLE>Asterisk Web-Voicemail: $folder Message $msgid</TITLE>
+<BODY BGCOLOR="white">
+$stdcontainerstart
+<FORM METHOD="post">
+<table width=100% align=center>
+<tr><td align=right colspan=3><font size=+1>$folder Message $msgid</font></td></tr>
+_EOH
+
+ print <<_EOH;
+<tr><td align=center colspan=3>
+<table>
+ <tr><td colspan=2 align=center><font size=+1>$folder <b>$msgid</b></font></td></tr>
+ <tr><td><b>Message:</b></td><td>$msgid</td></tr>\n
+ <tr><td><b>Mailbox:</b></td><td>$mbox\@$context</td></tr>\n
+ <tr><td><b>Folder:</b></td><td>$folder</td></tr>\n
+ <tr><td><b>From:</b></td><td>$fields->{callerid}</td></tr>\n
+ <tr><td><b>Duration:</b></td><td>$duration</td></tr>\n
+ <tr><td><b>Original Date:</b></td><td>$fields->{origdate}</td></tr>\n
+ <tr><td><b>Original Mailbox:</b></td><td>$fields->{origmailbox}</td></tr>\n
+ <tr><td><b>Caller Channel:</b></td><td>$fields->{callerchan}</td></tr>\n
+ <tr><td align=center colspan=2>
+ <input name="action" type=submit value="index">&nbsp;
+ <input name="action" type=submit value="delete ">&nbsp;
+ <input name="action" type=submit value="forward to -> ">&nbsp;
+ $mailboxes&nbsp;
+ <input name="action" type=submit value="save to ->">
+ $folders&nbsp;
+ <input name="action" type=submit value="play ">
+ <input name="action" type=submit value="download">
+</td></tr>
+<tr><td colspan=2 align=center>
+<embed width=400 height=40 src="vmail.cgi?action=audio&folder=$folder&mailbox=$mbox&context=$context&password=$passwd&msgid=$msgid&format=$format&dontcasheme=$$.$format" autostart=yes loop=false></embed>
+</td></tr></table>
+</td></tr>
+</table>
+<input type=hidden name="folder" value="$folder">
+<input type=hidden name="mailbox" value="$mbox">
+<input type=hidden name="context" value="$context">
+<input type=hidden name="password" value="$passwd">
+<input type=hidden name="msgid" value="$msgid">
+$stdcontainerend
+</BODY>\n
+_EOH
+ }
+}
+
+sub message_audio()
+{
+ my ($forcedownload) = @_;
+ my $folder = &untaint(param('folder'));
+ my $msgid = &untaint(param('msgid'));
+ my $mailbox = &untaint(param('mailbox'));
+ my $context = &untaint(param('context'));
+ my $format = param('format');
+ if (!$format) {
+ $format = &getcookie('format');
+ }
+ &untaint($format);
+
+ my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder/msg${msgid}.$format";
+
+ $msgid =~ /^\d\d\d\d$/ || die("Msgid Liar ($msgid)!");
+ grep(/^${format}$/, keys %formats) || die("Format Liar ($format)!");
+
+ # Mailbox and folder are already verified
+ if (open(AUDIO, "<$path")) {
+ $size = -s $path;
+ $|=1;
+ if ($forcedownload) {
+ print header(-type=>$formats{$format}->{'mime'}, -Content_length => $size, -attachment => "msg${msgid}.$format");
+ } else {
+ print header(-type=>$formats{$format}->{'mime'}, -Content_length => $size);
+ }
+
+ while(($amt = sysread(AUDIO, $data, 4096)) > 0) {
+ syswrite(STDOUT, $data, $amt);
+ }
+ close(AUDIO);
+ } else {
+ die("Hrm, can't seem to open $path\n");
+ }
+}
+
+sub message_index()
+{
+ my ($folder, $message) = @_;
+ my ($mbox, $context) = split(/\@/, param('mailbox'));
+ my $passwd = param('password');
+ my $message2;
+ my $msgcount;
+ my $hasmsg;
+ my $newmessages, $oldmessages;
+ my $format = param('format');
+ if (!$format) {
+ $format = &getcookie('format');
+ }
+ if (!$context) {
+ $context = param('context');
+ }
+ if (!$context) {
+ $context = "default";
+ }
+ if ($folder) {
+ $msgcount = &msgcountstr($context, $mbox, $folder);
+ $message2 = "&nbsp;&nbsp;&nbsp;Folder '$folder' has " . &msgcountstr($context, $mbox, $folder);
+ } else {
+ $newmessages = &msgcount($context, $mbox, "INBOX");
+ $oldmessages = &msgcount($context, $mbox, "Old");
+ if (($newmessages > 0) || ($oldmessages < 1)) {
+ $folder = "INBOX";
+ } else {
+ $folder = "Old";
+ }
+ $message2 = "You have";
+ if ($newmessages > 0) {
+ $message2 .= " <b>$newmessages</b> NEW";
+ if ($oldmessages > 0) {
+ $message2 .= "and <b>$oldmessages</b> OLD";
+ if ($oldmessages != 1) {
+ $message2 .= " messages.";
+ } else {
+ $message2 .= "message.";
+ }
+ } else {
+ if ($newmessages != 1) {
+ $message2 .= " messages.";
+ } else {
+ $message2 .= " message.";
+ }
+ }
+ } else {
+ if ($oldmessages > 0) {
+ $message2 .= " <b>$oldmessages</b> OLD";
+ if ($oldmessages != 1) {
+ $message2 .= " messages.";
+ } else {
+ $message2 .= " message.";
+ }
+ } else {
+ $message2 .= " <b>no</b> messages.";
+ }
+ }
+ }
+
+ my $folders = &folder_list('newfolder', $context, $mbox, $folder);
+ my $cfolders = &folder_list('changefolder', $context, $mbox, $folder);
+ my $mailboxes = &mailbox_list('forwardto', $context, $mbox);
+ print header(-cookie => &makecookie($format));
+ print <<_EOH;
+
+<TITLE>Asterisk Web-Voicemail: $mbox\@$context $folder</TITLE>
+<BODY BGCOLOR="white">
+$stdcontainerstart
+<FORM METHOD="post">
+<table width=100% align=center>
+<tr><td align=center colspan=2><font size=+2><I>$message</I></font></td></tr>
+<tr><td align=right colspan=2><font size=+1><b>$folder</b> Messages</font> <input type=submit name="action" value="change to ->">$cfolders</td></tr>
+<tr><td align=left colspan=2><font size=+1>$message2</font></td></tr>
+</table>
+<table width=100% align=center cellpadding=0 cellspacing=0>
+_EOH
+
+print "<tr><td>&nbsp;Msg</td><td>&nbsp;From</td><td>&nbsp;Duration</td><td>&nbsp;Date</td><td>&nbsp;</td></tr>\n";
+print "<tr><td><hr></td><td><hr></td><td><hr></td><td><hr></td><td></td></tr>\n";
+foreach $msg (&messages($context, $mbox, $folder)) {
+
+ $fields = &getfields($context, $mbox, $folder, $msg);
+ $duration = $fields->{'duration'};
+ if ($duration) {
+ $duration = sprintf "%d:%02d", $duration / 60, $duration % 60;
+ } else {
+ $duration = "<i>Unknown</i>";
+ }
+ $hasmsg++;
+ print "<tr><td><input type=checkbox name=\"msgselect\" value=\"$msg\">&nbsp;<b>$msg</b></td><td>$fields->{'callerid'}</td><td>$duration</td><td>$fields->{'origdate'}</td><td><input name='play$msg' alt=\"Play message $msg\" border=0 type=image align=left src=\"$astpath/play.gif\"></td></tr>\n";
+
+}
+if (!$hasmsg) {
+ print "<tr><td colspan=4 align=center><P><b><i>No messages</i></b><P></td></tr>";
+}
+
+print <<_EOH;
+</table>
+<table width=100% align=center>
+<tr><td align=right colspan=2>
+ <input type="submit" name="action" value="refresh">&nbsp;
+_EOH
+
+if ($hasmsg) {
+print <<_EOH;
+ <input type="submit" name="action" value="delete">&nbsp;
+ <input type="submit" name="action" value="save to ->">
+ $folders&nbsp;
+ <input type="submit" name="action" value="forward to ->">
+ $mailboxes
+_EOH
+}
+
+print <<_EOH;
+</td></tr>
+<tr><td align=right colspan=2>
+ <input type="submit" name="action" value="preferences">
+ <input type="submit" name="action" value="logout">
+</td></tr>
+</table>
+<input type=hidden name="folder" value="$folder">
+<input type=hidden name="mailbox" value="$mbox">
+<input type=hidden name="context" value="$context">
+<input type=hidden name="password" value="$passwd">
+</FORM>
+$stdcontainerend
+</BODY>\n
+_EOH
+}
+
+sub validfolder()
+{
+ my ($folder) = @_;
+ return grep(/^$folder$/, @validfolders);
+}
+
+sub folder_list()
+{
+ my ($name, $context, $mbox, $selected) = @_;
+ my $f;
+ my $count;
+ my $tmp = "<SELECT name=\"$name\">\n";
+ foreach $f (@validfolders) {
+ $count = &msgcount($context, $mbox, $f);
+ if ($f eq $selected) {
+ $tmp .= "<OPTION SELECTED>$f ($count)</OPTION>\n";
+ } else {
+ $tmp .= "<OPTION>$f ($count)</OPTION>\n";
+ }
+ }
+ $tmp .= "</SELECT>";
+}
+
+sub message_rename()
+{
+ my ($context, $mbox, $oldfolder, $old, $newfolder, $new) = @_;
+ my $oldfile, $newfile;
+ return if ($old eq $new) && ($oldfolder eq $newfolder);
+
+ if ($context =~ /^(\w+)$/) {
+ $context = $1;
+ } else {
+ die("Invalid Context<BR>\n");
+ }
+
+ if ($mbox =~ /^(\w+)$/) {
+ $mbox = $1;
+ } else {
+ die ("Invalid mailbox<BR>\n");
+ }
+
+ if ($oldfolder =~ /^(\w+)$/) {
+ $oldfolder = $1;
+ } else {
+ die("Invalid old folder<BR>\n");
+ }
+
+ if ($newfolder =~ /^(\w+)$/) {
+ $newfolder = $1;
+ } else {
+ die("Invalid new folder ($newfolder)<BR>\n");
+ }
+
+ if ($old =~ /^(\d\d\d\d)$/) {
+ $old = $1;
+ } else {
+ die("Invalid old Message<BR>\n");
+ }
+
+ if ($new =~ /^(\d\d\d\d)$/) {
+ $new = $1;
+ } else {
+ die("Invalid old Message<BR>\n");
+ }
+
+ my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$newfolder";
+ $path =~ /^(.*)$/;
+ $path = $1;
+ mkdir $path, 0770;
+ my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$oldfolder";
+ opendir(DIR, $path) || die("Unable to open directory\n");
+ my @files = grep /^msg${old}\.\w+$/, readdir(DIR);
+ closedir(DIR);
+ foreach $oldfile (@files) {
+ my $tmp = $oldfile;
+ if ($tmp =~ /^(msg${old}.\w+)$/) {
+ $tmp = $1;
+ $oldfile = $path . "/$tmp";
+ $tmp =~ s/msg${old}/msg${new}/;
+ $newfile = "/var/spool/asterisk/voicemail/$context/$mbox/$newfolder/$tmp";
+# print "Renaming $oldfile to $newfile<BR>\n";
+ rename($oldfile, $newfile);
+ }
+ }
+}
+
+sub file_copy()
+{
+ my ($orig, $new) = @_;
+ my $res;
+ my $data;
+ $orig =~ /^(.*)$/;
+ $orig = $1;
+ $new =~ /^(.*)$/;
+ $new = $1;
+ open(IN, "<$orig") || die("Unable to open '$orig'\n");
+ open(OUT, ">$new") || DIE("Unable to open '$new'\n");
+ while(($res = sysread(IN, $data, 4096)) > 0) {
+ syswrite(OUT, $data, $res);
+ }
+ close(OUT);
+ close(IN);
+}
+
+sub message_copy()
+{
+ my ($context, $mbox, $newmbox, $oldfolder, $old, $new) = @_;
+ my $oldfile, $newfile;
+ return if ($mbox eq $newmbox);
+
+ if ($mbox =~ /^(\w+)$/) {
+ $mbox = $1;
+ } else {
+ die ("Invalid mailbox<BR>\n");
+ }
+
+ if ($newmbox =~ /^(\w+)$/) {
+ $newmbox = $1;
+ } else {
+ die ("Invalid new mailbox<BR>\n");
+ }
+
+ if ($oldfolder =~ /^(\w+)$/) {
+ $oldfolder = $1;
+ } else {
+ die("Invalid old folder<BR>\n");
+ }
+
+ if ($old =~ /^(\d\d\d\d)$/) {
+ $old = $1;
+ } else {
+ die("Invalid old Message<BR>\n");
+ }
+
+ if ($new =~ /^(\d\d\d\d)$/) {
+ $new = $1;
+ } else {
+ die("Invalid old Message<BR>\n");
+ }
+
+ my $path = "/var/spool/asterisk/voicemail/$context/$newmbox";
+ $path =~ /^(.*)$/;
+ $path = $1;
+ mkdir $path, 0770;
+ my $path = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX";
+ $path =~ /^(.*)$/;
+ $path = $1;
+ mkdir $path, 0770;
+ my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$oldfolder";
+ opendir(DIR, $path) || die("Unable to open directory\n");
+ my @files = grep /^msg${old}\.\w+$/, readdir(DIR);
+ closedir(DIR);
+ foreach $oldfile (@files) {
+ my $tmp = $oldfile;
+ if ($tmp =~ /^(msg${old}.\w+)$/) {
+ $tmp = $1;
+ $oldfile = $path . "/$tmp";
+ $tmp =~ s/msg${old}/msg${new}/;
+ $newfile = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX/$tmp";
+# print "Copying $oldfile to $newfile<BR>\n";
+ &file_copy($oldfile, $newfile);
+ }
+ }
+}
+
+sub message_delete()
+{
+ my ($context, $mbox, $folder, $msg) = @_;
+ if ($mbox =~ /^(\w+)$/) {
+ $mbox = $1;
+ } else {
+ die ("Invalid mailbox<BR>\n");
+ }
+ if ($context =~ /^(\w+)$/) {
+ $context = $1;
+ } else {
+ die ("Invalid context<BR>\n");
+ }
+ if ($folder =~ /^(\w+)$/) {
+ $folder = $1;
+ } else {
+ die("Invalid folder<BR>\n");
+ }
+ if ($msg =~ /^(\d\d\d\d)$/) {
+ $msg = $1;
+ } else {
+ die("Invalid Message<BR>\n");
+ }
+ my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$folder";
+ opendir(DIR, $path) || die("Unable to open directory\n");
+ my @files = grep /^msg${msg}\.\w+$/, readdir(DIR);
+ closedir(DIR);
+ foreach $oldfile (@files) {
+ if ($oldfile =~ /^(msg${msg}.\w+)$/) {
+ $oldfile = $path . "/$1";
+# print "Deleting $oldfile<BR>\n";
+ unlink($oldfile);
+ }
+ }
+}
+
+sub message_forward()
+{
+ my ($toindex, @msgs) = @_;
+ my $folder = param('folder');
+ my ($mbox, $context) = split(/\@/, param('mailbox'));
+ my $newmbox = param('forwardto');
+ my $msg;
+ my $msgcount;
+ if (!$context) {
+ $context = param('context');
+ }
+ if (!$context) {
+ $context = "default";
+ }
+ $newmbox =~ s/(\w+)(\s+.*)?$/$1/;
+ if (!&validmailbox($context, $newmbox)) {
+ die("Bah! Not a valid mailbox '$newmbox'\n");
+ return "";
+ }
+
+ my $txt;
+ $context = &untaint($context);
+ $newmbox = &untaint($newmbox);
+ my $path = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX";
+ if (&lock_path($path) == 0) {
+ $msgcount = &msgcount($context, $newmbox, "INBOX");
+
+ if ($newmbox ne $mbox) {
+# print header;
+ foreach $msg (@msgs) {
+# print "Forwarding $msg from $mbox to $newmbox<BR>\n";
+ &message_copy($context, $mbox, $newmbox, $folder, $msg, sprintf "%04d", $msgcount);
+ $msgcount++;
+ }
+ $txt = "Forwarded messages " . join(', ', @msgs) . "to $newmbox";
+ } else {
+ $txt = "Can't forward messages to yourself!\n";
+ }
+ &unlock_path($path);
+ } else {
+ $txt = "Cannot forward messages: Unable to lock path.\n";
+ }
+ if ($toindex) {
+ &message_index($folder, $txt);
+ } else {
+ &message_play($txt, $msgs[0]);
+ }
+}
+
+sub message_delete_or_move()
+{
+ my ($toindex, $del, @msgs) = @_;
+ my $txt;
+ my $path;
+ my $y, $x;
+ my $folder = param('folder');
+ my $newfolder = param('newfolder') unless $del;
+ $newfolder =~ s/^(\w+)\s+.*$/$1/;
+ my ($mbox, $context) = split(/\@/, param('mailbox'));
+ if (!$context) {
+ $context = param('context');
+ }
+ if (!$context) {
+ $context = "default";
+ }
+ my $passwd = param('password');
+ $context = &untaint($context);
+ $mbox = &untaint($mbox);
+ $folder = &untaint($folder);
+ my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$folder";
+ if (&lock_path($path) == 0) {
+ my $msgcount = &msgcount($context, $mbox, $folder);
+ my $omsgcount = &msgcount($context, $mbox, $newfolder) if $newfolder;
+ # print header;
+ if ($newfolder ne $folder) {
+ $y = 0;
+ for ($x=0;$x<$msgcount;$x++) {
+ my $msg = sprintf "%04d", $x;
+ my $newmsg = sprintf "%04d", $y;
+ if (grep(/^$msg$/, @msgs)) {
+ if ($newfolder) {
+ &message_rename($context, $mbox, $folder, $msg, $newfolder, sprintf "%04d", $omsgcount);
+ $omsgcount++;
+ } else {
+ &message_delete($context, $mbox, $folder, $msg);
+ }
+ } else {
+ &message_rename($context, $mbox, $folder, $msg, $folder, $newmsg);
+ $y++;
+ }
+ }
+ if ($del) {
+ $txt = "Deleted messages " . join (', ', @msgs);
+ } else {
+ $txt = "Moved messages " . join (', ', @msgs) . " to $newfolder";
+ }
+ } else {
+ $txt = "Can't move a message to the same folder they're in already";
+ }
+ &unlock_path($path);
+ } else {
+ $txt = "Cannot move/delete messages: Unable to lock path.\n";
+ }
+ # Not as many messages now
+ $msgcount--;
+ if ($toindex || ($msgs[0] >= $msgcount)) {
+ &message_index($folder, $txt);
+ } else {
+ &message_play($txt, $msgs[0]);
+ }
+}
+
+if (param()) {
+ my $folder = param('folder');
+ my $changefolder = param('changefolder');
+ $changefolder =~ s/(\w+)\s+.*$/$1/;
+
+ my $newfolder = param('newfolder');
+ $newfolder =~ s/^(\w+)\s+.*$/$1/;
+ if ($newfolder && !&validfolder($newfolder)) {
+ print header;
+ die("Bah! new folder '$newfolder' isn't a folder.");
+ }
+ $action = param('action');
+ $msgid = param('msgid');
+ if (!$action) {
+ my ($tmp) = grep /^play\d\d\d\d\.x$/, param;
+ if ($tmp =~ /^play(\d\d\d\d)/) {
+ $msgid = $1;
+ $action = "play";
+ } else {
+ print header;
+ print "No message?<BR>\n";
+ return;
+ }
+ }
+ @msgs = param('msgselect');
+ @msgs = ($msgid) unless @msgs;
+ {
+ ($mailbox) = &check_login();
+ if (length($mailbox)) {
+ if ($action eq 'login') {
+ &message_index($folder, "Welcome, $mailbox");
+ } elsif (($action eq 'refresh') || ($action eq 'index')) {
+ &message_index($folder, "Welcome, $mailbox");
+ } elsif ($action eq 'change to ->') {
+ if (&validfolder($changefolder)) {
+ $folder = $changefolder;
+ &message_index($folder, "Welcome, $mailbox");
+ } else {
+ die("Bah! Not a valid change to folder '$changefolder'\n");
+ }
+ } elsif ($action eq 'play') {
+ &message_play("$mailbox $folder $msgid", $msgid);
+ } elsif ($action eq 'preferences') {
+ &message_prefs("refresh", $msgid);
+ } elsif ($action eq 'download') {
+ &message_audio(1);
+ } elsif ($action eq 'play ') {
+ &message_audio(0);
+ } elsif ($action eq 'audio') {
+ &message_audio(0);
+ } elsif ($action eq 'delete') {
+ &message_delete_or_move(1, 1, @msgs);
+ } elsif ($action eq 'delete ') {
+ &message_delete_or_move(0, 1, @msgs);
+ } elsif ($action eq 'forward to ->') {
+ &message_forward(1, @msgs);
+ } elsif ($action eq 'forward to -> ') {
+ &message_forward(0, @msgs);
+ } elsif ($action eq 'save to ->') {
+ &message_delete_or_move(1, 0, @msgs);
+ } elsif ($action eq 'save to -> ') {
+ &message_delete_or_move(0, 0, @msgs);
+ } elsif ($action eq 'logout') {
+ &login_screen("Logged out!\n");
+ }
+ } else {
+ sleep(1);
+ &login_screen("Login Incorrect!\n");
+ }
+ }
+} else {
+ &login_screen("\&nbsp;");
+}
diff --git a/trunk/contrib/scripts/vmdb.sql b/trunk/contrib/scripts/vmdb.sql
new file mode 100644
index 000000000..0b1fc38f1
--- /dev/null
+++ b/trunk/contrib/scripts/vmdb.sql
@@ -0,0 +1,66 @@
+DROP TABLE IF EXISTS voicemail;
+CREATE TABLE voicemail (
+ -- All of these column names are very specific, including "uniqueid". Do not change them if you wish voicemail to work.
+ uniqueid INT(5) NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ -- Mailbox context.
+ context CHAR(80) NOT NULL DEFAULT 'default',
+ -- Mailbox number. Should be numeric.
+ mailbox CHAR(80) NOT NULL,
+ -- Must be numeric. Negative if you don't want it to be changed from VoicemailMain
+ password CHAR(80) NOT NULL,
+ -- Used in email and for Directory app
+ fullname CHAR(80),
+ -- Email address (will get sound file if attach=yes)
+ email CHAR(80),
+ -- Email address (won't get sound file)
+ pager CHAR(80),
+ -- Attach sound file to email - YES/no
+ attach CHAR(3),
+ -- Which sound format to attach
+ attachfmt CHAR(10),
+ -- Send email from this address
+ serveremail CHAR(80),
+ -- Prompts in alternative language
+ language CHAR(20),
+ -- Alternative timezone, as defined in voicemail.conf
+ tz CHAR(30),
+ -- Delete voicemail from server after sending email notification - yes/NO
+ deletevoicemail CHAR(3),
+ -- Read back CallerID information during playback - yes/NO
+ saycid CHAR(3),
+ -- Allow user to send voicemail from within VoicemailMain - YES/no
+ sendvoicemail CHAR(3),
+ -- Listen to voicemail and approve before sending - yes/NO
+ review CHAR(3),
+ -- Warn user a temporary greeting exists - yes/NO
+ tempgreetwarn CHAR(3),
+ -- Allow '0' to jump out during greeting - yes/NO
+ operator CHAR(3),
+ -- Hear date/time of message within VoicemailMain - YES/no
+ envelope CHAR(3),
+ -- Hear length of message within VoicemailMain - yes/NO
+ sayduration CHAR(3),
+ -- Minimum duration in minutes to say
+ saydurationm INT(3),
+ -- Force new user to record name when entering voicemail - yes/NO
+ forcename CHAR(3),
+ -- Force new user to record greetings when entering voicemail - yes/NO
+ forcegreetings CHAR(3),
+ -- Context in which to dial extension for callback
+ callback CHAR(80),
+ -- Context in which to dial extension (from advanced menu)
+ dialout CHAR(80),
+ -- Context in which to execute 0 or * escape during greeting
+ exitcontext CHAR(80),
+ -- Maximum length of message (in seconds)
+ maxmessage INT(5),
+ -- Maximum messages in a folder (100 if not specified)
+ maxmsg INT(5),
+ -- Increase DB gain on recorded message by this amount (0.0 means none)
+ volgain DECIMAL(5,2),
+ -- IMAP user for authentication (if using IMAP storage)
+ imapuser VARCHAR(80),
+ -- IMAP password for authentication (if using IMAP storage)
+ imappassword VARCHAR(80),
+ stamp timestamp
+);