All pastes #951516 Raw Edit

Untitled

public text v1 · immutable
·published 2008-03-21 13:26 UTC
rendered paste body
#!/usr/bin/php -q
<?php

/**
// AGI directory Copyright (C) 2005 Greg MacLellan (greg@mtechsolutions.ca)
//
//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.


*/

/* --------WARNING---------
 * 
 * This script is auto-copied from an included module and will get overwritten.
 * If you modify it, you must change it to write only, in the agi-bin directory,
 * to keep it from getting changed.
 */

// set to 1 to say "zed" instead of "zee"
define("SAY_ZED",0);

/******************************************************************************/

define("DEBUG", 0);

define("DIR_LAST", 0);
define("DIR_FIRST", 1);
define("DIR_BOTH", 2);

define("NUM_DIGITS", 3);
define("MAX_REPEAT", 2); // how many times can we repeat the menu before hanging up?

// ordinal values of digits
define("D_0",48);
define("D_1",49);
define("D_2",50);
define("D_3",51);
define("D_4",52);
define("D_5",53);
define("D_6",54);
define("D_7",55);
define("D_8",56);
define("D_9",57);
define("D_POUND",35);
define("D_STAR",42);

include("phpagi.php");

function get_var( $agi, $value)
{
        $r = $agi->get_variable( $value );

        if ($r['result'] == 1)
        {
                $result = $r['data'];
                return $result;
        }
        else
                return '';
}

function output(&$var) {
        if (DEBUG) {
                global $logfile;

                if (!isset($logfile)) return false;

                ob_start();
                var_dump($var);
                $output = ob_get_contents();
                ob_end_clean();
                fwrite($logfile, $output);
        }
}


function parse_voicemailconf($filename, &$vmconf, &$section) {
        if (is_null($vmconf)) {
                $vmconf = array();
        }
        if (is_null($section)) {
                $section = "general";
        }

        if (file_exists($filename)) {
                $fd = fopen($filename, "r");
                while ($line = fgets($fd, 1024)) {
                        if (preg_match("/^\s*(\d+)\s*=>\s*(\d+),(.*),(.*),(.*),(.*)\s*([;#].*)?/",$line,$matches)) {
                                // "mailbox=>password,name,email,pager,options"
                                // this is a voicemail line
                                $vmconf[$section][ $matches[1] ] = array("mailbox"=>$matches[1],
                                                                        "pwd"=>$matches[2],
                                                                        "name"=>$matches[3],
                                                                        "email"=>$matches[4],
                                                                        "pager"=>$matches[5],
                                                                        );

                                // parse options
                                foreach (explode("|",$matches[6]) as $opt) {
                                        $temp = explode("=",$opt);
                                        if (isset($temp[1])) {
                                                list($key,$value) = $temp;
                                                $vmconf[$section][ $matches[1] ]["options"][$key] = $value;
                                        }
                                }
                        } else if (preg_match("/^\s*(\d+)\s*=>\s*dup,(.*)\s*([;#].*)?/",$line,$matches)) {
                                // "mailbox=>dup,name"
                                // duplace name line
                                $vmconf[$section][ $matches[1] ]["dups"][] = $matches[2];
                        } else if (preg_match("/^\s*#include\s+(.*)\s*([;#].*)?/",$line,$matches)) {
                                // include another file

                                if ($matches[1][0] == "/") {
                                        // absolute path
                                        $filename = $matches[1];
                                } else {
                                        // relative path
                                        $filename =  dirname($filename)."/".$matches[1];
                                }

                                parse_voicemailconf($filename, $vmconf, $section);

                        } else if (preg_match("/^\s*\[(.+)\]/",$line,$matches)) {
                                // section name
                                $section = strtolower($matches[1]);
                        } else if (preg_match("/^\s*([a-zA-Z0-9-_]+)\s*=\s*(.*?)\s*([;#].*)?$/",$line,$matches)) {
                                // name = value
                                // option line
                                $vmconf[$section][ $matches[1] ] = $matches[2];
                        }
                }
        }
}


/** Play a bunch of files, optionally accepting input and looping
 * @param $files                The file/files to play (for multiple files, pass array)
 * @param $escape_digits        The DTMF tones that can be pressed & returned, ie, "123*"
 * @param $timeout              The timeout waiting for a digit, or 0 to not wait at all.
 * @param $max_digits           Maximum number of digits to get. **NOT IMPLEMENTED YET.. 1 only**
 * @param $loop                 False for no loop, or an integer >0 being the number of times to loop. 
 * @param $loopreturn           Value to return when the loop expires
*/
function stream_multiple($files, $escape_digits = "", $timeout = 0, $max_digits = 1, $loop = false, $loopreturn = 0) {
        global $agi;

        if (!is_array($files)) {
                $files = array($files);
        }

        $i = 0;
        do {
                foreach ($files as $file) {
                        $agi->verbose("-- Playing '".$file."' (language 'en')");
                        $r = $agi->stream_file($file, $escape_digits);
                        $agi->conlog("stream_multiple: $file returned ".$r["result"]);
                        switch ($r["result"]) {
                                case 0: // they did nothing
                                break;
                                case -1: // they hungup
                                        $agi->verbose("remote user hungup");
                                        return -1;
                                break;
                                default: // they pressed a key
                                        return $r["result"];
                                break;
                        }
                }

                if ($timeout > 0) {
                        $r = $agi->wait_for_digit($timeout);
                        if (($r["result"] != 0) || (!$loop)) {
                                // return only if the reult is not 0 (timeout)
                                // or we're not doing a loop
                                return $r["result"];
                        }
                }

                if ($loop && (++$i > $loop)) {
                        return $loopreturn;
                }
        } while ($loop);

        return 0;
}

/** If $file.(wav|WAV|gsm|GSM) exists
 */
function sound_file_exists($file) {
        global $agi;

        foreach (array("gsm","GSM","wav","WAV") as $ext) {
                if (file_exists($file.".".$ext)) {
                        $agi->verbose("Found ".$file.".".$ext, 2);
                        return true;
                }
        }
        return false;
}

function string_to_digits($string) {
        $out = "";

        for($i=0; $i<strlen($string); $i++) {
                switch (strtoupper($string[$i])) {
                        case '1':
                                $out .= '1';
                        break;
                        case '2': case 'A': case 'B': case 'C':
                                $out .= '2';
                        break;
                        case '3': case 'D': case 'E': case 'F':
                                $out .= '3';
                        break;
                        case '4': case 'G': case 'H': case 'I':
                                $out .= '4';
                        break;
                        case '5': case 'J': case 'K': case 'L':
                                $out .= '5';
                        break;
                        case '6': case 'M': case 'N': case 'O':
                                $out .= '6';
                        break;
                        case '7': case 'P': case 'Q': case 'R': case 'S':
                                $out .= '7';
                        break;
                        case '8': case 'T': case 'U': case 'V':
                                $out .= '8';
                        break;
                        case '9': case 'W': case 'X': case 'Y': case 'Z':
                                $out .= '9';
                        break;
                }

                if ($i+1 == NUM_DIGITS) break;
        }

        return $out;
}

function say_alpha($string,$escape_digits) {
        $string = strtolower($string);
        $files = array();

        for($i=0; $i<strlen($string); $i++) {
                if (('a' <= $string[$i]) && ($string[$i] <= 'z')) {

                        if (($string[$i] == 'z') && SAY_ZED) {
                                $files[] = "letters/zed";
                        } else {
                                $files[] = "letters/".$string[$i];
                        }

                } else if (('1' <= $string[$i]) && ($string[$i] <= '0')) {
                        $files[] = "digits/".$string[$i];

                } else {
                        switch ($string[$i]) {
                                case "@": $files[] = "letters/at"; break;
                                case "-": $files[] = "letters/dash"; break;
                                case "$": $files[] = "letters/dollar"; break;
                                case ".": $files[] = "letters/dot"; break;
                                case "=": $files[] = "letters/equals"; break;
                                case "!": $files[] = "letters/exclaimation-point"; break;
                                case "+": $files[] = "letters/plus"; break;
                                case "/": case "\\": $files[] = "letters/slash"; break;
                                case " ": $files[] = "letters/space"; break;
                        }
                }
        }

        return stream_multiple($files,$escape_digits);
}

function do_directory($type, &$directory, $dial_context, $say_exten, $operator) {
        global $agi;
        global $voicemail_dir;

        $escape_digits = "1*";
        if ($operator) $escape_digits .= "0";

        switch ($type) {
                case DIR_FIRST: $intro = ($operator ? "dir-intro-fn-oper" : "dir-intro-fn"); break;
                case DIR_BOTH: $intro = ($operator ? "dir-intro-fnln-oper" : "dir-intro-fnln"); break;
                case DIR_LAST: default: $intro = ($operator ? "dir-intro-oper" : "dir-intro"); break;
        }

        $loop = 0;
        while ($loop < MAX_REPEAT) {
                $r = $agi->get_data($intro, 4000, NUM_DIGITS);

                if (($r["result"] == "0") && $operator) {
                        // operator
                        $agi->verbose("Dropping to operator");
                        // switch to o,1 in the current context
                        $agi->set_extension("o");
                        $agi->set_priority("1");
                        // exiting application immediately!
                        exit(0);
                }
                $digits = $r["result"];

                usleep(500); // pause a bit, so digit presses get cleared

                if ($digits !== "") {
                        // they entered SOMETHING, reset our loop
                        $loop = 0;
                }

                $i = 0;
                $digit = false;
                if (isset($directory[$digits]) && isset($directory[$digits][$i])) {
                        $loop = 0; // reset loop counter
                        do {
                                $match = & $directory[$digits][$i];

                                $maindirname = sprintf($voicemail_dir, $match["context"], $match["ext"]);

                                if (sound_file_exists($maindirname."/greet")) {
                                        $r = $agi->stream_file($maindirname."/greet",$escape_digits);
                                        if ($r["result"] > 0) $digit = $r["result"];
                                } else {
                                        $digit = say_alpha($match["name"],$escape_digits);
                                }

                                if (!$digit) {
                                        $digit = stream_multiple("dir-instr", $escape_digits, 3000);
                                }

                                switch ($digit) {
                                        case D_1: // dial this
                                                if ($say_exten) {
                                                        $agi->stream_file("pls-hold-while-try");
                                                        $agi->stream_file("to-extension");

                                                        $agi->say_digits($match["ext"]);
                                                }
                                                $agi->conlog("Dial ".$match["ext"]);

                                                $agi->set_context($dial_context);
                                                $agi->set_extension($match["ext"]);
                                                $agi->set_priority("1");
                                                exit(0);
                                        break;
                                        case D_STAR: // not correct
                                                $i += 1;
                                        break;
                                        case D_0: // operator
                                                if ($operator) {
                                                        $agi->verbose("Dropping to operator");
                                                        // switch to o,1 in the current context
                                                        $agi->set_extension("o");
                                                        $agi->set_priority("1");
                                                        // exiting application immediately!
                                                        exit(0);
                                                }
                                        break;
                                        case -1: // hungup
                                                $agi->conlog("User hungup");
                                                exit(1);
                                        break;
                                        case 0: // no response
                                                $loop++;
                                        break;
                                        case -2: // loop timed out
                                                $agi->stream_file("goodbye");
                                                $agi->hangup();
                                                exit(0);
                                        break;
                                }

                                if ($digit !== 0) {
                                        $loop = 0;
                                }
                                $digit = false;
                        } while (isset($directory[$digits][$i]) && ($loop < MAX_REPEAT));

                        if (!isset($directory[$digits][$i])) {
                                $agi->stream_file("dir-nomore");
                                $loop = 0; // reset our loop counter so it doesn't hangup
                        }
                } else if (!empty($digits) || ($digits === "0")) {
                        // strict type checking as they may have entered "0" (string) which is empty()
                        $agi->stream_file("dir-nomatch");
                } // else, we timed out

                $loop++;
        }
}

/******************************************************************************/

$agi = new AGI;

$directory_file = get_var($agi, "ASTETCDIR")."/voicemail.conf";

// where is voicemail stored?
$voicemail_dir  = get_var($agi, "ASTSPOOLDIR")."/voicemail/%s/%d";

// where should we store logs? (fixes #1912)
$log_dir        = get_var($agi, "ASTLOGDIR");

if (DEBUG) $logfile = fopen( $log_dir . "/directory.log","w");

$vmconf = array();
$null = null;
parse_voicemailconf($directory_file, $vmconf, $null);


if (!$argv[1]) {
        $agi->verbose("Notice: vm-context not specified.  Using 'default'");
        $vm_context = "default";
} else {
        $vm_context = trim($argv[1]);
}

if (!isset($vmconf[$vm_context]) && ($vm_context != "general")) {
        // we make an exception for "general" context,as it just includes other contexts
        $agi->verbose("Cannot find context ".$vm_context." in ".$directory_file);
        exit(1);
}

if (isset($argv[2])) {
        $dial_context = trim($argv[2]);
} else {
        $dial_context = $vm_context;
}

$operator = false;
$dir_type = DIR_FIRST;
$say_exten = false;

if (isset($argv[3])) {
        for($i=0; $i<strlen($argv[3]); $i++) {
                switch ($argv[3][$i]) {
                        case "f": case "F": 
                                $dir_type = DIR_FIRST;
                        break;
                        case "l": case "L": 
                                $dir_type = DIR_LAST;
                        break;
                        case "b": case "B": 
                                $dir_type = DIR_BOTH;
                        break;
                        case "o": case "O": 
                                $operator = true;
                        break;
                        case "e": case "E": 
                                $say_exten = true;
                        break;
                }
        }
}

if ($vm_context == "general") {
        $boxes = array();
        foreach ($vmconf as $context=>$arr) {
                // skip if it's general context -- this doesn't contain mailboxes
                if ($context == "general") continue;

                foreach ($arr as $key=>$box) {
                        // we could do if !isset($boxes[$key]) to NOT override mailboxes

                        // add in the context, otherwise we don't know what it is
                        $box["context"] = $context;

                        $boxes[$key] = $box;
                }
        }
} else {
        $boxes = &$vmconf[$vm_context];
}

$directory = array();
foreach ($boxes as $box) {
        if (!empty($box["name"])) {
                $name = explode(" ",$box["name"]);

                if (isset($box["context"])) {
                        $context = $box["context"];
                } else {
                        $context = $vm_context;
                }

                switch ($dir_type) {
                        case DIR_FIRST: // first name only
                                $digits = string_to_digits($name[0]);
                                $directory[$digits][] = array("ext"=>$box["mailbox"], "name"=>$box["name"], "context"=>$context);
                        break;
                        case DIR_BOTH: // all names
                                foreach ($name as $temp) {
                                        $digits = string_to_digits($temp);
                                        $directory[$digits][] = array("ext"=>$box["mailbox"], "name"=>$box["name"], "context"=>$cont
ext);
                                }
                        break;
                        case DIR_LAST: default: // last name only
                                $digits = string_to_digits(end($name));
                                $directory[$digits][] = array("ext"=>$box["mailbox"], "name"=>$box["name"], "context"=>$context);
                        break;
                }
        }
}

if (DEBUG) {
        output($argv);
        output($dir_type);
        output($directory);
}

do_directory($dir_type, $directory, $dial_context, $say_exten, $operator);

?>