/** * Processa dados crus da tabela no banco para instanciação de objetos de * ramais. * * @param Object $data Resultado de um select com todas as colunas no banco * de dados dos ramais. * @return Snep_Exten ramal criado a partir dos dados. */ private function processExten($data) { $tech = substr($data->canal, 0, strpos($data->canal, '/')); if ($tech == "SIP" || $tech == "IAX2") { $config = array("username" => $data->name, "secret" => $data->secret, "allow" => $data->allow, "type" => $data->type, "qualify" => $data->qualify, "dtmfmode" => $data->dtmfmode, "nat" => $data->nat, "call-limit" => $data->{'call-limit'}); if ($tech == "SIP") { $interface = new PBX_Asterisk_Interface_SIP($config); } else { $interface = new PBX_Asterisk_Interface_IAX2($config); } } else { if ($tech == "VIRTUAL") { $trunk = PBX_Trunks::get(substr($data->canal, strpos($data->canal, '/') + 1)); $interface = new PBX_Asterisk_Interface_VIRTUAL(array("channel" => $trunk->getInterface()->getCanal() . "/" . $exten_id)); } else { if ($tech == "MANUAL") { $interface = new PBX_Asterisk_Interface_VIRTUAL(array("channel" => substr($data->canal, strpos($data->canal, '/') + 1))); } else { if ($tech == "KHOMP") { $khomp_id = substr($data->canal, strpos($data->canal, '/') + 1); $khomp_board = substr($khomp_id, 1, strpos($khomp_id, 'c') - 1); $khomp_channel = substr($khomp_id, strpos($khomp_id, 'c') + 1); $interface = new PBX_Asterisk_Interface_KHOMP(array("board" => $khomp_board, "channel" => $khomp_channel)); } else { throw new Exception("Tecnologia {$tech} desconhecida ou invalida."); } } } } $exten = new Snep_Exten($data->name, $data->password, $data->callerid, $interface); $exten->setChannel($data->canal); $exten->setGroup($data->group); if ($data->authenticate) { $exten->lock(); } if ($data->dnd) { $exten->DNDEnable(); } if ($data->sigame != "") { $exten->setFollowMe($data->sigame); } if (is_numeric($data->pickupgroup)) { $exten->setPickupGroup($data->pickupgroup); } if ($data->usa_vc == 'yes') { $exten->setMailBox($data->mailbox); $exten->setEmail($data->email); } if ($data->time_total != NULL) { $exten->setTimeTotal($data->time_total); $exten->setCtrlType($data->time_chargeby); } return $exten; }
/** * Executa a ação. É chamado dentro de uma instancia usando AGI. * * @param Asterisk_AGI $asterisk * @param Asterisk_AGI_Request $request */ public function execute($asterisk, $request) { $log = Zend_Registry::get('log'); $tronco = PBX_Trunks::get($this->config['tronco']); // Montando as Flags para limite na ligação $flags = $this->config['dial_flags']; if (isset($this->config['dial_limit']) && $this->config['dial_limit'] > 0) { $flags .= "L(" . $this->config['dial_limit']; // play_warning_value if (isset($this->defaultConfig['play_warning']) && $this->defaultConfig['play_warning'] > 0) { $flags .= ":" . $this->defaultConfig['play_warning']; // warning_freq if (isset($this->defaultConfig['warning_freq']) && $this->defaultConfig['warning_freq'] > 0) { $flags .= ":" . $this->defaultConfig['warning_freq']; } } $flags .= ")"; if (isset($this->defaultConfig['warning_sound'])) { $warning_sound = $this->defaultConfig['warning_sound'] != "" ? $this->defaultConfig['warning_sound'] : "beep"; $asterisk->set_variable("LIMIT_WARNING_FILE", $warning_sound); } } if ($tronco->getDtmfDialMode()) { $dst_number = $tronco->getDtmfDialNumber(); $flags .= "D({$request->destino})"; } else { $dst_number = $request->destino; } if ($tronco->getInterface() instanceof PBX_Asterisk_Interface_SIP_NoAuth || $tronco->getInterface() instanceof PBX_Asterisk_Interface_IAX2_NoAuth) { $destiny = $tronco->getInterface()->getTech() . "/" . $dst_number . "@" . $tronco->getInterface()->getHost(); } else { $postfix = isset($this->config['omit_kgsm']) && $this->config['omit_kgsm'] == "true" ? "/orig=restricted" : ""; $destiny = $tronco->getInterface()->getCanal() . "/" . $dst_number . $postfix; } $flags .= "A({$this->config['announce']})"; $log->info("Discando para {$request->destino} atraves do tronco {$tronco->getName()}({$destiny})"); $dialstatus = $asterisk->get_variable("DIALSTATUS"); $lastdialstatus = $dialstatus['data']; if (Zend_Registry::get('outgoingNumber') !== "") { $asterisk->set_variable("CALLERID(num)", Zend_Registry::get('outgoingNumber')); } $log->debug("Dial({$destiny}, {$this->config['dial_timeout']}, {$flags}"); // ==== DIAL ==== $asterisk->exec_dial($destiny, $this->config['dial_timeout'], $flags); $dialstatus = $asterisk->get_variable("DIALSTATUS"); $log->debug("DIALSTATUS: " . $dialstatus['data']); // Enviar email de alerta. if (isset($this->config['alertEmail']) && $this->config['alertEmail'] != "") { $informations = array('Regra' => $this->getRule(), 'Hora da chamada' => date('H:i'), 'Data da chamada' => date('d/m/Y'), 'Origem Original' => $request->getOriginalCallerid(), 'Destino original' => $request->getOriginalExtension(), 'Origem' => $request->origem, 'Destino' => $request->destino, 'Status da Ligação' => $dialstatus['data']); if ($lastdialstatus != "") { $lastdialaction = null; foreach ($this->getRule()->getAcoes() as $action) { if ($action == $this) { break; } $cfg = $action->getConfigArray(); if ($action instanceof FaxOutAction) { $lastdialaction = PBX_Trunks::get($cfg['tronco']); } else { if ($action instanceof PBX_Rule_Action_DiscarRamal) { $lastdialaction = $cfg['ramal']; } } } $informations["\nHouve uma tentativa de ligação anterior"] = ""; $informations["Ultima ligação para"] = $lastdialaction; $informations["Estado da ultima ligação"] = $lastdialstatus; } $this->sendMailAlert(explode(",", $this->config['alertEmail']), $informations); } switch ($dialstatus['data']) { case 'ANSWER': case 'CANCEL': case 'NOANSWER': case 'BUSY': throw new PBX_Rule_Action_Exception_StopExecution("Fim da ligacao"); break; default: $log->err($dialstatus['data'] . " ao discar para {$request->destino} pelo tronco {$tronco}"); } }
/** * Procura o dono de uma interface baseado em canal. * * @param string $channel Canal da interface * @return object Objeto que representa o dono da interface (se houver) */ public static function getChannelOwner($channel) { $db = Snep_Db::getInstance(); $select = $db->select()->from('trunks'); $trunk_ifaces = $db->query($select)->fetchAll(); foreach ($trunk_ifaces as $interface) { if (preg_match("#^{$interface['id_regex']}\$#i", $channel)) { return PBX_Trunks::get($interface['id']); } } $select = $db->select()->from('peers')->where("name != 'admin' AND peer_type='R'"); $interfaces = $db->query($select)->fetchAll(); foreach ($interfaces as $interface) { if (preg_match("#^{$interface['canal']}\$#i", $channel)) { return PBX_Usuarios::get($interface['name']); } } return null; }
/** * Retorna um usuário em sua classe nativa. * * ex: PBX_Asterisk_Ramal e no futuro Snep_Agent * * @param int $userid * @return Snep_Usuario usuario */ public static function get($userid) { $db = Snep_Db::getInstance(); $userid = str_replace("'", "\\'", $userid); $select = $db->select()->from('peers')->where("name = '{$userid}' AND peer_type='R'"); $stmt = $db->query($select); $usuario = $stmt->fetchObject(); if (!$usuario) { throw new PBX_Exception_NotFound("Usuario {$userid} nao encontrado"); } $tech = substr($usuario->canal, 0, strpos($usuario->canal, '/')); if ($tech == "SIP") { require_once "PBX/Asterisk/Interface/SIP.php"; $interface = new PBX_Asterisk_Interface_SIP(array("username" => $usuario->name, "secret" => $usuario->secret)); } else { if ($tech == "IAX2") { require_once "PBX/Asterisk/Interface/IAX2.php"; $interface = new PBX_Asterisk_Interface_IAX2(array("username" => $usuario->name, "secret" => $usuario->secret)); } else { if ($tech == "MANUAL") { require_once "PBX/Asterisk/Interface/VIRTUAL.php"; $interface = new PBX_Asterisk_Interface_VIRTUAL(array("channel" => substr($usuario->canal, strpos($usuario->canal, '/') + 1))); } else { if ($tech == "VIRTUAL") { require_once "PBX/Asterisk/Interface/VIRTUAL.php"; $trunk = PBX_Trunks::get(substr($usuario->canal, strpos($usuario->canal, '/') + 1)); $interface = new PBX_Asterisk_Interface_VIRTUAL(array("channel" => $trunk->getInterface()->getCanal() . "/" . $userid)); } else { if ($tech == "KHOMP") { require_once "PBX/Asterisk/Interface/KHOMP.php"; $khomp_id = substr($usuario->canal, strpos($usuario->canal, '/') + 1); $khomp_board = substr($khomp_id, 1, strpos($khomp_id, 'c') - 1); $khomp_channel = substr($khomp_id, strpos($khomp_id, 'c') + 1); $interface = new PBX_Asterisk_Interface_KHOMP(array("board" => $khomp_board, "channel" => $khomp_channel)); } else { throw new Exception("Tecnologia {$tech} desconhecida ou invalida."); } } } } } $user = new Snep_Exten($usuario->name, $usuario->password, $usuario->callerid, $interface); $user->setGroup($usuario->group); if ($usuario->authenticate) { $user->lock(); } if ($usuario->dnd) { $user->DNDEnable(); } if ($usuario->sigame != "") { $user->setFollowMe($usuario->sigame); } if (is_numeric($usuario->pickupgroup)) { $user->setPickupGroup($usuario->pickupgroup); } if ($usuario->usa_vc) { $user->setMailBox($usuario->mailbox); $user->setEmail($usuario->email); } return $user; }
/** * Parse a route based on it's POST. * It's assumed here that all fields are already validated * * @param array $postData optional for ovewrite post data * @return PBX_Rule */ protected function parseRuleFromPost($post = null) { $post = $post === null ? $_POST : $post; $rule = new PBX_Rule(); // Adicionando dias da semana $weekDays = array("sun", "mon", "tue", "wed", "thu", "fri", "sat"); $rule->cleanValidWeekList(); foreach ($weekDays as $day) { if (in_array($day, $post['week'])) { $rule->addWeekDay($day); } } // Adicionando Origens foreach (explode(',', $post['srcValue']) as $src) { if (!strpos($src, ':')) { $rule->addSrc(array("type" => $src, "value" => "")); } else { $info = explode(':', $src); if (!is_array($info) or count($info) != 2) { throw new PBX_Exception_BadArg("Valor errado para origem da regra de negocio."); } if ($info[0] == "T") { try { PBX_Trunks::get($info[1]); } catch (PBX_Exception_NotFound $ex) { throw new PBX_Exception_BadArg("Tronco inválido para origem da regra"); } } $rule->addSrc(array("type" => $info[0], "value" => $info[1])); } } // Adding destinys foreach (explode(',', $post['dstValue']) as $dst) { if (!strpos($dst, ':')) { $rule->addDst(array("type" => $dst, "value" => "")); } else { $info = explode(':', $dst); if (!is_array($info) or count($info) != 2) { throw new PBX_Exception_BadArg("Valor errado para destino da regra de negocio."); } if ($info[0] == "T") { try { PBX_Trunks::get($info[1]); } catch (PBX_Exception_NotFound $ex) { throw new PBX_Exception_BadArg("Tronco inválido para destino da regra"); } } $rule->addDst(array("type" => $info[0], "value" => $info[1])); } } // Adding time $rule->cleanValidTimeList(); foreach (explode(',', $post['timeValue']) as $time_period) { $rule->addValidTime($time_period); } // Adding Description $rule->setDesc($post['desc']); // Defining recording order if (isset($post['record']) && $post['record']) { $rule->record(); } // Defining priority $rule->setPriority(substr($post['prio'], 1)); if (isset($post['actions_order'])) { parse_str($post['actions_order'], $actions_order); foreach ($actions_order['actions_list'] as $action) { $real_action = new $post["action_{$action}"]["action_type"](); $action_config = new Snep_Rule_ActionConfig($real_action->getConfig()); $real_action->setConfig($action_config->parseConfig($post["action_{$action}"])); $rule->addAction($real_action); } } return $rule; }
public function indexAction() { $this->view->breadcrumb = Snep_Breadcrumb::renderPath(array($this->view->translate("Routing"), $this->view->translate("Routes"), $this->view->translate("Simulator"))); $trunks = array(); foreach (PBX_Trunks::getAll() as $value) { $trunks[$value->getId()] = $value->getId() . " - " . $value->getName(); } $this->view->trunks = $trunks; if ($this->_request->getPost()) { $formData = $this->_request->getParams(); $extension = isset($formData['dst']) && $formData['dst'] != "" ? $formData['dst'] : 's'; $srcType = isset($formData['srcType']) ? $formData['srcType'] : NULL; $trunk = isset($formData['trunk']) ? $formData['trunk'] : NULL; $caller = isset($formData['caller']) && $formData['caller'] != "" ? $formData['caller'] : "unknown"; $time = isset($formData['time']) ? $formData['time'] : NULL; $dialplan = new PBX_Dialplan_Verbose(); if ($srcType == "exten") { try { $srcObj = PBX_Usuarios::get($caller); } catch (PBX_Exception_NotFound $ex) { $this->view->error = $this->view->translate($ex->getMessage()); $this->view->back = $this->view->translate("Back"); $this->renderScript('simulator/error.phtml'); return; } $channel = $srcObj->getInterface()->getCanal(); } else { if ($srcType == "trunk") { $srcObj = PBX_Trunks::get($trunk); $channel = $srcObj->getInterface()->getCanal(); } else { $srcObj = null; $channel = "unknown"; } } $request = new PBX_Asterisk_AGI_Request(array("agi_callerid" => $caller, "agi_extension" => $extension, "agi_channel" => $channel)); $request->setSrcObj($srcObj); $dialplan->setRequest($request); if ($time) { if (preg_match("/^[0-9]:([0-9]{2})\$/", $time)) { $time = "0" . $time; } $dialplan->setTime($time); } try { $dialplan->parse(); } catch (PBX_Exception_NotFound $ex) { $this->view->error = $this->view->translate("No rule found."); $this->view->back = $this->view->translate("Back"); $this->renderScript('simulator/error.phtml'); return; } if (count($dialplan->getMatches()) > 0) { $found = false; foreach ($dialplan->getMatches() as $index => $rule) { if ($rule->getId() == $dialplan->getLastRule()->getId()) { $state = "torun"; $found = true; } else { if ($found) { $state = "ignored"; } else { $state = "outdated"; } } $actions = array(); foreach ($rule->getAcoes() as $action) { $config = $action->getConfigArray(); if ($action instanceof CCustos) { $actions[] = $this->view->translate("Define Cost Center to ") . $config['ccustos']; } else { if ($action instanceof DiscarTronco) { $tronco = PBX_Trunks::get($config['tronco']); $actions[] = $this->view->translate("Dial through Trunk ") . $tronco->getName(); } else { if ($action instanceof DiscarRamal) { if (isset($config['ramal']) && $config['ramal'] != "") { $peer = $config['ramal']; } else { $peer = $extension; } try { $ramal = PBX_Usuarios::get($peer); $actions[] = $this->view->translate("Dial to extension %s", $ramal->getCallerid()); } catch (PBX_Exception_NotFound $ex) { $actions[] = "<strong style='color:red'>" . $this->view->translate("Failure on trial to dial extension %: non existent extension", $extension) . "</strong>"; } } else { if ($action instanceof Queue) { $actions[] = $this->view->translate("Direct to queue %s", $config['queue']); } else { if ($action instanceof Cadeado) { $actions[] = $this->view->translate("Request password"); } else { if ($action instanceof Context) { $actions[] = $this->view->translate("Redirect to context %s", $config['context']); } } } } } } } $srcs = array(); foreach ($rule->getSrcList() as $src) { $srcs[] = trim(implode(":", $src), ':'); } $srcs = implode(",", $srcs); $dsts = array(); foreach ($rule->getDstList() as $dst) { $dsts[] = trim(implode(":", $dst), ':'); } $dsts = implode(",", $dsts); $result[$index] = array("id" => $rule->getId(), "state" => $state, "caller" => $srcs, "dst" => $dsts, "desc" => $rule->getDesc(), "valid" => join(";", $rule->getValidTimeList()), "actions" => $actions); } $input = array("caller" => $caller, "dst" => $extension, "time" => $dialplan->getLastExecutionTime()); $this->view->input = $input; $this->view->result = $result; } } }
/** * Executa a ação. É chamado dentro de uma instancia usando AGI. * * @param Asterisk_AGI $asterisk * @param Asterisk_AGI_Request $request */ public function execute($asterisk, $request) { $log = Zend_Registry::get('log'); $trs = $this->i18n; $tronco = PBX_Trunks::get($this->config['tronco']); // Montando as Flags para limite na ligação $flags = $this->config['dial_flags']; if (isset($this->config['dial_limit']) && $this->config['dial_limit'] > 0) { $flags .= "L(" . $this->config['dial_limit']; // play_warning_value if (isset($this->defaultConfig['play_warning']) && $this->defaultConfig['play_warning'] > 0) { $flags .= ":" . $this->defaultConfig['play_warning']; // warning_freq if (isset($this->defaultConfig['warning_freq']) && $this->defaultConfig['warning_freq'] > 0) { $flags .= ":" . $this->defaultConfig['warning_freq']; } } $flags .= ")"; if (isset($this->defaultConfig['warning_sound'])) { $warning_sound = $this->defaultConfig['warning_sound'] != "" ? $this->defaultConfig['warning_sound'] : "beep"; $asterisk->set_variable("LIMIT_WARNING_FILE", $warning_sound); } } if ($tronco->getDtmfDialMode()) { $dst_number = $tronco->getDtmfDialNumber(); $flags .= "D({$request->destino})"; } else { $dst_number = $request->destino; } if ($tronco->getInterface() instanceof PBX_Asterisk_Interface_SIP_NoAuth || $tronco->getInterface() instanceof PBX_Asterisk_Interface_IAX2_NoAuth) { $destiny = $tronco->getInterface()->getTech() . "/" . $dst_number . "@" . $tronco->getInterface()->getHost(); } else { $postfix = isset($this->config['omit_kgsm']) && $this->config['omit_kgsm'] == "true" ? "/orig=restricted" : ""; $destiny = $tronco->getInterface()->getCanal() . "/" . $dst_number . $postfix; } $log->info("Dialing to {$request->destino} through trunk {$tronco->getName()}({$destiny})"); $dialstatus = $asterisk->get_variable("DIALSTATUS"); $lastdialstatus = $dialstatus['data']; if (Zend_Registry::get('outgoingNumber') !== "") { $asterisk->set_variable("CALLERID(num)", Zend_Registry::get('outgoingNumber')); } $log->debug("Dial({$destiny}, {$this->config['dial_timeout']}, {$flags})"); // ==== DIAL ==== $asterisk->exec_dial($destiny, $this->config['dial_timeout'], $flags); $dialstatus = $asterisk->get_variable("DIALSTATUS"); $log->debug("DIALSTATUS: " . $dialstatus['data']); // Enviar email de alerta. if (isset($this->config['alertEmail']) && $this->config['alertEmail'] != "") { $informations = array($trs->translate('Rule') => $this->getRule(), $trs->translate('Call Time') => date('H:i'), $trs->translate('Call Date') => date('d/m/Y'), $trs->translate('Original Source') => $request->getOriginalCallerid(), $trs->translate('Original Destination') => $request->getOriginalExtension(), $trs->translate('Source') => $request->origem, $trs->translate('Destination') => $request->destino, $trs->translate('Call status') => $dialstatus['data']); if ($lastdialstatus != "") { $lastdialaction = null; foreach ($this->getRule()->getAcoes() as $action) { if ($action == $this) { break; } $cfg = $action->getConfigArray(); if ($action instanceof DiscarTronco) { $lastdialaction = PBX_Trunks::get($cfg['tronco']); } else { if ($action instanceof DiscarRamal) { $lastdialaction = $cfg['ramal']; } } } $informations[$trs->translate("\nThere were a previous call attempt")] = ""; $informations[$trs->translate("Last call to")] = $lastdialaction; $informations[$trs->translate("Status of last call")] = $lastdialstatus; } $this->sendMailAlert(explode(",", $this->config['alertEmail']), $informations); } switch ($dialstatus['data']) { case 'ANSWER': case 'CANCEL': case 'NOANSWER': case 'BUSY': throw new PBX_Rule_Action_Exception_StopExecution("Call end"); break; default: $log->err($dialstatus['data'] . " dialing to {$request->destino} through trunk {$tronco}"); } }