function query($query) { global $conn, $query_on, $max_resets_conn; global $dsn; $resets = 0; while (true) { if ($conn) { $res = $conn->query($query); } /* if(!$res) { while(true) { if($resets >= ($max_resets_conn-1)) { Yate::Output("Could not execute: $query\n"); return null; } $resets++; if (!$conn) { $conn = DB::connect($dsn, true); break; sleep(1); }else $resets = $max_resets_conn; } }else */ break; } if ($query_on) { Yate::Output("Executed: {$query}" . "\n"); } return $res; }
function onDisconnect(&$ev, $reason) { global $ourcallid; Yate::Output("Channel {$ourcallid} was disconnected, reason: '{$reason}'"); // Sample action: redirect to info tone if user is busy if ($reason == "busy") { $m = new Yate("call.execute"); $m->id = $ev->id; $m->params["id"] = $ourcallid; $m->params["callto"] = "tone/info"; $m->Dispatch(); // Also send progressing so the tone goes through in early media $m = new Yate("call.progress"); $m->params["targetid"] = $ourcallid; $m->Dispatch(); return true; } return false; }
We MUST let messages return, handled or not */ if ($ev) { $ev->Acknowledge(); } break; case "answer": // Yate::Debug("PHP Answered: " . $ev->name . " id: " . $ev->id); break; case "installed": // Yate::Debug("PHP Installed: " . $ev->name); break; case "uninstalled": // Yate::Debug("PHP Uninstalled: " . $ev->name); break; default: // Yate::Output("PHP Event: " . $ev->type); } } if (is_file("{$user}/{$file}")) { Yate::Debug("Converting received message from .slin to .mp3."); $filename = "{$user}/{$file}"; $mp3path = str_replace(".slin", ".mp3", $filename); if (is_file("share/scripts/mp3ize.sh")) { passthru("share/scripts/mp3ize.sh {$mp3path} {$filename}"); } else { // passthru("/usr/local/share/yate/scripts/mp3ize.sh $mp3path $filename"); passthru("/usr/share/yate/scripts/mp3ize.sh {$mp3path} {$filename}"); } } Yate::Output("PHP leavemaildb : bye!"); /* vi: set ts=8 sw=4 sts=4 noet: */
function gotDTMF($text) { global $ourcallid; global $partycallid; global $state; Yate::Output("gotDTMF('" . $text . "') state: " . $state); switch ($text) { case "1": setState("record"); break; case "2": setState("play"); break; case "3": setState(""); break; case "#": setState("prompt"); break; } }
function endRoute($callto, $ok, $err) { global $partycallid; global $num; global $collect; if ($ok) { Yate::Output("Overlapped got route: '{$callto}' for '{$collect}'"); $m = new Yate("chan.masquerade"); $m->params["message"] = "call.execute"; $m->params["id"] = $partycallid; $m->params["callto"] = $callto; $m->params["caller"] = $num; $m->params["called"] = $collect; $m->Dispatch(); return; } if ($err != "incomplete") { setState("noroute"); } else { Yate::Output("Overlapped still incomplete: '{$collect}'"); } }
/** * See if this call uses the address book. If so then find the real number the call should be sent to and modify $called param * @param $called Number the call was placed to */ function routeToAddressBook(&$called, $username) { global $adb_keys; // debug("entered routeToAddressBook(called='$called', username='******')"); if (substr($called, 0, strlen($adb_keys)) != $adb_keys) { return; } debug("trying routeToAddressBook(called='{$called}', username='******')"); $number = substr($called, strlen($adb_keys), strlen($called)); $possible_names = get_possible_options($number); $query = "SELECT short_names.number, 1 as option_nr FROM short_names, extensions WHERE extensions.extension='{$username}' AND extensions.extension_id=short_names.extension_id AND short_name IN ({$possible_names}) UNION SELECT number, 2 as option_nr FROM short_names WHERE extension_id IS NULL AND short_name IN ({$possible_names}) ORDER BY option_nr"; $res = query_to_array($query); if (count($res)) { if (count($res) > 1) { Yate::Output("!!!!!!! Problem with finding real number from address book. Multiple mathces. Picking first one"); } $called = $res[0]["number"]; } else { debug("Called number '{$called}' seems to be using the address book. No match found. Left routing to continue."); } return; }
$text = $ev->GetValue("text"); for ($i = 0; $i < strlen($text); $i++) { gotDTMF($text[$i]); } $ev->handled = true; break; } /* This is extremely important. We MUST let messages return, handled or not */ if ($ev) { $ev->Acknowledge(); } break; case "answer": // Yate::Debug("PHP Answered: " . $ev->name . " id: " . $ev->id); if ($ev->name == "user.auth") { checkAuth($ev->retval); } break; case "installed": // Yate::Debug("PHP Installed: " . $ev->name); break; case "uninstalled": // Yate::Debug("PHP Uninstalled: " . $ev->name); break; default: // Yate::Output("PHP Event: " . $ev->type); } } Yate::Output("PHP voicemaildb : bye!"); /* vi: set ts=8 sw=4 sts=4 noet: */
function initUser() { global $vm_base; global $dir; global $mailbox; global $files; vmInitMessageDir($mailbox); vmGetMessageFiles($mailbox, $files); $dir = "{$vm_base}/{$mailbox}"; Yate::Output("found " . count($files) . " file entries for mailbox {$mailbox}"); setState("prompt"); }
function handle_pear_error($e) { Yate::Output($e->getMessage() . ' ' . print_r($e->getUserInfo(), true)); }
function onCommand($l, &$retval) { global $hosts; global $ban_failures; global $cmd_unban; if ($l == "banbrutes") { $gray = 0; $banned = 0; foreach ($hosts as &$host) { if ($host->banned()) { $banned++; } else { $gray++; } } $retval = "failures={$ban_failures},banned={$banned},gray={$gray}\r\n"; return true; } else { if ($l == "banbrutes list") { $retval = ""; $now = time(); foreach ($hosts as $addr => &$host) { if ($retval != "") { $retval .= ","; } if ($host->banned()) { $t = $host->when - $now; $retval .= "{$addr}=banned:{$t}s"; } else { $retval .= "{$addr}=gray:" . $host->fail; } } $retval .= "\r\n"; return true; } else { if (strpos($l, "banbrutes unban ") === 0) { $addr = substr($l, 16); if (isset($hosts[$addr])) { if ($hosts[$addr]->banned()) { $cmd = eval('return "' . $cmd_unban . '";'); Yate::Output("banbrutes: {$cmd}"); shell_exec($cmd); unset($hosts[$addr]); $retval = "Unbanned: {$addr}\r\n"; } else { unset($hosts[$addr]); $retval = "Removed from gray list: {$addr}\r\n"; } } else { $retval = "Not banned: {$addr}\r\n"; } return true; } else { if (strpos($l, "banbrutes failures ") === 0) { $fail = 1 * substr($l, 19); if ($fail > 1 && $fail <= 1000) { $ban_failures = $fail; return true; } } else { if (strpos($l, "banbrutes debug ") === 0) { $dbg = substr($l, 16); switch ($dbg) { case "true": case "yes": case "on": Yate::Debug(true); return true; case "false": case "no": case "off": Yate::Debug(false); return true; } } } } } } return false; }
function endRoute($callto, $ok, $err, $params) { global $partycallid; global $collect; global $final; global $queue; global $routeOnly; global $state; if ($ok && $callto != "-" && $callto != "error") { Yate::Output("Overlapped got route: '{$callto}' for '{$collect}'"); $m = new Yate("chan.masquerade"); $m->params = $params; $m->params["message"] = "call.execute"; $m->params["complete_minimal"] = true; $m->params["id"] = $partycallid; $m->params["callto"] = $callto; $m->Dispatch(); if (strlen($queue)) { // Masquerade the remaining digits // TODO: wait for call.execute to be processed to do that? $d = new Yate("chan.masquerade"); $d->params["message"] = "chan.dtmf"; $d->params["id"] = $partycallid; $d->params["tone"] = $queue; $d->Dispatch(); } return; } if ($final) { Yate::Output("Overlapped got final error '{$err}' for '{$collect}'"); Yate::SetLocal("reason", $err); setState(""); } else { if ($err != "incomplete") { Yate::Output("Overlapped got error '{$err}' for '{$collect}'"); Yate::SetLocal("reason", $err); setState(""); $final = true; } else { Yate::Debug("Overlapped still incomplete: '{$collect}'"); if ($routeOnly) { setState("noroute"); } else { // Don't use setState: we don't want to change the prompt $state = "prompt"; } // Check if got some other digits if ($queue != "") { gotDTMF(""); } } } }
break; } /* This is extremely important. We MUST let messages return, handled or not */ if ($ev) { $ev->Acknowledge(); } break; case "answer": //Yate::Debug("PHP Answered: " . $ev->name . " id: " . $ev->id); if ($ev->name == "call.route") { $destination = $ev->retval; if ($destination) { setState("send_call"); } else { setState("goodbye"); } } break; case "installed": // Yate::Debug("PHP Installed: " . $ev->name); break; case "uninstalled": // Yate::Debug("PHP Uninstalled: " . $ev->name); break; default: // Yate::Output("PHP Event: " . $ev->type); } } Yate::Output("PHP Auto Attendant: bye!"); /* vi: set ts=8 sw=4 sts=4 noet: */
/** * Create an IVR instance by name, used internally only * @param $ivrname Name of the IVR to create * @return Newly created IVR object */ private static function CreateIVR($ivrname) { global $yate_ivr_register; IVR::InitIVR(); if (isset($yate_ivr_register[$ivrname])) { $obj = new $yate_ivr_register[$ivrname](); $obj->ivrname = $ivrname; return $obj; } Yate::Output("IVR: Requested unknown IVR '{$ivrname}'"); return null; }
function onFax($id) { Yate::Output("Fax call detected on {$id}"); $m = new Yate("chan.masquerade"); $m->id = ""; // don't notify about message result $m->params["message"] = "call.execute"; $m->params["id"] = $id; // FIXME: generate an unique name for each call $m->params["callto"] = "fax/receive/spool/fax-rx.tif"; $m->params["reason"] = "fax"; $m->Dispatch(); }
function routeFailure($error, $ev) { $number = $ev->GetValue("called"); Yate::Output("Failed routing dialout to '{$number}' with error '{$error}'"); }
$ev->Acknowledge(); } break; case "answer": Yate::Debug("PHP Answered: " . $ev->name . " id: " . $ev->id); if (!$ev->handled) { if ($ev->name == "call.execute") { // call leg to operator didn't even start Yate::Output("Failed to start queue '{$queue}' call leg to: " . $ev->GetValue("callto")); $m = new Yate("chan.hangup"); $m->id = ""; $m->params["notify"] = $partycallid; $m->params["queue"] = $queue; $m->params["cdrtrack"] = "false"; $m->Dispatch(); } else { if ($ev->name == "chan.locate") { // caller hung up before we installed the hangup handler Yate::Output("Call {$partycallid} from '{$caller}' exited early from '{$queue}'"); Yate::SetLocal("reason", "nocall"); exit; } } } break; default: Yate::Debug("PHP Event: " . $ev->type); } } Yate::Debug("PHP: bye!"); /* vi: set ts=8 sw=4 sts=4 noet: */
/** * This static function initializes globals in the PHP Yate External Module. * It should be called before any other method. * @param $async (optional) True if asynchronous, polled mode is desired * @param $addr Hostname to connect to or UNIX socket path * @param $port TCP port to connect to, zero to use UNIX sockets * @param $role Role of this connection - "global" or "channel" * @return True if initialization succeeded, false if failed */ static function Init($async = false, $addr = "", $port = 0, $role = "") { global $yate_stdin, $yate_stdout, $yate_stderr; global $yate_socket, $yate_debug, $yate_output; $yate_debug = false; $yate_stdin = false; $yate_stdout = false; $yate_stderr = false; $yate_output = false; if ($addr) { $ok = false; if ($port) { $yate_socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $ok = @socket_connect($yate_socket, $addr, $port); } else { $yate_socket = @socket_create(AF_UNIX, SOCK_STREAM, 0); $ok = @socket_connect($yate_socket, $addr, $port); } if ($yate_socket === false || !$ok) { $yate_socket = false; $yate_stderr = fopen("php://stderr", "w"); Yate::Output("Socket error, initialization failed"); return false; } $yate_output = true; } else { $yate_socket = false; $yate_stdin = fopen("php://stdin", "r"); $yate_stdout = fopen("php://stdout", "w"); $yate_stderr = fopen("php://stderr", "w"); $role = ""; } flush(); set_error_handler("_yate_error_handler"); ob_implicit_flush(1); if ($async && function_exists("stream_set_blocking") && $yate_stdin) { stream_set_blocking($yate_stdin, false); } if ($role) { _yate_print("%%>connect:{$role}\n"); } return true; }
function Notify($state = false) { Yate::Debug("Notifying event " . $this->event . " for " . $this->match); if ($state !== false) { $this->state = $state; $this->pending = true; } if ($this->body == "") { Yate::Output("Empty body in event " . $this->event . " for " . $this->match); return; } $this->pending = false; $m = new Yate("xsip.generate"); $m->id = ""; $m->params["method"] = "NOTIFY"; $m->params["uri"] = $this->contact; $m->params["host"] = $this->host; $m->params["port"] = $this->port; $m->params["sip_Call-ID"] = $this->callid; $m->params["sip_From"] = $this->to; $m->params["sip_To"] = $this->from; $m->params["sip_Contact"] = "<" . $this->uri . ">"; $m->params["sip_Event"] = $this->event; $m->params["sip_Subscription-State"] = $this->state; $m->params["xsip_type"] = $this->media; $m->params["xsip_body"] = $this->body; $m->Dispatch(); }
function invalidate($address) { global $cache; foreach ($cache as $host => &$entries) { $changed = false; foreach ($entries as $idx => $cached) { if ($cached->address == $address) { Yate::Output("Invalidating {$address} of host {$host}"); unset($entries[$idx]); $changed = true; } } if (count($entries) == 0) { Yate::Debug("Invalidating entire host {$host}"); unset($cache[$host]); } else { if ($changed) { $cache[$host] = array_values($cache[$host]); } } } }
if ($ev === true) { // Yate::Output("PHP event: empty"); continue; } /* If we reached here we should have a valid object */ switch ($ev->type) { case "incoming": $conn = pg_connect("host=127.0.0.1 dbname=yate user=postgres password="******"SELECT username,password FROM yatet"); Yate::Output("Username : "******" password " . pg_fetch_result($query, 0, 1)); $ev->retval = pg_fetch_result($query, 0, 1); $ev->handled = true; /* This is extremely important. We MUST let messages return, handled or not */ $ev->Acknowledge(); break; case "answer": Yate::Output("PHP Answered: " . $ev->name . " id: " . $ev->id); break; case "installed": Yate::Output("PHP Installed: " . $ev->name); break; case "uninstalled": Yate::Output("PHP Uninstalled: " . $ev->name); break; default: Yate::Output("PHP Event: " . $ev->type); } } Yate::Output("PHP: bye!"); /* vi: set ts=8 sw=4 sts=4 noet: */
case "initialize": // Remember the called number for this call leg $calls[$chan] = $ev->GetValue("called"); break; case "finalize": // Forget about the call leg that got hung up unset($calls[$chan]); break; } } $calls = array(); $prefix = Yate::Arg(); if ($prefix == "") { // Hope this is a sensible default - else set a prefix from extmodule.conf $prefix = "#8"; Yate::Output("Pickup prefix not set, using default '{$prefix}'"); } Yate::SetLocal("trackparam", "pickup.php"); Yate::Install("call.route", 35); Yate::Install("call.cdr", 110, "direction", "outgoing"); Yate::SetLocal("restart", true); for (;;) { $ev = Yate::GetEvent(); if ($ev === false) { break; } if ($ev === true) { continue; } if ($ev->type == "incoming") { switch ($ev->name) {