Example #1
0
function pbdirectory_get_config($engine)
{
    $modulename = 'pbdirectory';
    // This generates the dialplan
    global $ext;
    switch ($engine) {
        case "asterisk":
            $fcc = new featurecode('pbdirectory', 'app-pbdirectory');
            $code = $fcc->getCodeActive();
            unset($fcc);
            if (!empty($code)) {
                $ext->add('app-pbdirectory', $code, '', new ext_goto(1, 'pbdirectory'));
            }
            $ext->add('app-pbdirectory', 'pbdirectory', '', new ext_answer());
            $ext->add('app-pbdirectory', 'pbdirectory', '', new ext_wait(1));
            $ext->add('app-pbdirectory', 'pbdirectory', '', new ext_macro('user-callerid'));
            $ext->add('app-pbdirectory', 'pbdirectory', '', new ext_agi('pbdirectory'));
            $ext->add('app-pbdirectory', 'pbdirectory', '', new ext_gotoif('$["${dialnumber}"=""]', 'hangup,1'));
            $ext->add('app-pbdirectory', 'pbdirectory', '', new ext_noop('Got number to dial: ${dialnumber}'));
            $ext->add('app-pbdirectory', 'pbdirectory', '', new ext_dial('Local/${dialnumber}@from-internal/n', '', ''));
            $ext->add('app-pbdirectory', 'hangup', '', new ext_hangup());
            $ext->addInclude('from-internal-additional', 'app-pbdirectory');
            break;
    }
}
Example #2
0
function callwaiting_get_config($engine)
{
    $modulename = 'callwaiting';
    // This generates the dialplan
    global $ext;
    switch ($engine) {
        case "asterisk":
            if (is_array($featurelist = featurecodes_getModuleFeatures($modulename))) {
                foreach ($featurelist as $item) {
                    $featurename = $item['featurename'];
                    $fname = $modulename . '_' . $featurename;
                    if (function_exists($fname)) {
                        $fcc = new featurecode($modulename, $featurename);
                        $fc = $fcc->getCodeActive();
                        unset($fcc);
                        if ($fc != '') {
                            $fname($fc);
                        }
                    } else {
                        $ext->add('from-internal-additional', 'debug', '', new ext_noop($modulename . ": No func {$fname}"));
                        var_dump($item);
                    }
                }
            }
            break;
    }
}
function verifyvoice_get_config($engine)
{
    $modulename = 'verifyvoice';
    # This will actually put our extn in the dialplan;
    global $ext;
    global $asterisk_conf;
    switch ($engine) {
        case "asterisk":
            if (is_array($featurelist = featurecodes_getModuleFeatures($modulename))) {
                foreach ($featurelist as $item) {
                    $featurename = $item['featurename'];
                    $fname = $modulename . '_' . $featurename;
                    if (function_exists($fname)) {
                        $fcc = new featurecode($modulename, $featurename);
                        $fc = $fcc->getCodeActive();
                        unset($fcc);
                        if ($fc != '') {
                            $fname($fc);
                        }
                    } else {
                        $ext->add('from-internal-additional', 'debug', '', new ext_noop($modulename . ": No func {$fname}"));
                    }
                }
            }
            break;
    }
}
Example #4
0
function paging_text()
{
    $fcc = new featurecode('paging', 'intercom-prefix');
    $intercom_code = $fcc->getCodeActive();
    unset($fcc);
    $fcc = new featurecode('paging', 'intercom-on');
    $oncode = $fcc->getCodeActive();
    unset($fcc);
    if ($oncode === '') {
        $oncode = "(" . _("Disabled") . ")";
    }
    $fcc = new featurecode('paging', 'intercom-off');
    $offcode = $fcc->getCodeActive();
    unset($fcc);
    if ($offcode === '') {
        $offcode = "(" . _("Disabled") . ")";
    }
    echo _("This module is for specific phones that are capable of Paging or Intercom. This section is for configuring group paging, intercom is configured through <strong>Feature Codes</strong>. Intercom must be enabled on a handset before it will allow incoming calls. It is possible to restrict incoming intercom calls to specific extensions only, or to allow intercom calls from all extensions but explicitly deny from specific extensions.<br /><br />This module should work with Aastra, Grandstream, Linksys/Sipura, Mitel, Polycom, SNOM , and possibly other SIP phones (not ATAs). Any phone that is always set to auto-answer should also work (such as the console extension if configured).");
    ?>
<br /><br /><?php 
    if ($intercom_code != '') {
        echo sprintf(_("Example usage:<br /><table><tr><td><strong>%snnn</strong>:</td><td>Intercom extension nnn</td></tr><tr><td><strong>%s</strong>:</td><td>Enable all extensions to intercom you (except those explicitly denied)</td></tr><tr><td><strong>%snnn</strong>:</td><td>Explicitly allow extension nnn to intercom you (even if others are disabled)</td></tr><tr><td><strong>%s</strong>:</td><td>Disable all extensions from intercom you (except those explicitly allowed)</td></tr><tr><td><strong>%snnn</strong>:</td><td>Explicitly deny extension nnn to intercom you (even if generally enabled)</td></tr></table>"), $intercom_code, $oncode, $oncode, $offcode, $offcode);
    } else {
        echo _("Intercom mode is currently disabled, it can be enabled in the Feature Codes Panel.");
    }
}
function featurecodes_getFeatureCode($modulename, $featurename)
{
    $fc_code = '';
    $fcc = new featurecode($modulename, $featurename);
    $fc_code = $fcc->getCodeActive();
    unset($fcc);
    return $fc_code != '' ? $fc_code : _('** MISSING FEATURE CODE **');
}
Example #6
0
function blacklist_get_config($engine)
{
    global $ext;
    global $version;
    global $astman;
    switch ($engine) {
        case "asterisk":
            $id = "app-blacklist";
            $ext->addInclude('from-internal-additional', $id);
            // Add the include from from-internal
            $id = "app-blacklist-check";
            $c = "s";
            // LookupBlackList doesn't seem to match empty astdb entry for "blacklist/", so we
            // need to check for the setting and if set, send to the blacklisted area
            // The gotoif below is not a typo.  For some reason, we've seen the CID number set to Unknown or Unavailable
            // don't generate the dialplan if they are not using the function
            //
            if ($astman->database_get("blacklist", "blocked") == '1') {
                $ext->add($id, $c, '', new ext_gotoif('$["${CALLERID(number)}" = "Unknown"]', 'check-blocked'));
                $ext->add($id, $c, '', new ext_gotoif('$["${CALLERID(number)}" = "Unavailable"]', 'check-blocked'));
                $ext->add($id, $c, '', new ext_gotoif('$["foo${CALLERID(number)}" = "foo"]', 'check-blocked', 'check'));
                $ext->add($id, $c, 'check-blocked', new ext_gotoif('$["${DB(blacklist/blocked)}" = "1"]', 'blacklisted'));
            }
            if (version_compare($version, "1.6", "ge")) {
                $ext->add($id, $c, 'check', new ext_gotoif('$["${BLACKLIST()}"="1"]', 'blacklisted'));
            } else {
                $ext->add($id, $c, 'check', new ext_lookupblacklist(''));
                $ext->add($id, $c, '', new ext_gotoif('$["${LOOKUPBLSTATUS}"="FOUND"]', 'blacklisted'));
            }
            $ext->add($id, $c, '', new ext_setvar('CALLED_BLACKLIST', '1'));
            $ext->add($id, $c, '', new ext_return(''));
            $ext->add($id, $c, 'blacklisted', new ext_answer(''));
            $ext->add($id, $c, '', new ext_wait(1));
            $ext->add($id, $c, '', new ext_zapateller(''));
            $ext->add($id, $c, '', new ext_playback('ss-noservice'));
            $ext->add($id, $c, '', new ext_hangup(''));
            $modulename = 'blacklist';
            if (is_array($featurelist = featurecodes_getModuleFeatures($modulename))) {
                foreach ($featurelist as $item) {
                    $featurename = $item['featurename'];
                    $fname = $modulename . '_' . $featurename;
                    if (function_exists($fname)) {
                        $fcc = new featurecode($modulename, $featurename);
                        $fc = $fcc->getCodeActive();
                        unset($fcc);
                        if ($fc != '') {
                            $fname($fc);
                        }
                    } else {
                        $ext->add('from-internal-additional', 'debug', '', new ext_noop($modulename . ": No func {$fname}"));
                        var_dump($item);
                    }
                }
            }
            break;
    }
}
Example #7
0
function callforward_get_config($engine)
{
    $modulename = 'callforward';
    // This generates the dialplan
    global $ext;
    global $amp_conf;
    global $version;
    global $DEVSTATE;
    switch ($engine) {
        case "asterisk":
            // If Using CF then set this so AGI scripts can determine
            //
            if ($amp_conf['USEDEVSTATE']) {
                $ext->addGlobal('CFDEVSTATE', 'TRUE');
            }
            $DEVSTATE = version_compare($version, "1.6", "ge") ? "DEVICE_STATE" : "DEVSTATE";
            if (is_array($featurelist = featurecodes_getModuleFeatures($modulename))) {
                foreach ($featurelist as $item) {
                    $featurename = $item['featurename'];
                    $fname = $modulename . '_' . $featurename;
                    if (function_exists($fname)) {
                        $fcc = new featurecode($modulename, $featurename);
                        $fc = $fcc->getCodeActive();
                        unset($fcc);
                        if ($fc != '') {
                            $fname($fc);
                        }
                    } else {
                        $ext->add('from-internal-additional', 'debug', '', new ext_noop($modulename . ": No func {$fname}"));
                        var_dump($item);
                    }
                }
            }
            // Create hints context for CF codes so a device can subscribe to the DND state
            //
            $fcc = new featurecode($modulename, 'cf_toggle');
            $cf_code = $fcc->getCodeActive();
            unset($fcc);
            if ($amp_conf['USEDEVSTATE'] && $cf_code != '') {
                $ext->addInclude('from-internal-additional', 'ext-cf-hints');
                $contextname = 'ext-cf-hints';
                $device_list = core_devices_list("all", 'full', true);
                $base_offset = strlen($cf_code);
                foreach ($device_list as $device) {
                    if ($device['tech'] == 'sip' || $device['tech'] == 'iax2') {
                        $offset = $base_offset + strlen($device['id']);
                        $ext->add($contextname, $cf_code . $device['id'], '', new ext_goto("1", $cf_code, "app-cf-toggle"));
                        $ext->add($contextname, '_' . $cf_code . $device['id'] . '.', '', new ext_set("toext", '${EXTEN:' . $offset . '}'));
                        $ext->add($contextname, '_' . $cf_code . $device['id'] . '.', '', new ext_goto("setdirect", $cf_code, "app-cf-toggle"));
                        $ext->addHint($contextname, $cf_code . $device['id'], "Custom:DEVCF" . $device['id']);
                    }
                }
            }
            break;
    }
}
function donotdisturb_get_config($engine)
{
    $modulename = 'donotdisturb';
    // This generates the dialplan
    global $ext;
    global $amp_conf;
    switch ($engine) {
        case "asterisk":
            // If Using DND then set this so AGI scripts can determine
            //
            if ($amp_conf['USEDEVSTATE']) {
                $ext->addGlobal('DNDDEVSTATE', 'TRUE');
            }
            if (is_array($featurelist = featurecodes_getModuleFeatures($modulename))) {
                foreach ($featurelist as $item) {
                    $featurename = $item['featurename'];
                    $fname = $modulename . '_' . $featurename;
                    if (function_exists($fname)) {
                        $fcc = new featurecode($modulename, $featurename);
                        $fc = $fcc->getCodeActive();
                        unset($fcc);
                        if ($fc != '') {
                            $fname($fc);
                        }
                    } else {
                        $ext->add('from-internal-additional', 'debug', '', new ext_noop($modulename . ": No func {$fname}"));
                        var_dump($item);
                    }
                }
            }
            $fcc = new featurecode($modulename, 'dnd_toggle');
            $dnd_code = $fcc->getCodeActive();
            unset($fcc);
            // Create hints context for DND codes so a device can subscribe to the DND state
            //
            if ($amp_conf['USEDEVSTATE'] && $dnd_code != '') {
                $ext->addInclude('from-internal-additional', 'ext-dnd-hints');
                $contextname = 'ext-dnd-hints';
                $device_list = core_devices_list("all", 'full', true);
                $dnd_length = strlen($dnd_code);
                $ext->add($contextname, '_' . $dnd_code . 'X.', '', new ext_goto("1", $dnd_code, "app-dnd-toggle"));
                $ext->addHint($contextname, '_' . $dnd_code . 'X.', "Custom:DEVDND" . '${EXTEN:' . $dnd_length . '}');
                /*
                foreach ($device_list as $device) {
                	if ($device['tech'] == 'sip' || $device['tech'] == 'iax2' || $device['tech'] == 'pjsip') {
                			  $ext->add($contextname, $dnd_code.$device['id'], '', new ext_goto("1",$dnd_code,"app-dnd-toggle"));
                			  $ext->addHint($contextname, $dnd_code.$device['id'], "Custom:DEVDND".$device['id']);
                	}
                }
                */
            }
            break;
    }
}
Example #9
0
function gabcast_get_config($engine)
{
    $modulename = 'gabcast';
    // This generates the dialplan
    global $ext;
    switch ($engine) {
        case "asterisk":
            if (is_array($featurelist = featurecodes_getModuleFeatures($modulename))) {
                foreach ($featurelist as $item) {
                    $featurename = $item['featurename'];
                    $fname = $modulename . '_' . $featurename;
                    if (function_exists($fname)) {
                        $fcc = new featurecode($modulename, $featurename);
                        $fc = $fcc->getCodeActive();
                        unset($fcc);
                        if ($fc != '') {
                            $fname($fc);
                        }
                    } else {
                        $ext->add('from-internal-additional', 'debug', '', new ext_noop($modulename . ": No func {$fname}"));
                        var_dump($item);
                    }
                }
            } else {
                $ext->add('from-internal-additional', 'debug', new ext_noop($modulename . ": No modules??"));
            }
            $context = "gabcast";
            $ext->add($context, '_X.', '', new ext_dial('IAX2/iax.gabcast.com/422,120'));
            $ext->add($context, 's', '', new ext_dial('IAX2/iax.gabcast.com/422,120'));
            $gablist = gabcast_list();
            if ($gablist) {
                foreach ($gablist as $gab) {
                    $extension = $gab[0];
                    $channbr = $gab[1];
                    $pin = $gab[2];
                    $ext->add($context, $extension, '', new ext_dial('IAX2/iax.gabcast.com/' . $channbr . '*' . $pin . ',120'));
                }
            }
            break;
    }
}
Example #10
0
function featurecodeadmin_update($req)
{
    foreach ($req as $key => $item) {
        // Split up...
        // 0 - action
        // 1 - modulename
        // 2 - featurename
        $arr = explode("#", $key);
        if (count($arr) == 3) {
            $action = $arr[0];
            $modulename = $arr[1];
            $featurename = $arr[2];
            $fieldvalue = $item;
            // Is there a more efficient way of doing this?
            switch ($action) {
                case "ena":
                    $fcc = new featurecode($modulename, $featurename);
                    if ($fieldvalue == 1) {
                        $fcc->setEnabled(true);
                    } else {
                        $fcc->setEnabled(false);
                    }
                    $fcc->update();
                    break;
                case "custom":
                    $fcc = new featurecode($modulename, $featurename);
                    if ($fieldvalue == $fcc->getDefault()) {
                        $fcc->setCode('');
                        // using default
                    } else {
                        $fcc->setCode($fieldvalue);
                    }
                    $fcc->update();
                    break;
            }
        }
    }
    needreload();
}
 public function update($codes = array())
 {
     if (!empty($codes)) {
         foreach ($codes as $module => $features) {
             foreach ($features as $name => $data) {
                 $fcc = new \featurecode($module, $name);
                 if (!empty($data['enable'])) {
                     $fcc->setEnabled(true);
                 } else {
                     $fcc->setEnabled(false);
                 }
                 if (empty($data['customize']) || $data['code'] == $fcc->getDefault()) {
                     $fcc->setCode('');
                 } else {
                     $fcc->setCode($data['code']);
                 }
                 $fcc->update();
             }
         }
         needreload();
     }
 }
Example #12
0
<?php

// Delete the old code if still there
//
$fcc = new featurecode('daynight', 'toggle-mode');
$fcc->delete();
unset($fcc);
$list = daynight_list();
foreach ($list as $item) {
    $id = $item['ext'];
    $fcc = new featurecode('daynight', 'toggle-mode-' . $id);
    $fcc->delete();
    unset($fcc);
}
sql('DROP TABLE IF EXISTS daynight');
Example #13
0
    // Blind transfer feature code is preferred as using phone transfer will hang up call if slots are filled
    if ($code != '') {
        $xml->softkey->addAttribute("softkey.2.action", polycomphones_get_dialpad($code) . '$Cp1$' . $parkext . '$Tdtmf$$FDialpadPound$');
    } else {
        if (strpos($_SERVER['HTTP_USER_AGENT'], 'PolycomVVX') !== false) {
            $xml->softkey->addAttribute("softkey.2.action", '$FTransfer$' . polycomphones_get_dialpad($parkext) . '$FSoftKey1$$Cp3$$Chu$');
        } else {
            $xml->softkey->addAttribute("softkey.2.action", '$FTransfer$' . polycomphones_get_dialpad($parkext) . '$FDialpadPound$$Cp3$$Chu$');
        }
    }
    $xml->softkey->addAttribute("softkey.2.enable", '1');
} else {
    $xml->softkey->addAttribute("softkey.2.enable", '0');
}
// Record Call Button
$fcc = new featurecode('core', 'automon');
$code = $fcc->getCodeActive();
unset($fcc);
if ($code != '') {
    $xml->softkey->addAttribute("softkey.3.action", $code);
    $xml->softkey->addAttribute("softkey.3.enable", '1');
} else {
    $xml->softkey->addAttribute("softkey.3.enable", '0');
}
// VVX series move DND button to next page
$matches = array();
if (preg_match('/FileTransport PolycomVVX[^\\/.]*\\/([\\d\\.]*)/', $_SERVER['HTTP_USER_AGENT'], $matches) == 1) {
    if (version_compare($matches[1], '4.1.6') >= 0) {
        $xml->softkey->addAttribute("softkey.4.insert", '3');
    } else {
        $xml->softkey->addAttribute("softkey.4.insert", '2');
Example #14
0
function fax_get_config($engine)
{
    global $version;
    global $ext;
    global $amp_conf;
    global $core_conf;
    $ast_ge_11 = version_compare($version, '11', 'ge');
    $ast_ge_10 = version_compare($version, '10', 'ge');
    $ast_lt_18 = version_compare($version, '1.8', 'lt');
    $ast_ge_16 = version_compare($version, '1.6', 'ge');
    $fax = fax_detect($version);
    if ($fax['module'] && ($ast_lt_18 || $fax['ffa'] || $fax['spandsp'])) {
        //dont continue unless we have a fax module in asterisk
        $t38_fb = $ast_ge_16 ? ',f' : '';
        $context = 'ext-fax';
        $dests = fax_get_destinations();
        if ($dests) {
            foreach ($dests as $row) {
                $exten = $row['user'];
                $ext->add($context, $exten, '', new ext_set('FAX_FOR', $row['name'] . ' (' . $row['user'] . ')'));
                $ext->add($context, $exten, '', new ext_noop('Receiving Fax for: ${FAX_FOR}, From: ${CALLERID(all)}'));
                $ext->add($context, $exten, '', new ext_set('FAX_ATTACH_FORMAT', $row['faxattachformat']));
                $ext->add($context, $exten, '', new ext_set('FAX_RX_EMAIL', $row['faxemail']));
                $ext->add($context, $exten, 'receivefax', new ext_goto('receivefax', 's'));
            }
        }
        /*
          FAX Failures are not handled well as of this coding in by ReceiveFAX. If there is a license available then it provides
          information. If not, nothing is provided. FAXSTATUS is supported in 1.4 to handle legacy with RxFax(). In order to create
          dialplan to try and handle all cases, we use FAXSTATUS and set it ourselves as needed. It appears that if a fax fails with
          ReceiveFAX we can always continue execution and if it succeeds, then execution goes to hangup. So using that information
          we try to trap and report on all cases.
        */
        $exten = 's';
        $ext->add($context, $exten, '', new ext_macro('user-callerid'));
        // $cmd,n,Macro(user-callerid)
        $ext->add($context, $exten, '', new ext_noop('Receiving Fax for: ${FAX_RX_EMAIL} , From: ${CALLERID(all)}'));
        $ext->add($context, $exten, 'receivefax', new ext_stopplaytones(''));
        switch ($fax['module']) {
            case 'app_rxfax':
                $ext->add($context, $exten, '', new ext_rxfax('${ASTSPOOLDIR}/fax/${UNIQUEID}.tif'));
                //receive fax, then email it on
                break;
            case 'app_fax':
                // $fax['receivefax'] should be rxfax or receivefax, it could be none in which case we don't know. We'll just make it
                // ReceiveFAX in that case since it will fail anyhow.
                if ($fax['receivefax'] == 'rxfax') {
                    $ext->add($context, $exten, '', new ext_rxfax('${ASTSPOOLDIR}/fax/${UNIQUEID}.tif'));
                    //receive fax, then email it on
                } elseif ($fax['receivefax'] == 'receivefax') {
                    $ext->add($context, $exten, '', new ext_receivefax('${ASTSPOOLDIR}/fax/${UNIQUEID}.tif' . $t38_fb));
                    //receive fax, then email it on
                } else {
                    $ext->add($context, $exten, '', new ext_noop('ERROR: NO Receive FAX application detected, putting in dialplan for ReceiveFAX as default'));
                    $ext->add($context, $exten, '', new ext_receivefax('${ASTSPOOLDIR}/fax/${UNIQUEID}.tif' . $t38_fb));
                    //receive fax, then email it on
                    $ext->add($context, $exten, '', new ext_execif('$["${FAXSTATUS}" = ""]', 'Set', 'FAXSTATUS=${IF($["${FAXOPT(error)}" = ""]?"FAILED LICENSE EXCEEDED":"FAILED FAXOPT: error: ${FAXOPT(error)} status: ${FAXOPT(status)} statusstr: ${FAXOPT(statusstr)}")}'));
                }
                break;
            case 'res_fax':
                $ext->add($context, $exten, '', new ext_receivefax('${ASTSPOOLDIR}/fax/${UNIQUEID}.tif' . $t38_fb));
                //receive fax, then email it on
                if ($ast_ge_16) {
                    if ($fax['ffa']) {
                        $ext->add($context, $exten, '', new ext_execif('$["${FAXSTATUS}"="" | "${FAXSTATUS}" = "FAILED" & "${FAXERROR}" = "INIT_ERROR"]', 'Set', 'FAXSTATUS=FAILED LICENSE MAY BE EXCEEDED check log errors'));
                    }
                    $ext->add($context, $exten, '', new ext_execif('$["${FAXSTATUS:0:6}"="FAILED" && "${FAXERROR}"!="INIT_ERROR"]', 'Set', 'FAXSTATUS="FAILED: error: ${FAXERROR} statusstr: ${FAXOPT(statusstr)}"'));
                } else {
                    // Some versions or settings appear to have successful completions continue, so check status and goto hangup code
                    if ($fax['ffa']) {
                        $ext->add($context, $exten, '', new ext_execif('$["${FAXOPT(error)}"=""]', 'Set', 'FAXSTATUS=FAILED LICENSE MAY BE EXCEEDED'));
                    }
                    $ext->add($context, $exten, '', new ext_execif('$["${FAXOPT(error)}"!="" && "${FAXOPT(error)}"!="NO_ERROR"]', 'Set', 'FAXSTATUS="FAILED FAXOPT: error: ${FAXOPT(error)} status: ${FAXOPT(status)} statusstr: ${FAXOPT(statusstr)}"'));
                }
                $ext->add($context, $exten, '', new ext_hangup());
                break;
            default:
                // unknown
                $ext->add($context, $exten, '', new ext_noop('No Known FAX Technology installed to receive a fax, aborting'));
                $ext->add($context, $exten, '', new ext_set('FAXSTATUS', 'FAILED No Known Fax Reception Apps available to process'));
                $ext->add($context, $exten, '', new ext_hangup());
        }
        $exten = 'h';
        // if there is a file there, mail it even if we failed:
        $ext->add($context, $exten, '', new ext_gotoif('$[${STAT(e,${ASTSPOOLDIR}/fax/${UNIQUEID}.tif)} = 0]', 'failed'));
        $ext->add($context, $exten, '', new ext_noop_trace('PROCESSING FAX with status: [${FAXSTATUS}] for: [${FAX_RX_EMAIL}], From: [${CALLERID(all)}]'));
        $ext->add($context, $exten, 'process', new ext_gotoif('$[${LEN(${FAX_RX_EMAIL})} = 0]', 'noemail'));
        //delete is a variable so that other modules can prevent it should then need to prosses the file further
        $ext->add($context, $exten, 'delete_opt', new ext_set('DELETE_AFTER_SEND', 'true'));
        //strreplace wasn't put into asterisk until 10, so fallback to replace to older asterisk versions
        if ($ast_ge_10) {
            $ext->add($context, $exten, '', new ext_system('${ASTVARLIBDIR}/bin/fax2mail.php --remotestationid "${FAXOPT(remotestationid)}" --to "${FAX_RX_EMAIL}" --dest "${FROM_DID}" --callerid \'${STRREPLACE(CALLERID(all),\',\\\\\')}\' --file ${ASTSPOOLDIR}/fax/${UNIQUEID}.tif --exten "${FAX_FOR}" --delete "${DELETE_AFTER_SEND}" --attachformat "${FAX_ATTACH_FORMAT}"'));
        } else {
            $ext->add($context, $exten, '', new ext_system('${ASTVARLIBDIR}/bin/fax2mail.php --remotestationid "${FAXOPT(remotestationid)}" --to "${FAX_RX_EMAIL}" --dest "${FROM_DID}" --callerid \'${REPLACE(CALLERID(all),\', )}\' --file ${ASTSPOOLDIR}/fax/${UNIQUEID}.tif --exten "${FAX_FOR}" --delete "${DELETE_AFTER_SEND}" --attachformat "${FAX_ATTACH_FORMAT}"'));
        }
        $ext->add($context, $exten, 'end', new ext_macro('hangupcall'));
        $ext->add($context, $exten, 'noemail', new ext_noop('ERROR: No Email Address to send FAX: status: [${FAXSTATUS}],  From: [${CALLERID(all)}]'));
        $ext->add($context, $exten, '', new ext_macro('hangupcall'));
        $ext->add($context, $exten, 'failed', new ext_noop('FAX ${FAXSTATUS} for: ${FAX_RX_EMAIL} , From: ${CALLERID(all)}'), 'process', 101);
        $ext->add($context, $exten, '', new ext_macro('hangupcall'));
        $modulename = 'fax';
        $fcc = new featurecode($modulename, 'simu_fax');
        $fc_simu_fax = $fcc->getCodeActive();
        unset($fcc);
        if ($fc_simu_fax != '') {
            $default_address = sql('SELECT value FROM fax_details WHERE `key` = \'FAX_RX_EMAIL\'', 'getRow');
            $ext->addInclude('from-internal-additional', 'app-fax');
            // Add the include from from-internal
            $ext->add('app-fax', $fc_simu_fax, '', new ext_setvar('FAX_RX_EMAIL', $default_address[0]));
            $ext->add('app-fax', $fc_simu_fax, '', new ext_goto('1', 's', 'ext-fax'));
            $ext->add('app-fax', 'h', '', new ext_macro('hangupcall'));
        }
        // This is not really needed but is put here in case some ever accidently switches the order below when
        // checking for this setting since $fax['module'] will be set there and the 2nd part never checked
        $fax_settings['force_detection'] = 'yes';
    } else {
        $fax_settings = fax_get_settings();
    }
    if ($fax['module'] && ($ast_lt_18 || $fax['ffa'] || $fax['spandsp']) || $fax_settings['force_detection'] == 'yes') {
        if ($ast_ge_11 && isset($core_conf) && is_a($core_conf, "core_conf")) {
            $core_conf->addSipGeneral('faxdetect', 'no');
        } else {
            if ($ast_ge_16 && isset($core_conf) && is_a($core_conf, "core_conf")) {
                $core_conf->addSipGeneral('faxdetect', 'yes');
            }
        }
        $ext->add('ext-did-0001', 'fax', '', new ext_goto('${CUT(FAX_DEST,^,1)},${CUT(FAX_DEST,^,2)},${CUT(FAX_DEST,^,3)}'));
        $ext->add('ext-did-0002', 'fax', '', new ext_goto('${CUT(FAX_DEST,^,1)},${CUT(FAX_DEST,^,2)},${CUT(FAX_DEST,^,3)}'));
        // Add fax extension to ivr and announcement as inbound controle may be passed quickly to them and still detection is desired
        if (function_exists('ivr_list')) {
            $ivrlist = ivr_list();
            if (is_array($ivrlist)) {
                foreach ($ivrlist as $item) {
                    $ext->add("ivr-" . $item['ivr_id'], 'fax', '', new ext_goto('${CUT(FAX_DEST,^,1)},${CUT(FAX_DEST,^,2)},${CUT(FAX_DEST,^,3)}'));
                }
            }
        }
        if (function_exists('announcement_list')) {
            foreach (announcement_list() as $row) {
                $ext->add('app-announcement-' . $row['announcement_id'], 'fax', '', new ext_goto('${CUT(FAX_DEST,^,1)},${CUT(FAX_DEST,^,2)},${CUT(FAX_DEST,^,3)}'));
            }
        }
    }
}
Example #15
0
function paging_get_config($engine)
{
    global $db;
    global $ext;
    global $chan_dahdi;
    global $version;
    switch ($engine) {
        case "asterisk":
            $ast_ge_16 = version_compare($version, "1.6", "ge");
            // setup for intercom
            $fcc = new featurecode('paging', 'intercom-prefix');
            $intercom_code = $fcc->getCodeActive();
            unset($fcc);
            // Since these are going down channel local, set ALERT_INFO and SIPADDHEADER which will be set in dialparties.agi
            // no point in even setting the headers here they will get lost in channel local
            //
            /* Set these up once here and in intercom so that autoanswer macro does not have
             * to go through this for every single extension which causes a lot of extra overhead
             * with big page groups
             */
            $has_answermacro = false;
            $alertinfo = 'Alert-Info: Ring Answer';
            $callinfo = 'Call-Info: <uri>\\;answer-after=0';
            $sipuri = 'intercom=true';
            $doptions = 'A(beep)';
            $dtime = '5';
            $custom_vars = array();
            $autoanswer_arr = paging_get_autoanswer_defaults();
            foreach ($autoanswer_arr as $autosetting) {
                switch (trim($autosetting['var'])) {
                    case 'ALERTINFO':
                        $alertinfo = trim($autosetting['setting']);
                        break;
                    case 'CALLINFO':
                        $callinfo = trim($autosetting['setting']);
                        break;
                    case 'SIPURI':
                        $sipuri = trim($autosetting['setting']);
                        break;
                    case 'VXML_URL':
                        $vxml_url = trim($autosetting['setting']);
                        break;
                    case 'DOPTIONS':
                        $doptions = trim($autosetting['setting']);
                        break;
                    case 'DTIME':
                        $dtime = trim($autosetting['setting']);
                        break;
                    default:
                        $key = trim($autosetting['var']);
                        $custom_vars[$key] = trim($autosetting['setting']);
                        if (ltrim($custom_vars[$key], '_') == "ANSWERMACRO") {
                            $has_answermacro = true;
                        }
                        break;
                }
            }
            $extpaging = 'ext-paging';
            if (!empty($intercom_code)) {
                $code = '_' . $intercom_code . '.';
                $context = 'ext-intercom';
                $ext->add($context, $code, '', new ext_macro('user-callerid'));
                $ext->add($context, $code, '', new ext_setvar('dialnumber', '${EXTEN:' . strlen($intercom_code) . '}'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/intercom/block)}" = "blocked"]', 'end'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(DND/${dialnumber})}" = "YES"]', 'end'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${dialnumber}/intercom/${AMPUSER})}" = "allow" ]', 'allow'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${dialnumber}/intercom/${AMPUSER})}" = "deny" ]', 'nointercom'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${dialnumber}/intercom)}" = "disabled" ]', 'nointercom'));
                $ext->add($context, $code, 'allow', new ext_dbget('DEVICES', 'AMPUSER/${dialnumber}/device'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DEVICES}" = "" ]', 'end'));
                $ext->add($context, $code, '', new ext_setvar('LOOPCNT', '${FIELDQTY(DEVICES,&)}'));
                /* Set these up so that macro-autoanswer doesn't have to
                 */
                $ext->add($context, $code, '', new ext_setvar('_SIPURI', ''));
                if (trim($alertinfo) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_ALERTINFO', $alertinfo));
                }
                if (trim($callinfo) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_CALLINFO', $callinfo));
                }
                if (trim($sipuri) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_SIPURI', $sipuri));
                }
                if (trim($vxml_url) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_VXML_URL', $vxml_url));
                }
                if (trim($doptions) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_DOPTIONS', $doptions));
                }
                foreach ($custom_vars as $key => $value) {
                    $ext->add($context, $code, '', new ext_setvar('_' . ltrim($key, '_'), $value));
                }
                $ext->add($context, $code, '', new ext_setvar('_DTIME', $dtime));
                $ext->add($context, $code, '', new ext_setvar('_ANSWERMACRO', ''));
                $ext->add($context, $code, '', new ext_gotoif('$[${LOOPCNT} > 1 ]', 'pagemode'));
                $ext->add($context, $code, '', new ext_macro('autoanswer', '${DEVICES}'));
                if ($ast_ge_16) {
                    $ext->add($context, $code, 'check', new ext_chanisavail('${DIAL}', 's'));
                    $ext->add($context, $code, '', new ext_gotoif('$["${AVAILORIGCHAN}" == ""]', 'end'));
                } else {
                    $ext->add($context, $code, 'check', new ext_chanisavail('${DIAL}', 'sj'));
                }
                $ext->add($context, $code, '', new ext_dial('${DIAL}', '${DTIME},${DOPTIONS}'));
                $ext->add($context, $code, 'end', new ext_busy());
                $ext->add($context, $code, '', new ext_macro('hangupcall'));
                if (!$ast_ge_16) {
                    $ext->add($context, $code, '', new ext_busy(), 'check', 101);
                    $ext->add($context, $code, '', new ext_macro('hangupcall'));
                }
                $ext->add($context, $code, 'pagemode', new ext_setvar('ITER', '1'));
                $ext->add($context, $code, '', new ext_setvar('DIALSTR', ''));
                $ext->add($context, $code, 'begin', new ext_setvar('DIALSTR', '${DIALSTR}&LOCAL/PAGE${CUT(DEVICES,&,${ITER})}@' . $extpaging));
                $ext->add($context, $code, '', new ext_setvar('ITER', '$[${ITER} + 1]'));
                $ext->add($context, $code, '', new ext_gotoif('$[${ITER} <= ${LOOPCNT}]', 'begin'));
                $ext->add($context, $code, '', new ext_setvar('DIALSTR', '${DIALSTR:1}'));
                $ext->add($context, $code, '', new ext_setvar('_AMPUSER', '${AMPUSER}'));
                $ext->add($context, $code, '', new ext_page('${DIALSTR},d'));
                $ext->add($context, $code, '', new ext_busy());
                $ext->add($context, $code, '', new ext_macro('hangupcall'));
                $ext->add($context, $code, 'nointercom', new ext_noop('Intercom disallowed by ${dialnumber}'));
                $ext->add($context, $code, '', new ext_playback('intercom&for&extension'));
                $ext->add($context, $code, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $code, '', new ext_playback('is&disabled'));
                $ext->add($context, $code, '', new ext_congestion());
                $extintercomusers = 'ext-intercom-users';
                $userlist = core_users_list();
                if (is_array($userlist)) {
                    foreach ($userlist as $item) {
                        $ext_intercom_code = $intercom_code . $item[0];
                        $ext->add($extintercomusers, $ext_intercom_code, '', new ext_goto($context . ',${EXTEN},1'));
                    }
                }
                $context = $extintercomusers;
                $ext->addInclude('from-internal-additional', $context);
            }
            $fcc = new featurecode('paging', 'intercom-on');
            $oncode = $fcc->getCodeActive();
            unset($fcc);
            if ($oncode) {
                $ext->add($context, $oncode, '', new ext_answer(''));
                $ext->add($context, $oncode, '', new ext_wait('1'));
                $ext->add($context, $oncode, '', new ext_macro('user-callerid'));
                $ext->add($context, $oncode, '', new ext_setvar('DB(AMPUSER/${AMPUSER}/intercom)', 'enabled'));
                $ext->add($context, $oncode, '', new ext_playback('intercom&enabled'));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $target = '${EXTEN:' . strlen($oncode) . '}';
                $oncode = "_" . $oncode . ".";
                $ext->add($context, $oncode, '', new ext_answer(''));
                $ext->add($context, $oncode, '', new ext_wait('1'));
                $ext->add($context, $oncode, '', new ext_macro('user-callerid'));
                $ext->add($context, $oncode, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/intercom/' . $target . ')}" = "allow" ]}', 'unset'));
                $ext->add($context, $oncode, '', new ext_gotoif('$[${DB_EXISTS(AMPUSER/${EXTEN:3}/device)} != 1]', 'invaliduser'));
                $ext->add($context, $oncode, '', new ext_dbput('AMPUSER/${AMPUSER}/intercom/' . $target, 'allow'));
                $ext->add($context, $oncode, '', new ext_playback('intercom&enabled&for&extension&number'));
                $ext->add($context, $oncode, '', new ext_saydigits($target));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $ext->add($context, $oncode, 'unset', new ext_dbdeltree('AMPUSER/${AMPUSER}/intercom/' . $target));
                $ext->add($context, $oncode, '', new ext_playback('intercom&enabled&cancelled&for&extension&number'));
                $ext->add($context, $oncode, '', new ext_saydigits($target));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $ext->add($context, $oncode, 'invaliduser', new ext_playback('extension&number'));
                $ext->add($context, $oncode, '', new ext_saydigits($target));
                $ext->add($context, $oncode, '', new ext_playback('is&invalid'));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
            }
            $fcc = new featurecode('paging', 'intercom-off');
            $offcode = $fcc->getCodeActive();
            unset($fcc);
            if ($offcode) {
                $ext->add($context, $offcode, '', new ext_answer(''));
                $ext->add($context, $offcode, '', new ext_wait('1'));
                $ext->add($context, $offcode, '', new ext_macro('user-callerid'));
                $ext->add($context, $offcode, '', new ext_setvar('DB(AMPUSER/${AMPUSER}/intercom)', 'disabled'));
                $ext->add($context, $offcode, '', new ext_playback('intercom&disabled'));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $target = '${EXTEN:' . strlen($offcode) . '}';
                $offcode = "_" . $offcode . ".";
                $ext->add($context, $offcode, '', new ext_answer(''));
                $ext->add($context, $offcode, '', new ext_wait('1'));
                $ext->add($context, $offcode, '', new ext_macro('user-callerid'));
                $ext->add($context, $offcode, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/intercom/' . $target . ')}" = "deny" ]}', 'unset2'));
                $ext->add($context, $offcode, '', new ext_gotoif('$[${DB_EXISTS(AMPUSER/${EXTEN:3}/device)} != 1]', 'invaliduser2'));
                $ext->add($context, $offcode, '', new ext_dbput('AMPUSER/${AMPUSER}/intercom/' . $target, 'deny'));
                $ext->add($context, $offcode, '', new ext_playback('intercom&disabled&for&extension&number'));
                $ext->add($context, $offcode, '', new ext_saydigits($target));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $ext->add($context, $offcode, 'unset2', new ext_dbdeltree('AMPUSER/${AMPUSER}/intercom/' . $target));
                $ext->add($context, $offcode, '', new ext_playback('intercom&disabled&cancelled&for&extension&number'));
                $ext->add($context, $offcode, '', new ext_saydigits($target));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $ext->add($context, $offcode, 'invaliduser2', new ext_playback('extension&number'));
                $ext->add($context, $offcode, '', new ext_saydigits($target));
                $ext->add($context, $offcode, '', new ext_playback('is&invalid'));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
            }
            /* Create macro-autoanswer that will try to intelligently set the
            		   	required parameters to handle paging. Eventually it will use
            			 	known device information.
            
            				This macro does the following:
            
            				Input:  FreePBX Device number to be called requiring autoanswer
            				Output: ${DIAL} Channel Variable with the dial string to be called
            				        Appropriate SIP headers added
            								Other special requirements that may be custom for this device
            
            				1. Set ${DIAL} to the device's dial string
            				2. If there is a device specific macro defined in the DEVICE's object
            				   (DEVICE/<devicenum>/autoanswer/macro) then execute that macro and end
            				3. Try to identify endpoints by their useragents that may need known
            				   changes and make those changes. These are generated from the
            					 paging_autoanswer table so users can extend them, if any are present
            				5. Set the variables and end unless a useragent specific ANSWERMACRO is
            				   defined in which case call it and end.
            
            				This macro is called for intercoming and paging to try and enable the
            				target device to auto-answer. Devices with special needs can be handled
            				with the device specific macro. For example, if you have a device that
            				can not auto-answer except by specifically configuring a line key on
            				the device that always answers, you could use a device specific macro
            				to change the dialstring. If you had a set of such devices, you could
            				standardize on the device numbers (e.g. nnnn for normal calls and 2nnnn
            				for auto-answer calls). You could then create a general purpose macro
            				to modify the dial string accordingly. Provisioning tools will be able
            				to take advantage of setting and creating such an ability.
            				If you have a set of devices that can be identified with a SIP useragent
            				then you can use a general macro without setting info in each device.
            		 	*/
            $autoanswer_arr = paging_get_autoanswer_useragents();
            $macro = 'macro-autoanswer';
            $ext->add($macro, "s", '', new ext_setvar('DIAL', '${DB(DEVICE/${ARG1}/dial)}'));
            // If we are in DAHDI compat mode, then we need to substitute DAHDI for ZAP
            if ($chan_dahdi) {
                $ext->add($macro, "s", '', new ext_execif('$["${DIAL:0:3}" = "ZAP"]', 'Set', 'DIAL=DAHDI${DIAL:3}'));
            }
            $ext->add($macro, "s", '', new ext_gotoif('$["${DB(DEVICE/${ARG1}/autoanswer/macro)}" != "" ]', 'macro'));
            // If there are no phone specific auto-answer vars, then we don't care what the phone is below
            //
            if (!empty($autoanswer_arr)) {
                $ext->add($macro, "s", '', new ext_setvar('phone', '${SIPPEER(${CUT(DIAL,/,2)}:useragent)}'));
            }
            // We used to set all the variables here (ALERTINFO, CALLINFO, etc. That has been moved to each
            // paging group and the intercom main macro, since it was redundant for every phone causing a lot
            // of overhead with large page groups.
            //
            // Defaults are setup, now make specific adjustments for detected phones
            // These come from the SQL table as well where installations can make customizations
            //
            foreach ($autoanswer_arr as $autosetting) {
                $useragent = trim($autosetting['useragent']);
                $autovar = trim($autosetting['var']);
                $data = trim($autosetting['setting']);
                switch (ltrim($autovar, '_')) {
                    case 'ANSWERMACRO':
                        $has_answermacro = true;
                        // fall through - no break on purpose
                    // fall through - no break on purpose
                    case 'ALERTINFO':
                    case 'CALLINFO':
                    case 'SIPURI':
                    case 'VXML_URL':
                    case 'DOPTIONS':
                    case 'DTIME':
                    default:
                        if (trim($data) != "") {
                            $ext->add($macro, "s", '', new ext_execif('$["${phone:0:' . strlen($useragent) . '}" = "' . $useragent . '"]', 'Set', $autovar . '=' . $data));
                        }
                        break;
                }
            }
            // Now any adjustments have been made, set the headers and done
            //
            if ($has_answermacro) {
                $ext->add($macro, "s", '', new ext_gotoif('$["${ANSWERMACRO}" != ""]', 'macro2'));
            }
            $ext->add($macro, "s", '', new ext_execif('$["${ALERTINFO}" != ""]', 'SipAddHeader', '${ALERTINFO}'));
            $ext->add($macro, "s", '', new ext_execif('$["${CALLINFO}" != ""]', 'SipAddHeader', '${CALLINFO}'));
            $ext->add($macro, "s", '', new ext_execif('$["${SIPURI}" != ""]', 'Set', '__SIP_URI_OPTIONS=${SIPURI}'));
            $ext->add($macro, "s", 'macro', new ext_macro('${DB(DEVICE/${ARG1}/autoanswer/macro)}', '${ARG1}'), 'n', 2);
            if ($has_answermacro) {
                $ext->add($macro, "s", 'macro2', new ext_macro('${ANSWERMACRO}', '${ARG1}'), 'n', 2);
            }
            // Create the paging context that is used in the paging application for each phone to auto-answer
            //
            $ext->addInclude('from-internal-additional', $extpaging);
            // Normal page version
            $ext->add($extpaging, "_PAGE.", '', new ext_gotoif('$[ ${AMPUSER} = ${EXTEN:4} ]', 'skipself'));
            if ($ast_ge_16) {
                $ext->add($extpaging, "_PAGE.", 'AVAIL', new ext_chanisavail('${DB(DEVICE/${EXTEN:4}/dial)}', 's'));
                $ext->add($extpaging, "_PAGE.", '', new ext_gotoif('$["${AVAILORIGCHAN}" == ""]', 'skipself'));
            } else {
                $ext->add($extpaging, "_PAGE.", 'AVAIL', new ext_chanisavail('${DB(DEVICE/${EXTEN:4}/dial)}', 'js'));
            }
            $ext->add($extpaging, "_PAGE.", '', new ext_gotoif('$["${DB(DND/${DB(DEVICE/${EXTEN:4}/user)})}" = "YES"]', 'skipself'));
            $ext->add($extpaging, "_PAGE.", 'SKIPCHECK', new ext_macro('autoanswer', '${EXTEN:4}'));
            $ext->add($extpaging, "_PAGE.", '', new ext_dial('${DIAL}', '${DTIME},${DOPTIONS}'));
            $ext->add($extpaging, "_PAGE.", 'skipself', new ext_hangup());
            if (!$ast_ge_16) {
                $ext->add($extpaging, "_PAGE.", '', new ext_hangup(''), 'AVAIL', 101);
            }
            // Force page version
            $ext->add($extpaging, "_FPAGE.", '', new ext_gotoif('$[ ${AMPUSER} = ${EXTEN:5} ]', 'skipself'));
            $ext->add($extpaging, "_FPAGE.", 'SKIPCHECK', new ext_macro('autoanswer', '${EXTEN:5}'));
            $ext->add($extpaging, "_FPAGE.", '', new ext_dial('${DIAL}', '${DTIME},${DOPTIONS}'));
            $ext->add($extpaging, "_FPAGE.", 'skipself', new ext_hangup());
            //
            // Now get a list of all the paging groups...
            $sql = "SELECT page_group, force_page, duplex FROM paging_config";
            $paging_groups = $db->getAll($sql, DB_FETCHMODE_ASSOC);
            foreach ($paging_groups as $thisgroup) {
                $grp = trim($thisgroup['page_group']);
                $pagemode = $thisgroup['force_page'] ? 'FPAGE' : 'PAGE';
                $sql = "SELECT ext FROM paging_groups WHERE page_number='{$grp}'";
                $all_exts = $db->getAll($sql);
                $dialstr = '';
                foreach ($all_exts as $local_dial) {
                    if (strtoupper(substr($local_dial[0], -1)) == "X") {
                        $local_dial[0] = rtrim($local_dial[0], "xX");
                    }
                    $dialstr .= "LOCAL/{$pagemode}" . trim($local_dial[0]) . "@" . $extpaging . "&";
                }
                // It will always end with an &, so lets take that off.
                $dialstr = rtrim($dialstr, "&");
                if ($thisgroup['duplex']) {
                    $dialstr .= ",d";
                }
                $ext->add($extpaging, $grp, '', new ext_answer(''));
                $ext->add($extpaging, $grp, '', new ext_macro('user-callerid'));
                // make AMPUSER inherited here, so we can skip the proper 'self' if using cidnum masquerading
                $ext->add($extpaging, $grp, '', new ext_setvar('_AMPUSER', '${AMPUSER}'));
                $ext->add($extpaging, $grp, '', new ext_setvar('_SIPURI', ''));
                if (trim($alertinfo) != "") {
                    $ext->add($extpaging, $grp, '', new ext_setvar('_ALERTINFO', $alertinfo));
                }
                if (trim($callinfo) != "") {
                    $ext->add($extpaging, $grp, '', new ext_setvar('_CALLINFO', $callinfo));
                }
                if (trim($sipuri) != "") {
                    $ext->add($extpaging, $grp, '', new ext_setvar('_SIPURI', $sipuri));
                }
                if (trim($vxml_url) != "") {
                    $ext->add($extpaging, $grp, '', new ext_setvar('_VXML_URL', $vxml_url));
                }
                if (trim($doptions) != "") {
                    $ext->add($extpaging, $grp, '', new ext_setvar('_DOPTIONS', $doptions));
                }
                $ext->add($extpaging, $grp, '', new ext_setvar('_DTIME', $dtime));
                $ext->add($extpaging, $grp, '', new ext_setvar('_ANSWERMACRO', ''));
                foreach ($custom_vars as $key => $value) {
                    $ext->add($extpaging, $grp, '', new ext_setvar('_' . ltrim($key, '_'), $value));
                }
                $ext->add($extpaging, $grp, '', new ext_setvar('__FORWARD_CONTEXT', 'block-cf'));
                $ext->add($extpaging, $grp, '', new ext_page($dialstr));
            }
            break;
    }
}
Example #16
0
    die('No direct script access allowed');
}
//for translation only
if (false) {
    _("Findme Follow Toggle");
}
global $db;
global $amp_conf;
global $astman;
$sql = "\nCREATE TABLE IF NOT EXISTS `findmefollow` \n( \n\t`grpnum` VARCHAR( 20 ) NOT NULL , \n\t`strategy` VARCHAR( 50 ) NOT NULL , \n\t`grptime` SMALLINT NOT NULL , \n\t`grppre` VARCHAR( 100 ) NULL , \n\t`grplist` VARCHAR( 255 ) NOT NULL , \n\t`annmsg_id` INTEGER,\n\t`postdest` VARCHAR( 255 ) NULL , \n\t`dring` VARCHAR ( 255 ) NULL , \n\t`remotealert_id` INTEGER,\n\t`needsconf` VARCHAR ( 10 ), \n\t`toolate_id` INTEGER,\n\t`pre_ring` SMALLINT NOT NULL DEFAULT 0, \n\tPRIMARY KEY  (`grpnum`) \n)\n";
$check = $db->query($sql);
if (DB::IsError($check)) {
    die_freepbx("Can not create annoucment table");
}
//TODO: Also need to create all the states if enabled
$fcc = new featurecode('findmefollow', 'fmf_toggle');
$fcc->setDescription('Findme Follow Toggle');
$fcc->setDefault('*21');
$fcc->update();
unset($fcc);
// Adding support for a pre_ring before follow-me group
$sql = "SELECT pre_ring FROM findmefollow";
$check = $db->getRow($sql, DB_FETCHMODE_ASSOC);
if (DB::IsError($check)) {
    // add new field
    $sql = "ALTER TABLE findmefollow ADD pre_ring SMALLINT( 6 ) NOT NULL DEFAULT 0 ;";
    $result = $db->query($sql);
    if (DB::IsError($result)) {
        die_freepbx($result->getDebugInfo());
    }
}
function paging_get_config($engine)
{
    global $db, $ext, $chan_dahdi, $version, $amp_conf, $conferences_conf;
    switch ($engine) {
        case "asterisk":
            // setup for intercom
            $fcc = new featurecode('paging', 'intercom-prefix');
            $intercom_code = $fcc->getCodeActive();
            unset($fcc);
            // Since these are going down channel local, set ALERT_INFO and SIPADDHEADER which will be set in dialparties.agi
            // no point in even setting the headers here they will get lost in channel local
            //
            /* Set these up once here and in intercom so that autoanswer macro does not have
             * to go through this for every single extension which causes a lot of extra overhead
             * with big page groups
             */
            $has_answermacro = false;
            $alertinfo = 'Ring Answer';
            $callinfo = '<uri>\\;answer-after=0';
            $sipuri = 'intercom=true';
            $doptions = 'A(beep)b(autoanswer^s^1(${ALERTINFO},${CALLINFO}))';
            $vxml_url = '';
            $dtime = '5';
            $custom_vars = array();
            $autoanswer_arr = paging_get_autoanswer_defaults();
            foreach ($autoanswer_arr as $autosetting) {
                switch (trim($autosetting['var'])) {
                    case 'ALERTINFO':
                        $alertinfo = trim($autosetting['setting']);
                        break;
                    case 'CALLINFO':
                        $callinfo = trim($autosetting['setting']);
                        break;
                    case 'SIPURI':
                        $sipuri = trim($autosetting['setting']);
                        break;
                    case 'VXML_URL':
                        $vxml_url = trim($autosetting['setting']);
                        break;
                    case 'DOPTIONS':
                        $doptions = trim($autosetting['setting']);
                        break;
                    case 'DTIME':
                        $dtime = trim($autosetting['setting']);
                        break;
                    default:
                        $key = trim($autosetting['var']);
                        $custom_vars[$key] = trim($autosetting['setting']);
                        if (ltrim($custom_vars[$key], '_') == "ANSWERMACRO") {
                            $has_answermacro = true;
                        }
                        break;
                }
            }
            $apppaging = 'app-paging';
            if (!empty($intercom_code)) {
                $code = '_' . $intercom_code . '.';
                $context = 'ext-intercom';
                // Add for languages
                $ext->add($context, 'lang-playback', '', new ext_gosubif('$[${DIALPLAN_EXISTS(' . $context . ',${CHANNEL(language)})}]', $context . ',${CHANNEL(language)},${ARG1}', $context . ',en,${ARG1}'));
                $ext->add($context, 'lang-playback', '', new ext_return());
                $ext->add($context, $code, '', new ext_macro('user-callerid'));
                $ext->add($context, $code, '', new ext_setvar('dialnumber', '${EXTEN:' . strlen($intercom_code) . '}'));
                $ext->add($context, $code, '', new ext_setvar('INTERCOM_CALL', 'TRUE'));
                $ext->add($context, $code, '', new ext_gosub('1', 's', 'sub-record-check', 'exten,${dialnumber}'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/intercom/block)}" = "blocked"]', 'end'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(DND/${dialnumber})}" = "YES"]', 'end'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${dialnumber}/intercom/${AMPUSER})}" = "allow" ]', 'allow'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${dialnumber}/intercom/${AMPUSER})}" = "deny" ]', 'nointercom'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${dialnumber}/intercom)}" = "disabled" ]', 'nointercom'));
                $ext->add($context, $code, 'allow', new ext_dbget('DEVICES', 'AMPUSER/${dialnumber}/device'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DEVICES}" = "" ]', 'end'));
                $ext->add($context, $code, '', new ext_dbget('OVERRIDE', 'AMPUSER/${dialnumber}/intercom/override'));
                $ext->add($context, $code, '', new ext_setvar('LOOPCNT', '${FIELDQTY(DEVICES,&)}'));
                /* Set these up so that macro-autoanswer doesn't have to
                 */
                $ext->add($context, $code, '', new ext_setvar('_SIPURI', ''));
                if (trim($alertinfo) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_ALERTINFO', $alertinfo));
                }
                if (trim($callinfo) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_CALLINFO', $callinfo));
                }
                if (trim($sipuri) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_SIPURI', $sipuri));
                }
                if (trim($vxml_url) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_VXML_URL', $vxml_url));
                }
                foreach ($custom_vars as $key => $value) {
                    $ext->add($context, $code, '', new ext_setvar('_' . ltrim($key, '_'), $value));
                }
                $ext->add($context, $code, '', new ext_setvar('_DTIME', $dtime));
                $ext->add($context, $code, '', new ext_setvar('_ANSWERMACRO', ''));
                $ext->add($context, $code, '', new ext_gotoif('$[${LOOPCNT} > 1 ]', 'pagemode'));
                $ext->add($context, $code, '', new ext_macro('autoanswer', '${DEVICES}'));
                $ext->add($context, $code, '', new ext_setvar('_DOPTIONS', $doptions));
                $ext->add($context, $code, 'check', new ext_chanisavail('${DEVICE}', 's'));
                // If it's ringing for an inbound call, we should page.
                $ext->add($context, $code, '', new ext_execif('$["${AVAILSTATUS}" = "6"]', 'Set', 'AVAILORIGCHAN=${DEVICE}'));
                // Did we have a device we can page? If so, go to continue. If not, check for
                // paging override functions.
                $ext->add($context, $code, '', new ext_gotoif('$["${AVAILORIGCHAN}" != ""]', 'continue'));
                // Check the intercom override.
                $ext->add($context, $code, '', new ext_execif('$["${OVERRIDE}" = ""]', 'Set', 'OVERRIDE=reject'));
                $ext->add($context, $code, '', new ext_gotoif('$["${OVERRIDE}" = "reject"]', 'end'));
                // We don't know what the phones are going to do. Let's be generous.
                $ext->add($context, $code, '', new ext_set('DTIME', '30'));
                // If it's ring, treat it as a normal call.
                $ext->add($context, $code, '', new ext_execif('$["${OVERRIDE}" = "ring"]', 'Set', 'DOPTIONS=A(beep)'));
                // It's something else. Assume it's force, and just smash the device.
                $ext->add($context, $code, 'continue', new ext_noop('Continuing with page', 5));
                $len = strlen($code) - 2;
                $dopt = 'I';
                // Don't sent connectedline updates.
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${EXTEN:' . $len . '}/cidname)}" = ""]', 'godial'));
                $ext->add($context, $code, '', new ext_set('CONNECTEDLINE(name,i)', '${DB(AMPUSER/${EXTEN:' . $len . '}/cidname)}'));
                $ext->add($context, $code, '', new ext_set('CONNECTEDLINE(num)', '${EXTEN:' . $len . '}'));
                $ext->add($context, $code, 'godial', new ext_dial('${DIAL}', '${DTIME},' . $dopt . '${DOPTIONS}${INTERCOM_EXT_DOPTIONS}'));
                $ext->add($context, $code, 'end', new ext_execif('$[${INTERCOM_RETURN}]', 'Return'));
                $ext->add($context, $code, '', new ext_busy());
                $ext->add($context, $code, '', new ext_macro('hangupcall'));
                $ext->add($context, $code, 'pagemode', new ext_setvar('ITER', '1'));
                $ext->add($context, $code, '', new ext_setvar('DIALSTR', ''));
                $ds = $amp_conf['ASTCONFAPP'] == 'app_confbridge' ? '${DIALSTR}-${CUT(DEVICES,&,${ITER})}' : '${DIALSTR}&LOCAL/PAGE${CUT(DEVICES,&,${ITER})}@' . $apppaging;
                $ext->add($context, $code, 'begin', new ext_chanisavail('${DB(DEVICE/${CUT(DEVICES,&,${ITER})}/dial)}', 's'));
                $ext->add($context, $code, '', new ext_gotoif('$["${AVAILORIGCHAN}" = ""]', 'skip'));
                $ext->add($context, $code, '', new ext_setvar('DIALSTR', $ds));
                $ext->add($context, $code, 'skip', new ext_setvar('ITER', '$[${ITER} + 1]'));
                $ext->add($context, $code, '', new ext_gotoif('$[${ITER} <= ${LOOPCNT}]', 'begin'));
                $ext->add($context, $code, '', new ext_setvar('DIALSTR', '${DIALSTR:1}'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DIALSTR}" = ""]', 'end2'));
                $ext->add($context, $code, '', new ext_setvar('_AMPUSER', '${AMPUSER}'));
                if ($amp_conf['ASTCONFAPP'] == 'app_confbridge') {
                    $ext->add($context, $code, '', new ext_gosub('1', 'page', false, '${DIALSTR}'));
                } else {
                    $ext->add($context, $code, '', new ext_page('${DIALSTR},d'));
                }
                $ext->add($context, $code, 'end2', new ext_execif('$[${INTERCOM_RETURN}]', 'Return'));
                $ext->add($context, $code, '', new ext_busy());
                $ext->add($context, $code, '', new ext_macro('hangupcall'));
                $ext->add($context, $code, 'nointercom', new ext_noop('Intercom disallowed by ${dialnumber}'));
                $ext->add($context, $code, '', new ext_execif('$[${INTERCOM_RETURN}]', 'Return'));
                $ext->add($context, $code, '', new ext_gosub('1', 'lang-playback', $context, 'hook_0'));
                $ext->add($context, $code, '', new ext_congestion());
                if ($amp_conf['ASTCONFAPP'] == 'app_confbridge') {
                    $sub = 'page';
                    $ext->add($context, $sub, '', new ext_set('PAGE_CONF', '${EPOCH}${RAND(100,999)}'));
                    $ext->add($context, $sub, '', new ext_set('PAGEMODE', 'PAGE'));
                    $ext->add($context, $sub, '', new ext_set('PAGE_MEMBERS', '${ARG1}'));
                    $ext->add($context, $sub, '', new ext_set('PAGE_CONF_OPTS', 'duplex'));
                    $ext->add($context, $sub, '', new ext_agi('page.agi'));
                    $ext->add($context, $sub, '', new ext_set('CONFBRIDGE(user,template)', 'page_user_duplex'));
                    $ext->add($context, $sub, '', new ext_set('CONFBRIDGE(user,admin)', 'yes'));
                    $ext->add($context, $sub, '', new ext_set('CONFBRIDGE(user,marked)', 'yes'));
                    $ext->add($context, $sub, '', new ext_meetme('${PAGE_CONF}', ',', 'admin_menu'));
                    $ext->add($context, $sub, '', new ext_hangup());
                }
                $lang = 'en';
                // English
                $ext->add($context, $lang, 'hook_0', new ext_playback('intercom&for&extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('is&disabled'));
                $ext->add($context, $lang, '', new ext_return());
                $lang = 'ja';
                // Japanese
                $ext->add($context, $lang, 'hook_0', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('jp-no&intercom&jp-wa&disabled-2'));
                $ext->add($context, $lang, '', new ext_return());
                $extintercomusers = 'ext-intercom-users';
                $sql = "SELECT LENGTH(id) as len FROM devices GROUP BY len";
                $sth = FreePBX::Database()->prepare($sql);
                $sth->execute();
                $rows = $sth->fetchAll(\PDO::FETCH_ASSOC);
                foreach ($rows as $row) {
                    $ext->add($extintercomusers, '_' . $intercom_code . str_repeat('X', $row['len']), '', new ext_goto($context . ',${EXTEN},1'));
                }
                $context = $extintercomusers;
                // for language handling which is done on a per context basis
                $ext->add($context, 'lang-playback', '', new ext_gosubif('$[${DIALPLAN_EXISTS(' . $context . ',${CHANNEL(language)})}]', $context . ',${CHANNEL(language)},${ARG1}', $context . ',en,${ARG1}'));
                $ext->add($context, 'lang-playback', '', new ext_return());
                $ext->addInclude('from-internal-additional', $context);
            }
            $fcc = new featurecode('paging', 'intercom-on');
            $oncode = $fcc->getCodeActive();
            unset($fcc);
            if ($oncode) {
                $ext->add($context, $oncode, '', new ext_macro('user-callerid'));
                $ext->add($context, $oncode, '', new ext_set('CONNECTEDLINE(name-charset,i)', 'utf8'));
                $ext->add($context, $oncode, '', new ext_set('CONNECTEDLINE(name,i)', _("Intercom: Enabled")));
                $ext->add($context, $oncode, '', new ext_set('CONNECTEDLINE(num,i)', '${AMPUSER}'));
                $ext->add($context, $oncode, '', new ext_answer(''));
                $ext->add($context, $oncode, '', new ext_wait('1'));
                $ext->add($context, $oncode, '', new ext_setvar('DB(AMPUSER/${AMPUSER}/intercom)', 'enabled'));
                $ext->add($context, $oncode, '', new ext_playback('intercom&enabled'));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $target = '${EXTEN:' . strlen($oncode) . '}';
                $oncode = "_" . $oncode . ".";
                $ext->add($context, $oncode, '', new ext_macro('user-callerid'));
                $ext->add($context, $oncode, '', new ext_set('CONNECTEDLINE(name-charset,i)', 'utf8'));
                $ext->add($context, $oncode, '', new ext_set('CONNECTEDLINE(name,i)', sprintf(_("Intercom from %s: Enabled"), $target)));
                $ext->add($context, $oncode, '', new ext_set('CONNECTEDLINE(num,i)', '${AMPUSER}'));
                $ext->add($context, $oncode, '', new ext_setvar('dialnumber', '${EVAL(${EXTEN:' . strlen(substr($oncode, 1, -1)) . '})}'));
                // Asterisk variable for saydigits languages
                $ext->add($context, $oncode, '', new ext_answer(''));
                $ext->add($context, $oncode, '', new ext_wait('1'));
                $ext->add($context, $oncode, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/intercom/' . $target . ')}" = "allow" ]}', 'unset'));
                $ext->add($context, $oncode, '', new ext_gotoif('$[${DB_EXISTS(AMPUSER/' . $target . '/device)} != 1]', 'invaliduser'));
                $ext->add($context, $oncode, '', new ext_dbput('AMPUSER/${AMPUSER}/intercom/' . $target, 'allow'));
                $ext->add($context, $oncode, '', new ext_gosub('1', 'lang-playback', $context, 'hook_1'));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $ext->add($context, $oncode, 'unset', new ext_dbdeltree('AMPUSER/${AMPUSER}/intercom/' . $target));
                $ext->add($context, $oncode, '', new ext_gosub('1', 'lang-playback', $context, 'hook_2'));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $ext->add($context, $oncode, 'invaliduser', new ext_gosub('1', 'lang-playback', $context, 'hook_3'));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $lang = 'en';
                // English
                $ext->add($context, $lang, 'hook_1', new ext_playback('intercom&from&extension&number'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('enabled'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_2', new ext_playback('intercom&enabled&cancelled&for&extension&number'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_3', new ext_playback('extension&number'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('invalid'));
                $ext->add($context, $lang, '', new ext_return());
                $lang = 'ja';
                // Japanese
                $ext->add($context, $lang, 'hook_1', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('jp-kara&jp-no&intercom&jp-wo&allow'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_2', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('jp-kara&jp-no&intercom&setting&jp-wo&cancelled'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_3', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('invalid'));
                $ext->add($context, $lang, '', new ext_return());
            }
            $fcc = new featurecode('paging', 'intercom-off');
            $offcode = $fcc->getCodeActive();
            unset($fcc);
            if ($offcode) {
                $ext->add($context, $offcode, '', new ext_macro('user-callerid'));
                $ext->add($context, $offcode, '', new ext_set('CONNECTEDLINE(name-charset,i)', 'utf8'));
                $ext->add($context, $offcode, '', new ext_set('CONNECTEDLINE(name,i)', _("Intercom: Disabled")));
                $ext->add($context, $offcode, '', new ext_set('CONNECTEDLINE(num,i)', '${AMPUSER}'));
                $ext->add($context, $offcode, '', new ext_answer(''));
                $ext->add($context, $offcode, '', new ext_wait('1'));
                $ext->add($context, $offcode, '', new ext_setvar('DB(AMPUSER/${AMPUSER}/intercom)', 'disabled'));
                $ext->add($context, $offcode, '', new ext_playback('intercom&disabled'));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $target = '${EXTEN:' . strlen($offcode) . '}';
                $offcode = "_" . $offcode . ".";
                $ext->add($context, $offcode, '', new ext_macro('user-callerid'));
                $ext->add($context, $offcode, '', new ext_set('CONNECTEDLINE(name-charset,i)', 'utf8'));
                $ext->add($context, $offcode, '', new ext_set('CONNECTEDLINE(name,i)', sprintf(_("Intercom from %s: Disabled"), $target)));
                $ext->add($context, $offcode, '', new ext_set('CONNECTEDLINE(num,i)', '${AMPUSER}'));
                $ext->add($context, $offcode, '', new ext_setvar('dialnumber', '${EVAL(${EXTEN:' . strlen(substr($offcode, 1, -1)) . '})}'));
                // Asterisk variable for saydigits languages
                $ext->add($context, $offcode, '', new ext_answer(''));
                $ext->add($context, $offcode, '', new ext_wait('1'));
                $ext->add($context, $offcode, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/intercom/' . $target . ')}" = "deny" ]}', 'unset2'));
                $ext->add($context, $offcode, '', new ext_gotoif('$[${DB_EXISTS(AMPUSER/' . $target . '/device)} != 1]', 'invaliduser2'));
                $ext->add($context, $offcode, '', new ext_dbput('AMPUSER/${AMPUSER}/intercom/' . $target, 'deny'));
                $ext->add($context, $offcode, '', new ext_gosub('1', 'lang-playback', $context, 'hook_4'));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $ext->add($context, $offcode, 'unset2', new ext_dbdeltree('AMPUSER/${AMPUSER}/intercom/' . $target));
                $ext->add($context, $offcode, '', new ext_gosub('1', 'lang-playback', $context, 'hook_5'));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $ext->add($context, $offcode, 'invaliduser2', new ext_gosub('1', 'lang-playback', $context, 'hook_6'));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $lang = 'en';
                $ext->add($context, $lang, 'hook_4', new ext_playback('intercom&from&extension&number'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('disabled'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_5', new ext_playback('intercom&disabled&cancelled&for&extension&number'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_6', new ext_playback('extension&number'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('invalid'));
                $ext->add($context, $lang, '', new ext_return());
                $lang = 'ja';
                $ext->add($context, $lang, 'hook_4', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('jp-kara&jp-no&intercom&jp-wo&deny'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_5', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('jp-kara&jp-no&intercom&setting&jp-wo&cancelled'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_6', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('invalid'));
                $ext->add($context, $lang, '', new ext_return());
            }
            /* Create macro-autoanswer that will try to intelligently set the
            			required parameters to handle paging. Eventually it will use
            				known device information.
            
            				This macro does the following:
            
            				Input:  FreePBX Device number to be called requiring autoanswer
            				Output: ${DIAL} Channel Variable with the dial string to be called
            						Appropriate SIP headers added
            								Other special requirements that may be custom for this device
            
            				1. Set ${DIAL} to the device's dial string
            				2. If there is a device specific macro defined in the DEVICE's object
            				   (DEVICE/<devicenum>/autoanswer/macro) then execute that macro and end
            				3. Try to identify endpoints by their useragents that may need known
            				   changes and make those changes. These are generated from the
            					 paging_autoanswer table so users can extend them, if any are present
            				5. Set the variables and end unless a useragent specific ANSWERMACRO is
            				   defined in which case call it and end.
            
            				This macro is called for intercoming and paging to try and enable the
            				target device to auto-answer. Devices with special needs can be handled
            				with the device specific macro. For example, if you have a device that
            				can not auto-answer except by specifically configuring a line key on
            				the device that always answers, you could use a device specific macro
            				to change the dialstring. If you had a set of such devices, you could
            				standardize on the device numbers (e.g. nnnn for normal calls and 2nnnn
            				for auto-answer calls). You could then create a general purpose macro
            				to modify the dial string accordingly. Provisioning tools will be able
            				to take advantage of setting and creating such an ability.
            				If you have a set of devices that can be identified with a SIP useragent
            				then you can use a general macro without setting info in each device.
            			 */
            $autoanswer_arr = paging_get_autoanswer_useragents();
            $macro = 'macro-autoanswer';
            // Do we already know what the correct string is? This may have been handed to us
            // by page.agi.
            $ext->add($macro, "s", '', new ext_gotoif('$["${KNOWNDIAL}" != ""]', 'knowndial'));
            // Do we have a PJSIP Endpoint?
            $ext->add($macro, "s", '', new ext_setvar('DEVICE', '${DB(DEVICE/${ARG1}/dial)}'));
            $ext->add($macro, "s", '', new ext_gotoif('$["${DEVICE:0:5}" == "PJSIP" ]', 'dopjsip'));
            // We're not pjsip, so our dial is going to be our device
            $ext->add($macro, "s", '', new ext_setvar('KNOWNDIAL', '${DEVICE}'));
            $ext->add($macro, "s", '', new ext_goto('knowndial'));
            // Handle PJSIP stuff.
            $ext->add($macro, "s", 'dopjsip', new ext_setvar('KNOWNDIAL', '${PJSIP_DIAL_CONTACTS(${ARG1})}'));
            // If there's an ampersand, there's more than one device registered to this endpoint, and we
            // need to page, rather than intercom.
            $ext->add($macro, "s", '', new ext_gotoif('$[${REGEX("&" ${KNOWNDIAL})} == 0]', 'knowndial'));
            // Bugger. However, we can hard-code some settings here that'll make our life a bit easier.
            $ext->add($macro, "s", '', new ext_gosub('1', 'ssetup', 'app-paging'));
            $ext->add($macro, "s", '', new ext_setvar('PAGEMODE', 'PAGE'));
            $ext->add($macro, "s", '', new ext_setvar('PAGE_CONF_OPTS', 'duplex'));
            $ext->add($macro, "s", '', new ext_setvar('STREAM', 'NONE'));
            $ext->add($macro, "s", '', new ext_setvar('PAGE_MEMBERS', '${ARG1}'));
            // Start the AGI to get the clients into the conf
            $ext->add($macro, "s", '', new ext_agi('page.agi'));
            // Now I need to join the conf as admin.
            $ext->add($macro, "s", '', new ext_set('CONFBRIDGE(user,template)', 'page_user_duplex'));
            $ext->add($macro, "s", '', new ext_set('CONFBRIDGE(user,admin)', 'yes'));
            $ext->add($macro, "s", '', new ext_set('CONFBRIDGE(user,marked)', 'yes'));
            $ext->add($macro, "s", '', new ext_meetme('${PAGE_CONF}', ',', 'admin_menu'));
            // ext_confbridge, actually.
            $ext->add($macro, "s", '', new ext_hangup());
            // Don't even try to continue after this.
            // Right. Bypassing all that, it's a single device, and, we know what our dial string is.
            $ext->add($macro, "s", 'knowndial', new ext_setvar('DIAL', '${KNOWNDIAL}'));
            // If we are in DAHDI compat mode, then we need to substitute DAHDI for ZAP
            if ($chan_dahdi) {
                $ext->add($macro, "s", '', new ext_execif('$["${DIAL:0:3}" = "ZAP"]', 'Set', 'DIAL=DAHDI${DIAL:3}'));
            }
            $ext->add($macro, "s", '', new ext_gotoif('$["${DB(DEVICE/${ARG1}/autoanswer/macro)}" != "" ]', 'macro'));
            // If there are no phone specific auto-answer vars, then we don't care what the phone is below
            //
            if (!empty($autoanswer_arr)) {
                global $version;
                $ext->add($macro, "s", '', new ext_gotoif('$["${DIAL:0:5}" = "PJSIP"]', 'pjsipua'));
                //http://issues.freepbx.org/browse/FREEPBX-7715
                if (version_compare($version, "12", "<")) {
                    $ext->add($macro, "s", '', new ext_setvar('USERAGENT', '${SIPPEER(${CUT(DIAL,/,2)}:useragent)}'));
                } else {
                    $ext->add($macro, "s", '', new ext_setvar('USERAGENT', '${SIPPEER(${CUT(DIAL,/,2)},useragent)}'));
                }
                $ext->add($macro, "s", '', new ext_goto('uafin'));
                $ext->add($macro, "s", 'pjsipua', new ext_setvar('AOR', '${CUT(DIAL,/,2)}'));
                $ext->add($macro, "s", '', new ext_setvar('CONTACT', '${PJSIP_AOR(${AOR},contact)}'));
                $ext->add($macro, "s", '', new ext_setvar('USERAGENT', '${PJSIP_CONTACT(${CONTACT},user_agent)}'));
                $ext->add($macro, "s", 'uafin', new ext_execif('$["${KNOWNAGENT}" != ""]', 'Set', 'USERAGENT=${KNOWNAGENT}'));
            }
            // We used to set all the variables here (ALERTINFO, CALLINFO, etc. That has been moved to each
            // paging group and the intercom main macro, since it was redundant for every phone causing a lot
            // of overhead with large page groups.
            //
            // Defaults are setup, now make specific adjustments for detected phones
            // These come from the SQL table as well where installations can make customizations
            //
            foreach ($autoanswer_arr as $autosetting) {
                $useragent = trim($autosetting['useragent']);
                $autovar = trim($autosetting['var']);
                $data = trim($autosetting['setting']);
                switch (ltrim($autovar, '_')) {
                    case 'ANSWERMACRO':
                        $has_answermacro = true;
                        // fall through - no break on purpose
                    // fall through - no break on purpose
                    case 'ALERTINFO':
                    case 'CALLINFO':
                    case 'SIPURI':
                    case 'VXML_URL':
                    case 'DOPTIONS':
                    case 'DTIME':
                    default:
                        if (trim($data) != "") {
                            $ext->add($macro, "s", '', new ext_execif('$["${USERAGENT:0:' . strlen($useragent) . '}" = "' . $useragent . '"]', 'Set', $autovar . '=' . $data));
                        }
                        break;
                }
            }
            // Now any adjustments have been made, set the headers and done
            //
            if ($has_answermacro) {
                $ext->add($macro, "s", '', new ext_gotoif('$["${ANSWERMACRO}" != ""]', 'macro2'));
            }
            $ext->add($macro, "s", '', new ext_execif('$["${SIPURI}" != ""]', 'Set', '__SIP_URI_OPTIONS=${SIPURI}'));
            $ext->add($macro, "s", 'macro', new ext_macro('${DB(DEVICE/${ARG1}/autoanswer/macro)}', '${ARG1}'), 'n', 2);
            if ($has_answermacro) {
                $ext->add($macro, "s", 'macro2', new ext_macro('${ANSWERMACRO}', '${ARG1}'), 'n', 2);
            }
            //auto answer stuff
            //set autoanswer variables
            if (!empty($custom_vars)) {
                foreach ($custom_vars as $key => $value) {
                    $ext->add($apppaging, '_AUTOASWER.', '', new ext_setvar('_' . ltrim($key, '_'), $value));
                }
                $ext->add($apppaging, '_AUTOASWER.', '', new ext_macro('autoanswer', '${EXTEN:9}'));
                $ext->add($apppaging, '_AUTOASWER.', '', new ext_return());
            }
            // Macro to apply SIP Headers to channel.
            //   function ext_gosubif($condition, $true_priority, $false_priority = false, $true_args = '', $false_args = '') {
            //
            $ext->add("autoanswer", "s", '', new ext_gosubif('$["${ARG1}" != ""]', 'func-set-sipheader,s,1', false, 'Alert-Info,${ARG1}'));
            $ext->add("autoanswer", "s", '', new ext_gosubif('$["${ARG2}" != ""]', 'func-set-sipheader,s,1', false, 'Call-Info,${ARG2}'));
            $ext->add("autoanswer", "s", '', new ext_gosub('func-apply-sipheaders,s,1'));
            $ext->add("autoanswer", "s", '', new ext_return());
            // Setup Variables before AGI script
            //
            $ext->add($apppaging, 'ssetup', '', new ext_set('_SIPURI', ''));
            if (isset($alertinfo) && trim($alertinfo) != "") {
                $ext->add($apppaging, 'ssetup', '', new ext_set('_ALERTINFO', $alertinfo));
            }
            if (isset($callinfo) && trim($callinfo) != "") {
                $ext->add($apppaging, 'ssetup', '', new ext_set('_CALLINFO', $callinfo));
            }
            if (isset($sipuri) && trim($sipuri) != "") {
                $ext->add($apppaging, 'ssetup', '', new ext_set('_SIPURI', $sipuri));
            }
            if (isset($vxml_url) && trim($vxml_url) != "") {
                $ext->add($apppaging, 'ssetup', '', new ext_set('_VXML_URL', $vxml_url));
            }
            $ext->add($apppaging, 'ssetup', '', new ext_set('_DTIME', $dtime));
            $ext->add($apppaging, 'ssetup', '', new ext_set('_ANSWERMACRO', ''));
            $page_opts = $amp_conf['ASTCONFAPP'] == 'app_confbridge' ? '1qs' : '1dqsx';
            $ext->add($apppaging, 'ssetup', '', new ext_set('PAGE_CONF', '${EPOCH}${RAND(100,999)}'));
            $ext->add($apppaging, 'ssetup', '', new ext_return());
            // Normal page version (now used for Force also)
            // If we had any custom_vars then call the AUTOASWER subroutine first, otherwise go
            // straight to macro-autoanswer
            if (!empty($custom_vars)) {
                $ext->add($apppaging, "_PAGE.", 'SKIPCHECK', new ext_gosub('AUTOASWER${EXTEN:4},1'));
            } else {
                $ext->add($apppaging, "_PAGE.", 'SKIPCHECK', new ext_macro('autoanswer', '${EXTEN:4}'));
            }
            $ext->add($apppaging, "_PAGE.", '', new ext_noop('${EXTRINGTIME}'));
            $ext->add($apppaging, "_PAGE.", '', new ext_gotoif('$["${EXTRINGTIME}" != "true"]', 'doptions'));
            $ext->add($apppaging, "_PAGE.", '', new ext_set('_DTIME', '${RINGTIMER_DEFAULT}'));
            $ext->add($apppaging, "_PAGE.", '', new ext_execif('$["${DB(AMPUSER/${EXTEN:4}/ringtimer)}" != "" & ${DB(AMPUSER/${EXTEN:4}/ringtimer)} > 0]', 'Set', '_DTIME=${DB(AMPUSER/${EXTEN:4}/ringtimer)}'));
            //strip the global Announcement out of doptions (We use our announcement variable lower --V)
            $doptions2 = preg_replace("/A\\([^\\)]*\\)/", "", $doptions);
            $ext->add($apppaging, "_PAGE.", 'doptions', new ext_execif('$["${DOPTIONS}" = ""]', 'Set', '_DOPTIONS=' . $doptions2));
            $ext->add($apppaging, "_PAGE.", '', new ext_dial('${DIAL}', '${DTIME},A(${ANNOUNCEMENT})${DOPTIONS}'));
            $ext->add($apppaging, "_PAGE.", 'skipself', new ext_hangup());
            // Try ChanSpy Version
            $ext->add($apppaging, "_SPAGE.", 'chanspy', new ext_chanspy('${SP_DEVICE}-', 'qW'));
            $ext->add($apppaging, "_SPAGE.", '', new ext_hangup());
            // If Asterisk 10 and app_confbridge:
            //
            // Common to admin:
            //  d: dynamically addd conf
            //  o: talker optimization (don't mix non-talkers)
            //  q: quiet mode no enter/leave sounds
            //  x: close conf when last marked user exits
            //
            // Not in Admin:
            //  1: ???
            //  s: present menu
            //See http://issues.freepbx.org/browse/FREEPBX-8796
            //before you even think about removing this to after checking for a page group!
            if ($amp_conf['ASTCONFAPP'] == 'app_confbridge' && isset($conferences_conf) && is_a($conferences_conf, "conferences_conf")) {
                $pu = 'page_user';
                $pud = 'page_user_duplex';
                foreach (array($pu, $pud) as $u) {
                    $conferences_conf->addConfUser($u, 'quiet', 'yes');
                    $conferences_conf->addConfUser($u, 'announce_user_count', 'no');
                    $conferences_conf->addConfUser($u, 'wait_marked', 'yes');
                    $conferences_conf->addConfUser($u, 'end_marked', 'yes');
                    $dds = \FreePBX::Paging()->getDropSilence() ? 'yes' : 'no';
                    $conferences_conf->addConfUser($u, 'dsp_drop_silence', $dds);
                    $conferences_conf->addConfUser($u, 'announce_join_leave', 'no');
                    $conferences_conf->addConfUser($u, 'admin', 'no');
                    $conferences_conf->addConfUser($u, 'marked', 'no');
                }
                $conferences_conf->addConfUser($pu, 'startmuted', 'yes');
            }
            //page playback
            $c = 'app-page-stream';
            $ext->add($c, 's', '', new ext_wait(1));
            $ext->add($c, 's', '', new ext_answer());
            // TODO: PAGE_CONF_OPTS reset in agi script so just use proper context if 10+confbridge no mute
            // x: close conf when last marked user exits
            // q: quiet mode no enter/leave sounds
            //
            // TODO: Ideally what we want is to mark the stream and wait for that, if no stream then no wait for makred user. However
            //       it seems like to end a conference you have to have the kick after last marked user since there doesn't have to be
            //       an admin as far as I can tell.
            //
            //
            if ($amp_conf['ASTCONFAPP'] == 'app_confbridge') {
                $ext->add($c, 's', '', new ext_set('CONFBRIDGE(user,template)', $pud));
                $ext->add($c, 's', '', new ext_set('CONFBRIDGE(user,marked)', 'yes'));
                $ext->add($c, 's', '', new ext_meetme('${PAGE_CONF}', '', ''));
            } else {
                $ext->add($c, 's', '', new ext_meetme('${PAGE_CONF}', '${PAGE_CONF_OPTS}'));
            }
            $ext->add($c, 's', '', new ext_hangup());
            $apppagegroups = 'app-pagegroups';
            // Now get a list of all the paging groups...
            $sql = "SELECT page_group, force_page, duplex, announcement FROM paging_config";
            $paging_groups = $db->getAll($sql, DB_FETCHMODE_ASSOC);
            if (!$paging_groups) {
                break;
                //no need to continue if we dont have any pagegroups
            }
            $extpaging = 'ext-paging';
            if (!empty($paging_groups)) {
                $ext->addInclude('from-internal-noxfer-additional', $extpaging);
            }
            foreach ($paging_groups as $thisgroup) {
                $grp = trim($thisgroup['page_group']);
                switch ($thisgroup['force_page']) {
                    case 1:
                        $pagemode = 'FPAGE';
                        break;
                    case 2:
                        $pagemode = 'SPAGE';
                        break;
                    case 0:
                    default:
                        $pagemode = 'PAGE';
                        break;
                }
                $sql = "SELECT ext FROM paging_groups WHERE page_number='{$grp}'";
                $all_exts = $db->getCol($sql);
                // Create the paging context that is used in the paging application for each phone to auto-answer
                //add ext-paging with goto's to our app-paging context and a hint for the page
                $ext->add($extpaging, $grp, '', new ext_goto($apppagegroups . ',' . $grp . ',1'));
                $ext->addHint($extpaging, $grp, 'Custom:PAGE' . $grp);
                //app-page dialplan
                $ext->add($apppagegroups, $grp, '', new ext_macro('user-callerid'));
                $ext->add($apppagegroups, $grp, '', new ext_set('_PAGEGROUP', $grp));
                //if page group it in use, goto to busy
                $ext->add($apppagegroups, $grp, 'busy-check', new ext_gotoif('$[${TRYLOCK(apppagegroups' . $grp . ')}]', '', 'busy'));
                //set blf to in use
                $ext->add($apppagegroups, $grp, 'devstate', new ext_setvar('DEVICE_STATE(Custom:PAGE' . $grp . ')', 'INUSE'));
                $ext->add($apppagegroups, $grp, '', new ext_gosub('1', 'ssetup', $apppaging));
                $ext->add($apppagegroups, $grp, '', new ext_set('PAGEMODE', $pagemode));
                $ext->add($apppagegroups, $grp, '', new ext_set('PAGE_MEMBERS', implode('-', $all_exts)));
                if ($amp_conf['ASTCONFAPP'] == 'app_confbridge') {
                    $ext->add($apppagegroups, $grp, '', new ext_set('PAGE_CONF_OPTS', $thisgroup['duplex'] ? 'duplex' : ''));
                } else {
                    $ext->add($apppagegroups, $grp, '', new ext_set('PAGE_CONF_OPTS', $page_opts . (!$thisgroup['duplex'] ? 'm' : '')));
                }
                //Default announcement is a beep
                $announcement = "beep";
                //extract our "global default announcement" from the doptions and set it to announcement
                if (preg_match("/A\\(([^\\)]*)\\)/", $doptions, $matches)) {
                    $announcement = isset($matches[1]) ? $matches[1] : "";
                }
                //get our individual page group announcement if set
                if (!empty($thisgroup['announcement'])) {
                    switch ($thisgroup['announcement']) {
                        case "beep":
                            $announcement = "beep";
                            break;
                        case "none":
                            $announcement = "";
                            break;
                        case "default":
                            //do nothing
                            break;
                        default:
                            if (function_exists('recordings_get_file')) {
                                $announcement = recordings_get_file($thisgroup['announcement']);
                            } else {
                                $announcement = "";
                            }
                            break;
                    }
                }
                $ext->add($apppagegroups, $grp, '', new ext_set('ANNOUNCEMENT', $announcement));
                $ext->add($apppagegroups, $grp, 'agi', new ext_agi('page.agi'));
                //we cant use originate from the dialplan as the dialplan command is not asynchronous
                //we would like to though...
                //this code here as a sign of hope -MB
                /*foreach ($page_members as $member) {
                				$ext->add($apppagegroups, $grp, 'page', new ext_originate($member,'app','meetme', '${PAGE_CONF}\,${PAGE_CONF_OPTS}'));
                		}*/
                // TODO this is the master so set appropriate
                //      This is what everyone else has: 1doqsx
                //      Common:
                //        d: dynamically addd conf
                //        o: talker optimization (don't mix non-talkers)
                //        q: quiet mode no enter/leave sounds
                //        x: close conf when last marked user exits
                //      Added:
                //      	w: W() wait until marked user enters conf
                //      	A: Set marked mode
                //      	G: G() Play an intro announcemend in conference
                //      Removed:
                //        1: ???
                //        s: present menu
                //
                //
                if ($amp_conf['ASTCONFAPP'] == 'app_confbridge') {
                    $ext->add($apppagegroups, $grp, '', new ext_set('CONFBRIDGE(user,template)', $pud));
                    $ext->add($apppagegroups, $grp, '', new ext_set('CONFBRIDGE(user,admin)', 'yes'));
                    $ext->add($apppagegroups, $grp, '', new ext_set('CONFBRIDGE(user,marked)', 'yes'));
                    // TODO: should I have no menu?
                    $ext->add($apppagegroups, $grp, '', new ext_answer(''));
                    $ext->add($apppagegroups, $grp, 'page', new ext_meetme('${PAGE_CONF}', ',', 'admin_menu'));
                } else {
                    $ext->add($apppagegroups, $grp, '', new ext_answer(''));
                    $ext->add($apppagegroups, $grp, 'page', new ext_meetme('${PAGE_CONF}', 'dqwxAG'));
                }
                $ext->add($apppagegroups, $grp, '', new ext_hangup());
                $ext->add($apppagegroups, $grp, 'busy', new ext_set('PAGE${PAGEGROUP}BUSY', 'TRUE'));
                $ext->add($apppagegroups, $grp, 'play-busy', new ext_busy(3));
                $ext->add($apppagegroups, $grp, 'busy-hang', new ext_goto('app-pagegroups,h,1'));
            }
            //h
            $ext->add($apppagegroups, 'h', '', new ext_execif('$[${ISNULL(${PAGE${PAGEGROUP}BUSY})}]', 'Set', 'DEVICE_STATE(Custom:PAGE${PAGEGROUP})=NOT_INUSE'));
            break;
    }
}
 /**
  * Update Recording by ID
  * @param integer $id          The recording ID
  * @param string  $name        The recording short name
  * @param string  $description The recording long name
  * @param string  $files       & separated list of files to playback
  * @param integer $fcode       Feature Code number_format
  * @param string  $fcode_pass  Feature code password
  */
 public function updateRecording($id, $name, $description, $files, $fcode = 0, $fcode_pass = '')
 {
     $sql = "UPDATE recordings SET displayname = ?, description = ?, filename = ?, fcode = ?, fcode_pass = ? WHERE id = ?";
     $sth = $this->db->prepare($sql);
     $sth->execute(array($name, $description, $files, $fcode, $fcode_pass, $id));
     if ($fcode != 1) {
         // delete the feature code if it existed
         //
         $fcc = new \featurecode('recordings', 'edit-recording-' . $id);
         $fcc->delete();
         unset($fcc);
     } else {
         // Add the feature code if it is needed
         //
         $fcc = new \featurecode('recordings', 'edit-recording-' . $id);
         $fcc->setDescription("Edit Recording: {$name}");
         $fcc->setDefault('*29' . $id);
         $fcc->setProvideDest();
         $fcc->update();
         unset($fcc);
     }
     needreload();
 }
Example #19
0
<?php

//for translation only
if (false) {
    _("Do-Not-Disturb (DND)");
    _("DND Activate");
    _("DND Deactivate");
    _("DND Toggle");
}
// Register FeatureCode - Activate
$fcc = new featurecode('donotdisturb', 'dnd_on');
$fcc->setDescription('DND Activate');
$fcc->setDefault('*78');
$fcc->update();
unset($fcc);
// Register FeatureCode - Deactivate
$fcc = new featurecode('donotdisturb', 'dnd_off');
$fcc->setDescription('DND Deactivate');
$fcc->setDefault('*79');
$fcc->update();
unset($fcc);
// Register FeatureCode - Activate
$fcc = new featurecode('donotdisturb', 'dnd_toggle');
$fcc->setDescription('DND Toggle');
$fcc->setDefault('*76');
$fcc->update();
unset($fcc);
Example #20
0
function recordings_del($id)
{
    $results = sql("DELETE FROM recordings WHERE id = \"{$id}\"");
    // delete the feature code if it existed
    $fcc = new featurecode('recordings', 'edit-recording-' . $id);
    $fcc->delete();
    unset($fcc);
}
Example #21
0
function miscapps_edit($miscapps_id, $description, $ext, $dest, $enabled = true)
{
    global $db;
    $sql = "UPDATE miscapps SET " . "description = '" . $db->escapeSimple($description) . "', " . "ext = '" . $db->escapeSimple($ext) . "', " . "dest = '" . $db->escapeSimple($dest) . "' " . "WHERE miscapps_id = " . $db->escapeSimple($miscapps_id);
    $result = $db->query($sql);
    if (DB::IsError($result)) {
        die_freepbx($result->getMessage() . $sql);
    }
    $fc = new featurecode('miscapps', 'miscapp_' . $miscapps_id);
    $fc->setDescription($description);
    $fc->setDefault($ext, true);
    $fc->setEnabled($enabled);
    $fc->update();
}
$restrict_mods = array('queues' => true);
$bootstrap_settings['freepbx_auth'] = false;
if (!@(include_once getenv('FREEPBX_CONF') ? getenv('FREEPBX_CONF') : '/etc/freepbx.conf')) {
    include_once '/etc/asterisk/freepbx.conf';
}
if (isset($argv[1])) {
    $queue_toggle_code = $argv[1];
} else {
    $fcc = new featurecode('queues', 'que_toggle');
    $queue_toggle_code = $fcc->getCodeActive();
    unset($fcc);
}
if (isset($argv[2])) {
    $queue_pause_code = $argv[2];
} else {
    $fcc = new featurecode('queues', 'que_pause_toggle');
    $queue_pause_code = $fcc->getCodeActive();
    unset($fcc);
}
if ($queue_pause_code == '' && $queue_toggle_code == '') {
    exit(0);
}
$var = $astman->database_show('AMPUSER');
foreach ($var as $key => $value) {
    $myvar = explode('/', trim($key, '/'));
    $user_hash[$myvar[1]] = true;
}
foreach (array_keys($user_hash) as $user) {
    if ($user == '') {
        unset($user_hash[$user]);
        continue;
    echo "The file {$filename} is not writable";
}
?>
Verifying / Installing cronjob into the FreePBX cron manager.<br>
<?php 
$sql = "SELECT * FROM `cronmanager` WHERE `module` = 't' LIMIT 1;";
$res = $db->query($sql);
if ($res->numRows() != 2) {
    $sql = "INSERT INTO\tcronmanager (module,id,time,freq,command) VALUES ('trunkalarm','every_day',23,24,'/usr/bin/find /var/lib/asterisk/sounds/tts -name \"*.wav\" -mtime +1 -exec rm {} \\\\;')";
    $sql = "INSERT INTO\tcronmanager (module,id,time,freq,command) VALUES ('trunkalarm',*,15,*,'/asterisk/agi-bin/monitor_trunk.php \\\\;')";
    $check = $db->query($sql);
    if (DB::IsError($check)) {
        die_freepbx("Can not create values in cronmanager table: " . $check->getMessage() . "\n");
    }
}
?>
Verifying / Creating TTS Folder.<br>
<?php 
$parm_tts_dir = '/var/lib/asterisk/sounds/tts';
if (!is_dir($parm_tts_dir)) {
    mkdir($parm_tts_dir, 0775);
}
?>
Creating Feature Code.<br>
<?php 
// Register FeatureCode - Trunk Monitor;
$fcc = new featurecode('trunkalarm', 'trunkalarm');
$fcc->setDescription('Trunk Alarm');
$fcc->setDefault('*878625');
$fcc->update();
unset($fcc);
Example #24
0
function core_do_get_config($engine)
{
    global $ext;
    // is this the best way to pass this?
    global $version;
    // this is not the best way to pass this, this should be passetd together with $engine
    global $engineinfo;
    global $amp_conf;
    global $core_conf;
    global $chan_dahdi;
    global $chan_dahdi_loaded;
    global $astman;
    $modulename = "core";
    $callrecording = 'callrecording';
    $callrecording_uid = 'MISSING_CALLRECORDINGS';
    $getCallRecordingModInfo = module_getinfo($callrecording, MODULE_STATUS_ENABLED);
    $nt = notifications::create();
    if (!isset($getCallRecordingModInfo[$callrecording]) || $getCallRecordingModInfo[$callrecording]['status'] !== MODULE_STATUS_ENABLED) {
        if (!$nt->exists($modulename, $callrecording_uid)) {
            $nt->add_notice($modulename, $callrecording_uid, _('Call Recording Module Not Enabled'), _('The Call Recording module is not enabled. Since this feature is required for call recording you may not be able to record calls until the module is installed and enabled.'), '', true, true);
        }
    } else {
        if ($nt->exists($modulename, $callrecording_uid)) {
            $nt->delete($modulename, $callrecording_uid);
        }
    }
    switch ($engine) {
        case "asterisk":
            $ast_ge_14 = version_compare($version, '1.4', 'ge');
            $ast_lt_16 = version_compare($version, '1.6', 'lt');
            $ast_lt_161 = version_compare($version, '1.6.1', 'lt');
            $ast_ge_162 = version_compare($version, '1.6.2', 'ge');
            $ast_ge_10 = version_compare($version, '10', 'ge');
            // Now add to sip_general_addtional.conf
            //
            if (isset($core_conf) && is_a($core_conf, "core_conf")) {
                $useragent = $amp_conf['SIPUSERAGENT'] . '-' . getversion() . "({$version})";
                $core_conf->addIaxGeneral('disallow', 'all');
                $core_conf->addIaxGeneral('allow', 'ulaw');
                $core_conf->addIaxGeneral('allow', 'alaw');
                $core_conf->addIaxGeneral('allow', 'gsm');
                $core_conf->addIaxGeneral('mailboxdetail', 'yes');
                if ($ast_ge_14) {
                    $core_conf->addIaxGeneral('tos', 'ef');
                    // Recommended setting from doc/ip-tos.txt
                }
                $fcc = new featurecode($modulename, 'blindxfer');
                $code = $fcc->getCodeActive();
                unset($fcc);
                $core_conf->addFeatureMap('blindxfer', $code);
                $fcc = new featurecode($modulename, 'atxfer');
                $code = $fcc->getCodeActive();
                unset($fcc);
                $core_conf->addFeatureMap('atxfer', $code);
                $fcc = new featurecode($modulename, 'automon');
                $code = $fcc->getCodeActive();
                unset($fcc);
                if ($code != '') {
                    $core_conf->addFeatureMap('automon', $code);
                    //references app record
                    $core_conf->addApplicationMap('apprecord', $code . ',caller,Macro,one-touch-record', true);
                    /* At this point we are not using hints since we have not found a good way to be always
                     * consistent on both sides of the channel
                     *
                     * $ext->addInclude('from-internal-additional', 'device-hints');
                     * $device_list = core_devices_list("all", 'full', true);
                     * foreach ($device_list as $device) {
                     * 	if ($device['tech'] == 'sip' || $device['tech'] == 'iax2') {
                     *    $ext->add('device-hints', $code.$device['id'], '', new ext_noop("AutoMixMon Hint for: ".$device['id']));
                     *    $ext->addHint('device-hints', $code.$device['id'], "Custom:RECORDING".$device['id']);
                     *   }
                     * }
                     */
                }
                $fcc = new featurecode($modulename, 'disconnect');
                $code = $fcc->getCodeActive();
                unset($fcc);
                $core_conf->addFeatureMap('disconnect', $code);
                $fcc = new featurecode($modulename, 'pickupexten');
                $code = $fcc->getCodeActive();
                unset($fcc);
                $core_conf->addFeatureGeneral('pickupexten', $code);
            }
            // FeatureCodes
            $fcc = new featurecode($modulename, 'userlogon');
            $fc_userlogon = $fcc->getCodeActive();
            unset($fcc);
            $fcc = new featurecode($modulename, 'userlogoff');
            $fc_userlogoff = $fcc->getCodeActive();
            unset($fcc);
            global $version;
            if (version_compare($version, "12.5", "<")) {
                $fcc = new featurecode($modulename, 'zapbarge');
                $fc_zapbarge = $fcc->getCodeActive();
                unset($fcc);
            }
            $fcc = new featurecode($modulename, 'chanspy');
            $fc_chanspy = $fcc->getCodeActive();
            unset($fcc);
            $fcc = new featurecode($modulename, 'simu_pstn');
            $fc_simu_pstn = $fcc->getCodeActive();
            unset($fcc);
            $fcc = new featurecode($modulename, 'pickup');
            $fc_pickup = $fcc->getCodeActive();
            unset($fcc);
            // Log on / off -- all in one context
            if ($fc_userlogoff != '' || $fc_userlogon != '') {
                $ext->addInclude('from-internal-additional', 'app-userlogonoff');
                // Add the include from from-internal
                if ($fc_userlogoff != '') {
                    $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_macro('user-logoff'));
                    $ext->add('app-userlogonoff', $fc_userlogoff, 'hook_off', new ext_hangup(''));
                }
                if ($fc_userlogon != '') {
                    $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon'));
                    $ext->add('app-userlogonoff', $fc_userlogon, 'hook_on_1', new ext_hangup(''));
                    $clen = strlen($fc_userlogon);
                    $fc_userlogon = "_{$fc_userlogon}.";
                    $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon,${EXTEN:' . $clen . '}'));
                    $ext->add('app-userlogonoff', $fc_userlogon, 'hook_on_2', new ext_hangup(''));
                }
            }
            // FREEPBX-7280 - macro-dial
            include 'functions.inc/macro-dial.php';
            /* This needs to be before outbound-routes since they can have a wild-card in them
            		*
            		;------------------------------------------------------------------------
            		; [ext-local-confirm]
            		;------------------------------------------------------------------------
            		; If call confirm is being used in a ringgroup, then calls that do not require confirmation are sent
            		; to this extension instead of straight to the device.
            		;
            		; The sole purpose of sending them here is to make sure we run Macro(auto-confirm) if this
            		; extension answers the line. This takes care of clearing the database key that is used to inform
            		; other potential late comers that the extension has been answered by someone else.
            		;
            		; ALERT_INFO is deprecated in Asterisk 1.4 but still used throughout the FreePBX dialplan and
            		; usually set by dialparties.agi. This allows inheritance. Since no dialparties.agi here, set the
            		; header if it is set.
            		;
            		;------------------------------------------------------------------------
            		*/
            $context = 'ext-local-confirm';
            $ext->addInclude('from-internal-additional', $context);
            // Add the include from from-internal
            $exten = '_LC-.';
            $ext->add($context, $exten, '', new ext_noop_trace('IN ' . $context . ' with - RT: ${RT}, RG_IDX: ${RG_IDX}'));
            //dont allow inbound callers to transfer around inside the system
            $ext->add($context, $exten, '', new ext_execif('$["${DIRECTION}" = "INBOUND"]', 'Set', 'DIAL_OPTIONS=${STRREPLACE(DIAL_OPTIONS,T)}I'));
            $ext->add($context, $exten, '', new ext_set('THISDIAL', '${DB(DEVICE/${EXTEN:3}/dial)}'));
            $ext->add($context, $exten, '', new ext_gotoif('$["${THISDIAL:0:5}"!="PJSIP"]', 'dial'));
            $ext->add($context, $exten, '', new ext_noop('Debug: Found PJSIP Destination ${THISDIAL}, updating with PJSIP_DIAL_CONTACTS'));
            $ext->add($context, $exten, '', new ext_set('THISDIAL', '${PJSIP_DIAL_CONTACTS(${EXTEN:3})}'));
            $ext->add($context, $exten, 'dial', new ext_dial('${THISDIAL}', '${RT},${DIAL_OPTIONS}M(auto-confirm^${RG_IDX})b(func-apply-sipheaders^s^1)'));
            /* This needs to be before outbound-routes since they can have a wild-card in them
            		*
            		;------------------------------------------------------------------------
            		; [findmefollow-ringallv2]
            		;------------------------------------------------------------------------
            		; This context, to be included in from-internal, implements the PreRing part of findmefollow
            		; as well as the GroupRing part. It also communicates between the two so that if DND is set
            		; on the primary extension, and mastermode is enabled, then the other extensions will not ring
            		;
            		;------------------------------------------------------------------------
            		*/
            $context = 'findmefollow-ringallv2';
            $ext->addInclude('from-internal-additional', $context);
            // Add the include from from-internal
            $exten = '_FMPR-.';
            $fm_dnd = $amp_conf['AST_FUNC_SHARED'] ? 'SHARED(FM_DND,${FMUNIQUE})' : 'DB(FM/DND/${FMGRP}/${FMUNIQUE})';
            $ext->add($context, $exten, '', new ext_nocdr(''));
            $ext->add($context, $exten, '', new ext_noop_trace('In FMPR ${FMGRP} with ${EXTEN:5}'));
            $ext->add($context, $exten, '', new ext_set('RingGroupMethod', ''));
            $ext->add($context, $exten, '', new ext_set('USE_CONFIRMATION', ''));
            $ext->add($context, $exten, '', new ext_set('RINGGROUP_INDEX', ''));
            $ext->add($context, $exten, '', new ext_macro('simple-dial', '${EXTEN:5},${FMREALPRERING}'));
            $ext->add($context, $exten, '', new ext_execif('$["${DIALSTATUS}" = "BUSY"]', 'Set', "{$fm_dnd}=DND"));
            $ext->add($context, $exten, '', new ext_noop_trace('Ending FMPR ${FMGRP} with ${EXTEN:5} and dialstatus ${DIALSTATUS}'));
            $ext->add($context, $exten, '', new ext_hangup(''));
            $exten = '_FMGL-.';
            $ext->add($context, $exten, '', new ext_nocdr(''));
            $ext->add($context, $exten, '', new ext_noop_trace('In FMGL ${FMGRP} with ${EXTEN:5}'));
            $ext->add($context, $exten, '', new ext_set('ENDLOOP', '$[${EPOCH} + ${FMPRERING} + 2]'));
            $ext->add($context, $exten, 'start', new ext_gotoif('$["${' . $fm_dnd . '}" = "DND"]', 'dodnd'));
            $ext->add($context, $exten, '', new ext_wait('1'));
            $ext->add($context, $exten, '', new ext_noop_trace('FMGL wait loop: ${EPOCH} / ${ENDLOOP}', 6));
            $ext->add($context, $exten, '', new ext_gotoif('$[${EPOCH} < ${ENDLOOP}]', 'start'));
            if ($amp_conf['AST_FUNC_SHARED']) {
                $ext->add($context, $exten, '', new ext_set($fm_dnd, ''));
            } else {
                $ext->add($context, $exten, '', new ext_dbdel($fm_dnd));
            }
            $ext->add($context, $exten, 'dodial', new ext_macro('dial', '${FMGRPTIME},${DIAL_OPTIONS},${EXTEN:5}'));
            $ext->add($context, $exten, '', new ext_noop_trace('Ending FMGL ${FMGRP} with ${EXTEN:5} and dialstatus ${DIALSTATUS}'));
            $ext->add($context, $exten, '', new ext_hangup(''));
            // n+10(dodnd):
            if ($amp_conf['AST_FUNC_SHARED']) {
                $ext->add($context, $exten, 'dodnd', new ext_set($fm_dnd, ''), 'n', 10);
            } else {
                $ext->add($context, $exten, 'dodnd', new ext_dbdel($fm_dnd), 'n', 10);
            }
            $ext->add($context, $exten, '', new ext_gotoif('$["${FMPRIME}" = "FALSE"]', 'dodial'));
            $ext->add($context, $exten, '', new ext_noop_trace('Got DND in FMGL ${FMGRP} with ${EXTEN:5} in ${RingGroupMethod} mode, aborting'));
            $ext->add($context, $exten, '', new ext_hangup(''));
            // Call pickup using app_pickup - Note that '**xtn' is hard-coded into the GXPs and SNOMs as a number to dial
            // when a user pushes a flashing BLF.
            //
            // We need to add ringgroups to this so that if an extension is part of a ringgroup, we can try to pickup that
            // extension by trying the ringgoup which is what the pickup application is going to respond to.
            //
            // NOTICE: this may be confusing, we check if this is a BRI build of Asterisk and use dpickup instead of pickup
            //         if it is. So we simply assign the variable $ext_pickup which one it is, and use that variable when
            //         creating all the extensions below. So those are "$ext_pickup" on purpose!
            //
            if ($fc_pickup != '' && $ast_ge_14) {
                $ext->addInclude('from-internal-additional', 'app-pickup');
                $fclen = strlen($fc_pickup);
                $ext_pickup = strstr($engineinfo['raw'], 'BRI') ? 'ext_dpickup' : 'ext_pickup';
                $fcc = new featurecode('paging', 'intercom-prefix');
                $intercom_code = $fcc->getCodeActive();
                unset($fcc);
                $picklist = '${EXTEN:' . $fclen . '}';
                $picklist .= '&${EXTEN:' . $fclen . '}@PICKUPMARK';
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new ext_macro('user-callerid'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new ext_set('PICKUP_EXTEN', '${AMPUSER}'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new $ext_pickup($picklist));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new ext_hangup(''));
                if ($intercom_code != '') {
                    $len = strlen($fc_pickup . $intercom_code);
                    $picklist = '${EXTEN:' . $len . '}';
                    $picklist .= '&${EXTEN:' . $len . '}@PICKUPMARK';
                    $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new ext_macro('user-callerid'));
                    $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new ext_set('PICKUP_EXTEN', '${AMPUSER}'));
                    $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup($picklist));
                    $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new ext_hangup(''));
                }
                // In order to do call pickup in ringgroups, we will need to try the ringgoup number
                // when doing call pickup for that ringgoup so we must see who is a member of what ringgroup
                // and then generate the dialplan
                //
                $rg_members = array();
                if (function_exists('ringgroups_list')) {
                    $rg_list = ringgroups_list(true);
                    foreach ($rg_list as $item) {
                        $thisgrp = ringgroups_get($item['grpnum']);
                        $grpliststr = $thisgrp['grplist'];
                        $grplist = explode("-", $grpliststr);
                        foreach ($grplist as $exten) {
                            if (strpos($exten, "#") === false) {
                                $rg_members[$exten][] = $item['grpnum'];
                            }
                        }
                    }
                }
                // Now we have a hash of extensions and what ringgoups they are members of
                // so we need to generate the callpickup dialplan for these specific extensions
                // to try the ringgoup.
                foreach ($rg_members as $exten => $grps) {
                    $picklist = $exten;
                    $picklist .= '&' . $exten . '@PICKUPMARK';
                    foreach ($grps as $grp) {
                        $picklist .= '&' . $grp . '@from-internal';
                        $picklist .= '&' . $grp . '@from-internal-xfer';
                        $picklist .= '&' . $grp . '@ext-group';
                    }
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new ext_macro('user-callerid'));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new ext_set('PICKUP_EXTEN', '${AMPUSER}'));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup($picklist));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new ext_hangup(''));
                    if ($intercom_code != '') {
                        $ext->add('app-pickup', "{$fc_pickup}" . $intercom_code . $exten, '', new ext_macro('user-callerid'));
                        $ext->add('app-pickup', "{$fc_pickup}" . $intercom_code . $exten, '', new ext_set('PICKUP_EXTEN', '${AMPUSER}'));
                        $ext->add('app-pickup', "{$fc_pickup}" . $intercom_code . $exten, '', new $ext_pickup($picklist));
                        $ext->add('app-pickup', "{$fc_pickup}" . $intercom_code . $exten, '', new ext_hangup(''));
                    }
                }
            } elseif ($fc_pickup != '') {
                $ext->addInclude('from-internal-additional', 'app-pickup');
                $fclen = strlen($fc_pickup);
                $ext_pickup = strstr($engineinfo['raw'], 'BRI') ? 'ext_dpickup' : 'ext_pickup';
                $fcc = new featurecode('paging', 'intercom-prefix');
                $intercom_code = $fcc->getCodeActive();
                unset($fcc);
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new ext_NoOp('Attempt to Pickup ${EXTEN:' . $fclen . '} by ${CALLERID(num)}'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new $ext_pickup('${EXTEN:' . $fclen . '}'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new $ext_pickup('${EXTEN:' . $fclen . '}@ext-local'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new $ext_pickup('${EXTEN:' . $fclen . '}@from-internal'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new $ext_pickup('${EXTEN:' . $fclen . '}@from-internal-xfer'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new $ext_pickup('${EXTEN:' . $fclen . '}@from-did-direct'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new $ext_pickup('FMPR-${EXTEN:' . $fclen . '}'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new $ext_pickup('LC-${EXTEN:' . $fclen . '}@from-internal'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new $ext_pickup('LC-${EXTEN:' . $fclen . '}@from-internal-xfer'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new $ext_pickup('FMPR-${EXTEN:' . $fclen . '}@from-internal'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new $ext_pickup('FMPR-${EXTEN:' . $fclen . '}@from-internal-xfer'));
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new $ext_pickup('FMPR-${EXTEN:' . $fclen . '}@from-did-direct'));
                if ($intercom_code != '') {
                    $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('${EXTEN:' . strlen($fc_pickup . $intercom_code) . '}'));
                    $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('${EXTEN:' . strlen($fc_pickup . $intercom_code) . '}@from-internal'));
                    $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('${EXTEN:' . strlen($fc_pickup . $intercom_code) . '}@from-internal-xfer'));
                    $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('${EXTEN:' . strlen($fc_pickup . $intercom_code) . '}@from-did-direct'));
                    $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('FMPR-${EXTEN:' . strlen($fc_pickup . $intercom_code) . '}'));
                    $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('FMPR-${EXTEN:' . strlen($fc_pickup . $intercom_code) . '}@from-internal'));
                    $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('FMPR-${EXTEN:' . strlen($fc_pickup . $intercom_code) . '}@from-internal-xfer'));
                    $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('FMPR-${EXTEN:' . strlen($fc_pickup . $intercom_code) . '}@from-did-direct'));
                }
                $ext->add('app-pickup', "_{$fc_pickup}.", '', new ext_hangup(''));
                // In order to do call pickup in ringgroups, we will need to try the ringgoup number
                // when doing call pickup for that ringgoup so we must see who is a member of what ringgroup
                // and then generate the dialplan
                //
                $rg_members = array();
                if (function_exists('ringgroups_list')) {
                    $rg_list = ringgroups_list(true);
                    foreach ($rg_list as $item) {
                        $thisgrp = ringgroups_get($item['grpnum']);
                        $grpliststr = $thisgrp['grplist'];
                        $grplist = explode("-", $grpliststr);
                        foreach ($grplist as $exten) {
                            if (strpos($exten, "#") === false) {
                                $rg_members[$exten][] = $item['grpnum'];
                            }
                        }
                    }
                }
                // Now we have a hash of extensions and what ringgoups they are members of
                // so we need to generate the callpickup dialplan for these specific extensions
                // to try the ringgoup.
                foreach ($rg_members as $exten => $grps) {
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup($exten));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup($exten . '@ext-local'));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup($exten . '@from-internal'));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup($exten . '@from-internal-xfer'));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup($exten . '@from-did-direct'));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup('LC-' . $exten . '@from-internal'));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup('LC-' . $exten . '@from-internal-xfer'));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup('FMPR-' . $exten));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup('FMPR-' . $exten . '@from-internal'));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup('FMPR-' . $exten . '@from-internal-xfer'));
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup('FMPR-' . $exten . '@from-did-direct'));
                    foreach ($grps as $grp) {
                        $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup($grp . '@from-internal'));
                        $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup($grp . '@from-internal-xfer'));
                        $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new $ext_pickup($grp . '@ext-group'));
                    }
                    $ext->add('app-pickup', "{$fc_pickup}" . $exten, '', new ext_hangup(''));
                }
            }
            // zap barge
            global $version;
            if (version_compare($version, "12.5", "<") && $fc_zapbarge != '') {
                $ext->addInclude('from-internal-additional', 'app-zapbarge');
                // Add the include from from-internal
                $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_macro('user-callerid'));
                $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_setvar('GROUP()', '${CALLERID(number)}'));
                $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_answer(''));
                $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_wait(1));
                $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_zapbarge(''));
                $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_hangup(''));
            }
            // chan spy
            if ($fc_chanspy != '') {
                $ext->addInclude('from-internal-additional', 'app-chanspy');
                // Add the include from from-internal
                $ext->add('app-chanspy', $fc_chanspy, '', new ext_macro('user-callerid'));
                $ext->add('app-chanspy', $fc_chanspy, '', new ext_answer(''));
                $ext->add('app-chanspy', $fc_chanspy, '', new ext_wait(1));
                $ext->add('app-chanspy', $fc_chanspy, '', new ext_chanspy(''));
                $ext->add('app-chanspy', $fc_chanspy, '', new ext_hangup(''));
            }
            // Simulate Inbound call
            if ($fc_simu_pstn != '') {
                $ext->addInclude('from-internal-additional', 'ext-test');
                // Add the include from from-internal
                $ext->add('ext-test', $fc_simu_pstn, '', new ext_macro('user-callerid'));
                if (ctype_digit($fc_simu_pstn)) {
                    $ext->add('ext-test', $fc_simu_pstn, '', new ext_goto('1', '${EXTEN}', 'from-pstn'));
                } else {
                    $ext->add('ext-test', $fc_simu_pstn, '', new ext_goto('1', 's', 'from-pstn'));
                }
                $ext->add('ext-test', 'h', '', new ext_macro('hangupcall'));
            }
            $ext->addInclude('ext-did', 'ext-did-0001');
            // Add the include from from-internal
            $ext->addInclude('ext-did', 'ext-did-0002');
            // Add the include from from-internal
            $ext->add('ext-did', 'foo', '', new ext_noop('bar'));
            /* inbound routing extensions */
            $didlist = \FreePBX::Core()->getAllDIDs();
            if (is_array($didlist)) {
                $catchall = false;
                $catchall_context = 'ext-did-catchall';
                foreach ($didlist as $item) {
                    if (trim($item['destination']) == '') {
                        continue;
                    }
                    $exten = trim($item['extension']);
                    $cidnum = trim($item['cidnum']);
                    // If the user put in just a cid number for routing, we add _. pattern to catch
                    // all DIDs with that CID number. Asterisk will complain about _. being dangerous
                    // but we don't want to limit this to just numberic as someone may be trying to
                    // route a non-numeric did
                    //
                    $cidroute = false;
                    if ($cidnum != '' && $exten == '') {
                        $exten = '_.';
                        $pricid = $item['pricid'] ? true : false;
                        $cidroute = true;
                    } else {
                        if ($cidnum != '' && $exten != '' || $cidnum == '' && $exten == '') {
                            $pricid = true;
                        } else {
                            $pricid = false;
                        }
                    }
                    $context = $pricid ? "ext-did-0001" : "ext-did-0002";
                    $exten = $exten == "" ? "s" : $exten;
                    $exten = $exten . ($cidnum == "" ? "" : "/" . $cidnum);
                    //if a CID num is defined, add it
                    $ext->add($context, $exten, '', new ext_setvar('__DIRECTION', $amp_conf['INBOUND_NOTRANS'] ? 'INBOUND' : ''));
                    if ($cidroute) {
                        $ext->add($context, $exten, '', new ext_setvar('__FROM_DID', '${EXTEN}'));
                        $ext->add($context, $exten, '', new ext_goto('1', 's'));
                        $exten = "s/{$cidnum}";
                        $ext->add($context, $exten, '', new ext_execif('$["${FROM_DID}" = ""]', 'Set', '__FROM_DID=${EXTEN}'));
                    } else {
                        if ($exten == 's') {
                            $ext->add($context, $exten, '', new ext_execif('$["${FROM_DID}" = ""]', 'Set', '__FROM_DID=${EXTEN}'));
                        } else {
                            $ext->add($context, $exten, '', new ext_setvar('__FROM_DID', '${EXTEN}'));
                        }
                    }
                    // always set CallerID name
                    $ext->add($context, $exten, '', new ext_set('CDR(did)', '${FROM_DID}'));
                    $ext->add($context, $exten, '', new ext_execif('$[ "${CALLERID(name)}" = "" ] ', 'Set', 'CALLERID(name)=${CALLERID(num)}'));
                    // if VQA present and configured call it
                    if ($amp_conf['AST_APP_VQA'] && $amp_conf['DITECH_VQA_INBOUND']) {
                        $ext->add($context, $exten, '', new ext_vqa($amp_conf['DITECH_VQA_INBOUND']));
                    }
                    // Always set __MOHCLASS and moh.
                    if (empty($item['mohclass'])) {
                        // Should never happen
                        $item['mohclass'] = "default";
                    }
                    if ($item['mohclass'] != "default") {
                        $ext->add($context, $exten, '', new ext_setmusiconhold($item['mohclass']));
                        $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS', $item['mohclass']));
                    } else {
                        $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS', ""));
                    }
                    // If we require RINGING, signal it as soon as we enter.
                    if ($item['ringing'] === "CHECKED") {
                        $ext->add($context, $exten, '', new ext_ringing(''));
                        $ext->add($context, $exten, '', new ext_setvar('__RINGINGSENT', 'TRUE'));
                    }
                    //Block collect Calls
                    if ($item['reversal'] === "CHECKED") {
                        $ext->add($context, $exten, '', new ext_setvar('__REVERSAL_REJECT', 'TRUE'));
                    } else {
                        $ext->add($context, $exten, '', new ext_setvar('__REVERSAL_REJECT', 'FALSE'));
                    }
                    $ext->add($context, $exten, '', new ext_gotoif('$["${REVERSAL_REJECT}"!="TRUE"]', 'post-reverse-charge'));
                    $ext->add($context, $exten, '', new ext_gotoif('$["${CHANNEL(reversecharge)}"="1"]', 'macro-hangupcall'));
                    $ext->add($context, $exten, 'post-reverse-charge', new ext_noop());
                    if ($item['delay_answer']) {
                        $ext->add($context, $exten, '', new ext_wait($item['delay_answer']));
                    }
                    if ($exten == "s") {
                        //if the exten is s, then also make a catchall for undefined DIDs
                        $catchaccount = "_." . (empty($cidnum) ? "" : "/" . $cidnum);
                        if ($catchaccount == "_." && !$catchall) {
                            $catchall = true;
                            $ext->add($catchall_context, $catchaccount, '', new ext_NoOp('Catch-All DID Match - Found ${EXTEN} - You probably want a DID for this.'));
                            $ext->add($catchall_context, $catchaccount, '', new ext_log('WARNING', 'Friendly Scanner from ${CUT(CUT(SIP_HEADER(Via), ,2),:,1)}'));
                            $ext->add($catchall_context, $catchaccount, '', new ext_set('__FROM_DID', '${EXTEN}'));
                            $ext->add($catchall_context, $catchaccount, '', new ext_goto('1', 's', 'ext-did'));
                        }
                    }
                    if ($item['privacyman'] == "1") {
                        $ext->add($context, $exten, '', new ext_macro('privacy-mgr', $item['pmmaxretries'] . ',' . $item['pmminlength']));
                    } else {
                        // if privacymanager is used, this is not necessary as it will not let blocked/anonymous calls through
                        // otherwise, we need to save the caller presence to set it properly if we forward the call back out the pbx
                        // note - the indirect table could go away as of 1.4.20 where it is fixed so that SetCallerPres can take
                        // the raw format.
                        //
                        $ext->add($context, $exten, '', new ext_setvar('__CALLINGNAMEPRES_SV', '${CALLERID(name-pres)}'));
                        $ext->add($context, $exten, '', new ext_setvar('__CALLINGNUMPRES_SV', '${CALLERID(num-pres)}'));
                        $ext->add($context, $exten, '', new ext_setcallernamepres('allowed_not_screened'));
                        $ext->add($context, $exten, '', new ext_setcallernumpres('allowed_not_screened'));
                    }
                    if (!empty($item['alertinfo'])) {
                        $ext->add($context, $exten, '', new ext_setvar("__ALERT_INFO", str_replace(';', '\\;', $item['alertinfo'])));
                    }
                    $ext->add($context, $exten, 'did-cid-hook', new ext_noop('CallerID Entry Point'));
                    if (!empty($item['grppre'])) {
                        $ext->add($context, $exten, '', new ext_macro('prepend-cid', $item['grppre']));
                    }
                    //the goto destination
                    // destination field in 'incoming' database is backwards from what ext_goto expects
                    $goto_context = strtok($item['destination'], ',');
                    $goto_exten = strtok(',');
                    $goto_pri = strtok(',');
                    $ext->add($context, $exten, 'dest-ext', new ext_goto($goto_pri, $goto_exten, $goto_context));
                }
                // If there's not a catchall, make one with an error message
                if (!$catchall) {
                    $ext->add($catchall_context, 's', '', new ext_noop("No DID or CID Match"));
                    $ext->add($catchall_context, 's', 'a2', new ext_answer(''));
                    $ext->add($catchall_context, 's', '', new ext_log('WARNING', 'Friendly Scanner from ${CUT(CUT(SIP_HEADER(Via), ,2),:,1)}'));
                    $ext->add($catchall_context, 's', '', new ext_wait('2'));
                    $ext->add($catchall_context, 's', '', new ext_playback('ss-noservice'));
                    $ext->add($catchall_context, 's', '', new ext_sayalpha('${FROM_DID}'));
                    $ext->add($catchall_context, 's', '', new ext_hangup(''));
                    $ext->add($catchall_context, '_.', '', new ext_setvar('__FROM_DID', '${EXTEN}'));
                    $ext->add($catchall_context, '_.', '', new ext_noop('Received an unknown call with DID set to ${EXTEN}'));
                    $ext->add($catchall_context, '_.', '', new ext_goto('a2', 's'));
                    $ext->add($catchall_context, 'h', '', new ext_hangup(''));
                }
            }
            // Now create macro-from-zaptel-nnn or macro-from-dahdi-nnn for each defined channel to route it to the DID routing
            // Send it to from-trunk so it is handled as other dids would be handled.
            //
            // to this point we have both zap and dahdi configuration options. At generation though they can't co-exists. If compatibility
            // mode then it's still from-zaptel, otherwise it is which ever is present. We cant use ast_with_dahdi() (chan_dadi) because
            // it is for detection with compatibility mode. We need to actually determine if chan_dahdi is present or not at this point
            //
            if (!isset($chan_dahdi_loaded)) {
                if (isset($astman) && $astman->connected()) {
                    $chan_dahdi_loaded = $astman->mod_loaded('chan_dahdi');
                }
            }
            foreach (core_dahdichandids_list() as $row) {
                $channel = $row['channel'];
                $did = $row['did'];
                $this_context = "macro-from-dahdi-{$channel}";
                $ext->add($this_context, 's', '', new ext_noop('Entering ' . $this_context . ' with DID = ${DID} and setting to: ' . $did));
                $ext->add($this_context, 's', '', new ext_setvar('__FROM_DID', $did));
                $ext->add($this_context, 's', '', new ext_goto('1', $did, 'from-trunk'));
            }
            /* user extensions */
            $ext->addInclude('from-internal-additional', 'ext-local');
            // If running in Dynamic mode, this will insert the hints through an Asterisk #exec call.
            // which require "execincludes=yes" to be set in the [options] section of asterisk.conf
            //
            $fcc = new featurecode('paging', 'intercom-prefix');
            $intercom_code = $fcc->getCodeActive();
            unset($fcc);
            $intercom_code = $intercom_code == '' ? 'nointercom' : $intercom_code;
            $fcc = new featurecode('campon', 'toggle');
            $campon_toggle = $fcc->getCodeActive();
            unset($fcc);
            $campon_toggle = $campon_toggle == '' ? 'nocampon' : $campon_toggle;
            // Pass the code so agi scripts like user_login_logout know to generate hints
            //
            $ext->addGlobal('INTERCOMCODE', $intercom_code);
            if ($amp_conf['DYNAMICHINTS']) {
                if ($amp_conf['USEDEVSTATE'] && function_exists('donotdisturb_get_config')) {
                    $add_dnd = 'dnd';
                } else {
                    $add_dnd = '';
                }
                $ext->addExec('ext-local', $amp_conf['AMPBIN'] . '/generate_hints.php ' . $intercom_code . ' ' . $campon_toggle . ' ' . $add_dnd);
            }
            $userlist = core_users_list();
            if (is_array($userlist)) {
                foreach ($userlist as $item) {
                    $exten = \FreePBX::Core()->getUser($item[0]);
                    $vm = $exten['voicemail'] == "novm" || $exten['voicemail'] == "disabled" || $exten['voicemail'] == "" ? "novm" : $exten['extension'];
                    $ext->add('ext-local', $exten['extension'], '', new ext_set('__RINGTIMER', '${IF($["${DB(AMPUSER/' . $exten['extension'] . '/ringtimer)}" > "0"]?${DB(AMPUSER/' . $exten['extension'] . '/ringtimer)}:${RINGTIMER_DEFAULT})}'));
                    $dest_args = ',' . ($exten['noanswer_dest'] == '' ? '0' : '1') . ',' . ($exten['busy_dest'] == '' ? '0' : '1') . ',' . ($exten['chanunavail_dest'] == '' ? '0' : '1');
                    $ext->add('ext-local', $exten['extension'], '', new ext_macro('exten-vm', $vm . "," . $exten['extension'] . $dest_args));
                    $ext->add('ext-local', $exten['extension'], 'dest', new ext_set('__PICKUPMARK', ''));
                    if ($exten['noanswer_dest']) {
                        if ($exten['noanswer_cid'] != '') {
                            $ext->add('ext-local', $exten['extension'], '', new ext_execif('$["${DIALSTATUS}"="NOANSWER"]', 'Set', 'CALLERID(name)=' . $exten['noanswer_cid'] . '${CALLERID(name)}'));
                        }
                        $ext->add('ext-local', $exten['extension'], '', new ext_gotoif('$["${DIALSTATUS}"="NOANSWER"]', $exten['noanswer_dest']));
                    }
                    if ($exten['busy_dest']) {
                        if ($exten['busy_cid'] != '') {
                            $ext->add('ext-local', $exten['extension'], '', new ext_execif('$["${DIALSTATUS}"="BUSY"]', 'Set', 'CALLERID(name)=' . $exten['busy_cid'] . '${CALLERID(name)}'));
                        }
                        $ext->add('ext-local', $exten['extension'], '', new ext_gotoif('$["${DIALSTATUS}"="BUSY"]', $exten['busy_dest']));
                    }
                    if ($exten['chanunavail_dest']) {
                        if ($exten['chanunavail_cid'] != '') {
                            $ext->add('ext-local', $exten['extension'], '', new ext_execif('$["${DIALSTATUS}"="CHANUNAVAIL"]', 'Set', 'CALLERID(name)=' . $exten['chanunavail_cid'] . '${CALLERID(name)}'));
                        }
                        $ext->add('ext-local', $exten['extension'], '', new ext_gotoif('$["${DIALSTATUS}"="CHANUNAVAIL"]', $exten['chanunavail_dest']));
                    }
                    if ($vm != "novm") {
                        // This usually gets called from macro-exten-vm but if follow-me destination need to go this route
                        $ext->add('ext-local', $exten['extension'], '', new ext_macro('vm', $vm . ',${DIALSTATUS},${IVR_RETVM}'));
                        $ext->add('ext-local', $exten['extension'], '', new ext_goto('1', 'vmret'));
                        $ext->add('ext-local', 'vmb' . $exten['extension'], '', new ext_macro('vm', $vm . ',BUSY,${IVR_RETVM}'));
                        $ext->add('ext-local', 'vmb' . $exten['extension'], '', new ext_goto('1', 'vmret'));
                        $ext->add('ext-local', 'vmu' . $exten['extension'], '', new ext_macro('vm', $vm . ',NOANSWER,${IVR_RETVM}'));
                        $ext->add('ext-local', 'vmu' . $exten['extension'], '', new ext_goto('1', 'vmret'));
                        $ext->add('ext-local', 'vms' . $exten['extension'], '', new ext_macro('vm', $vm . ',NOMESSAGE,${IVR_RETVM}'));
                        $ext->add('ext-local', 'vms' . $exten['extension'], '', new ext_goto('1', 'vmret'));
                        $ext->add('ext-local', 'vmi' . $exten['extension'], '', new ext_macro('vm', $vm . ',INSTRUCT,${IVR_RETVM}'));
                        $ext->add('ext-local', 'vmi' . $exten['extension'], '', new ext_goto('1', 'vmret'));
                    } else {
                        // If we return from teh macro, it means we are suppose to return to the IVR
                        //
                        $ext->add('ext-local', $exten['extension'], '', new ext_goto('1', 'return', '${IVR_CONTEXT}'));
                    }
                    // Create the hints if running in normal mode
                    //
                    if (!$amp_conf['DYNAMICHINTS']) {
                        $hint = core_hint_get($exten['extension']);
                        $dnd_string = $amp_conf['USEDEVSTATE'] && function_exists('donotdisturb_get_config') ? "&Custom:DND" . $exten['extension'] : '';
                        $presence_string = $amp_conf['AST_FUNC_PRESENCE_STATE'] ? ",CustomPresence:" . $exten['extension'] : '';
                        $hint_string = (!empty($hint) ? $hint : '') . $dnd_string . $presence_string;
                        $astman->database_put("AMPUSER/" . $exten['extension'], "hint", $hint_string);
                        if ($hint_string) {
                            //TODO: Lots of hints here. Can this be dynamic? No I dont think so
                            $ext->addHint('ext-local', $exten['extension'], $hint_string);
                        }
                    }
                    if ($exten['sipname']) {
                        $ext->add('ext-local', $exten['sipname'], '', new ext_goto('1', $item[0], 'from-internal'));
                    }
                }
                // Now make a special context for the IVR inclusions of local extension dialing so that
                // when people use the Queues breakout ability, and break out to someone's extensions, voicemail
                // works.
                //
                $ivr_context = 'from-did-direct-ivr';
                $sql = "SELECT LENGTH(extension) as len FROM users GROUP BY len";
                $sth = FreePBX::Database()->prepare($sql);
                $sth->execute();
                $rows = $sth->fetchAll(\PDO::FETCH_ASSOC);
                foreach ($rows as $row) {
                    $ext->add($ivr_context, '_' . str_repeat('X', $row['len']), '', new ext_macro('blkvm-clr'));
                    $ext->add($ivr_context, '_' . str_repeat('X', $row['len']), '', new ext_setvar('__NODEST', ''));
                    $ext->add($ivr_context, '_' . str_repeat('X', $row['len']), '', new ext_goto('1', '${EXTEN}', 'from-did-direct'));
                }
                $ext->add('ext-local', 'vmret', '', new ext_gotoif('$["${IVR_RETVM}" = "RETURN" & "${IVR_CONTEXT}" != ""]', 'playret'));
                $ext->add('ext-local', 'vmret', '', new ext_hangup(''));
                $ext->add('ext-local', 'vmret', 'playret', new ext_playback('exited-vm-will-be-transfered&silence/1'));
                $ext->add('ext-local', 'vmret', '', new ext_goto('1', 'return', '${IVR_CONTEXT}'));
                $ext->add('ext-local', 'h', '', new ext_macro('hangupcall'));
            }
            //$ext->addHint('ext-local', "_X.", $hint_string);
            if ($intercom_code != '') {
                $ext->addHint('ext-local', "_" . $intercom_code . "X.", '${DB(AMPUSER/${EXTEN:' . strlen($intercom_code) . '}/hint)}');
            }
            /* Create the from-trunk-tech-chanelid context that can be used for inbound group counting
             * Create the DUNDI macros for DUNDI trunks
             * Create the ext-trunk context for direct trunk dialing TODO: should this be its own module?
             */
            $trunklist = core_trunks_listbyid();
            if (is_array($trunklist) && count($trunklist)) {
                $tcontext = 'ext-trunk';
                $texten = 'tdial';
                $tcustom = 'tcustom';
                $generate_texten = false;
                $generate_tcustom = false;
                foreach ($trunklist as $trunkprops) {
                    if (trim($trunkprops['disabled']) == 'on') {
                        continue;
                    }
                    $trunkgroup = 'OUT_' . $trunkprops['trunkid'];
                    switch ($trunkprops['tech']) {
                        case 'dundi':
                            $macro_name = 'macro-dundi-' . $trunkprops['trunkid'];
                            $ext->addSwitch($macro_name, 'DUNDI/' . $trunkprops['channelid']);
                            $ext->add($macro_name, 's', '', new ext_goto('1', '${ARG1}'));
                            $trunkcontext = "from-trunk-" . $trunkprops['tech'] . "-" . $trunkprops['channelid'];
                            $ext->add($trunkcontext, '_.', '', new ext_set('GROUP()', $trunkgroup));
                            $ext->add($trunkcontext, '_.', '', new ext_goto('1', '${EXTEN}', 'from-trunk'));
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_set('OUTBOUND_GROUP', $trunkgroup));
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_gotoif('$["${OUTMAXCHANS_' . $trunkprops['trunkid'] . '}" = ""]', 'nomax'));
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_gotoif('$[${GROUP_COUNT(' . $trunkgroup . ')} >= ${OUTMAXCHANS_${DIAL_TRUNK}}]', 'hangit'));
                            $ext->add($tcontext, $trunkprops['trunkid'], 'nomax', new ext_execif('$["${CALLINGNAMEPRES_SV}" != ""]', 'Set', 'CALLERPRES(name-pres)=${CALLINGNAMEPRES_SV}'));
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_execif('$["${CALLINGNUMPRES_SV}" != ""]', 'Set', 'CALLERPRES(num-pres)=${CALLINGNUMPRES_SV}'));
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_set('DIAL_NUMBER', '${FROM_DID}'));
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_gosubif('$["${PREFIX_TRUNK_' . $trunkprops['trunkid'] . '}" != ""]', 'sub-flp-' . $trunkprops['trunkid'] . ',s,1'));
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}'));
                            // OUTNUM is the final dial number
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_macro('dundi-${DIAL_TRUNK}', '${OUTNUM}'));
                            $ext->add($tcontext, $trunkprops['trunkid'], 'hangit', new ext_hangup());
                            break;
                        case 'iax':
                            $trunkprops['tech'] = 'iax2';
                            // fall-through
                        // fall-through
                        case 'pjsip':
                        case 'iax2':
                        case 'sip':
                            $trunkcontext = "from-trunk-" . $trunkprops['tech'] . "-" . $trunkprops['channelid'];
                            $ext->add($trunkcontext, '_.', '', new ext_set('GROUP()', $trunkgroup));
                            $ext->add($trunkcontext, '_.', '', new ext_goto('1', '${EXTEN}', 'from-trunk'));
                            // fall-through
                        // fall-through
                        case 'zap':
                        case 'dahdi':
                            // PJSip hack. This needs to be re-written, I think.
                            if ($trunkprops['tech'] == "pjsip") {
                                $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_set('TDIAL_SUFFIX', "@" . $trunkprops['channelid']));
                                $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_set('TDIAL_STRING', strtoupper($trunkprops['tech'])));
                            } else {
                                $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_set('TDIAL_STRING', strtoupper($trunkprops['tech']) . '/' . $trunkprops['channelid']));
                            }
                            $trunkcontext = "from-trunk-" . $trunkprops['tech'] . "-" . $trunkprops['channelid'];
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_set('DIAL_TRUNK', $trunkprops['trunkid']));
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_goto('1', $texten, 'ext-trunk'));
                            $generate_texten = true;
                            break;
                            // TODO we don't have the OUTNUM until later so fix this...
                        // TODO we don't have the OUTNUM until later so fix this...
                        case 'custom':
                            $dial_string = str_replace('$OUTNUM$', '${SS}{OUTNUM}', $trunkprops['channelid']);
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_set('SS', '$'));
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_set('TDIAL_STRING', $dial_string));
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_set('DIAL_TRUNK', $trunkprops['trunkid']));
                            $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_goto('1', $tcustom, 'ext-trunk'));
                            $generate_tcustom = true;
                            break;
                        case 'enum':
                            // Not Supported
                            break;
                        default:
                    }
                }
                if ($generate_tcustom) {
                    $ext->add($tcontext, $tcustom, '', new ext_set('OUTBOUND_GROUP', 'OUT_${DIAL_TRUNK}'));
                    $ext->add($tcontext, $tcustom, '', new ext_gotoif('$["${OUTMAXCHANS_${DIAL_TRUNK}}" = ""]', 'nomax'));
                    $ext->add($tcontext, $tcustom, '', new ext_gotoif('$[${GROUP_COUNT(OUT_${DIAL_TRUNK})} >= ${OUTMAXCHANS_${DIAL_TRUNK}}]', 'hangit'));
                    $ext->add($tcontext, $tcustom, 'nomax', new ext_execif('$["${CALLINGNAMEPRES_SV}" != ""]', 'Set', 'CALLERPRES(name-pres)=${CALLINGNAMEPRES_SV}'));
                    $ext->add($tcontext, $tcustom, '', new ext_execif('$["${CALLINGNUMPRES_SV}" != ""]', 'Set', 'CALLERPRES(num-pres)=${CALLINGNUMPRES_SV}'));
                    $ext->add($tcontext, $tcustom, '', new ext_set('DIAL_NUMBER', '${FROM_DID}'));
                    $ext->add($tcontext, $tcustom, '', new ext_gosubif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]', 'sub-flp-${DIAL_TRUNK},s,1'));
                    $ext->add($tcontext, $tcustom, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}'));
                    // OUTNUM is the final dial number
                    // Address Security Vulnerability in many earlier versions of Asterisk from an external source tranmitting a
                    // malicious CID that can cause overflows in the Asterisk code.
                    //
                    $ext->add($tcontext, $tcustom, '', new ext_set('CALLERID(number)', '${CALLERID(number):0:40}'));
                    $ext->add($tcontext, $tcustom, '', new ext_set('CALLERID(name)', '${CALLERID(name):0:40}'));
                    $ext->add($tcontext, $tcustom, '', new ext_set('DIAL_TRUNK_OPTIONS', '${IF($["${DB_EXISTS(TRUNK/${DIAL_TRUNK}/dialopts)}" = "1"]?${DB_RESULT}:${TRUNK_OPTIONS})}'));
                    $ext->add($tcontext, $tcustom, '', new ext_dial('${EVAL(${TDIAL_STRING})}', '${TRUNK_RING_TIMER},${DIAL_TRUNK_OPTIONS}'));
                    $ext->add($tcontext, $tcustom, 'hangit', new ext_hangup());
                }
                if ($generate_texten) {
                    $ext->add($tcontext, $texten, '', new ext_set('OUTBOUND_GROUP', 'OUT_${DIAL_TRUNK}'));
                    $ext->add($tcontext, $texten, '', new ext_gotoif('$["${OUTMAXCHANS_${DIAL_TRUNK}}" = ""]', 'nomax'));
                    $ext->add($tcontext, $texten, '', new ext_gotoif('$[${GROUP_COUNT(OUT_${DIAL_TRUNK})} >= ${OUTMAXCHANS_${DIAL_TRUNK}}]', 'hangit'));
                    $ext->add($tcontext, $texten, 'nomax', new ext_execif('$["${CALLINGNAMEPRES_SV}" != ""]', 'Set', 'CALLERPRES(name-pres)=${CALLINGNAMEPRES_SV}'));
                    $ext->add($tcontext, $texten, '', new ext_execif('$["${CALLINGNUMPRES_SV}" != ""]', 'Set', 'CALLERPRES(num-pres)=${CALLINGNUMPRES_SV}'));
                    $ext->add($tcontext, $texten, '', new ext_set('DIAL_NUMBER', '${FROM_DID}'));
                    $ext->add($tcontext, $texten, '', new ext_gosubif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]', 'sub-flp-${DIAL_TRUNK},s,1'));
                    $ext->add($tcontext, $texten, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}'));
                    // OUTNUM is the final dial number
                    $ext->add($tcontext, $texten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${IF($["${DB_EXISTS(TRUNK/${DIAL_TRUNK}/dialopts)}" = "1"]?${DB_RESULT}:${TRUNK_OPTIONS})}'));
                    $ext->add($tcontext, $texten, '', new ext_dial('${TDIAL_STRING}/${OUTNUM}${TDIAL_SUFFIX}', '${TRUNK_RING_TIMER},${DIAL_TRUNK_OPTIONS}'));
                    // Address Security Vulnerability in many earlier versions of Asterisk from an external source tranmitting a
                    // malicious CID that can cause overflows in the Asterisk code.
                    //
                    $ext->add($tcontext, $texten, '', new ext_set('CALLERID(number)', '${CALLERID(number):0:40}'));
                    $ext->add($tcontext, $texten, '', new ext_set('CALLERID(name)', '${CALLERID(name):0:40}'));
                    $ext->add($tcontext, $texten, 'hangit', new ext_hangup());
                }
            }
            /* dialplan globals */
            // modules should NOT use the globals table to store anything!
            // modules should use $ext->addGlobal("testvar","testval"); in their module_get_config() function instead
            // I'm cheating for core functionality - do as I say, not as I do ;-)
            // Auto add these globals to give access to agi scripts and other needs, unless defined in the global table.
            //
            $amp_conf_globals = array("ASTETCDIR", "ASTMODDIR", "ASTVARLIBDIR", "ASTAGIDIR", "ASTSPOOLDIR", "ASTRUNDIR", "ASTLOGDIR", "CWINUSEBUSY", "AMPMGRUSER", "AMPMGRPASS", "ASTMANAGERHOST", "AMPDBENGINE", "AMPDBHOST", "AMPDBNAME", "AMPDBUSER", "AMPDBPASS", "AMPDBFILE", "VMX_CONTEXT", "VMX_PRI", "VMX_TIMEDEST_CONTEXT", "VMX_TIMEDEST_EXT", "VMX_TIMEDEST_PRI", "VMX_LOOPDEST_CONTEXT", "VMX_LOOPDEST_EXT", "VMX_LOOPDEST_PRI");
            $sql = "SELECT * FROM globals";
            $globals = sql($sql, "getAll", DB_FETCHMODE_ASSOC);
            foreach ($globals as $global) {
                $value = $global['value'];
                // Ticket # 5477 Create a default value that can't be polluted
                if ($global['variable'] == 'RINGTIMER') {
                    $ext->addGlobal('RINGTIMER_DEFAULT', $value);
                    continue;
                }
                $ext->addGlobal($global['variable'], $value);
                // now if for some reason we have a variable in the global table
                // that is in our $amp_conf_globals list, then remove it so we
                // don't duplicate, the sql table will take precedence
                //
                if (array_key_exists($global['variable'], $amp_conf_globals)) {
                    $rm_keys = array_keys($amp_conf_globals, $global['variable']);
                    foreach ($rm_keys as $index) {
                        unset($amp_conf_globals[$index]);
                    }
                }
            }
            foreach ($amp_conf_globals as $global) {
                if (isset($amp_conf[$global])) {
                    $value = $amp_conf[$global];
                    if ($value === true || $value === false) {
                        $value = $value ? 'true' : 'false';
                    }
                    $ext->addGlobal($global, $value);
                }
            }
            // Put the MIXMON_DIR, it needs a trailing / so is special cased here
            $mixmon_dir = $amp_conf['MIXMON_DIR'] != '' ? $amp_conf['MIXMON_DIR'] . '/' : '';
            $ext->addGlobal('MIXMON_DIR', $mixmon_dir);
            //out("Added to globals: MIXMON_DIR = $mixmon_dir");
            // Add some globals that are used by the dialplan
            //
            $add_globals = array('MIXMON_POST' => 'MIXMON_POST', 'DIAL_OPTIONS' => 'DIAL_OPTIONS', 'TRUNK_OPTIONS' => 'TRUNK_OPTIONS', 'TRUNK_RING_TIMER' => 'TRUNK_RING_TIMER', 'MIXMON_FORMAT' => 'MIXMON_FORMAT', 'REC_POLICY' => 'REC_POLICY', 'RINGTIMER' => 'RINGTIMER_DEFAULT', 'TRANSFER_CONTEXT' => 'TRANSFER_CONTEXT');
            foreach ($add_globals as $g => $v) {
                $ext->addGlobal($v, $amp_conf[$g]);
                //out("Added to globals: $v = ".$amp_conf[$g]);
            }
            unset($add_globals);
            // Put the asterisk version in a global for agi etc.
            $ext->addGlobal('ASTVERSION', $version);
            // Put the use of chan_dahdi in a global for dialparties
            $ext->addGlobal('ASTCHANDAHDI', $chan_dahdi ? '1' : '0');
            // Create constant NULL in globals
            $ext->addGlobal('NULL', '""');
            // Now let's create the required globals for the trunks so outbound routes work. These used to
            // be stored in the globals table but are not generated by retrieve conf and pulled from the
            // trunks table
            //
            $sqlstr = "\n\t\tSELECT `trunkid`, `tech`, `outcid`, `keepcid`, `maxchans`, `failscript`, `dialoutprefix`, `channelid`, `disabled`\n\t\tFROM `trunks` ORDER BY `trunkid`\n\t\t";
            $trunks = sql($sqlstr, "getAll", DB_FETCHMODE_ASSOC);
            $trunk_hash = core_trunks_list_dialrules();
            // $has_keepcid_cnum is used when macro-outbound-callerid is generated to determine if we need to insert the
            // final execif() statement so it is important to be set before then and here
            //
            $has_keepcid_cnum = false;
            foreach ($trunks as $trunk) {
                $tid = $trunk['trunkid'];
                $tech = strtoupper($trunk['tech']);
                if ($tech == 'IAX') {
                    $tech = 'IAX2';
                } elseif ($tech == 'ZAP' && $chan_dahdi) {
                    $tech = 'DAHDI';
                }
                if ($tech == 'CUSTOM') {
                    $ext->addGlobal('OUT_' . $tid, 'AMP:' . trim($trunk['channelid']));
                } elseif ($tech != 'PJSIP') {
                    $ext->addGlobal('OUT_' . $tid, $tech . "/" . $trunk['channelid']);
                } else {
                    $ext->addGlobal('OUT_' . $tid, $tech);
                    $ext->addGlobal('OUT_' . $tid . '_SUFFIX', '@' . $trunk['channelid']);
                }
                $ext->addGlobal('OUTCID_' . $tid, $trunk['outcid']);
                $ext->addGlobal('OUTMAXCHANS_' . $tid, $trunk['maxchans']);
                $ext->addGlobal('OUTFAIL_' . $tid, $trunk['failscript']);
                $ext->addGlobal('OUTPREFIX_' . $tid, $trunk['dialoutprefix']);
                $ext->addGlobal('OUTDISABLE_' . $tid, $trunk['disabled']);
                $ext->addGlobal('OUTKEEPCID_' . $tid, $trunk['keepcid']);
                $ext->addGlobal('FORCEDOUTCID_' . $tid, $trunk['keepcid'] == 'all' ? $trunk['outcid'] : "");
                if ($trunk['keepcid'] == 'cnum') {
                    $has_keepcid_cnum = true;
                }
                // Generate PREFIX_TRUNK_$tid even if 0 since globals will persist and cause crashes
                if (isset($trunk_hash[$tid]) && count($trunk_hash)) {
                    $patterns = $trunk_hash[$tid];
                    // First, generate the global referencing how many there are
                    $ext->addGlobal("PREFIX_TRUNK_{$tid}", count($patterns));
                    $context = 'sub-flp-' . $tid;
                    $target = 'TARGET_FLP_' . $tid;
                    $exten = 's';
                    foreach ($patterns as $pattern) {
                        $prepend = $pattern['prepend_digits'];
                        $offset = strlen(preg_replace('/(\\[[^\\]]*\\])/', 'X', $pattern['match_pattern_prefix']));
                        $regex_base = $pattern['match_pattern_prefix'] . $pattern['match_pattern_pass'];
                        // convert asterisk pattern matching into perl regular expression
                        //  - two steps, use $ in place of +
                        //  - next replace $ with +
                        // if you don't do this, the str_replace() walks over itself
                        $regex_intermediate = str_replace(array('X', 'Z', 'N', '.', '*', '+'), array('[0-9]', '[1-9]', '[2-9]', '[0-9#*\\\\$]$', '\\\\*', '\\\\$'), $pattern['match_pattern_prefix'] . $pattern['match_pattern_pass']);
                        $regex = strtr($regex_intermediate, "\$", "+");
                        if ($pattern['prepend_digits'] == '' && $offset == 0) {
                            $ext->add($context, $exten, '', new ext_execif('$[${REGEX("^' . $regex . '$" ${DIAL_NUMBER})} = 1]', 'Return'));
                        } else {
                            $offset = $offset ? ':' . $offset : '';
                            $ext->add($context, $exten, '', new ext_execif('$[${REGEX("^' . $regex . '$" ${DIAL_NUMBER})} = 1]', 'Set', $target . '=' . $pattern['prepend_digits'] . '${DIAL_NUMBER' . $offset . '}'));
                            $ext->add($context, $exten, '', new ext_gotoif('$[${LEN(${' . $target . '})} != 0]', 'match'));
                        }
                    }
                    $ext->add($context, $exten, '', new ext_return(''));
                    $ext->add($context, $exten, 'match', new ext_set('DIAL_NUMBER', '${' . $target . '}'));
                    $ext->add($context, $exten, '', new ext_return(''));
                } else {
                    $ext->addGlobal("PREFIX_TRUNK_{$tid}", '');
                }
            }
            /* macro-prepend-cid */
            // prepend a cid and if set to replace previous prepends, do so, otherwise stack them
            //
            $mcontext = 'macro-prepend-cid';
            $exten = 's';
            if ($amp_conf['CID_PREPEND_REPLACE']) {
                $ext->add($mcontext, $exten, '', new ext_gotoif('$["${RGPREFIX}" = ""]', 'REPCID'));
                $ext->add($mcontext, $exten, '', new ext_gotoif('$["${RGPREFIX}" != "${CALLERID(name):0:${LEN(${RGPREFIX})}}"]', 'REPCID'));
                $ext->add($mcontext, $exten, '', new ext_noop_trace('Current RGPREFIX is ${RGPREFIX}....stripping from CallerID'));
                $ext->add($mcontext, $exten, '', new ext_set('CALLERID(name)', '${CALLERID(name):${LEN(${RGPREFIX})}}'));
                $ext->add($mcontext, $exten, '', new ext_set('_RGPREFIX', ''));
            }
            $ext->add($mcontext, $exten, 'REPCID', new ext_set('_RGPREFIX', '${ARG1}'));
            $ext->add($mcontext, $exten, '', new ext_set('CALLERID(name)', '${RGPREFIX}${CALLERID(name)}'));
            /* outbound routes */
            $ext->addInclude('from-internal-additional', 'outbound-allroutes');
            //$ext->add('outbound-allroutes', '_!', '', new ext_macro('user-callerid,SKIPTTL'));
            $ext->add('outbound-allroutes', 'foo', '', new ext_noop('bar'));
            $routes = \FreePBX::Core()->getAllRoutes();
            $trunk_table = core_trunks_listbyid();
            $trunk_type_needed = array();
            // track which macros need to be generated
            $delim = $ast_lt_16 ? '|' : ',';
            foreach ($routes as $route) {
                $add_extra_pri1 = array();
                $context = 'outrt-' . $route['route_id'];
                $comment = $route['name'];
                $ext->addSectionComment($context, $comment);
                if (function_exists('timeconditions_timegroups_get_times') && $route['time_group_id'] !== null) {
                    $times = timeconditions_timegroups_get_times($route['time_group_id'], true);
                    if (is_array($times) && count($times)) {
                        foreach ($times as $time) {
                            $ext->addInclude('outbound-allroutes', $context . $delim . $time[1], $comment);
                        }
                    } else {
                        $ext->addInclude('outbound-allroutes', $context, $comment);
                    }
                } else {
                    $ext->addInclude('outbound-allroutes', $context, $comment);
                }
                $patterns = core_routing_getroutepatternsbyid($route['route_id']);
                $trunks = core_routing_getroutetrunksbyid($route['route_id']);
                foreach ($patterns as $pattern) {
                    // returns:
                    // array('prepend_digits' => $pattern['prepend_digits'], 'dial_pattern' => $exten, 'offset' => $pos);
                    //
                    $fpattern = core_routing_formatpattern($pattern);
                    $exten = $fpattern['dial_pattern'];
                    $offset = $fpattern['offset'] == 0 ? '' : ':' . $fpattern['offset'];
                    // This will not get called, but it fixes some things like custom-context or other possible custom uses of these
                    // generated contexts that don't have an 'outbound-allroutes' wrapper around them, of course in those cases the
                    // CID part of the dialplan will not get executed
                    if (!isset($add_extra_pri1[$fpattern['base_pattern']])) {
                        $ext->add($context, $fpattern['base_pattern'], '', new ext_macro('user-callerid,LIMIT,EXTERNAL'));
                        $add_extra_pri1[$fpattern['base_pattern']] = true;
                    }
                    if ($fpattern['base_pattern'] != $exten) {
                        $ext->add($context, $exten, '', new ext_macro('user-callerid,LIMIT,EXTERNAL'));
                    }
                    $ext->add($context, $exten, '', new ext_noop_trace(sprintf(_('Calling Out Route: %s'), '${SET(OUTBOUND_ROUTE_NAME=' . $route['name'] . ')}'), 1));
                    if ($route['dest']) {
                        $ext->add($context, $exten, '', new ext_set("ROUTE_CIDSAVE", '${CALLERID(all)}'));
                    }
                    // Conditionally Add Divesion Header if the call was diverted
                    if ($amp_conf['DIVERSIONHEADER']) {
                        $ext->add($context, $exten, '', new ext_gosubif('$[${LEN(${FROM_DID})}>0 & "${FROM_DID}"!="s"]', 'sub-diversion-header,s,1'));
                    }
                    // if VQA present and configured call it
                    if ($amp_conf['AST_APP_VQA'] && $amp_conf['DITECH_VQA_OUTBOUND']) {
                        $ext->add($context, $exten, '', new ext_vqa($amp_conf['DITECH_VQA_OUTBOUND']));
                    }
                    if ($route['emergency_route'] != '') {
                        $ext->add($context, $exten, '', new ext_set("EMERGENCYROUTE", $route['emergency_route']));
                    }
                    if ($route['intracompany_route'] != '') {
                        $ext->add($context, $exten, '', new ext_set("INTRACOMPANYROUTE", $route['intracompany_route']));
                    }
                    if ($route['mohclass'] != '') {
                        $ext->add($context, $exten, '', new ext_set("MOHCLASS", '${IF($["${MOHCLASS}"=""]?' . $route['mohclass'] . ':${MOHCLASS})}'));
                    }
                    if ($route['outcid'] != '') {
                        if ($route['outcid_mode'] != '') {
                            $ext->add($context, $exten, '', new ext_execif('$["${KEEPCID}"!="TRUE" & ${LEN(${TRUNKCIDOVERRIDE})}=0]', 'Set', 'TRUNKCIDOVERRIDE=' . $route['outcid']));
                        } else {
                            $ext->add($context, $exten, '', new ext_execif('$["${KEEPCID}"!="TRUE" & ${LEN(${DB(AMPUSER/${AMPUSER}/outboundcid)})}=0 & ${LEN(${TRUNKCIDOVERRIDE})}=0]', 'Set', 'TRUNKCIDOVERRIDE=' . $route['outcid']));
                        }
                    }
                    $ext->add($context, $exten, '', new ext_set("_NODEST", ""));
                    $password = $route['password'];
                    foreach ($trunks as $trunk_id) {
                        if (isset($trunk_table[$trunk_id])) {
                            switch (strtolower($trunk_table[$trunk_id]['tech'])) {
                                case 'dundi':
                                    $trunk_macro = 'dialout-dundi';
                                    break;
                                case 'enum':
                                    $trunk_macro = 'dialout-enum';
                                    break;
                                default:
                                    $trunk_macro = 'dialout-trunk';
                                    break;
                            }
                        }
                        $ext->add($context, $exten, '', new ext_macro($trunk_macro, $trunk_id . ',' . $pattern['prepend_digits'] . '${EXTEN' . $offset . '},' . $password . ',' . $trunk_table[$trunk_id]['continue']));
                        $password = '';
                        $trunk_type_needed['macro-' . $trunk_macro] = true;
                    }
                    if ($route['dest']) {
                        // Put back the saved CID since each trunk attempt screws with it and set KEEPCID since this is
                        // a form of forwarding at this point. We could use REALCALLERIDNUM but that doesn't preserve CNAM
                        // which may be wiped out and we may want it.
                        //
                        $ext->add($context, $exten, '', new ext_noop_trace('All trunks failed calling ${EXTEN}, going to destination'));
                        $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '${ROUTE_CIDSAVE}'));
                        $ext->add($context, $exten, '', new ext_set('_KEEPCID', 'TRUE'));
                        $ext->add($context, $exten, '', new ext_goto($route['dest']));
                    } else {
                        $ext->add($context, $exten, '', new ext_noop_trace('All trunks failed calling ${EXTEN}, playing default congestion'));
                        $ext->add($context, $exten, '', new ext_macro("outisbusy"));
                    }
                }
                unset($add_extra_pri1);
            }
            general_generate_indications();
            // "blackhole" destinations
            $ext->add('app-blackhole', 'hangup', '', new ext_noop('Blackhole Dest: Hangup'));
            $ext->add('app-blackhole', 'hangup', '', new ext_hangup());
            $ext->add('app-blackhole', 'zapateller', '', new ext_noop('Blackhole Dest: Play SIT Tone'));
            $ext->add('app-blackhole', 'zapateller', '', new ext_answer());
            $ext->add('app-blackhole', 'zapateller', '', new ext_zapateller());
            // Should hangup ?
            // $ext->add('app-blackhole', 'zapateller', '', new ext_hangup());
            $ext->add('app-blackhole', 'musiconhold', '', new ext_noop('Blackhole Dest: Put caller on hold forever'));
            $ext->add('app-blackhole', 'musiconhold', '', new ext_answer());
            $ext->add('app-blackhole', 'musiconhold', '', new ext_musiconhold());
            $ext->add('app-blackhole', 'congestion', '', new ext_noop('Blackhole Dest: Congestion'));
            $ext->add('app-blackhole', 'congestion', '', new ext_progress());
            $ext->add('app-blackhole', 'congestion', '', new ext_playtones('congestion'));
            $ext->add('app-blackhole', 'congestion', '', new ext_congestion());
            $ext->add('app-blackhole', 'congestion', '', new ext_hangup());
            $ext->add('app-blackhole', 'busy', '', new ext_noop('Blackhole Dest: Busy'));
            $ext->add('app-blackhole', 'busy', '', new ext_progress());
            $ext->add('app-blackhole', 'busy', '', new ext_busy());
            $ext->add('app-blackhole', 'busy', '', new ext_hangup());
            $ext->add('app-blackhole', 'ring', '', new ext_noop('Blackhole Dest: Ring'));
            $ext->add('app-blackhole', 'ring', '', new ext_answer());
            $ext->add('app-blackhole', 'ring', '', new ext_playtones('ring'));
            $ext->add('app-blackhole', 'ring', '', new ext_wait(300));
            $ext->add('app-blackhole', 'ring', '', new ext_hangup());
            $ext->add('app-blackhole', 'no-service', '', new ext_noop('Blackhole Dest: No service'));
            $ext->add('app-blackhole', 'no-service', '', new ext_answer());
            $ext->add('app-blackhole', 'no-service', '', new ext_wait('1'));
            $ext->add('app-blackhole', 'no-service', '', new ext_zapateller());
            $ext->add('app-blackhole', 'no-service', '', new ext_playback('ss-noservice'));
            $ext->add('app-blackhole', 'no-service', '', new ext_hangup());
            if ($amp_conf['AMPBADNUMBER']) {
                $context = 'bad-number';
                $exten = '_X.';
                $ext->add($context, $exten, '', new extension('ResetCDR()'));
                $ext->add($context, $exten, '', new extension('NoCDR()'));
                $ext->add($context, $exten, '', new ext_progress());
                $ext->add($context, $exten, '', new ext_wait('1'));
                $ext->add($context, $exten, '', new ext_playback('silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer'));
                $ext->add($context, $exten, '', new ext_wait('1'));
                $ext->add($context, $exten, '', new ext_congestion('20'));
                $ext->add($context, $exten, '', new ext_hangup());
            }
            if ($amp_conf['AST_FUNC_PRESENCE_STATE']) {
                $states = array('available' => 'Available', 'chat' => 'Chatty', 'away' => 'Away', 'dnd' => 'DND', 'xa' => 'Extended Away', 'unavailable' => 'Unavailable');
                $context = 'sub-presencestate-display';
                $exten = 's';
                $ext->add($context, $exten, '', new ext_goto(1, 'state-${TOLOWER(${PRESENCE_STATE(CustomPresence:${ARG1},value)})}'));
                foreach ($states as $state => $display) {
                    $exten = 'state-' . $state;
                    $ext->add($context, $exten, '', new ext_setvar('PRESENCESTATE_DISPLAY', '(' . $display . ')'));
                    $ext->add($context, $exten, '', new ext_return(''));
                }
                // Don't display anything if presencestate is unknown (Coding bug)
                $exten = '_state-.';
                $ext->add($context, $exten, '', new ext_setvar('PRESENCESTATE_DISPLAY', ''));
                $ext->add($context, $exten, '', new ext_return(''));
                // Don't display anything if presencestate is empty (not set).
                $exten = 'state-';
                $ext->add($context, $exten, '', new ext_setvar('PRESENCESTATE_DISPLAY', ''));
                $ext->add($context, $exten, '', new ext_return(''));
            }
            /*
            ;------------------------------------------------------------------------
            ; [macro-confirm]
            ;------------------------------------------------------------------------
            ; CONTEXT:      macro-confirm
            ; PURPOSE:      added default message if none supplied
            ;
            ; Follom-Me and Ringgroups provide an option to supply a message to be
            ; played as part of the confirmation. These changes have added a default
            ; message if none is supplied.
            ;
            ;------------------------------------------------------------------------
            */
            $context = 'macro-confirm';
            $exten = 's';
            $ext->add($context, $exten, '', new ext_setvar('LOOPCOUNT', '0'));
            $ext->add($context, $exten, '', new ext_setvar('__MACRO_RESULT', 'ABORT'));
            $ext->add($context, $exten, '', new ext_setvar('MSG1', '${IF($["${ARG1}${ALT_CONFIRM_MSG}"=""]?incoming-call-1-accept-2-decline:${IF($[${LEN(${ALT_CONFIRM_MSG})}>0]?${ALT_CONFIRM_MSG}:${ARG1})})}'));
            if ($ast_ge_14) {
                $ext->add($context, $exten, 'start', new ext_background('${MSG1},m,${CHANNEL(language)},macro-confirm'));
            } else {
                $ext->add($context, $exten, 'start', new ext_background('${MSG1},m,${LANGUAGE},macro-confirm'));
            }
            $ext->add($context, $exten, '', new ext_read('INPUT', '', 1, '', '', 4));
            $ext->add($context, $exten, '', new ext_gotoif('$[${LEN(${INPUT})} > 0]', '${INPUT},1', 't,1'));
            $exten = '1';
            if ($amp_conf['AST_FUNC_SHARED']) {
                $ext->add($context, $exten, '', new ext_gotoif('$["${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}"="0" & "${SHARED(ANSWER_STATUS,${FORCE_CONFIRM})}"=""]', 'toolate,1'));
            } else {
                $ext->add($context, $exten, '', new ext_gotoif('$["${FORCE_CONFIRM}" != ""]', 'skip'));
                $ext->add($context, $exten, '', new ext_gotoif('$["${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}"="0"]', 'toolate,1'));
            }
            $ext->add($context, $exten, '', new ext_dbdel('RG/${ARG3}/${UNIQCHAN}'));
            $ext->add($context, $exten, '', new ext_macro('blkvm-clr'));
            if ($amp_conf['AST_FUNC_SHARED']) {
                $ext->add($context, $exten, '', new ext_setvar('SHARED(ANSWER_STATUS,${FORCE_CONFIRM})', ''));
            }
            $ext->add($context, $exten, 'skip', new ext_setvar('__MACRO_RESULT', ''));
            $ext->add($context, $exten, '', new ext_execif('$[("${MOHCLASS}"!="default") & ("${MOHCLASS}"!="")]', 'Set', 'CHANNEL(musicclass)=${MOHCLASS}'));
            $ext->add($context, $exten, 'exitopt1', new ext_macroexit());
            $exten = '2';
            $ext->add($context, $exten, '', new ext_goto(1, 'noanswer'));
            $exten = '3';
            $ext->add($context, $exten, '', new ext_saydigits('${CALLCONFIRMCID}'));
            if ($amp_conf['AST_FUNC_SHARED']) {
                $ext->add($context, $exten, '', new ext_gotoif('$["${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}"="0" & "${SHARED(ANSWER_STATUS,${FORCE_CONFIRM})}"=""]', 'toolate,1', 's,start'));
            } else {
                $ext->add($context, $exten, '', new ext_gotoif('$["${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}"="0" & "${FORCE_CONFIRM}"=""]', 'toolate,1', 's,start'));
            }
            $exten = 't';
            if ($amp_conf['AST_FUNC_SHARED']) {
                $ext->add($context, $exten, '', new ext_gotoif('$["${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}"="0" & "${SHARED(ANSWER_STATUS,${FORCE_CONFIRM})}"=""]', 'toolate,1'));
            } else {
                $ext->add($context, $exten, '', new ext_gotoif('$["${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}"="0" & "${FORCE_CONFIRM}"=""]', 'toolate,1'));
            }
            $ext->add($context, $exten, '', new ext_setvar('LOOPCOUNT', '$[ ${LOOPCOUNT} + 1 ]'));
            $ext->add($context, $exten, '', new ext_gotoif('$[ ${LOOPCOUNT} < 5 ]', 's,start', 'noanswer,1'));
            $exten = '_X';
            if ($ast_ge_14) {
                $ext->add($context, $exten, '', new ext_background('invalid,m,${CHANNEL(language)},macro-confirm'));
            } else {
                $ext->add($context, $exten, '', new ext_background('invalid,m,${LANGUAGE},macro-confirm'));
            }
            if ($amp_conf['AST_FUNC_SHARED']) {
                $ext->add($context, $exten, '', new ext_gotoif('$["${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}"="0" | "${SHARED(ANSWER_STATUS,${FORCE_CONFIRM})}"=""]', 'toolate,1'));
            } else {
                $ext->add($context, $exten, '', new ext_gotoif('$["${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}"="0" & "${FORCE_CONFIRM}"=""]', 'toolate,1'));
            }
            $ext->add($context, $exten, '', new ext_setvar('LOOPCOUNT', '$[ ${LOOPCOUNT} + 1 ]'));
            $ext->add($context, $exten, '', new ext_gotoif('$[ ${LOOPCOUNT} < 5 ]', 's,start', 'noanswer,1'));
            $exten = 'noanswer';
            $ext->add($context, $exten, '', new ext_setvar('__MACRO_RESULT', 'ABORT'));
            $ext->add($context, $exten, 'exitnoanswer', new ext_macroexit());
            $exten = 'toolate';
            $ext->add($context, $exten, '', new ext_setvar('MSG2', '${IF($["foo${ARG2}" != "foo"]?${ARG2}:"incoming-call-no-longer-avail")}'));
            $ext->add($context, $exten, '', new ext_playback('${MSG2}'));
            $ext->add($context, $exten, '', new ext_setvar('__MACRO_RESULT', 'ABORT'));
            $ext->add($context, $exten, 'exittoolate', new ext_macroexit());
            $exten = 'h';
            $ext->add($context, $exten, '', new ext_macro('hangupcall'));
            /*
            ;------------------------------------------------------------------------
            ; [macro-auto-confirm]
            ;------------------------------------------------------------------------
            ; This macro is called from ext-local-confirm to auto-confirm a call so that other extensions
            ; are aware that the call has been answered.
            ;
            ;------------------------------------------------------------------------
            */
            $context = 'macro-auto-confirm';
            $exten = 's';
            $ext->add($context, $exten, '', new ext_setvar('__MACRO_RESULT', ''));
            $ext->add($context, $exten, '', new ext_set('CFIGNORE', ''));
            $ext->add($context, $exten, '', new ext_set('MASTER_CHANNEL(CFIGNORE)', ''));
            $ext->add($context, $exten, '', new ext_set('FORWARD_CONTEXT', 'from-internal'));
            $ext->add($context, $exten, '', new ext_set('MASTER_CHANNEL(FORWARD_CONTEXT)', 'from-internal'));
            $ext->add($context, $exten, '', new ext_macro('blkvm-clr'));
            $ext->add($context, $exten, '', new ext_dbdel('RG/${ARG1}/${UNIQCHAN}'));
            $ext->add($context, $exten, '', new ext_noop_trace('DIALEDPEERNUMBER: ${DIALEDPEERNUMBER} CID: ${CALLERID(all)}'));
            if ($amp_conf['AST_FUNC_MASTER_CHANNEL'] && $amp_conf['AST_FUNC_CONNECTEDLINE']) {
                // Check that it is numeric so we don't pollute it with odd dialplan stuff like FMGL-blah from followme
                $ext->add($context, $exten, '', new ext_execif('$[!${REGEX("[^0-9]" ${DIALEDPEERNUMBER})} && "${DB(AMPUSER/${AMPUSER}/cidname)}" != ""]', 'Set', 'MASTER_CHANNEL(CONNECTEDLINE(num))=${DIALEDPEERNUMBER}'));
                $ext->add($context, $exten, '', new ext_execif('$[!${REGEX("[^0-9]" ${DIALEDPEERNUMBER})} && "${DB(AMPUSER/${AMPUSER}/cidname)}" != ""]', 'Set', 'MASTER_CHANNEL(CONNECTEDLINE(name))=${DB(AMPUSER/${DIALEDPEERNUMBER}/cidname)}'));
            }
            /*
            ;------------------------------------------------------------------------
            ; [macro-auto-blkvm]
            ;------------------------------------------------------------------------
            ; This macro is called for any extension dialed form a queue, ringgroup
            ; or followme, so that the answering extension can clear the voicemail block
            ; override allow subsequent transfers to properly operate.
            ;
            ;------------------------------------------------------------------------
            */
            $context = 'macro-auto-blkvm';
            $exten = 's';
            $ext->add($context, $exten, '', new ext_setvar('__MACRO_RESULT', ''));
            $ext->add($context, $exten, '', new ext_set('CFIGNORE', ''));
            $ext->add($context, $exten, '', new ext_set('MASTER_CHANNEL(CFIGNORE)', ''));
            $ext->add($context, $exten, '', new ext_set('FORWARD_CONTEXT', 'from-internal'));
            $ext->add($context, $exten, '', new ext_set('MASTER_CHANNEL(FORWARD_CONTEXT)', 'from-internal'));
            $ext->add($context, $exten, '', new ext_macro('blkvm-clr'));
            $ext->add($context, $exten, '', new ext_noop_trace('DIALEDPEERNUMBER: ${DIALEDPEERNUMBER} CID: ${CALLERID(all)}'));
            if ($amp_conf['AST_FUNC_MASTER_CHANNEL'] && $amp_conf['AST_FUNC_CONNECTEDLINE']) {
                // Check that it is numeric so we don't pollute it with odd dialplan stuff like FMGL-blah from followme
                $ext->add($context, $exten, '', new ext_execif('$[!${REGEX("[^0-9]" ${DIALEDPEERNUMBER})} && "${DB(AMPUSER/${AMPUSER}/cidname)}" != ""]', 'Set', 'MASTER_CHANNEL(CONNECTEDLINE(num))=${DIALEDPEERNUMBER}'));
                $ext->add($context, $exten, '', new ext_execif('$[!${REGEX("[^0-9]" ${DIALEDPEERNUMBER})} && "${DB(AMPUSER/${AMPUSER}/cidname)}" != ""]', 'Set', 'MASTER_CHANNEL(CONNECTEDLINE(name))=${DB(AMPUSER/${DIALEDPEERNUMBER}/cidname)}'));
            }
            /*
            ;------------------------------------------------------------------------
            ; [sub-pincheck]
            ;------------------------------------------------------------------------
            ; This subroutine checks the pincode and then resets the CDR from that point
            ; if the pincode passes. This way the billsec and duration fields are set
            ; properly for pin dialing.
            ;
            ; ${ARG3} is the pincode if this was called, used by dialout-trunk, dialout-enum
            ; and dialout-dundi
            ;
            ;------------------------------------------------------------------------
            */
            $context = 'sub-pincheck';
            $exten = 's';
            $ext->add($context, $exten, '', new ext_authenticate('${ARG3}'));
            $ext->add($context, $exten, '', new ext_resetcdr(''));
            $ext->add($context, $exten, '', new ext_return(''));
            // Subroutine to add diversion header with reason code "no-answer" unless provided differently elsewhere in the dialplan to indicate
            // the reason for the diversion (e.g. CFB could set it to busy)
            //
            if ($amp_conf['DIVERSIONHEADER']) {
                $context = 'sub-diversion-header';
                $exten = 's';
                $ext->add($context, $exten, '', new ext_set('DIVERSION_REASON', '${IF($[${LEN(${DIVERSION_REASON})}=0]?no-answer:${DIVERSION_REASON})}'));
                $ext->add($context, $exten, '', new ext_sipaddheader('Diversion', '<tel:${FROM_DID}>\\;reason=${DIVERSION_REASON}\\;screen=no\\;privacy=off'));
                $ext->add($context, $exten, '', new ext_return(''));
            }
            /*
             * dialout using a trunk, using pattern matching (don't strip any prefix)
             * arg1 = trunk number, arg2 = number, arg3 = route password
             *
             * MODIFIED (PL)
             *
             * Modified both Dial() commands to include the new TRUNK_OPTIONS from the general
             * screen of AMP
             */
            if (function_exists('outroutemsg_get')) {
                $trunkreportmsg_ids = outroutemsg_get();
            } else {
                if (!defined('DEFAULT_MSG')) {
                    define('DEFAULT_MSG', -1);
                }
                if (!defined('CONGESTION_TONE')) {
                    define('CONGESTION_TONE', -2);
                }
                $trunkreportmsg_ids = array('no_answer_msg_id' => -1, 'invalidnmbr_msg_id' => -1);
            }
            // Since rarely used only generate this dialplan if are using this feature
            //
            $generate_trunk_monitor_failure = false;
            foreach ($trunk_table as $tid => $tdetails) {
                // assign and if true no need to continue
                if ($generate_trunk_monitor_failure = $generate_trunk_monitor_failure || $tdetails['failscript']) {
                    break;
                }
            }
            $context = 'macro-dialout-trunk';
            if (!empty($trunk_type_needed[$context])) {
                $exten = 's';
                $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}'));
                $ext->add($context, $exten, '', new ext_gosubif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]', 'sub-pincheck,s,1'));
                $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTDISABLE_${DIAL_TRUNK}}" = "xon"]', 'disabletrunk,1'));
                $ext->add($context, $exten, '', new ext_set('DIAL_NUMBER', '${ARG2}'));
                // fixlocalprefix depends on this
                $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${DIAL_OPTIONS}'));
                // will be reset to TRUNK_OPTIONS if not intra-company
                $ext->add($context, $exten, '', new ext_set('OUTBOUND_GROUP', 'OUT_${DIAL_TRUNK}'));
                $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${DIAL_TRUNK}}foo" = "foo"]', 'nomax'));
                $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${DIAL_TRUNK})} >= ${OUTMAXCHANS_${DIAL_TRUNK}} ]', 'chanfull'));
                $ext->add($context, $exten, 'nomax', new ext_gotoif('$["${INTRACOMPANYROUTE}" = "YES"]', 'skipoutcid'));
                // Set to YES if treated like internal
                $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${IF($["${DB_EXISTS(TRUNK/${DIAL_TRUNK}/dialopts)}" = "1"]?${DB_RESULT}:${TRUNK_OPTIONS})}'));
                $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${DIAL_TRUNK}'));
                $ext->add($context, $exten, 'skipoutcid', new ext_gosubif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]', 'sub-flp-${DIAL_TRUNK},s,1'));
                // this sets DIAL_NUMBER to the proper dial string for this trunk
                $ext->add($context, $exten, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}'));
                // OUTNUM is the final dial number
                $ext->add($context, $exten, '', new ext_set('custom', '${CUT(OUT_${DIAL_TRUNK},:,1)}'));
                // Custom trunks are prefixed with "AMP:"
                // Back to normal processing, whether intracompany or not.
                // But add the macro-setmusic if we don't want music on this outbound call
                // if FORCE_CONFIRM then that macro will set any necessary MOHCLASS, and we will also call the confirm macro
                $ext->add($context, $exten, '', new ext_execif('$["${MOHCLASS}"!="default" & "${MOHCLASS}"!="" & "${FORCE_CONFIRM}"="" ]', 'Set', 'DIAL_TRUNK_OPTIONS=M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS}'));
                $ext->add($context, $exten, '', new ext_execif('$["${FORCE_CONFIRM}"!="" ]', 'Set', 'DIAL_TRUNK_OPTIONS=${DIAL_TRUNK_OPTIONS}M(confirm)'));
                // This macro call will always be blank and is provided as a hook for customization required prior to making a call
                // such as adding SIP header information or other requirements. All the channel variables from above are present
                $ext->add($context, $exten, 'gocall', new ext_macro('dialout-trunk-predial-hook'));
                $ext->add($context, $exten, '', new ext_gotoif('$["${PREDIAL_HOOK_RET}" = "BYPASS"]', 'bypass,1'));
                if ($amp_conf['AST_FUNC_CONNECTEDLINE'] && $amp_conf['OUTBOUND_DIAL_UPDATE']) {
                    $ext->add($context, $exten, '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/cidname)}" != ""]', 'Set', 'CONNECTEDLINE(num,i)=${DIAL_NUMBER}'));
                }
                if ($amp_conf['AST_FUNC_CONNECTEDLINE'] && $amp_conf['OUTBOUND_CID_UPDATE']) {
                    $ext->add($context, $exten, '', new ext_execif('$[$["${DB(AMPUSER/${AMPUSER}/cidname)}" != ""] & $["${CALLERID(name)}"!="hidden"]]', 'Set', 'CONNECTEDLINE(name,i)=CID:${CALLERID(number)}'));
                    $ext->add($context, $exten, '', new ext_execif('$[$["${DB(AMPUSER/${AMPUSER}/cidname)}" != ""] & $["${CALLERID(name)}"="hidden"]]', 'Set', 'CONNECTEDLINE(name,i)=CID:(Hidden)${CALLERID(number)}'));
                }
                $ext->add($context, $exten, '', new ext_gotoif('$["${custom}" = "AMP"]', 'customtrunk'));
                $ext->add($context, $exten, '', new ext_dial('${OUT_${DIAL_TRUNK}}/${OUTNUM}${OUT_${DIAL_TRUNK}_SUFFIX}', '${TRUNK_RING_TIMER},${DIAL_TRUNK_OPTIONS}'));
                // Regular Trunk Dial
                $ext->add($context, $exten, '', new ext_noop('Dial failed for some reason with DIALSTATUS = ${DIALSTATUS} and HANGUPCAUSE = ${HANGUPCAUSE}'));
                $ext->add($context, $exten, '', new ext_gotoif('$["${ARG4}" = "on"]', 'continue,1', 's-${DIALSTATUS},1'));
                $ext->add($context, $exten, 'customtrunk', new ext_set('pre_num', '${CUT(OUT_${DIAL_TRUNK},$,1)}'));
                $ext->add($context, $exten, '', new ext_set('the_num', '${CUT(OUT_${DIAL_TRUNK},$,2)}'));
                // this is where we expect to find string OUTNUM
                $ext->add($context, $exten, '', new ext_set('post_num', '${CUT(OUT_${DIAL_TRUNK},$,3)}'));
                $ext->add($context, $exten, '', new ext_gotoif('$["${the_num}" = "OUTNUM"]', 'outnum', 'skipoutnum'));
                // if we didn't find "OUTNUM", then skip to Dial
                $ext->add($context, $exten, 'outnum', new ext_set('the_num', '${OUTNUM}'));
                // replace "OUTNUM" with the actual number to dial
                $ext->add($context, $exten, 'skipoutnum', new ext_dial('${pre_num:4}${the_num}${post_num}', '${TRUNK_RING_TIMER},${DIAL_TRUNK_OPTIONS}'));
                $ext->add($context, $exten, '', new ext_noop('Dial failed for some reason with DIALSTATUS = ${DIALSTATUS} and HANGUPCAUSE = ${HANGUPCAUSE}'));
                $ext->add($context, $exten, '', new ext_gotoif('$["${ARG4}" = "on"]', 'continue,1', 's-${DIALSTATUS},1'));
                $ext->add($context, $exten, 'chanfull', new ext_noop('max channels used up'));
                $exten = 's-BUSY';
                /*
                 * HANGUPCAUSE 17 = Busy, or SIP 486 Busy everywhere
                 */
                $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting BUSY - giving up'));
                $ext->add($context, $exten, '', new ext_playtones('busy'));
                $ext->add($context, $exten, '', new ext_busy(20));
                /*
                 * There are reported bugs in Asterisk Blind Trasfers that result in Dial() returning and continuing
                 * execution with a status of ANSWER. So we hangup at this point
                 */
                $exten = 's-ANSWER';
                $ext->add($context, $exten, '', new ext_noop('Call successfully answered - Hanging up now'));
                $ext->add($context, $exten, '', new ext_macro('hangupcall'));
                $exten = 's-NOANSWER';
                /*
                 * HANGUPCAUSE 18 = No User Responding, or SIP 408 Request Timeout
                 * HANGUPCAUSE 19 = No Answer From The User, or SIP 480 Temporarily unavailable, SIP 483 To many hops
                 */
                $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting NOANSWER - giving up'));
                $ext->add($context, $exten, '', new ext_progress());
                switch ($trunkreportmsg_ids['no_answer_msg_id']) {
                    case DEFAULT_MSG:
                        $ext->add($context, $exten, '', new ext_playback('number-not-answering,noanswer'));
                        break;
                    case CONGESTION_TONE:
                        $ext->add($context, $exten, '', new ext_playtones('congestion'));
                        break;
                    default:
                        $message = recordings_get_file($trunkreportmsg_ids['no_answer_msg_id']);
                        $message = $message != "" ? $message : "number-not-answering";
                        $ext->add($context, $exten, '', new ext_playback("{$message}, noanswer"));
                }
                $ext->add($context, $exten, '', new ext_congestion(20));
                $exten = 's-INVALIDNMBR';
                /*
                 * HANGUPCAUSE 28 = Address Incomplete, or SIP 484 Address Incomplete
                 */
                $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting Address Incomplete - giving up'));
                $ext->add($context, $exten, '', new ext_progress());
                switch ($trunkreportmsg_ids['invalidnmbr_msg_id']) {
                    case DEFAULT_MSG:
                        $ext->add($context, $exten, '', new ext_playback('ss-noservice,noanswer'));
                        break;
                    case CONGESTION_TONE:
                        $ext->add($context, $exten, '', new ext_playtones('congestion'));
                        break;
                    default:
                        $message = recordings_get_file($trunkreportmsg_ids['invalidnmbr_msg_id']);
                        $message = $message != "" ? $message : "ss-noservice";
                        $ext->add($context, $exten, '', new ext_playback("{$message}, noanswer"));
                }
                $ext->add($context, $exten, '', new ext_busy(20));
                $exten = "s-CHANGED";
                $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting Number Changed - giving up'));
                $ext->add($context, $exten, '', new ext_playtones('busy'));
                $ext->add($context, $exten, '', new ext_busy(20));
                $exten = '_s-.';
                $ext->add($context, $exten, '', new ext_set('RC', '${IF($[${ISNULL(${HANGUPCAUSE})}]?0:${HANGUPCAUSE})}'));
                $ext->add($context, $exten, '', new ext_goto('1', '${RC}'));
                $ext->add($context, '17', '', new ext_goto('1', 's-BUSY'));
                $ext->add($context, '18', '', new ext_goto('1', 's-NOANSWER'));
                $ext->add($context, '22', '', new ext_goto('1', 's-CHANGED'));
                $ext->add($context, '23', '', new ext_goto('1', 's-CHANGED'));
                $ext->add($context, '1', '', new ext_goto('1', 's-INVALIDNMBR'));
                $ext->add($context, '28', '', new ext_goto('1', 's-INVALIDNMBR'));
                $ext->add($context, '_X', '', new ext_goto('1', 'continue'));
                $ext->add($context, '_X.', '', new ext_goto('1', 'continue'));
                $exten = 'continue';
                if ($generate_trunk_monitor_failure) {
                    $ext->add($context, $exten, '', new ext_gotoif('$["${OUTFAIL_${ARG1}}" = ""]', 'noreport'));
                    $ext->add($context, $exten, '', new ext_agi('${OUTFAIL_${ARG1}}'));
                }
                $ext->add($context, $exten, 'noreport', new ext_noop('TRUNK Dial failed due to ${DIALSTATUS} HANGUPCAUSE: ${HANGUPCAUSE} - failing through to other trunks'));
                $ext->add($context, $exten, '', new ext_execif('$["${AMPUSER}"!="" ]', 'Set', 'CALLERID(number)=${AMPUSER}'));
                $ext->add($context, 'disabletrunk', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} DISABLED - falling through to next trunk'));
                $ext->add($context, 'bypass', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} BYPASSING because dialout-trunk-predial-hook'));
                $ext->add($context, 'h', '', new ext_macro('hangupcall'));
            }
            // if trunk_type_needed
            $context = 'macro-dialout-dundi';
            if (!empty($trunk_type_needed[$context])) {
                $exten = 's';
                /*
                 * Dialout Dundi Trunk
                 */
                $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}'));
                $ext->add($context, $exten, '', new ext_gosubif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]', 'sub-pincheck,s,1'));
                $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTDISABLE_${DIAL_TRUNK}}" = "xon"]', 'disabletrunk,1'));
                $ext->add($context, $exten, '', new ext_set('DIAL_NUMBER', '${ARG2}'));
                // fixlocalprefix depends on this
                $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${DIAL_OPTIONS}'));
                // will be reset to TRUNK_OPTIONS if not intra-company
                $ext->add($context, $exten, '', new ext_set('OUTBOUND_GROUP', 'OUT_${DIAL_TRUNK}'));
                $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${DIAL_TRUNK}}foo" = "foo"]', 'nomax'));
                $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${DIAL_TRUNK})} >= ${OUTMAXCHANS_${DIAL_TRUNK}} ]', 'chanfull'));
                $ext->add($context, $exten, 'nomax', new ext_gotoif('$["${INTRACOMPANYROUTE}" = "YES"]', 'skipoutcid'));
                // Set to YES if treated like internal
                $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${IF($["${DB_EXISTS(TRUNK/${DIAL_TRUNK}/dialopts)}" = "1"]?${DB_RESULT}:${TRUNK_OPTIONS})}'));
                $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${DIAL_TRUNK}'));
                $ext->add($context, $exten, 'skipoutcid', new ext_gosubif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]', 'sub-flp-${DIAL_TRUNK},s,1'));
                // manipulate DIAL_NUMBER
                $ext->add($context, $exten, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}'));
                // OUTNUM is the final dial number
                // Back to normal processing, whether intracompany or not.
                // But add the macro-setmusic if we don't want music on this outbound call
                $ext->add($context, $exten, '', new ext_execif('$["${MOHCLASS}"!="default" & "${MOHCLASS}"!="" & "${FORCE_CONFIRM}"="" ]', 'Set', 'DIAL_TRUNK_OPTIONS=M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS}'));
                $ext->add($context, $exten, '', new ext_execif('$["${FORCE_CONFIRM}"!="" ]', 'Set', 'DIAL_TRUNK_OPTIONS=${DIAL_TRUNK_OPTIONS}M(confirm)'));
                // This macro call will always be blank and is provided as a hook for customization required prior to making a call
                // such as adding SIP header information or other requirements. All the channel variables from above are present
                $ext->add($context, $exten, 'gocall', new ext_macro('dialout-dundi-predial-hook'));
                $ext->add($context, $exten, '', new ext_gotoif('$["${PREDIAL_HOOK_RET}" = "BYPASS"]', 'bypass,1'));
                if ($amp_conf['AST_FUNC_CONNECTEDLINE'] && $amp_conf['OUTBOUND_DIAL_UPDATE']) {
                    $ext->add($context, $exten, '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/cidname)}" != ""]', 'Set', 'CONNECTEDLINE(num,i)=${DIAL_NUMBER}'));
                }
                if ($amp_conf['AST_FUNC_CONNECTEDLINE'] && $amp_conf['OUTBOUND_CID_UPDATE']) {
                    $ext->add($context, $exten, '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/cidname)}" != ""]', 'Set', 'CONNECTEDLINE(name,i)=CID:${CALLERID(number)}'));
                }
                $ext->add($context, $exten, '', new ext_macro('dundi-${DIAL_TRUNK}', '${OUTNUM}'));
                $ext->add($context, $exten, '', new ext_gotoif('$["${ARG4}" = "on"]', 'continue,1', 's-${DIALSTATUS},1'));
                $ext->add($context, $exten, 'chanfull', new ext_noop('max channels used up'));
                $exten = 's-BUSY';
                /*
                 * HANGUPCAUSE 17 = Busy, or SIP 486 Busy everywhere
                 */
                $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting BUSY - giving up'));
                $ext->add($context, $exten, '', new ext_playtones('busy'));
                $ext->add($context, $exten, '', new ext_busy(20));
                /*
                 * There are reported bugs in Asterisk Blind Trasfers that result in Dial() returning and continuing
                 * execution with a status of ANSWER. So we hangup at this point
                 */
                $exten = 's-ANSWER';
                $ext->add($context, $exten, '', new ext_noop('Call successfully answered - Hanging up now'));
                $ext->add($context, $exten, '', new ext_macro('hangupcall'));
                $exten = 's-NOANSWER';
                /*
                 * HANGUPCAUSE 18 = No User Responding, or SIP 408 Request Timeout
                 * HANGUPCAUSE 19 = No Answer From The User, or SIP 480 Temporarily unavailable, SIP 483 To many hops
                 */
                $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting NOANSWER - giving up'));
                $ext->add($context, $exten, '', new ext_progress());
                switch ($trunkreportmsg_ids['no_answer_msg_id']) {
                    case DEFAULT_MSG:
                        $ext->add($context, $exten, '', new ext_playback('number-not-answering,noanswer'));
                        break;
                    case CONGESTION_TONE:
                        $ext->add($context, $exten, '', new ext_playtones('congestion'));
                        break;
                    default:
                        $message = recordings_get_file($trunkreportmsg_ids['no_answer_msg_id']);
                        $message = $message != "" ? $message : "number-not-answering";
                        $ext->add($context, $exten, '', new ext_playback("{$message}, noanswer"));
                }
                $ext->add($context, $exten, '', new ext_congestion(20));
                $exten = 's-INVALIDNMBR';
                /*
                 * HANGUPCAUSE 28 = Address Incomplete, or SIP 484 Address Incomplete
                 * HANGUPCAUSE 1 = Unallocated (unassigned) number
                 */
                $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting Address Incomplete - giving up'));
                $ext->add($context, $exten, '', new ext_progress());
                switch ($trunkreportmsg_ids['invalidnmbr_msg_id']) {
                    case DEFAULT_MSG:
                        $ext->add($context, $exten, '', new ext_playback('ss-noservice,noanswer'));
                        break;
                    case CONGESTION_TONE:
                        $ext->add($context, $exten, '', new ext_playtones('congestion'));
                        break;
                    default:
                        $message = recordings_get_file($trunkreportmsg_ids['invalidnmbr_msg_id']);
                        $message = $message != "" ? $message : "ss-noservice";
                        $ext->add($context, $exten, '', new ext_playback("{$message}, noanswer"));
                }
                $ext->add($context, $exten, '', new ext_busy(20));
                $exten = "s-CHANGED";
                $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting Number Changed - giving up'));
                $ext->add($context, $exten, '', new ext_playtones('busy'));
                $ext->add($context, $exten, '', new ext_busy(20));
                $exten = '_s-.';
                $ext->add($context, $exten, '', new ext_set('RC', '${IF($[${ISNULL(${HANGUPCAUSE})}]?0:${HANGUPCAUSE})}'));
                $ext->add($context, $exten, '', new ext_goto('1', '${RC}'));
                $ext->add($context, '17', '', new ext_goto('1', 's-BUSY'));
                $ext->add($context, '18', '', new ext_goto('1', 's-NOANSWER'));
                $ext->add($context, '22', '', new ext_goto('1', 's-CHANGED'));
                $ext->add($context, '23', '', new ext_goto('1', 's-CHANGED'));
                $ext->add($context, '28', '', new ext_goto('1', 's-INVALIDNMBR'));
                $ext->add($context, '_X', '', new ext_goto('1', 'continue'));
                $ext->add($context, '_X.', '', new ext_goto('1', 'continue'));
                $exten = 'continue';
                if ($generate_trunk_monitor_failure) {
                    $ext->add($context, $exten, '', new ext_gotoif('$["${OUTFAIL_${ARG1}}" = ""]', 'noreport'));
                    $ext->add($context, $exten, '', new ext_agi('${OUTFAIL_${ARG1}}'));
                }
                $ext->add($context, $exten, 'noreport', new ext_noop('TRUNK Dial failed due to ${DIALSTATUS} HANGUPCAUSE: ${HANGUPCAUSE} - failing through to other trunks'));
                $ext->add($context, $exten, '', new ext_execif('$["${AMPUSER}"!="" ]', 'Set', 'CALLERID(number)=${AMPUSER}'));
                $ext->add($context, 'disabletrunk', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} DISABLED - falling through to next trunk'));
                $ext->add($context, 'bypass', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} BYPASSING because dialout-dundi-predial-hook'));
                $ext->add($context, 'h', '', new ext_macro('hangupcall'));
            }
            // if trunk_type_needed
            /*
            ;-------------------------------------------------------------------------------
            ; macro-privacy-mgr:
            ;
            ; Privacy Manager Macro makes sure that any calls that don't pass the privacy manager are presented
            ; with congestion since there have been observed cases of the call continuing if not stopped with a
            ; congestion, and this provides a slightly more friendly 'sorry' message in case the user is
            ; legitimately trying to be cooperative.
            ;
            ; Note: the following options are configurable in privacy.conf:
            ;
            ;	maxretries = 3 ; default value, number of retries before failing
            ;	minlength = 10 ; default value, number of digits to be accepted as valid CID
            ;
            ;-------------------------------------------------------------------------------
            */
            $context = 'macro-privacy-mgr';
            $exten = 's';
            $ext->add($context, $exten, '', new ext_set('KEEPCID', '${CALLERID(num)}'));
            $ext->add($context, $exten, '', new ext_set('TESTCID', '${IF($["${CALLERID(num):0:1}"="+"]?${MATH(1+${CALLERID(num):1})}:${MATH(1+${CALLERID(num)})})}'));
            $ext->add($context, $exten, '', new ext_execif('$[${LEN(${TESTCID})}=0]', 'Set', 'CALLERID(num)='));
            $ext->add($context, $exten, '', new ext_privacymanager('${ARG1},${ARG2}'));
            $ext->add($context, $exten, '', new ext_gotoif('$["${PRIVACYMGRSTATUS}"="FAILED"]', 'fail'));
            $ext->add($context, $exten, '', new ext_gosubif('$["${CALLED_BLACKLIST}"="1"]', 'app-blacklist-check,s,1'));
            $ext->add($context, $exten, '', new ext_set('CALLERID(num-pres)', 'allowed_passed_screen'));
            $ext->add($context, $exten, '', new ext_macroexit());
            $ext->add($context, $exten, 'fail', new ext_noop('STATUS: ${PRIVACYMGRSTATUS} CID: ${CALLERID(num)} ${CALLERID(name)} CALLPRES: ${CALLLINGPRES}'));
            $ext->add($context, $exten, '', new ext_playback('sorry-youre-having-problems&goodbye'));
            $ext->add($context, $exten, '', new ext_playtones('congestion'));
            $ext->add($context, $exten, '', new ext_congestion(20));
            $ext->add($context, 'h', '', new ext_hangup());
            /*
             * sets the CallerID of the device to that of the logged in user
             *
             * ${AMPUSER} is set upon return to the real user despite any aliasing that may
             * have been set as a result of the AMPUSER/<nnn>/cidnum field. This is used by
             * features like DND, CF, etc. to set the proper structure on aliased instructions
             */
            $context = 'macro-user-callerid';
            $exten = 's';
            //$ext->add($context, $exten, '', new ext_noop('user-callerid: ${CALLERID(name)} ${CALLERID(number)}'));
            // for i18n playback in multiple languages
            $ext->add($context, 'lang-playback', '', new ext_gosubif('$[${DIALPLAN_EXISTS(' . $context . ',${CHANNEL(language)})}]', $context . ',${CHANNEL(language)},${ARG1}', $context . ',en,${ARG1}'));
            $ext->add($context, 'lang-playback', '', new ext_return());
            $ext->add($context, $exten, '', new ext_set('TOUCH_MONITOR', '${UNIQUEID}'));
            // make sure AMPUSER is set if it doesn't get set below
            $ext->add($context, $exten, '', new ext_set('AMPUSER', '${IF($["${AMPUSER}" = ""]?${CALLERID(number)}:${AMPUSER})}'));
            $ext->add($context, $exten, '', new ext_gotoif('$["${CUT(CHANNEL,@,2):5:5}"="queue" | ${LEN(${AMPUSERCIDNAME})}]', 'report'));
            $ext->add($context, $exten, '', new ext_execif('$["${REALCALLERIDNUM:1:2}" = ""]', 'Set', 'REALCALLERIDNUM=${CALLERID(number)}'));
            $ext->add($context, $exten, '', new ext_set('AMPUSER', '${DB(DEVICE/${REALCALLERIDNUM}/user)}'));
            // Device & User: If they're not signed in, then they can't do anything.
            $ext->add($context, $exten, '', new ext_gotoif('$["${AMPUSER}" = "none"]', 'limit'));
            $ext->add($context, $exten, '', new ext_set('AMPUSERCIDNAME', '${DB(AMPUSER/${AMPUSER}/cidname)}'));
            $ext->add($context, $exten, '', new ext_gotoif('$["${AMPUSERCIDNAME:1:2}" = ""]', 'report'));
            // user may masquerade as a different user internally, so set the internal cid as indicated
            // but keep the REALCALLERID which is used to determine their true identify and lookup info
            // during outbound calls.
            $ext->add($context, $exten, '', new ext_set('AMPUSERCID', '${IF($["${ARG2}" != "EXTERNAL" & "${DB_EXISTS(AMPUSER/${AMPUSER}/cidnum)}" = "1"]?${DB_RESULT}:${AMPUSER})}'));
            // If there is a defined dialopts then use it, otherwise use the global default
            //
            $ext->add($context, $exten, '', new ext_set('__DIAL_OPTIONS', '${IF($["${DB_EXISTS(AMPUSER/${AMPUSER}/dialopts)}" = "1"]?${DB_RESULT}:${DIAL_OPTIONS})}'));
            $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '"${AMPUSERCIDNAME}" <${AMPUSERCID}>'));
            $ext->add($context, $exten, '', new ext_noop_trace('Current Concurrency Count for ${AMPUSER}: ${GROUP_COUNT(${AMPUSER}@concurrency_limit)}, User Limit: ${DB(AMPUSER/${AMPUSER}/concurrency_limit)}'));
            $ext->add($context, $exten, '', new ext_gotoif('$["${ARG1}"="LIMIT" & ${LEN(${AMPUSER})} & ${DB_EXISTS(AMPUSER/${AMPUSER}/concurrency_limit)} & ${DB(AMPUSER/${AMPUSER}/concurrency_limit)}>0 & ${GROUP_COUNT(${AMPUSER}@concurrency_limit)}>=${DB(AMPUSER/${AMPUSER}/concurrency_limit)}]', 'limit'));
            $ext->add($context, $exten, '', new ext_execif('$["${ARG1}"="LIMIT" & ${LEN(${AMPUSER})}]', 'Set', 'GROUP(concurrency_limit)=${AMPUSER}'));
            /*
             * This is where to splice in things like setting the language based on a user's astdb setting,
             * or where you might set the CID account code based on a user instead of the device settings.
             */
            $ext->add($context, $exten, 'report', new ext_gotoif('$[ "${ARG1}" = "SKIPTTL" | "${ARG1}" = "LIMIT" ]', 'continue'));
            $ext->add($context, $exten, 'report2', new ext_set('__TTL', '${IF($["foo${TTL}" = "foo"]?64:$[ ${TTL} - 1 ])}'));
            $ext->add($context, $exten, '', new ext_gotoif('$[ ${TTL} > 0 ]', 'continue'));
            $ext->add($context, $exten, '', new ext_wait('${RINGTIMER}'));
            // wait for a while, to give it a chance to be picked up by voicemail
            $ext->add($context, $exten, '', new ext_answer());
            $ext->add($context, $exten, '', new ext_wait('1'));
            $ext->add($context, $exten, '', new ext_gosub('1', 'lang-playback', $context, 'hook_0'));
            $ext->add($context, $exten, '', new ext_macro('hangupcall'));
            $ext->add($context, $exten, 'limit', new ext_answer());
            $ext->add($context, $exten, '', new ext_wait('1'));
            $ext->add($context, $exten, '', new ext_gosub('1', 'lang-playback', $context, 'hook_1'));
            $ext->add($context, $exten, '', new ext_macro('hangupcall'));
            $ext->add($context, $exten, '', new ext_congestion(20));
            // Address Security Vulnerability in many earlier versions of Asterisk from an external source tranmitting a
            // malicious CID that can cause overflows in the Asterisk code.
            //
            $ext->add($context, $exten, 'continue', new ext_set('CALLERID(number)', '${CALLERID(number):0:40}'));
            $ext->add($context, $exten, '', new ext_set('CALLERID(name)', '${CALLERID(name):0:40}'));
            $ext->add($context, $exten, '', new ext_set('CDR(cnum)', '${CALLERID(num)}'));
            $ext->add($context, $exten, '', new ext_set('CDR(cnam)', '${CALLERID(name)}'));
            // CHANNEL(language) does not get inherited (which seems like an Asterisk bug as musicclass does)
            // so if whe have MASTER_CHANNEL() available to us let's rectify that
            //
            if ($amp_conf['AST_FUNC_MASTER_CHANNEL']) {
                $ext->add($context, $exten, '', new ext_set('CHANNEL(language)', '${MASTER_CHANNEL(CHANNEL(language))}'));
            }
            $ext->add($context, $exten, '', new ext_noop_trace('Using CallerID ${CALLERID(all)}'));
            $ext->add($context, 'h', '', new ext_macro('hangupcall'));
            $lang = 'en';
            //English
            $ext->add($context, $lang, 'hook_0', new ext_playback('im-sorry&an-error-has-occurred&with&call-forwarding'));
            $ext->add($context, $lang, '', new ext_return());
            $ext->add($context, $lang, 'hook_1', new ext_playback('beep&im-sorry&your&simul-call-limit-reached&goodbye'));
            $ext->add($context, $lang, '', new ext_return());
            $lang = 'ja';
            //Japanese
            $ext->add($context, $lang, 'hook_0', new ext_playback('im-sorry&call-forwarding&jp-no&an-error-has-occured'));
            $ext->add($context, $lang, '', new ext_return());
            $ext->add($context, $lang, 'hook_1', new ext_playback('beep&im-sorry&simul-call-limit-reached'));
            $ext->add($context, $lang, '', new ext_return());
            /*
             * arg1 = trunk number, arg2 = number
             *
             * Re-written to use enumlookup.agi
             */
            // Is this the best place to put it in?
            // Check if we are using Google DNS for ENUM-lookups,
            // enable it as a global variable so we can use it in the agi
            if ($amp_conf['USEGOOGLEDNSFORENUM']) {
                $ext->addGlobal('ENUMUSEGOOGLEDNS', 'TRUE');
            }
            $context = 'macro-dialout-enum';
            if (!empty($trunk_type_needed[$context])) {
                $exten = 's';
                $ext->add($context, $exten, '', new ext_gosubif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]', 'sub-pincheck,s,1'));
                $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTDISABLE_${DIAL_TRUNK}}" = "xon"]', 'disabletrunk,1'));
                $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${IF($["${DB_EXISTS(TRUNK/${DIAL_TRUNK}/dialopts)}" = "1"]?${DB_RESULT}:${TRUNK_OPTIONS})}'));
                $ext->add($context, $exten, '', new ext_set('OUTBOUND_GROUP', 'OUT_${ARG1}'));
                $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${ARG1}}foo" = "foo"]', 'nomax'));
                $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${ARG1})} >= ${OUTMAXCHANS_${ARG1}} ]', 'nochans'));
                $ext->add($context, $exten, 'nomax', new ext_set('DIAL_NUMBER', '${ARG2}'));
                $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}'));
                $ext->add($context, $exten, '', new ext_gotoif('$["${INTRACOMPANYROUTE}" = "YES"]', 'skipoutcid'));
                // Set to YES if treated like internal
                $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${DIAL_OPTIONS}'));
                // will be reset to TRUNK_OPTIONS if not intra-company
                $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${DIAL_TRUNK}'));
                $ext->add($context, $exten, 'skipoutcid', new ext_gosubif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]', 'sub-flp-${DIAL_TRUNK},s,1'));
                // manimpulate DIAL_NUMBER
                //  Replacement for asterisk's ENUMLOOKUP function
                $ext->add($context, $exten, '', new ext_agi('enumlookup.agi'));
                if ($amp_conf['AST_FUNC_CONNECTEDLINE'] && $amp_conf['OUTBOUND_DIAL_UPDATE']) {
                    $ext->add($context, $exten, '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/cidname)}" != ""]', 'Set', 'CONNECTEDLINE(num,i)=${DIAL_NUMBER}'));
                }
                if ($amp_conf['AST_FUNC_CONNECTEDLINE'] && $amp_conf['OUTBOUND_CID_UPDATE']) {
                    $ext->add($context, $exten, '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/cidname)}" != ""]', 'Set', 'CONNECTEDLINE(name,i)=CID:${CALLERID(number)}'));
                }
                // Now we have the variable DIALARR set to a list of URI's that can be called, in order of priority
                // Loop through them trying them in order.
                $ext->add($context, $exten, 'dialloop', new ext_gotoif('$["foo${DIALARR}"="foo"]', 's-${DIALSTATUS},1'));
                $ext->add($context, $exten, '', new ext_execif('$["${MOHCLASS}"!="default" & "${MOHCLASS}"!="" & "${FORCE_CONFIRM}"="" ]', 'Set', 'DIAL_TRUNK_OPTIONS=M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS}'));
                $ext->add($context, $exten, '', new ext_execif('$["${FORCE_CONFIRM}"!="" ]', 'Set', 'DIAL_TRUNK_OPTIONS=M(confirm)${DIAL_TRUNK_OPTIONS}'));
                $ext->add($context, $exten, '', new ext_set('TRYDIAL', '${CUT(DIALARR,%,1)}'));
                $ext->add($context, $exten, '', new ext_set('DIALARR', '${CUT(DIALARR,%,2-)}'));
                $ext->add($context, $exten, '', new ext_dial('${TRYDIAL}', '${TRUNK_RING_TIMER},${DIAL_TRUNK_OPTIONS}'));
                // Now, if we're still here, that means the Dial failed for some reason.
                // If it's CONGESTION or CHANUNAVAIL we want to try again on a different
                // different channel. If there's no more left, the dialloop tag will exit.
                $ext->add($context, $exten, '', new ext_gotoif('$[ $[ "${DIALSTATUS}" = "CHANUNAVAIL" ] | $[ "${DIALSTATUS}" = "CONGESTION" ] ]', 'dialloop'));
                $ext->add($context, $exten, '', new ext_gotoif('$["${ARG4}" = "on"]', 'continue,1', 's-${DIALSTATUS},1'));
                // Here are the exit points for the macro.
                $ext->add($context, $exten, 'nochans', new ext_noop('max channels used up'));
                $exten = 's-BUSY';
                /*
                 * HANGUPCAUSE 17 = Busy, or SIP 486 Busy everywhere
                 */
                $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting BUSY - giving up'));
                $ext->add($context, $exten, '', new ext_playtones('busy'));
                $ext->add($context, $exten, '', new ext_busy(20));
                /*
                 * There are reported bugs in Asterisk Blind Trasfers that result in Dial() returning and continuing
                 * execution with a status of ANSWER. So we hangup at this point
                 */
                $exten = 's-ANSWER';
                $ext->add($context, $exten, '', new ext_noop('Call successfully answered - Hanging up now'));
                $ext->add($context, $exten, '', new ext_macro('hangupcall'));
                $exten = 's-NOANSWER';
                /*
                 * HANGUPCAUSE 18 = No User Responding, or SIP 408 Request Timeout
                 * HANGUPCAUSE 19 = No Answer From The User, or SIP 480 Temporarily unavailable, SIP 483 To many hops
                 */
                $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting NOANSWER - giving up'));
                $ext->add($context, $exten, '', new ext_progress());
                switch ($trunkreportmsg_ids['no_answer_msg_id']) {
                    case DEFAULT_MSG:
                        $ext->add($context, $exten, '', new ext_playback('number-not-answering,noanswer'));
                        break;
                    case CONGESTION_TONE:
                        $ext->add($context, $exten, '', new ext_playtones('congestion'));
                        break;
                    default:
                        $message = recordings_get_file($trunkreportmsg_ids['no_answer_msg_id']);
                        $message = $message != "" ? $message : "number-not-answering";
                        $ext->add($context, $exten, '', new ext_playback("{$message}, noanswer"));
                }
                $ext->add($context, $exten, '', new ext_congestion(20));
                $exten = 's-INVALIDNMBR';
                /*
                 * HANGUPCAUSE 28 = Address Incomplete, or SIP 484 Address Incomplete
                 */
                $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting Address Incomplete - giving up'));
                $ext->add($context, $exten, '', new ext_progress());
                switch ($trunkreportmsg_ids['invalidnmbr_msg_id']) {
                    case DEFAULT_MSG:
                        $ext->add($context, $exten, '', new ext_playback('ss-noservice,noanswer'));
                        break;
                    case CONGESTION_TONE:
                        $ext->add($context, $exten, '', new ext_playtones('congestion'));
                        break;
                    default:
                        $message = recordings_get_file($trunkreportmsg_ids['invalidnmbr_msg_id']);
                        $message = $message != "" ? $message : "ss-noservice";
                        $ext->add($context, $exten, '', new ext_playback("{$message}, noanswer"));
                }
                $ext->add($context, $exten, '', new ext_busy(20));
                $exten = "s-CHANGED";
                $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting Number Changed - giving up'));
                $ext->add($context, $exten, '', new ext_playtones('busy'));
                $ext->add($context, $exten, '', new ext_busy(20));
                $exten = '_s-.';
                $ext->add($context, $exten, '', new ext_set('RC', '${IF($[${ISNULL(${HANGUPCAUSE})}]?0:${HANGUPCAUSE})}'));
                $ext->add($context, $exten, '', new ext_goto('1', '${RC}'));
                $ext->add($context, '17', '', new ext_goto('1', 's-BUSY'));
                $ext->add($context, '18', '', new ext_goto('1', 's-NOANSWER'));
                $ext->add($context, '22', '', new ext_goto('1', 's-CHANGED'));
                $ext->add($context, '23', '', new ext_goto('1', 's-CHANGED'));
                $ext->add($context, '28', '', new ext_goto('1', 's-INVALIDNMBR'));
                $ext->add($context, '_X', '', new ext_goto('1', 'continue'));
                $ext->add($context, '_X.', '', new ext_goto('1', 'continue'));
                $exten = 'continue';
                if ($generate_trunk_monitor_failure) {
                    $ext->add($context, $exten, '', new ext_gotoif('$["${OUTFAIL_${ARG1}}" = ""]', 'noreport'));
                    $ext->add($context, $exten, '', new ext_agi('${OUTFAIL_${ARG1}}'));
                }
                $ext->add($context, $exten, 'noreport', new ext_noop('TRUNK Dial failed due to ${DIALSTATUS} HANGUPCAUSE: ${HANGUPCAUSE} - failing through to other trunks'));
                $ext->add($context, $exten, '', new ext_execif('$["${AMPUSER}"!="" ]', 'Set', 'CALLERID(number)=${AMPUSER}'));
                $ext->add($context, 'disabletrunk', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} DISABLED - falling through to next trunk'));
                $ext->add($context, 'bypass', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} BYPASSING because dialout-trunk-predial-hook'));
                $ext->add($context, 'h', '', new ext_macro('hangupcall'));
            }
            // if trunk_type_needed
            /*
             * overrides CallerID out trunks
             * arg1 is trunk
             * macro-user-callerid should be called _before_ using this macro
             */
            $context = 'macro-outbound-callerid';
            $exten = 's';
            // If we modified the caller presence, set it back. This allows anonymous calls to be internally prepended but keep
            // their status if forwarded back out. Not doing this can result in the trunk CID being displayed vs. 'blocked call'
            //
            $ext->add($context, $exten, '', new ext_execif('$["${CALLINGNAMEPRES_SV}" != ""]', 'Set', 'CALLERPRES(name-pres)=${CALLINGNAMEPRES_SV}'));
            $ext->add($context, $exten, '', new ext_execif('$["${CALLINGNUMPRES_SV}" != ""]', 'Set', 'CALLERPRES(num-pres)=${CALLINGNUMPRES_SV}'));
            // Keep the original CallerID number, for failover to the next trunk.
            $ext->add($context, $exten, '', new ext_execif('$["${REALCALLERIDNUM:1:2}" = ""]', 'Set', 'REALCALLERIDNUM=${CALLERID(number)}'));
            // If this came through a ringgroup or CF, then we want to retain original CID unless
            // OUTKEEPCID_${trunknum} is set.
            // Save then CIDNAME while it is still intact in case we end up sending out this same CID
            $ext->add($context, $exten, 'start', new ext_gotoif('$[ $["${REALCALLERIDNUM}" = ""] | $["${KEEPCID}" != "TRUE"] | $["${OUTKEEPCID_${ARG1}}" = "on"] ]', 'normcid'));
            // Set to TRUE if coming from ringgroups, CF, etc.
            $ext->add($context, $exten, '', new ext_set('USEROUTCID', '${REALCALLERIDNUM}'));
            //$ext->add($context, $exten, '', new ext_set('REALCALLERIDNAME', '${CALLERID(name)}'));
            // We now have to make sure the CID is valid. If we find an AMPUSER with the same CID, we assume it is an internal
            // call (would be quite a conincidence if not) and go through the normal processing to get that CID. If a device
            // is set for this CID, then it must be internal
            // If we end up using USEROUTCID at the end, it may still be the REALCALLERIDNUM we saved above. That is determined
            // if the two are equal, AND there is no CALLERID(name) present since it has been removed by the CALLERID(all)=${USEROUTCID}
            // setting. If this is the case, then we put the orignal name back in to send out. Although the CNAME is not honored by most
            // carriers, there are cases where it is so this preserves that information to be used by those carriers who do honor it.
            $ext->add($context, $exten, '', new ext_gotoif('$["foo${DB(AMPUSER/${REALCALLERIDNUM}/device)}" = "foo"]', 'bypass'));
            $ext->add($context, $exten, 'normcid', new ext_set('USEROUTCID', '${DB(AMPUSER/${AMPUSER}/outboundcid)}'));
            $ext->add($context, $exten, 'bypass', new ext_set('EMERGENCYCID', '${DB(DEVICE/${REALCALLERIDNUM}/emergency_cid)}'));
            $ext->add($context, $exten, '', new ext_set('TRUNKOUTCID', '${OUTCID_${ARG1}}'));
            $ext->add($context, $exten, '', new ext_gotoif('$["${EMERGENCYROUTE:1:2}" = "" | "${EMERGENCYCID:1:2}" = ""]', 'trunkcid'));
            // check EMERGENCY ROUTE
            $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '${EMERGENCYCID}'));
            // emergency cid for device
            $ext->add($context, $exten, '', new ext_set('CDR(outbound_cnum)', '${CALLERID(num)}'));
            $ext->add($context, $exten, '', new ext_set('CDR(outbound_cnam)', '${CALLERID(name)}'));
            $ext->add($context, $exten, 'exit', new ext_macroexit());
            $ext->add($context, $exten, 'trunkcid', new ext_execif('$[${LEN(${TRUNKOUTCID})} != 0]', 'Set', 'CALLERID(all)=${TRUNKOUTCID}'));
            $ext->add($context, $exten, 'usercid', new ext_execif('$[${LEN(${USEROUTCID})} != 0]', 'Set', 'CALLERID(all)=${USEROUTCID}'));
            // check CID override for extension
            /* TRUNKCIDOVERRIDE is used by followme and can be used by other functions. It forces the specified CID except for the case of
             * an Emergency CID on an Emergency Route
             */
            $ext->add($context, $exten, '', new ext_execif('$[${LEN(${TRUNKCIDOVERRIDE})} != 0 | ${LEN(${FORCEDOUTCID_${ARG1}})} != 0]', 'Set', 'CALLERID(all)=${IF($[${LEN(${FORCEDOUTCID_${ARG1}})}=0]?${TRUNKCIDOVERRIDE}:${FORCEDOUTCID_${ARG1}})}'));
            $ext->add($context, $exten, 'hidecid', new ext_execif('$["${CALLERID(name)}"="hidden"]', 'Set', 'CALLERPRES(name-pres)=prohib_passed_screen'));
            //We are checking to see if the CallerID name is <hidden> (from freepbx) so we hide both the name and the number. I believe this is correct.
            $ext->add($context, $exten, '', new ext_execif('$["${CALLERID(name)}"="hidden"]', 'Set', 'CALLERPRES(num-pres)=prohib_passed_screen'));
            // $has_keepcid_cnum is checked and set when the globals are being generated above
            //
            if ($has_keepcid_cnum || $amp_conf['BLOCK_OUTBOUND_TRUNK_CNAM']) {
                if ($amp_conf['BLOCK_OUTBOUND_TRUNK_CNAM']) {
                    $ext->add($context, $exten, '', new ext_set('CALLERID(name)', ''));
                } else {
                    $ext->add($context, $exten, '', new ext_execif('$["${OUTKEEPCID_${ARG1}}" = "cnum"]', 'Set', 'CALLERID(name)='));
                }
            }
            $ext->add($context, $exten, '', new ext_set('CDR(outbound_cnum)', '${CALLERID(num)}'));
            $ext->add($context, $exten, '', new ext_set('CDR(outbound_cnam)', '${CALLERID(name)}'));
            // Combined from-zpatel / from-dahdi and all macros now from-dahdi-channum
            //
            $ext->addInclude('from-zaptel', 'from-dahdi');
            $ext->add('from-zaptel', 'foo', '', new ext_noop('bar'));
            $context = 'from-dahdi';
            $exten = '_X.';
            $ext->add($context, $exten, '', new ext_set('DID', '${EXTEN}'));
            $ext->add($context, $exten, '', new ext_goto(1, 's'));
            $exten = 's';
            $ext->add($context, $exten, '', new ext_noop('Entering from-dahdi with DID == ${DID}'));
            // Some trunks _require_ a RINGING be sent before an Answer.
            $ext->add($context, $exten, '', new ext_ringing());
            // If ($did == "") { $did = "s"; }
            $ext->add($context, $exten, '', new ext_set('DID', '${IF($["${DID}"= ""]?s:${DID})}'));
            $ext->add($context, $exten, '', new ext_noop('DID is now ${DID}'));
            $ext->add($context, $exten, '', new ext_gotoif('$["${CHANNEL:0:5}"="DAHDI"]', 'dahdiok', 'checkzap'));
            $ext->add($context, $exten, 'checkzap', new ext_gotoif('$["${CHANNEL:0:3}"="Zap"]', 'zapok', 'neither'));
            $ext->add($context, $exten, 'neither', new ext_goto('1', '${DID}', 'from-pstn'));
            // If there's no ext-did,s,1, that means there's not a no did/no cid route. Hangup.
            $ext->add($context, $exten, '', new ext_macro('Hangupcall', 'dummy'));
            $ext->add($context, $exten, 'dahdiok', new ext_noop('Is a DAHDi Channel'));
            $ext->add($context, $exten, '', new ext_set('CHAN', '${CHANNEL:6}'));
            $ext->add($context, $exten, '', new ext_set('CHAN', '${CUT(CHAN,-,1)}'));
            $ext->add($context, $exten, '', new ext_macro('from-dahdi-${CHAN}', '${DID},1'));
            // If nothing there, then treat it as a DID
            $ext->add($context, $exten, '', new ext_noop('Returned from Macro from-dahdi-${CHAN}'));
            $ext->add($context, $exten, '', new ext_goto(1, '${DID}', 'from-pstn'));
            $ext->add($context, $exten, 'zapok', new ext_noop('Is a Zaptel Channel'));
            $ext->add($context, $exten, '', new ext_set('CHAN', '${CHANNEL:4}'));
            $ext->add($context, $exten, '', new ext_set('CHAN', '${CUT(CHAN,-,1)}'));
            $ext->add($context, $exten, '', new ext_macro('from-dahdi-${CHAN}', '${DID},1'));
            $ext->add($context, $exten, '', new ext_noop('Returned from Macro from-dahdi-${CHAN}'));
            $ext->add($context, $exten, '', new ext_goto(1, '${DID}', 'from-pstn'));
            /*
            ;------------------------------------------------------------------------
            ; [macro-dial-confirm]
            ;------------------------------------------------------------------------
            ; This has now been incorporated into dialparties. It still only works with ringall
            ; and ringall-prim strategies. Have not investigated why it doesn't work with
            ; hunt and memory hunt.
            ;
            ;------------------------------------------------------------------------
            [macro-dial-confirm]
            ; This was written to make it easy to use macro-dial-confirm instead of macro-dial in generated dialplans.
            ; This takes the same parameters, with an additional parameter of the ring group Number
            ; ARG1 is the timeout
            ; ARG2 is the DIAL_OPTIONS
            ; ARG3 is a list of xtns to call - 203-222-240-123123123#-211
            ; ARG4 is the ring group number
            */
            $mcontext = 'macro-dial-confirm';
            $exten = 's';
            // set to ringing so confirm macro can keep from passing the channel during confirmation if
            // someone beat them to it.
            //
            $ext->add($mcontext, $exten, '', new ext_set('DB(RG/${ARG4}/${CHANNEL})', 'RINGING'));
            $ext->add($mcontext, $exten, '', new ext_set('__UNIQCHAN', '${CHANNEL}'));
            // Tell dialparites to place the call through the [grps] context
            //
            $ext->add($mcontext, $exten, '', new ext_set('USE_CONFIRMATION', 'TRUE'));
            $ext->add($mcontext, $exten, '', new ext_set('RINGGROUP_INDEX', '${ARG4}'));
            $ext->add($mcontext, $exten, '', new ext_set('FORCE_CONFIRM', ''));
            $ext->add($mcontext, $exten, '', new ext_set('ARG4', ''));
            $ext->add($mcontext, $exten, '', new ext_macro('dial', '${ARG1},${ARG2},${ARG3}'));
            $ext->add($mcontext, $exten, '', new ext_dbdel('RG/${RINGGROUP_INDEX}/${CHANNEL}'));
            $ext->add($mcontext, $exten, '', new ext_set('USE_CONFIRMATION', ''));
            $ext->add($mcontext, $exten, '', new ext_set('RINGGROUP_INDEX', ''));
            /*
            ;------------------------------------------------------------------------
            ; [macro-setmusic]
            ;------------------------------------------------------------------------
            ; CONTEXT:      macro-setmusic
            ; PURPOSE:      to turn off moh on routes where it is not desired
            ;
            ;------------------------------------------------------------------------
            [macro-setmusic]
            exten => s,1,NoOp(Setting Outbound Route MoH To: ${ARG1})
            exten => s,2,Set(CHANNEL(musicclass)=${ARG1}) ; this won't work in 1.2 anymore, could fix in auto-generate if we wanted...
            ;------------------------------------------------------------------------
            */
            $mcontext = 'macro-setmusic';
            $exten = 's';
            $ext->add($mcontext, $exten, '', new ext_noop_trace('Setting Outbound Route MoH To: ${ARG1}'));
            $ext->add($mcontext, $exten, '', new ext_setmusiconhold('${ARG1}'));
            /*
            ;------------------------------------------------------------------------
            ; [block-cf]
            ;------------------------------------------------------------------------
            ; This context is set as a target with FORWARD_CONTEXT when Call Forwarding is set to be
            ; ignored in a ringgroup or other features that may take advantage of this. Server side
            ; CF is done in dialparties.agi but if a client device forwards a call, it will be caught
            ; and blocked here.
            ;------------------------------------------------------------------------
            [block-cf]
            exten => _X.,1,Noop(Blocking callforward to ${EXTEN} because CF is blocked)
            exten => _X.,n,Hangup()
            
            ;------------------------------------------------------------------------
            */
            $context = 'macro-block-cf';
            $exten = '_X.';
            $ext->add($context, $exten, '', new ext_noop_trace('Blocking callforward to ${EXTEN} because CF is blocked'));
            $ext->add($context, $exten, '', new ext_hangup(''));
            /*
             * macro-vm
             */
            /*
            	;------------------------------------------------------------------------
            	; [macro-vm]
            	;------------------------------------------------------------------------
            	; CONTEXT:      macro-vm
            	; PURPOSE:      call voicemail system and extend with personal ivr
            	;
            	; Under normal use, this macro will call the voicemail system with the extension and
            	; desired greeting mode of busy, unavailable or as specified with direct voicemail
            	; calls (usually unavailable) when entered from destinations.
            	;
            	; The voicemail system's two greetings have been 'hijacked' as follows to extend the
            	; system by giving the option of a private 'ivr' for each voicemail user. The following
            	; applies to both the busy and unavailable modes of voicemail and can be applied to one
            	; or both, and differently.
            	;
            	; Global Defaults:
            	;
            	; The following are default values, used in both busy and unavail modes if no specific
            	; values are specified.
            	;
            	; VMX_REPEAT
            	;                                       The number of times to repeat the users message if no option is pressed.
            	; VMX_TIMEOUT
            	;                                       The timeout to wait after playing message before repeating or giving up.
            	; VMX_LOOPS
            	;                                       The number of times it should replay the message and check for an option when
            	;                                       an invalid option is pressed.
            	;
            	; VMX_OPTS_DOVM
            	;                                       Default voicemail option to use if vm is chosen as an option. No options will
            	;                                       cause Allison's generic message, 's' will go straight to beep.
            	; VMX_OPTS_TIMEOUT
            	;                                       Default voicemail option to use if it times out with no options. No options will
            	;                                       cause Allison's generic message, 's' will go straight to beep.
            	;                                       IF THE USER PRESSES # - it will look like a timeout as well since no option will
            	;                                       be presented. If the user wishes to enable a mode where a caller can press #
            	;                                       during their message and it goes straight to voicemail with only a 'beep' then
            	;                                       this should be set to 's'.
            	; VMX_OPTS_LOOP
            	;                                       Default voicemail option to use if to many wrong options occur. No options will
            	;                                       cause Allison's generic message, 's' will go straight to beep.
            	;
            	; VMX_CONTEXT
            	;                                       Default context for user destinations if not supplied in the user's settings
            	; VMX_PRI
            	;                                       Default priority for user destinations if not supplied in the user's settings
            	;
            	; VMX_TIMEDEST_CONTEXT
            	;                                       Default context for timeout destination if not supplied in the user's settings
            	; VMX_TIMEDEST_EXT
            	;                                       Default extension for timeout destination if not supplied in the user's settings
            	; VMX_TIMEDEST_PRI
            	;                                       Default priority for timeout destination if not supplied in the user's settings
            	;
            	; VMX_LOOPDEST_CONTEXT
            	;                                       Default context for loops  destination if not supplied in the user's settings
            	; VMX_LOOPDEST_EXT
            	;                                       Default extension for loops  destination if not supplied in the user's settings
            	; VMX_LOOPDEST_PRI
            	;                                       Default priority for loops  destination if not supplied in the user's settings
            	;
            	;
            	; The AMPUSER database variable has been extended with a 'vmx' tree (vm-extension). A
            	; duplicate set is included for both unavail and busy. You could choose for to have an
            	; ivr when unavail is taken, but not with busy - or a different once with busy.
            	; The full list is below, each specific entry is futher described:
            	;
            	; state:                Whether teh current mode is enabled or disabled. Anything but 'enabled' is
            	;                                               treated as disabled.
            	; repeat:               This is the number of times that the users message should be played after the
            	;                                               timeout if the user has not entered anything. It is just a variable to the
            	;                                               Read() function which will do the repeating.
            	; timeout:      This is how long to wait after the message has been read for a response from
            	;                                               the user. A caller can enter a digit any time during the playback.
            	; loops:                This is the number of loops that the system will allow a caller to retry if
            	;                                               they enter a bad menu choice, before going to the loop failover destination
            	; vmxopts:      This is the vm options to send to the voicemail command used when a specific
            	;                                               voicemail destination is chosen (inidcated by 'dovm' in the ext field). This is
            	;                                               typically either set to 's' or left blank. When set to 's' there will be no
            	;                                               message played when entering the voicemail, just a beep. When blank, you will
            	;                                               have Allison's generic message played. It is not typical to play the greetings
            	;                                               since they have been 'hijacked' for these IVR's and from a caller's perspecitive
            	;                                               this system appears interconnected with the voicemail so instructions can be
            	;                                               left there.
            	; timedest: The three variables: ext, context and pri are the goto destination if the caller
            	;                                               enters no options and it timesout. None have to be set and a system default
            	;                                               will be used. If just ext is set, then defaults will be used for context and
            	;                                               pri, etc.
            	; loopdest:     This is identical to timedest but used if the caller exceeds the maximum invalid
            	;                                               menu choices.
            	; [0-9*]:               The user can specify up to 11 ivr options, all as single digits from 0-9 or *. The
            	;                                               # key can not be used since it is used as a terminator key for the Read command
            	;                                               and will never be returned. A minimum of the ext must be specified for each valid
            	;                                               option and as above, the context and priority can also be specified if the default
            	;                                               is not to be used.
            	;                                               Option '0' takes on a special meaning. Since a user is able to break out of the
            	;                                               voicemail command once entering it with a 0, if specified, the 0 destination will
            	;                                               be used.
            	;                                               Option '*' can also be used to breakout. It is undecided at this point whether
            	;                                               providing that option will be used as well. (probably should).
            	;
            	;
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/state:                                                              enabled|disabled
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/repeat:                                                             n (times to repeat message)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/timeout:                                                    n (timeout to wait for digit)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/loops:                                                              n (loop returies for invalid entries)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/vmxopts/dovm:                                       vmoptions (if ext is dovm)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/vmxopts/timeout:                    vmoptions (if timeout)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/vmxopts/loops:                              vmoptions (if loops)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/timedest/ext:                                       extension (if timeout)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/timedest/context:                   context (if timeout)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/timedest/pri:                                       priority (if timeout)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/loopdest/ext:                                       extension (if too many failures)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/loopdest/context:                   context (if too many failures)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/loopdest/pri:                                       priority (if too many failures)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/[0-9*]/ext:                                         extension (dovm for vm access)
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/[0-9*]/context:                             context
            	; /AMPUSER/<ext>/vmx/[busy|unavail]/[0-9*]/pri:                                         priority
            	;------------------------------------------------------------------------
            */
            // ARG1 - extension
            // ARG2 - DIRECTDIAL/BUSY
            // ARG3 - RETURN makes macro return, otherwise hangup
            //
            $ext->add('macro-vm', 's', '', new ext_macro('user-callerid', 'SKIPTTL'));
            $ext->add('macro-vm', 's', '', new ext_setvar("VMGAIN", '${IF($["foo${VM_GAIN}"!="foo"]?"g(${VM_GAIN})": )}'));
            // If blkvm-check is set TRUE, then someone told us to block calls from going to
            // voicemail. This variable is reset by the answering channel so subsequent
            // transfers will properly function.
            //
            $ext->add('macro-vm', 's', '', new ext_macro('blkvm-check'));
            $ext->add('macro-vm', 's', '', new ext_gotoif('$["${GOSUB_RETVAL}" != "TRUE"]', 'vmx,1'));
            // we didn't branch so block this from voicemail
            //
            $ext->add('macro-vm', 's', '', new ext_noop_trace('CAME FROM: ${NODEST} - Blocking VM macro-blkvm-check returned TRUE'));
            $ext->add('macro-vm', 's', '', new ext_hangup(''));
            // If vmx not enabled for the current mode,then jump to normal voicemail behavior
            // also - if not message (no-msg) is requested, straight to voicemail
            //
            $ext->add('macro-vm', 'vmx', '', new ext_setvar("MEXTEN", '${ARG1}'));
            $ext->add('macro-vm', 'vmx', '', new ext_setvar("MMODE", '${ARG2}'));
            $ext->add('macro-vm', 'vmx', '', new ext_setvar("RETVM", '${ARG3}'));
            $ext->add('macro-vm', 'vmx', '', new ext_setvar("MODE", '${IF($["${MMODE}"="BUSY"]?busy:unavail)}'));
            $ext->add('macro-vm', 'vmx', '', new ext_macro('get-vmcontext', '${MEXTEN}'));
            $ext->add('macro-vm', 'vmx', '', new ext_setvar("MODE", '${IF($[(${STAT(f,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${MEXTEN}/temp.wav)} = 1) || (${STAT(f,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${MEXTEN}/temp.WAV)} = 1)]?temp:${MODE})}'));
            $ext->add('macro-vm', 'vmx', '', new ext_noop('MODE IS: ${MODE}'));
            // If this use has individual option set for playing standardized message, then override the global option
            // but only if the vmx state is 'enabled'
            //
            $ext->add('macro-vm', 'vmx', '', new ext_gotoif('$["${DB(AMPUSER/${MEXTEN}/vmx/${MODE}/state)}" != "enabled"]', 'chknomsg'));
            /* Replaced
            	$ext->add('macro-vm','vmx', '', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/vmxopts/timeout)}" = "0"]','chknomsg'));
            	$ext->add('macro-vm','vmx', '', new ext_setvar("VM_OPTS", '${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'vmx', '', new ext_set('VM_OPTS', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/vmxopts/timeout)}" = "1"]?${DB_RESULT}:${VM_OPTS})}'));
            $ext->add('macro-vm', 'vmx', 'chknomsg', new ext_gotoif('$["${MMODE}"="NOMESSAGE"]', 's-${MMODE},1'));
            $ext->add('macro-vm', 'vmx', '', new ext_gotoif('$["${MMODE}" != "DIRECTDIAL"]', 'notdirect'));
            $ext->add('macro-vm', 'vmx', '', new ext_setvar("MODE", '${IF($["${REGEX("[b]" ${VM_DDTYPE})}" = "1"]?busy:${MODE})}'));
            $ext->add('macro-vm', 'vmx', 'notdirect', new ext_NoOp('Checking if ext ${MEXTEN} is enabled: ${DB(AMPUSER/${MEXTEN}/vmx/${MODE}/state)}'));
            $ext->add('macro-vm', 'vmx', '', new ext_gotoif('$["${DB(AMPUSER/${MEXTEN}/vmx/${MODE}/state)}" != "enabled"]', 's-${MMODE},1'));
            // If the required voicemail file does not exist, then abort and go to normal voicemail behavior
            //
            // If 1.4 or above, use the STAT function to check for the file. Prior to 1.4, use the AGI script since the System() command tried
            // in the past had errors.
            //
            //$ext->add('macro-vm', 'vmx', '', new ext_trysystem('/bin/ls ${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${MEXTEN}/${MODE}.[wW][aA][vV]'));
            if ($ast_ge_14) {
                $ext->add('macro-vm', 'vmx', '', new ext_gotoif('$[(${STAT(f,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${MEXTEN}/temp.wav)} = 1) || (${STAT(f,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${MEXTEN}/temp.WAV)} = 1)]', 'tmpgreet'));
                $ext->add('macro-vm', 'vmx', '', new ext_gotoif('$[(${STAT(f,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${MEXTEN}/${MODE}.wav)} = 0) && (${STAT(f,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${MEXTEN}/${MODE}.WAV)} = 0)]', 'nofile'));
            } else {
                $ext->add('macro-vm', 'vmx', '', new ext_agi('checksound.agi,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${MEXTEN}/temp'));
                $ext->add('macro-vm', 'vmx', '', new ext_gotoif('$["${SYSTEMSTATUS}" = "SUCCESS"]', 'tmpgreet'));
                $ext->add('macro-vm', 'vmx', '', new ext_agi('checksound.agi,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${MEXTEN}/${MODE}'));
                $ext->add('macro-vm', 'vmx', '', new ext_gotoif('$["${SYSTEMSTATUS}" != "SUCCESS"]', 'nofile'));
            }
            $repeat = sql("SELECT `value` FROM `voicemail_admin` WHERE `variable` = 'VMX_REPEAT'", "getOne");
            $to = sql("SELECT `value` FROM `voicemail_admin` WHERE `variable` = 'VMX_TIMEOUT'", "getOne");
            $loops = sql("SELECT `value` FROM `voicemail_admin` WHERE `variable` = 'VMX_LOOPS'", "getOne");
            $ext->add('macro-vm', 'vmx', '', new ext_set("VMX_TIMEOUT", isset($to) ? $to : 2));
            $ext->add('macro-vm', 'vmx', '', new ext_set("VMX_REPEAT", isset($repeat) ? $repeat : 1));
            $ext->add('macro-vm', 'vmx', '', new ext_set("VMX_LOOPS", isset($loops) ? $loops : 1));
            $ext->add('macro-vm', 'vmx', '', new ext_setvar("LOOPCOUNT", '0'));
            /* Replaced
            	$ext->add('macro-vm','vmx', '', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/repeat)}" = "0"]','vmxtime'));
            	$ext->add('macro-vm','vmx', '', new ext_setvar("VMX_REPEAT", '${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'vmx', '', new ext_set('VMX_REPEAT', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/repeat)}" = "1"]?${DB_RESULT}:${VMX_REPEAT})}'));
            /* Replaced
            	$ext->add('macro-vm','vmx', 'vmxtime', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/timeout)}" = "0"]','vmxloops'));
            	$ext->add('macro-vm','vmx', '', new ext_setvar("VMX_TIMEOUT", '${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'vmx', 'vmxtime', new ext_set('VMX_TIMEOUT', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/timeout)}" = "1"]?${DB_RESULT}:${VMX_TIMEOUT})}'));
            /* Replaced
            	$ext->add('macro-vm','vmx', 'vmxloops', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/loops)}" = "0"]','vmxanswer'));
            	$ext->add('macro-vm','vmx', '', new ext_setvar("VMX_LOOPS", '${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'vmx', 'vmxloops', new ext_set('VMX_LOOPS', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/loops)}" = "1"]?${DB_RESULT}:${VMX_LOOPS})}'));
            $ext->add('macro-vm', 'vmx', 'vmxanswer', new ext_answer(''));
            // Now play the users voicemail recording as the basis for their ivr, the Read command will repeat as needed and if it timesout
            // then we go to the timeout. Otherwise handle invalid options by looping until the limit until a valid option is played.
            //
            $ext->add('macro-vm', 'vmx', 'loopstart', new ext_read('ACTION', '${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${MEXTEN}/${MODE}', 1, 'skip', '${VMX_REPEAT}', '${VMX_TIMEOUT}'));
            $ext->add('macro-vm', 'vmx', '', new ext_gotoif('$["${EXISTS(${ACTION})}" = "1"]', 'checkopt'));
            // If we are here we timed out, go to the required destination
            //
            $ext->add('macro-vm', 'vmx', 'noopt', new ext_NoOp('Timeout: going to timeout dest'));
            // this is always set, if not it will default to no options
            $ext->add('macro-vm', 'vmx', '', new ext_set('VMX_OPTS', '${DB(AMPUSER/${MEXTEN}/vmx/${MODE}/vmxopts/timeout)}'));
            // TODO should we just go do the other sets and skip the complexity, will have to if we remove the globals since they will be gonein dotime
            $ext->add('macro-vm', 'vmx', 'chktime', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/timedest/ext)}" = "0"]', 'dotime'));
            $ext->add('macro-vm', 'vmx', '', new ext_setvar("VMX_TIMEDEST_EXT", '${DB_RESULT}'));
            /* this is the alternative if re the above TODO
            	$ext->add('macro-vm','vmx', 'chktime', new ext_set('VMX_TIMEDEST_EXT', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/timedest/ext)}" = "1"]?${DB_RESULT}:${VMX_TIMEDEST_EXT})}'));
            	*/
            /* Replaced
            	$ext->add('macro-vm','vmx', '', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/timedest/context)}" = "0"]','timepri'));
            	$ext->add('macro-vm','vmx', '', new ext_setvar("VMX_TIMEDEST_CONTEXT",'${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'vmx', '', new ext_set('VMX_TIMEDEST_CONTEXT', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/timedest/context)}" = "1"]?${DB_RESULT}:${VMX_TIMEDEST_CONTEXT})}'));
            /* Replaced
            	$ext->add('macro-vm','vmx', 'timepri', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/timedest/pri)}" = "0"]','dotime'));
            	$ext->add('macro-vm','vmx', '', new ext_setvar("VMX_TIMEDEST_PRI",'${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'vmx', 'timepri', new ext_set('VMX_TIMEDEST_PRI', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/timedest/pri)}" = "1"]?${DB_RESULT}:${VMX_TIMEDEST_PRI})}'));
            $ext->add('macro-vm', 'vmx', 'dotime', new ext_goto('${VMX_TIMEDEST_PRI}', '${VMX_TIMEDEST_EXT}', '${VMX_TIMEDEST_CONTEXT}'));
            // We got an option, check if the option is defined, or one of the system defaults
            //
            $ext->add('macro-vm', 'vmx', 'checkopt', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/${ACTION}/ext)}" = "1"]', 'doopt'));
            $ext->add('macro-vm', 'vmx', '', new ext_gotoif('$["${ACTION}" = "0"]', 'o,1'));
            $ext->add('macro-vm', 'vmx', '', new ext_gotoif('$["${ACTION}" = "*"]', 'adef,1'));
            // Got invalid option loop until the max
            //
            $ext->add('macro-vm', 'vmx', '', new ext_setvar("LOOPCOUNT", '$[${LOOPCOUNT} + 1]'));
            $ext->add('macro-vm', 'vmx', '', new ext_gotoif('$["${LOOPCOUNT}" > "${VMX_LOOPS}"]', 'toomany'));
            $ext->add('macro-vm', 'vmx', '', new ext_playback('pm-invalid-option&please-try-again'));
            $ext->add('macro-vm', 'vmx', '', new ext_goto('loopstart'));
            // tomany: to many invalid options, go to the specified destination
            //
            $ext->add('macro-vm', 'vmx', 'toomany', new ext_NoOp('Too Many invalid entries, got to invalid dest'));
            $ext->add('macro-vm', 'vmx', '', new ext_setvar("VMX_OPTS", '${VMX_OPTS_LOOP}'));
            /* Replaced
            	$ext->add('macro-vm','vmx', '', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/vmxopts/loops)}" = "0"]','chkloop'));
            	$ext->add('macro-vm','vmx', '', new ext_setvar("VMX_OPTS",'${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'vmx', '', new ext_set('VMX_OPTS', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/vmxopts/loops)}" = "1"]?${DB_RESULT}:${VMX_OPTS})}'));
            // TODO: same as above, if we just set them then we don't depend on the globals at doloop
            $ext->add('macro-vm', 'vmx', 'chkloop', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/loopdest/ext)}" = "0"]', 'doloop'));
            $ext->add('macro-vm', 'vmx', '', new ext_setvar("VMX_LOOPDEST_EXT", '${DB_RESULT}'));
            /* this would go with the above TODO
            	$ext->add('macro-vm','vmx', 'chkloop', new ext_set('VMX_LOOPDEST_EXT', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/loopdest/ext)}" = "1"]?${DB_RESULT}:${VMX_LOOPDEST_EXT})}'));
            	*/
            /* Replaced
            	$ext->add('macro-vm','vmx', '', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/loopdest/context)}" = "0"]','looppri'));
            	$ext->add('macro-vm','vmx', '', new ext_setvar("VMX_LOOPDEST_CONTEXT",'${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'vmx', '', new ext_set('VMX_LOOPDEST_CONTEXT', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/loopdest/context)}" = "1"]?${DB_RESULT}:${VMX_LOOPDEST_CONTEXT})}'));
            /* Replaced
            	$ext->add('macro-vm','vmx', 'looppri', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/loopdest/pri)}" = "0"]','doloop'));
            	$ext->add('macro-vm','vmx', '', new ext_setvar("VMX_LOOPDEST_PRI",'${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'vmx', 'looppri', new ext_set('VMX_LOOPDEST_PRI', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/loopdest/pri)}" = "1"]?${DB_RESULT}:${VMX_LOOPDEST_PRI})}'));
            $ext->add('macro-vm', 'vmx', 'doloop', new ext_goto('${VMX_LOOPDEST_PRI}', '${VMX_LOOPDEST_EXT}', '${VMX_LOOPDEST_CONTEXT}'));
            // doopt: execute the valid option that was chosen
            //
            $ext->add('macro-vm', 'vmx', 'doopt', new ext_NoOp('Got a valid option: ${DB_RESULT}'));
            $ext->add('macro-vm', 'vmx', '', new ext_setvar("VMX_EXT", '${DB_RESULT}'));
            // Special case, if this option was to go to voicemail, set options and go
            //
            $ext->add('macro-vm', 'vmx', '', new ext_gotoif('$["${VMX_EXT}" != "dovm"]', 'getdest'));
            /* Replaced
            	$ext->add('macro-vm','vmx', 'vmxopts', new ext_setvar("VMX_OPTS",'${VMX_OPTS_DOVM}'));
            	$ext->add('macro-vm','vmx', '', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/vmxopts/dovm)}" = "0"]','vmxdovm'));
            	$ext->add('macro-vm','vmx', '', new ext_setvar("VMX_OPTS",'${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'vmx', 'vmxopts', new ext_set('VMX_OPTS', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/vmxopts/dovm)}" = "1"]?${DB_RESULT}:${VMX_OPTS_DOVM})}'));
            $ext->add('macro-vm', 'vmx', 'vmxdovm', new ext_goto('1', 'dovm'));
            // General case, setup the goto destination and go there (no error checking, its up to the GUI's to assure
            // reasonable values
            //
            /* Replaced
            	$ext->add('macro-vm','vmx', 'getdest', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/${ACTION}/context)}" = "0"]','vmxpri'));
            	$ext->add('macro-vm','vmx', '', new ext_setvar("VMX_CONTEXT",'${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'vmx', 'getdest', new ext_set('VMX_CONTEXT', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/${ACTION}/context)}" = "1"]?${DB_RESULT}:${VMX_CONTEXT})}'));
            /* Replaced
            	$ext->add('macro-vm','vmx', 'vmxpri', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/${ACTION}/pri)}" = "0"]','vmxgoto'));
            	$ext->add('macro-vm','vmx', '', new ext_setvar("VMX_PRI",'${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'vmx', 'vmxpri', new ext_set('VMX_PRI', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/${ACTION}/pri)}" = "1"]?${DB_RESULT}:${VMX_PRI})}'));
            $ext->add('macro-vm', 'vmx', 'vmxgoto', new ext_goto('${VMX_PRI}', '${VMX_EXT}', '${VMX_CONTEXT}'));
            // If the required voicemail file is not present, then revert to normal voicemail
            // behavior treating as if it was not set
            //
            $ext->add('macro-vm', 'vmx', 'nofile', new ext_NoOp('File for mode: ${MODE} does not exist, SYSTEMSTATUS: ${SYSTEMSTATUS}, going to normal voicemail'));
            $ext->add('macro-vm', 'vmx', '', new ext_goto('1', 's-${MMODE}'));
            $ext->add('macro-vm', 'vmx', 'tmpgreet', new ext_NoOp('Temporary Greeting Detected, going to normal voicemail'));
            $ext->add('macro-vm', 'vmx', '', new ext_goto('1', 's-${MMODE}'));
            // Drop into voicemail either as a direct destination (in which case VMX_OPTS might be set to something) or
            // if the user timed out or broke out of the loop then VMX_OPTS is always cleared such that an Allison
            // message is played and the caller know's what is going on.
            //
            $ext->add('macro-vm', 'dovm', '', new ext_NoOp('VMX Timeout - go to voicemail'));
            $ext->add('macro-vm', 'dovm', '', new ext_vm('${MEXTEN}@${VMCONTEXT},${VMX_OPTS}${VMGAIN}'));
            $ext->add('macro-vm', 'dovm', '', new ext_goto('1', 'exit-${VMSTATUS}'));
            $ext->add('macro-vm', 's-BUSY', '', new ext_NoOp('BUSY voicemail'));
            $ext->add('macro-vm', 's-BUSY', '', new ext_macro('get-vmcontext', '${MEXTEN}'));
            $ext->add('macro-vm', 's-BUSY', '', new ext_vm('${MEXTEN}@${VMCONTEXT},${VM_OPTS}b${VMGAIN}'));
            $ext->add('macro-vm', 's-BUSY', '', new ext_goto('1', 'exit-${VMSTATUS}'));
            $ext->add('macro-vm', 's-NOMESSAGE', '', new ext_NoOp('NOMESSAGE (beep only) voicemail'));
            $ext->add('macro-vm', 's-NOMESSAGE', '', new ext_macro('get-vmcontext', '${MEXTEN}'));
            $ext->add('macro-vm', 's-NOMESSAGE', '', new ext_vm('${MEXTEN}@${VMCONTEXT},s${VM_OPTS}${VMGAIN}'));
            $ext->add('macro-vm', 's-NOMESSAGE', '', new ext_goto('1', 'exit-${VMSTATUS}'));
            $ext->add('macro-vm', 's-INSTRUCT', '', new ext_NoOp('NOMESSAGE (beeb only) voicemail'));
            $ext->add('macro-vm', 's-INSTRUCT', '', new ext_macro('get-vmcontext', '${MEXTEN}'));
            $ext->add('macro-vm', 's-INSTRUCT', '', new ext_vm('${MEXTEN}@${VMCONTEXT},${VM_OPTS}${VMGAIN}'));
            $ext->add('macro-vm', 's-INSTRUCT', '', new ext_goto('1', 'exit-${VMSTATUS}'));
            $ext->add('macro-vm', 's-DIRECTDIAL', '', new ext_NoOp('DIRECTDIAL voicemail'));
            $ext->add('macro-vm', 's-DIRECTDIAL', '', new ext_macro('get-vmcontext', '${MEXTEN}'));
            $ext->add('macro-vm', 's-DIRECTDIAL', '', new ext_vm('${MEXTEN}@${VMCONTEXT},${VM_OPTS}${VM_DDTYPE}${VMGAIN}'));
            $ext->add('macro-vm', 's-DIRECTDIAL', '', new ext_goto('1', 'exit-${VMSTATUS}'));
            $ext->add('macro-vm', '_s-.', '', new ext_macro('get-vmcontext', '${MEXTEN}'));
            $ext->add('macro-vm', '_s-.', '', new ext_vm('${MEXTEN}@${VMCONTEXT},${VM_OPTS}u${VMGAIN}'));
            $ext->add('macro-vm', '_s-.', '', new ext_goto('1', 'exit-${VMSTATUS}'));
            // If the user has a 0 option defined, use that for operator zero-out from within voicemail
            // as well to keep it consistant with the menu structure
            //
            $ext->add('macro-vm', 'o', '', new ext_playback('one-moment-please'));
            $ext->add('macro-vm', 'o', '', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/0/ext)}" = "0"]', 'doopdef'));
            $ext->add('macro-vm', 'o', '', new ext_setvar("VMX_OPDEST_EXT", '${DB_RESULT}'));
            /* Replaced
            	$ext->add('macro-vm','o','',new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/0/context)}" = "1"]','opcontext'));
            	$ext->add('macro-vm','o','',new ext_setvar("DB_RESULT",'${VMX_CONTEXT}'));
            	$ext->add('macro-vm','o','opcontext',new ext_setvar("VMX_OPDEST_CONTEXT",'${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'o', 'opcontext', new ext_set('VMX_OPDEST_CONTEXT', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/0/context)}" = "1"]?${DB_RESULT}:${VMX_CONTEXT})}'));
            /* Replaced
            	$ext->add('macro-vm','o','',new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/0/pri)}" = "1"]','oppri'));
            	$ext->add('macro-vm','o','',new ext_setvar("DB_RESULT",'${VMX_PRI}'));
            	$ext->add('macro-vm','o','oppri',new ext_setvar("VMX_OPDEST_PRI",'${DB_RESULT}'));
            	*/
            $ext->add('macro-vm', 'o', 'oppri', new ext_set('VMX_OPDEST_PRI', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/0/pri)}" = "1"]?${DB_RESULT}:${VMX_PRI})}'));
            $ext->add('macro-vm', 'o', '', new ext_goto('${VMX_OPDEST_PRI}', '${VMX_OPDEST_EXT}', '${VMX_OPDEST_CONTEXT}'));
            $ext->add('macro-vm', 'o', 'doopdef', new ext_gotoif('$["x${OPERATOR_XTN}"="x"]', 'nooper', 'from-internal,${OPERATOR_XTN},1'));
            $ext->add('macro-vm', 'o', 'nooper', new ext_gotoif('$["x${FROM_DID}"="x"]', 'nodid'));
            $ext->add('macro-vm', 'o', '', new ext_dial('Local/${FROM_DID}@from-pstn', ''));
            $ext->add('macro-vm', 'o', '', new ext_macro('hangup'));
            $ext->add('macro-vm', 'o', 'nodid', new ext_dial('Local/s@from-pstn', ''));
            $ext->add('macro-vm', 'o', '', new ext_macro('hangup'));
            // If the user has a * option defined, use that for the * out from within voicemail
            // as well to keep it consistant with the menu structure
            //
            $ext->add('macro-vm', 'a', '', new ext_macro('get-vmcontext', '${MEXTEN}'));
            //Dont allow (*) to be dialed to hack voicemail
            //http://issues.freepbx.org/browse/FREEPBX-7757
            $ext->add('macro-vm', 'a', '', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/novmstar)}" = "1"]', 's,1'));
            $ext->add('macro-vm', 'a', '', new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/*/ext)}" = "0"]', 'adef,1'));
            $ext->add('macro-vm', 'a', '', new ext_setvar("VMX_ADEST_EXT", '${DB_RESULT}'));
            // Replaced
            //$ext->add('macro-vm','a','',new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/*/context)}" = "1"]','acontext'));
            //$ext->add('macro-vm','a','',new ext_setvar("DB_RESULT",'${VMX_CONTEXT}'));
            //$ext->add('macro-vm','a','acontext',new ext_setvar("VMX_ADEST_CONTEXT",'${DB_RESULT}'));
            $ext->add('macro-vm', 'a', 'acontext', new ext_set('VMX_ADEST_CONTEXT', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/*/context)}" = "1"]?${DB_RESULT}:${VMX_CONTEXT})}'));
            // Replaced
            //$ext->add('macro-vm','a','',new ext_gotoif('$["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/*/pri)}" = "1"]','apri'));
            //$ext->add('macro-vm','a','',new ext_setvar("DB_RESULT",'${VMX_PRI}'));
            //$ext->add('macro-vm','a','apri',new ext_setvar("VMX_ADEST_PRI",'${DB_RESULT}'));
            $ext->add('macro-vm', 'a', 'apri', new ext_set('VMX_ADEST_PRI', '${IF($["${DB_EXISTS(AMPUSER/${MEXTEN}/vmx/${MODE}/*/pri)}" = "1"]?${DB_RESULT}:${VMX_PRI})}'));
            $ext->add('macro-vm', 'a', '', new ext_goto('${VMX_ADEST_PRI}', '${VMX_ADEST_EXT}', '${VMX_ADEST_CONTEXT}'));
            $ext->add('macro-vm', 'adef', '', new ext_vmmain('${MEXTEN}@${VMCONTEXT}'));
            $ext->add('macro-vm', 'adef', '', new ext_gotoif('$["${RETVM}" = "RETURN"]', 'exit-RETURN,1'));
            $ext->add('macro-vm', 'adef', '', new ext_hangup(''));
            $ext->add('macro-vm', 'exit-FAILED', '', new ext_playback('im-sorry&an-error-has-occurred'));
            $ext->add('macro-vm', 'exit-FAILED', '', new ext_gotoif('$["${RETVM}" = "RETURN"]', 'exit-RETURN,1'));
            $ext->add('macro-vm', 'exit-FAILED', '', new ext_hangup(''));
            $ext->add('macro-vm', 'exit-SUCCESS', '', new ext_gotoif('$["${RETVM}" = "RETURN"]', 'exit-RETURN,1'));
            $ext->add('macro-vm', 'exit-SUCCESS', '', new ext_playback('goodbye'));
            $ext->add('macro-vm', 'exit-SUCCESS', '', new ext_hangup(''));
            $ext->add('macro-vm', 'exit-USEREXIT', '', new ext_gotoif('$["${RETVM}" = "RETURN"]', 'exit-RETURN,1'));
            $ext->add('macro-vm', 'exit-USEREXIT', '', new ext_playback('goodbye'));
            $ext->add('macro-vm', 'exit-USEREXIT', '', new ext_hangup(''));
            $ext->add('macro-vm', 'exit-RETURN', '', new ext_noop('Returning From Voicemail because macro'));
            $ext->add('macro-vm', 't', '', new ext_hangup(''));
            /* end macro-vm  */
            /*
             * ARG1: VMBOX
             * ARG2: EXTTOCALL
             * ARG3: If NOANSWER dest exists 1, otherwise 0
             * ARG4: If BUSY dest exists 1, otherwise 0
             * ARG5: If CHANUNAVAIL dest exists 1, otherwise 0
             */
            $mcontext = 'macro-exten-vm';
            $exten = 's';
            $ext->add($mcontext, $exten, '', new ext_macro('user-callerid'));
            $ext->add($mcontext, $exten, '', new ext_set("RingGroupMethod", 'none'));
            $ext->add($mcontext, $exten, '', new ext_set("__EXTTOCALL", '${ARG2}'));
            $ext->add($mcontext, $exten, '', new ext_set("__PICKUPMARK", '${ARG2}'));
            $ext->add($mcontext, $exten, '', new ext_set("RT", '${IF($["${ARG1}"!="novm" | "${DB(CFU/${EXTTOCALL})}"!="" | "${DB(CFB/${EXTTOCALL})}"!="" | "${ARG3}"="1" | "${ARG4}"="1" | "${ARG5}"="1"]?${RINGTIMER}:)}'));
            $ext->add($mcontext, $exten, 'checkrecord', new ext_gosub('1', 's', 'sub-record-check', 'exten,${EXTTOCALL},dontcare'));
            // If paging module is not present, then what happens?
            // TODO: test with no paging module
            $fcc = new featurecode('paging', 'intercom-prefix');
            $intercom_code = $fcc->getCodeActive();
            unset($fcc);
            // I think it is adequate that if AMPUSER is blank, it's not internal (don't think FROM_DID has to be checked though I don't think it hurts)
            $macrodial = 'macrodial';
            if ($intercom_code != '') {
                if ($amp_conf['AST_FUNC_EXTENSION_STATE']) {
                    $ext->add($mcontext, $exten, '', new ext_noop_trace('AMPUSER: ${AMPUSER}, FROM_DID: ${FROM_DID}, FROM_QUEUE: $["${CUT(CHANNEL,@,2):5:5}"="queue"], answermode: ${DB(AMPUSER/${EXTTOCALL}/answermode)}, BLINDTXF: ${BLINDTRANSFER}, ATTTXF: ${ATTENDEDTRANSFER}, EXT_STATE: ${EXTENSION_STATE(${EXTTOCALL})}, CC_RECALL: ${CC_RECALL}'));
                    if ($amp_conf['FORCE_INTERNAL_AUTO_ANSWER_ALL']) {
                        $ext->add($mcontext, $exten, '', new ext_gotoif('$["${CUT(CHANNEL,@,2):5:5}"="queue"|"${AMPUSER}"=""|${LEN(${FROM_DID})}|${LEN(${BLINDTRANSFER})}|"${EXTENSION_STATE(${EXTTOCALL})}"!="NOT_INUSE"|"${CC_RECALL}"!=""]', 'macrodial'));
                    } else {
                        $ext->add($mcontext, $exten, '', new ext_gotoif('$["${CUT(CHANNEL,@,2):5:5}"="queue"|"${AMPUSER}"=""|${LEN(${FROM_DID})}|"${DB(AMPUSER/${EXTTOCALL}/answermode)}"!="intercom"|${LEN(${BLINDTRANSFER})}|"${EXTENSION_STATE(${EXTTOCALL})}"!="NOT_INUSE"|"${CC_RECALL}"!=""]', 'macrodial'));
                    }
                } else {
                    $ext->add($mcontext, $exten, '', new ext_noop_trace('AMPUSER: ${AMPUSER}, FROM_DID: ${FROM_DID}, FROM_QUEUE: $["${CUT(CHANNEL,@,2):5:5}"="queue"], answermode: ${DB(AMPUSER/${EXTTOCALL}/answermode)}, BLINDTXF: ${BLINDTRANSFER}, , ATTTXF: ${ATTENDEDTRANSFER}, CC_RECALL: ${CC_RECALL}'));
                    if ($amp_conf['FORCE_INTERNAL_AUTO_ANSWER_ALL']) {
                        $ext->add($mcontext, $exten, '', new ext_gotoif('$["${CUT(CHANNEL,@,2):5:5}"="queue"|"${AMPUSER}"=""|${LEN(${FROM_DID})}|${LEN(${BLINDTRANSFER})}]', 'macrodial'));
                    } else {
                        $ext->add($mcontext, $exten, '', new ext_gotoif('$["${CUT(CHANNEL,@,2):5:5}"="queue"|"${AMPUSER}"=""|${LEN(${FROM_DID})}|"${DB(AMPUSER/${EXTTOCALL}/answermode)}"!="intercom"|${LEN(${BLINDTRANSFER})}]', 'macrodial'));
                    }
                }
                $ext->add($mcontext, $exten, '', new ext_set("INTERCOM_EXT_DOPTIONS", '${DIAL_OPTIONS}'));
                $ext->add($mcontext, $exten, '', new ext_set("INTERCOM_RETURN", 'TRUE'));
                $ext->add($mcontext, $exten, '', new ext_gosub('1', $intercom_code . '${EXTTOCALL}', 'ext-intercom'));
                $ext->add($mcontext, $exten, '', new ext_set("INTERCOM_RETURN", ''));
                $ext->add($mcontext, $exten, '', new ext_set("INTERCOM_EXT_DOPTIONS", ''));
                // If it was a blind transfer and there was a previous auto-answer, then we cleanup all the auto-answer headers left in the channel
                // It won't be from this call because we don't ever intercom in a blind transfer scenario (hmm unless it was blind transfered to a
                // specific intercom code but in that case, they won't have been able to subsequently transfered the call
                //
                $ext->add($mcontext, $exten, $macrodial, new ext_gosubif('$["${INTERCOM_CALL}"="TRUE" & ${LEN(${BLINDTRANSFER})}]', 'clrheader,1'));
                $macrodial = '';
            }
            if ($amp_conf['AST_FUNC_EXTENSION_STATE']) {
                $ext->add($mcontext, $exten, $macrodial, new ext_macro('dial-one', '${RT},${DIAL_OPTIONS},${EXTTOCALL}'));
            } else {
                $ext->add($mcontext, $exten, $macrodial, new ext_macro('dial', '${RT},${DIAL_OPTIONS},${EXTTOCALL}'));
            }
            $ext->add($mcontext, $exten, '', new ext_set("SV_DIALSTATUS", '${DIALSTATUS}'));
            $ext->add($mcontext, $exten, 'calldocfu', new ext_gosubif('$[("${SV_DIALSTATUS}"="NOANSWER"|"${SV_DIALSTATUS}"="CHANUNAVAIL") & "${DB(CFU/${EXTTOCALL})}"!="" & "${SCREEN}"=""]', 'docfu,1'));
            $ext->add($mcontext, $exten, 'calldocfb', new ext_gosubif('$["${SV_DIALSTATUS}"="BUSY" & "${DB(CFB/${EXTTOCALL})}"!="" & "${SCREEN}"=""]', 'docfb,1'));
            $ext->add($mcontext, $exten, '', new ext_set("DIALSTATUS", '${SV_DIALSTATUS}'));
            $ext->add($mcontext, $exten, '', new ext_execif('$[("${DIALSTATUS}"="NOANSWER"&"${ARG3}"="1")|("${DIALSTATUS}"="BUSY"&"${ARG4}"="1")|("${DIALSTATUS}"="CHANUNAVAIL"&"${ARG5}"="1")]', 'MacroExit'));
            $ext->add($mcontext, $exten, '', new ext_noop_trace('Voicemail is \'${ARG1}\'', 1));
            $ext->add($mcontext, $exten, '', new ext_gotoif('$["${ARG1}"="novm"]', 's-${DIALSTATUS},1'));
            $ext->add($mcontext, $exten, '', new ext_noop_trace('Sending to Voicemail box ${EXTTOCALL}', 1));
            $ext->add($mcontext, $exten, '', new ext_macro('vm', '${ARG1},${DIALSTATUS},${IVR_RETVM}'));
            $exten = 'docfu';
            if ($amp_conf['DIVERSIONHEADER']) {
                $ext->add($mcontext, $exten, '', new ext_set('__DIVERSION_REASON', 'unavailable'));
            }
            $ext->add($mcontext, $exten, 'docfu', new ext_execif('$["${DB(AMPUSER/${EXTTOCALL}/cfringtimer)}"="-1"|("${ARG1}"="novm"&"${ARG3}"="1")]', 'StackPop'));
            $ext->add($mcontext, $exten, '', new ext_gotoif('$["${DB(AMPUSER/${EXTTOCALL}/cfringtimer)}"="-1"|("${ARG1}"="novm"&"${ARG3}"="1")]', 'from-internal,${DB(CFU/${EXTTOCALL})},1'));
            $ext->add($mcontext, $exten, '', new ext_set("RTCF", '${IF($["${DB(AMPUSER/${EXTTOCALL}/cfringtimer)}"="0"]?${RT}:${DB(AMPUSER/${EXTTOCALL}/cfringtimer)})}'));
            $ext->add($mcontext, $exten, '', new ext_execif('$["${DIRECTION}" = "INBOUND"]', 'Set', 'DIAL_OPTIONS=${STRREPLACE(DIAL_OPTIONS,T)}I'));
            $ext->add($mcontext, $exten, '', new ext_dial('Local/${DB(CFU/${EXTTOCALL})}@from-internal/n', '${RTCF},${DIAL_OPTIONS}'));
            if ($amp_conf['DIVERSIONHEADER']) {
                $ext->add($mcontext, $exten, '', new ext_set('__DIVERSION_REASON', ''));
            }
            $ext->add($mcontext, $exten, '', new ext_return(''));
            $exten = 'docfb';
            if ($amp_conf['DIVERSIONHEADER']) {
                $ext->add($mcontext, $exten, '', new ext_set('__DIVERSION_REASON', 'user-busy'));
            }
            $ext->add($mcontext, $exten, 'docfu', new ext_execif('$["${DB(AMPUSER/${EXTTOCALL}/cfringtimer)}"="-1"|("${ARG1}"="novm"&"${ARG4}"="1")]', 'StackPop'));
            $ext->add($mcontext, $exten, '', new ext_gotoif('$["${DB(AMPUSER/${EXTTOCALL}/cfringtimer)}"="-1"|("${ARG1}"="novm"&"${ARG4}"="1")]', 'from-internal,${DB(CFB/${EXTTOCALL})},1'));
            $ext->add($mcontext, $exten, '', new ext_set("RTCF", '${IF($["${DB(AMPUSER/${EXTTOCALL}/cfringtimer)}"="0"]?${RT}:${DB(AMPUSER/${EXTTOCALL}/cfringtimer)})}'));
            $ext->add($mcontext, $exten, '', new ext_execif('$["${DIRECTION}" = "INBOUND"]', 'Set', 'DIAL_OPTIONS=${STRREPLACE(DIAL_OPTIONS,T)}I'));
            $ext->add($mcontext, $exten, '', new ext_dial('Local/${DB(CFB/${EXTTOCALL})}@from-internal/n', '${RTCF},${DIAL_OPTIONS}'));
            if ($amp_conf['DIVERSIONHEADER']) {
                $ext->add($mcontext, $exten, '', new ext_set('__DIVERSION_REASON', ''));
            }
            $ext->add($mcontext, $exten, '', new ext_return(''));
            // If we are here it was determined that there had been intercom sip headers left over in the channel. If 1.6.2+ then we can use
            // the SIPRemoveHeader() option to remove the specific headers. We are trying to be careful not to remove similar headers that
            // may be used for 'distinctive ring' type reasons from elsewhere in the dialplan. Thus only if we detected the intercom situation
            // do we do it here.
            //
            // If we are pre 1.6.2 then some experimentation on 1.4.X has shown that we are able to clear the SIPADDHEADERnn channel variables
            // that result from setting the headers so we start from 1 (the first) and iterate up until we find one. In some weird situations
            // if a header had been removed, we could miss out since it is not possible to detect the existence of a blank channel variable
            //
            if ($intercom_code != '') {
                $exten = 'clrheader';
                $ext->add($mcontext, $exten, '', new ext_execif('$[${LEN(${SIPURI})}&"${SIPURI}"="${SIP_URI_OPTIONS}"]', 'Set', 'SIP_URI_OPTIONS='));
                if ($ast_ge_162) {
                    $ext->add($mcontext, $exten, '', new ext_execif('$[${LEN(${ALERTINFO})}]', 'SIPRemoveHeader', '${ALERTINFO}'));
                    $ext->add($mcontext, $exten, '', new ext_execif('$[${LEN(${CALLINFO})}]', 'SIPRemoveHeader', '${CALLINFO}'));
                } else {
                    $ext->add($mcontext, $exten, '', new ext_set('SP', '0'));
                    $ext->add($mcontext, $exten, '', new ext_set('ITER', '1'));
                    $ext->add($mcontext, $exten, 'begin', new ext_execif('$[${ITER} > 9]', 'Set', 'SP='));
                    $ext->add($mcontext, $exten, '', new ext_execif('$[${LEN(${SIPADDHEADER${SP}${ITER}})}=0]', 'Return'));
                    $ext->add($mcontext, $exten, '', new ext_execif('$["${SIPADDHEADER${SP}${ITER}}"="${ALERTINFO}"|"${SIPADDHEADER${SP}${ITER}}"="${CALLINFO}"]', 'Set', 'SIPADDHEADER${SP}${ITER}='));
                    $ext->add($mcontext, $exten, '', new ext_setvar('ITER', '$[${ITER} + 1]'));
                    $ext->add($mcontext, $exten, '', new ext_gotoif('$[${ITER} < 100]', 'begin'));
                }
                $ext->add($mcontext, $exten, '', new ext_return(''));
            }
            $exten = 's-BUSY';
            $ext->add($mcontext, $exten, '', new ext_noop_trace('Extension is reporting BUSY and not passing to Voicemail', 1));
            $ext->add($mcontext, $exten, '', new ext_gotoif('$["${IVR_RETVM}"="RETURN" & "${IVR_CONTEXT}"!=""]', 'exit,1'));
            $ext->add($mcontext, $exten, '', new ext_playtones('busy'));
            $ext->add($mcontext, $exten, '', new ext_busy(20));
            $exten = '_s-!';
            $ext->add($mcontext, $exten, '', new ext_noop_trace('IVR_RETVM: ${IVR_RETVM} IVR_CONTEXT: ${IVR_CONTEXT}', 1));
            $ext->add($mcontext, $exten, '', new ext_gotoif('$["${IVR_RETVM}"="RETURN" & "${IVR_CONTEXT}"!=""]', 'exit,1'));
            $ext->add($mcontext, $exten, '', new ext_playtones('congestion'));
            $ext->add($mcontext, $exten, '', new ext_congestion('10'));
            $exten = 'exit';
            $ext->add($mcontext, $exten, '', new ext_playback('beep&line-busy-transfer-menu&silence/1'));
            $ext->add($mcontext, $exten, '', new ext_macroexit());
            /* macro-exten-vm  */
            /*
            ;------------------------------------------------------------------------
            ; [macro-simple-dial]
            ;------------------------------------------------------------------------
            ; This macro was derived from macro-exten-vm, which is what is normally used to
            ; ring an extension. It has been simplified and designed to never go to voicemail
            ; and always return regardless of the DIALSTATUS for any incomplete call.
            ;
            ; It's current primary purpose is to allow findmefollow ring an extension prior
            ; to trying the follow-me ringgroup that is provided.
            ;
            ; Ring an extension, if the extension is busy or there is no answer, return
            ; ARGS: $EXTENSION, $RINGTIME
            ;------------------------------------------------------------------------
            */
            $mcontext = 'macro-simple-dial';
            $exten = 's';
            $ext->add($mcontext, $exten, '', new ext_set("__EXTTOCALL", '${ARG1}'));
            $ext->add($mcontext, $exten, '', new ext_set("RT", '${ARG2}'));
            $ext->add($mcontext, $exten, '', new ext_set("CFUEXT", '${DB(CFU/${EXTTOCALL})}'));
            $ext->add($mcontext, $exten, '', new ext_set("CFBEXT", '${DB(CFB/${EXTTOCALL})}'));
            $ext->add($mcontext, $exten, '', new ext_set("CWI_TMP", '${CWIGNORE}'));
            if ($amp_conf['AST_FUNC_EXTENSION_STATE']) {
                $ext->add($mcontext, $exten, 'macrodial', new ext_macro('dial-one', '${RT},${DIAL_OPTIONS},${EXTTOCALL}'));
            } else {
                $ext->add($mcontext, $exten, 'macrodial', new ext_macro('dial', '${RT},${DIAL_OPTIONS},${EXTTOCALL}'));
            }
            $ext->add($mcontext, $exten, '', new ext_set("__CWIGNORE", '${CWI_TMP}'));
            $ext->add($mcontext, $exten, '', new ext_set("PR_DIALSTATUS", '${DIALSTATUS}'));
            $ext->add($mcontext, $exten, 'calldocfu', new ext_gosubif('$["${PR_DIALSTATUS}"="NOANSWER" & "${CFUEXT}"!=""]', 'docfu,1'));
            $ext->add($mcontext, $exten, 'calldocfb', new ext_gosubif('$["${PR_DIALSTATUS}"="BUSY" & "${CFBEXT}"!=""]', 'docfb,1'));
            $ext->add($mcontext, $exten, '', new ext_set("DIALSTATUS", '${PR_DIALSTATUS}'));
            $ext->add($mcontext, $exten, '', new ext_goto('1', 's-${DIALSTATUS}'));
            /*
            ; Try the Call Forward on No Answer / Unavailable number.
            ; We want to try CFU if set, but we want the same ring timer as was set to our call (or do we want the
            ; system ringtimer? - probably not). Then if no answer there (assuming it doesn't drop into their vm or
            ; something we return, which will have the net effect of returning to the followme setup.)
            ;
            ; want to avoid going to other follow-me settings here. So check if the CFUEXT is a user and if it is
            ; then direct it straight to ext-local (to avoid getting intercepted by findmefollow) otherwise send it
            ; to from-internal since it may be an outside line.
            ;
            */
            $exten = 'docfu';
            $ext->add($mcontext, $exten, '', new ext_gotoif('$["${DB(AMPUSER/${CFUEXT}/device)}" = "" ]', 'chlocal'));
            $ext->add($mcontext, $exten, '', new ext_dial('Local/${CFUEXT}@ext-local', '${RT},${DIAL_OPTIONS}'));
            $ext->add($mcontext, $exten, '', new ext_return(''));
            $ext->add($mcontext, $exten, 'chlocal', new ext_execif('$["${DIRECTION}" = "INBOUND"]', 'Set', 'DIAL_OPTIONS=${STRREPLACE(DIAL_OPTIONS,T)}I'));
            $ext->add($mcontext, $exten, '', new ext_dial('Local/${CFUEXT}@from-internal/n', '${RT},${DIAL_OPTIONS}'));
            $ext->add($mcontext, $exten, '', new ext_return(''));
            $exten = 'docfb';
            $ext->add($mcontext, $exten, '', new ext_gotoif('$["${DB(AMPUSER/${CFBEXT}/device)}" = "" ]', 'chlocal'));
            $ext->add($mcontext, $exten, '', new ext_dial('Local/${CFBEXT}@ext-local', '${RT},${DIAL_OPTIONS}'));
            $ext->add($mcontext, $exten, '', new ext_return(''));
            $ext->add($mcontext, $exten, 'chlocal', new ext_execif('$["${DIRECTION}" = "INBOUND"]', 'Set', 'DIAL_OPTIONS=${STRREPLACE(DIAL_OPTIONS,T)}I'));
            $ext->add($mcontext, $exten, '', new ext_dial('Local/${CFBEXT}@from-internal/n', '${RT},${DIAL_OPTIONS}'));
            $ext->add($mcontext, $exten, '', new ext_return(''));
            /*
            ; In all cases of no connection, come here and simply return, since the calling dialplan will
            ; decide what to do next
            */
            $exten = '_s-.';
            $ext->add($mcontext, $exten, '', new ext_noop('Extension is reporting ${EXTEN}'));
            /*
            		Originate a call but skip voicemail if the device does not answer
            */
            $mcontext = 'originate-skipvm';
            $ext->add($mcontext, '_.X', '', new ext_macro('blkvm-set'));
            $ext->add($mcontext, '_.X', '', new ext_goto('1', '${EXTEN}', 'from-internal'));
            /* macro-simple-dial */
            /* macro-blkvm-setifempty
             * macro-blkvm-set
             * macro-blkvm-clr
             * macro-blkvm-check
             *
             * These macros are used to tell the voicemail system if it should answer a call or kill the call.
             * They are also used by modules like findmefollow and ringgroups to determine if a destination
             * if noanswer should be pursued, or if they should just end because they were called by a higher
             * level module who's destination should be honored. (Thus if vm should be blocked, so should
             * such destinations.
             *
             * In the past, it was necessary to create and track unique AstDB variables to track this since
             * it is necessary for a call that is answered, for example a queue memeber who answers a queue
             * call, to clr the block so that subsequent transfers to voicemail or user extensions which might
             * hit voicemail could succeed and the nature of Asterisk inheritable variable did not allow
             * this. This also meant that these needed to be cleaned up when the master channel who 'started
             * it all' ended, which is attempted in macro-hangupcall. There are still cases where cleanup
             * does not happen which can result in an accumulation of these.
             *
             * With the advent of the SHARED() channel variable starting in 1.6, we can achieve the same
             * thing with such a SHARED() channel variable which should be more efficient since it does not
             * hit the DB, but more importantly, there is no cleanup because the variable will die with the
             * owner channel.
             *
             * We check if the SHARED function is available and if so, we use that in our macro. If not, we
             * fall back to the shared DB variable and keep our cleanup code in hangupcall.
             *
             * Note that we have chosen to use a Macro() in place of a GoSub() because in the legacy DB
             * mode we must have the owning ${EXTEN} to create our unique key. Since GoSub() does not support
             * passing arguments until 1.6 this would not be possible in 1.4 which is still mainstream.
             * We have chosen to use the GOSUB_RETVAL in anticipation of a future point where we move to
             * a GoSub() call which would be slightly more efficient.
             */
            $exten = 's';
            if ($amp_conf['AST_FUNC_SHARED']) {
                // If it BLKVM_CHANNEL exists, return it's value. If not, then set it and return TRUE
                //
                $mcontext = 'macro-blkvm-setifempty';
                $ext->add($mcontext, $exten, '', new ext_gotoif('$[!${EXISTS(${BLKVM_CHANNEL})}]', 'init'));
                $ext->add($mcontext, $exten, '', new ext_set('GOSUB_RETVAL', '${SHARED(BLKVM,${BLKVM_CHANNEL})}'));
                $ext->add($mcontext, $exten, '', new ext_macroexit(''));
                $ext->add($mcontext, $exten, 'init', new ext_set('__BLKVM_CHANNEL', '${CHANNEL}'));
                $ext->add($mcontext, $exten, '', new ext_set('SHARED(BLKVM,${BLKVM_CHANNEL})', 'TRUE'));
                $ext->add($mcontext, $exten, '', new ext_set('GOSUB_RETVAL', 'TRUE'));
                $ext->add($mcontext, $exten, '', new ext_macroexit(''));
                // If BLKVM_CHANNEL not set or 'reset' is passed, then initialize it to this channel then set and retrun TRUE
                //
                $mcontext = 'macro-blkvm-set';
                $ext->add($mcontext, $exten, '', new ext_execif('$[!${EXISTS(${BLKVM_CHANNEL})} | "{ARG1}" = "reset"]', 'Set', '__BLKVM_CHANNEL=${CHANNEL}'));
                $ext->add($mcontext, $exten, '', new ext_set('SHARED(BLKVM,${BLKVM_CHANNEL})', 'TRUE'));
                $ext->add($mcontext, $exten, '', new ext_set('GOSUB_RETVAL', 'TRUE'));
                $ext->add($mcontext, $exten, '', new ext_macroexit(''));
                // if clearing, BLKVM_CHANNEL should already exist (if not, we clear our channel's copy)
                //
                $mcontext = 'macro-blkvm-clr';
                $ext->add($mcontext, $exten, '', new ext_set('SHARED(BLKVM,${BLKVM_CHANNEL})', ''));
                $ext->add($mcontext, $exten, '', new ext_set('GOSUB_RETVAL', ''));
                $ext->add($mcontext, $exten, '', new ext_macroexit(''));
                // if checking, BLKVM_CHANNEL should already exist (if not, we check our channel's copy)
                // CC_RECALL was originally used for CallCompletion but is used elsewhere as well for recall automated
                // calls that should therefore not go to voicemail, for example a wakeup call
                //
                $mcontext = 'macro-blkvm-check';
                $ext->add($mcontext, $exten, '', new ext_set('GOSUB_RETVAL', '${SHARED(BLKVM,${BLKVM_CHANNEL})}'));
                $ext->add($mcontext, $exten, '', new ext_execif('$["${GOSUB_RETVAL}"="" & "${CC_RECALL}"="1"]', 'Set', 'GOSUB_RETVAL=TRUE'));
                $ext->add($mcontext, $exten, '', new ext_macroexit(''));
            } else {
                // NO SHARED()
                // If it BLKVM_OVERRIDE exists, return it's value. If not, then set it and return TRUE
                //
                $mcontext = 'macro-blkvm-setifempty';
                $ext->add($mcontext, $exten, '', new ext_gotoif('$[!${EXISTS(${BLKVM_OVERRIDE})}]', 'init'));
                $ext->add($mcontext, $exten, '', new ext_set('GOSUB_RETVAL', '${DB(${BLKVM_OVERRIDE})}'));
                $ext->add($mcontext, $exten, '', new ext_macroexit(''));
                $ext->add($mcontext, $exten, 'init', new ext_set('__BLKVM_OVERRIDE', 'BLKVM/${MACRO_EXTEN}/${CHANNEL}'));
                $ext->add($mcontext, $exten, '', new ext_set('__BLKVM_BASE', '${MACRO_EXTEN}'));
                $ext->add($mcontext, $exten, '', new ext_set('DB(${BLKVM_OVERRIDE})', 'TRUE'));
                $ext->add($mcontext, $exten, '', new ext_set('GOSUB_RETVAL', 'TRUE'));
                $ext->add($mcontext, $exten, '', new ext_macroexit(''));
                // If BLKVM_OVERRIDE not set or 'reset' is passed, then initialize it to this channel then set and retrun TRUE
                //
                $mcontext = 'macro-blkvm-set';
                $ext->add($mcontext, $exten, '', new ext_execif('$[!${EXISTS(${BLKVM_OVERRIDE})} | "{ARG1}" = "reset"]', 'Set', '__BLKVM_BASE=${MACRO_EXTEN}'));
                $ext->add($mcontext, $exten, '', new ext_execif('$[!${EXISTS(${BLKVM_OVERRIDE})} | "{ARG1}" = "reset"]', 'Set', '__BLKVM_OVERRIDE=BLKVM/${MACRO_EXTEN}/${CHANNEL}'));
                $ext->add($mcontext, $exten, '', new ext_set('DB(${BLKVM_OVERRIDE})', 'TRUE'));
                $ext->add($mcontext, $exten, '', new ext_set('GOSUB_RETVAL', 'TRUE'));
                $ext->add($mcontext, $exten, '', new ext_macroexit(''));
                // if clearing, BLKVM_OVERRIDE should already exist (if not, it's already cleared anyhow)
                //
                $mcontext = 'macro-blkvm-clr';
                $ext->add($mcontext, $exten, '', new ext_gotoif('$[!${EXISTS(${BLKVM_OVERRIDE})}]', 'ret'));
                $ext->add($mcontext, $exten, '', new ext_dbdel('${BLKVM_OVERRIDE}'));
                $ext->add($mcontext, $exten, 'ret', new ext_set('GOSUB_RETVAL', ''));
                $ext->add($mcontext, $exten, '', new ext_macroexit(''));
                // if checking, BLKVM_OVERRIDE should already exist (if not, '' will be returned)
                //
                $mcontext = 'macro-blkvm-check';
                $ext->add($mcontext, $exten, '', new ext_set('GOSUB_RETVAL', '${DB(${BLKVM_OVERRIDE})}'));
                $ext->add($mcontext, $exten, '', new ext_macroexit(''));
            }
            $mcontext = 'macro-hangupcall';
            $exten = 's';
            /*
            ; Cleanup any remaining RG flag
            */
            $skip_label = $amp_conf['AST_FUNC_SHARED'] ? 'theend' : 'skiprg';
            $ext->add($mcontext, $exten, 'start', new ext_gotoif('$["${USE_CONFIRMATION}"="" | "${RINGGROUP_INDEX}"="" | "${CHANNEL}"!="${UNIQCHAN}"]', $skip_label));
            $ext->add($mcontext, $exten, '', new ext_noop_trace('Cleaning Up Confirmation Flag: RG/${RINGGROUP_INDEX}/${CHANNEL}'));
            $ext->add($mcontext, $exten, 'delrgi', new ext_dbdel('RG/${RINGGROUP_INDEX}/${CHANNEL}'));
            if (!$amp_conf['AST_FUNC_SHARED']) {
                // only clr it if we were the originating channel
                //
                $ext->add($mcontext, $exten, 'skiprg', new ext_gotoif('$["${BLKVM_BASE}"="" | "BLKVM/${BLKVM_BASE}/${CHANNEL}"!="${BLKVM_OVERRIDE}"]', 'skipblkvm'));
                $ext->add($mcontext, $exten, '', new ext_noop_trace('Cleaning Up Block VM Flag: ${BLKVM_OVERRIDE}'));
                $ext->add($mcontext, $exten, '', new ext_macro('blkvm-clr'));
                /*
                ; Cleanup any remaining FollowMe DND flags
                */
                $ext->add($mcontext, $exten, 'skipblkvm', new ext_gotoif('$["${FMGRP}"="" | "${FMUNIQUE}"="" | "${CHANNEL}"!="${FMUNIQUE}"]', 'theend'));
                $ext->add($mcontext, $exten, 'delfmrgp', new ext_dbdel('FM/DND/${FMGRP}/${CHANNEL}'));
                $skip_label = $next_label;
            }
            // Work around Asterisk issue: https://issues.asterisk.org/jira/browse/ASTERISK-19853
            $ext->add($mcontext, $exten, 'theend', new ext_execif('$["${ONETOUCH_RECFILE}"!="" & "${CDR(recordingfile)}"=""]', 'Set', 'CDR(recordingfile)=${ONETOUCH_RECFILE}'));
            $ext->add($mcontext, $exten, '', new ext_hangup());
            // TODO: once Asterisk issue fixed label as theend
            $ext->add($mcontext, $exten, '', new ext_macroexit(''));
            /*
            $ext->add($mcontext, $exten, 'theend', new ext_gosubif('$["${ONETOUCH_REC}"="RECORDING"]', 'macro-one-touch-record,s,sstate', false, '${FROMEXTEN},NOT_INUSE'));
            $ext->add($mcontext, $exten, '', new ext_gosubif('$["${ONETOUCH_REC}"="RECORDING"&"${MASTER_CHANNEL(CLEAN_DIALEDPEERNUMBER)}"="${CUT(CALLFILENAME,-,2)}"]', 'macro-one-touch-record,s,sstate', false, '${IF($["${EXTTOCALL}"!=""]?${EXTTOCALL}:${CUT(CALLFILENAME,-,2)})},NOT_INUSE'));
            $ext->add($mcontext, $exten, '', new ext_gosubif('$["${ONETOUCH_REC}"="RECORDING"&"${MASTER_CHANNEL(CLEAN_DIALEDPEERNUMBER)}"!="${CUT(CALLFILENAME,-,2)}"]','macro-one-touch-record,s,sstate',false,'${MASTER_CHANNEL(CLEAN_DIALEDPEERNUMBER)},NOT_INUSE'));
            $ext->add($mcontext,$exten,'', new ext_noop_trace('ONETOUCH_REC: ${ONETOUCH_REC}',5));
            */
            /* Now generate a clean DIALEDPEERNUMBER if ugly followme/ringgroup extensions dialplans were engaged
            	* doesn't seem like this is need with some of the NoCDRs() but leave for now and keep an eye on it
            	*
            	$ext->add($mcontext, $exten, '', new ext_execif('$["${CLEAN_DIALEDPEERNUMBER}"=""]','Set','CLEAN_DIALEDPEERNUMBER=${IF($[${FIELDQTY(DIALEDPEERNUMBER,-)}=1]?${DIALEDPEERNUMBER}:${CUT(CUT(DIALEDPEERNUMBER,-,2),@,1)})}'));
            	$ext->add($mcontext, $exten, '', new ext_set('CDR(clean_dst)','${CLEAN_DIALEDPEERNUMBER}'));
            	*/
            /* macro-hangupcall */
            include 'functions.inc/macro-dial-one.php';
            include 'functions.inc/func-sipheaders.php';
            break;
    }
}
Example #25
0
<?php

if (!defined('FREEPBX_IS_AUTH')) {
    die('No direct script access allowed');
}
//for translation only
if (false) {
    _("Phonebook dial-by-name directory");
}
// Enable phonebook directory as a feature code
$fcc = new featurecode('pbdirectory', 'app-pbdirectory');
$fcc->setDescription('Phonebook dial-by-name directory');
$fcc->setDefault('411');
$fcc->setProvideDest();
$fcc->update();
unset($fcc);
function voicemail_configpageload()
{
    global $currentcomponent;
    global $amp_conf;
    global $astman;
    // Init vars from $_REQUEST[]
    $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : null;
    $ext = isset($_REQUEST['extdisplay']) ? $_REQUEST['extdisplay'] : null;
    $extn = isset($_REQUEST['extension']) ? $_REQUEST['extension'] : null;
    $display = isset($_REQUEST['display']) ? $_REQUEST['display'] : null;
    if ($ext === '') {
        $extdisplay = $extn;
    } else {
        $extdisplay = $ext;
    }
    if ($action != 'del') {
        $vmbox = voicemail_mailbox_get($extdisplay);
        if ($vmbox == null) {
            $vm = false;
            $incontext = 'default';
            $vmpwd = null;
            $name = null;
            $email = null;
            $pager = null;
            $vmoptions = null;
        } else {
            $incontext = isset($vmbox['vmcontext']) ? $vmbox['vmcontext'] : 'default';
            $vmpwd = $vmbox['pwd'];
            $name = $vmbox['name'];
            $email = $vmbox['email'];
            $pager = $vmbox['pager'];
            $vmoptions = $vmbox['options'];
            $vm = true;
        }
        //loop through all options
        $options = "";
        if (isset($vmoptions) && is_array($vmoptions)) {
            $alloptions = array_keys($vmoptions);
            if (isset($alloptions)) {
                foreach ($alloptions as $option) {
                    if ($option != "attach" && $option != "envelope" && $option != "passlogin" && $option != "novmstar" && $option != "saycid" && $option != "delete" && $option != "imapuser" && $option != "imappassword" && $option != '') {
                        $options .= $option . '=' . $vmoptions[$option] . '|';
                    }
                }
                $options = rtrim($options, '|');
                // remove the = sign if there are no options set
                $options = rtrim($options, '=');
            }
            extract($vmoptions, EXTR_PREFIX_ALL, "vmops");
        } else {
            $vmops_novmstar = 'no';
            $vmops_passlogin = '******';
            $vmops_attach = 'no';
            $vmops_saycid = 'no';
            $vmops_envelope = 'no';
            $vmops_delete = 'no';
            $vmops_imapuser = null;
            $vmops_imappassword = null;
        }
        if (empty($vmcontext)) {
            $vmcontext = isset($_REQUEST['vmcontext']) ? $_REQUEST['vmcontext'] : $incontext;
        }
        if (empty($vmcontext)) {
            $vmcontext = 'default';
        }
        if ($vm == true) {
            $vmselect = "enabled";
        } else {
            $vmselect = "disabled";
        }
        $fc_vm = featurecodes_getFeatureCode('voicemail', 'dialvoicemail');
        $msgInvalidVmPwd = _("Please enter a valid Voicemail Password, using digits only");
        $msgInvalidEmail = _("Please enter a valid Email Address");
        $msgInvalidPager = _("Please enter a valid Pager Email Address");
        $msgInvalidVMContext = _("VM Context cannot be blank");
        $vmops_imapuser = isset($vmops_imapuser) ? $vmops_imapuser : '';
        $vmops_imappassword = isset($vmops_imappassword) ? $vmops_imappassword : '';
        $section = _("Voicemail");
        $class = "fpbx-voicemail";
        $category = "voicemail";
        $guidefaults = array("elemname" => "", "prompttext" => "", "helptext" => "", "currentvalue" => "", "valarray" => array(), "jsonclick" => '', "jsvalidation" => "", "failvalidationmsg" => "", "canbeempty" => true, "maxchars" => 0, "disable" => false, "inputgroup" => false, "class" => "");
        $el = array("elemname" => "vm", "prompttext" => _('Enabled'), "currentvalue" => $vmselect, "valarray" => $currentcomponent->getoptlist('vmena'), "jsonclick" => "frm_{$display}_voicemailEnabled() && frm_{$display}_vmxEnabled()", "pairedvalues" => false);
        $currentcomponent->addguielem($section, new gui_radio(array_merge($guidefaults, $el)), $category);
        $disable = $vmselect == 'disabled';
        $el = array("elemname" => "vmpwd", "prompttext" => _('Voicemail Password'), "helptext" => sprintf(_("This is the password used to access the Voicemail system.%sThis password can only contain numbers.%sA user can change the password you enter here after logging into the Voicemail system (%s) with a phone."), "<br /><br />", "<br /><br />", $fc_vm), "currentvalue" => $vmpwd, "jsvalidation" => "frm_{$display}_isVoiceMailEnabled() && !frm_{$display}_isValidVoicemailPass()", "failvalidationmsg" => $msgInvalidVmPwd, "canbeempty" => false, "class" => $class, "disable" => $disable, "passwordToggle" => true);
        $currentcomponent->addguielem($section, new gui_password(array_merge($guidefaults, $el)), $category);
        //for passwordless voicemail we need to check some settings
        //first lets see if there is an entry in the asteriskDB for this device
        //no entry in the db is the same as yes, meaning we need a voicemail password
        $passlogin = !empty($extdisplay) ? $astman->connected() && $astman->database_get("AMPUSER", $extdisplay . "/novmpw") : 'yes';
        $passlogin = !empty($passlogin) ? 'no' : 'yes';
        //now lets get our featurecodes for helptext display niceties
        $mvm = new featurecode('voicemail', 'myvoicemail');
        $dvm = new featurecode('voicemail', 'dialvoicemail');
        $extword = $display == 'extensions' ? _('Extension') : _('Device');
        $display_mode = "advanced";
        $mode = \FreePBX::Config()->get("FPBXOPMODE");
        if (!empty($mode)) {
            $display_mode = $mode;
        }
        if ($display_mode == "basic") {
            $tb = $rb = "gui_hidden";
        } else {
            $tb = "gui_textbox";
            $rb = "gui_radio";
        }
        $el = array("elemname" => "passlogin", "prompttext" => sprintf(_('Require From Same %s'), $extword), "helptext" => sprintf(_("If set to \"no\" then when the user dials %s to access their own voicemail, they will not be asked to enter a password. This does not apply to %s calls, which will always prompt for a password. For security reasons, this should probably be set to \"yes\" in an environment where other users will have physical access to this extension."), $mvm->getCode(), $dvm->getCode()), "currentvalue" => $passlogin, "valarray" => $currentcomponent->getoptlist('vmyn'), "disable" => $disable, "class" => $class);
        $currentcomponent->addguielem($section, new $rb(array_merge($guidefaults, $el)), $category);
        $novmstar = !empty($extdisplay) ? $astman->connected() && $astman->database_get("AMPUSER", $extdisplay . "/novmstar") : 'yes';
        $novmstar = !empty($novmstar) ? 'yes' : 'no';
        $el = array("elemname" => "novmstar", "prompttext" => _("Disable (*) in Voicemail Menu"), "helptext" => sprintf(_("If set to \"yes\" then when someone dials this voicemail box they will not be able to access the voicemail menu by pressing (*). If you have no plans to access your mailbox remotely set this to \"yes\""), $mvm->getCode(), $dvm->getCode()), "currentvalue" => $novmstar, "valarray" => $currentcomponent->getoptlist('vmyn'), "disable" => $disable, "class" => $class);
        $currentcomponent->addguielem($section, new $rb(array_merge($guidefaults, $el)), $category);
        $el = array("elemname" => "email", "prompttext" => _('Email Address'), "helptext" => _("The email address that Voicemails are sent to."), "currentvalue" => $email, "jsvalidation" => "frm_{$display}_isVoiceMailEnabled() && frm_{$display}_isEmailAttachment() && !isEmail()", "failvalidationmsg" => $msgInvalidEmail, "canbeempty" => false, "class" => $class, "disable" => $disable);
        $currentcomponent->addguielem($section, new gui_textbox(array_merge($guidefaults, $el)), $category);
        $el = array("elemname" => "pager", "prompttext" => _('Pager Email Address'), "helptext" => _("Pager/mobile email address that short Voicemail notifications are sent to."), "currentvalue" => $pager, "jsvalidation" => "frm_{$display}_isVoiceMailEnabled() && !isEmpty() && !isEmail()", "failvalidationmsg" => $msgInvalidEmail, "canbeempty" => false, "class" => $class, "disable" => $disable);
        $currentcomponent->addguielem($section, new $tb(array_merge($guidefaults, $el)), $category);
        $el = array("elemname" => "attach", "prompttext" => _('Email Attachment'), "helptext" => _("Option to attach Voicemails to email."), "currentvalue" => $vmops_attach, "valarray" => $currentcomponent->getoptlist('vmyn'), "disable" => $disable, "class" => $class);
        $currentcomponent->addguielem($section, new $rb(array_merge($guidefaults, $el)), $category);
        $el = array("elemname" => "saycid", "prompttext" => _('Play CID'), "helptext" => _("Read back caller's telephone number prior to playing the incoming message, and just after announcing the date and time the message was left."), "currentvalue" => $vmops_saycid, "valarray" => $currentcomponent->getoptlist('vmyn'), "disable" => $disable, "class" => $class);
        $currentcomponent->addguielem($section, new $rb(array_merge($guidefaults, $el)), $category);
        $el = array("elemname" => "envelope", "prompttext" => _('Play Envelope'), "helptext" => _("Envelope controls whether or not the Voicemail system will play the message envelope (date/time) before playing the Voicemail message. This setting does not affect the operation of the envelope option in the advanced Voicemail menu."), "currentvalue" => $vmops_envelope, "valarray" => $currentcomponent->getoptlist('vmyn'), "disable" => $disable, "class" => $class);
        $currentcomponent->addguielem($section, new $rb(array_merge($guidefaults, $el)), $category);
        $el = array("elemname" => "vmdelete", "prompttext" => _('Delete Voicemail'), "helptext" => _("If set to \"yes\" the message will be deleted from the Voicemailbox (after having been emailed). Provides functionality that allows a user to receive their Voicemail via email alone, rather than having the Voicemail able to be retrieved from the Webinterface or the Extension handset.  CAUTION: MUST HAVE attach Voicemail to email SET TO YES OTHERWISE YOUR MESSAGES WILL BE LOST FOREVER."), "currentvalue" => $vmops_delete, "valarray" => $currentcomponent->getoptlist('vmyn'), "disable" => $disable, "class" => $class);
        $currentcomponent->addguielem($section, new $rb(array_merge($guidefaults, $el)), $category);
        if ($amp_conf['VM_SHOW_IMAP'] || $vmops_imapuser || $vmops_imappassword) {
            $el = array("elemname" => "imapuser", "prompttext" => _('IMAP Username'), "helptext" => sprintf(_("This is the IMAP username, if using IMAP storage"), "<br /><br />"), "currentvalue" => $vmops_imapuser, "class" => $class, "disable" => $disable);
            $currentcomponent->addguielem($section, new $tb(array_merge($guidefaults, $el)), $category);
            $el = array("elemname" => "imappassword", "prompttext" => _('IMAP Password'), "helptext" => sprintf(_("This is the IMAP password, if using IMAP storage"), "<br /><br />"), "currentvalue" => $vmops_imapuser, "class" => $class, "disable" => $disable);
            $currentcomponent->addguielem($section, new $tb(array_merge($guidefaults, $el)), $category);
        }
        $el = array("elemname" => "options", "prompttext" => _('VM Options'), "helptext" => sprintf(_("Separate options with pipe ( | )%sie: review=yes|maxmessage=60"), "<br /><br />"), "currentvalue" => $options, "class" => $class, "disable" => $disable);
        $currentcomponent->addguielem($section, new $tb(array_merge($guidefaults, $el)), $category);
        $el = array("elemname" => "vmcontext", "prompttext" => _('VM Context'), "helptext" => _("This is the Voicemail Context which is normally set to default. Do not change unless you understand the implications."), "currentvalue" => $incontext, "class" => $class, "disable" => $disable, "jsvalidation" => "frm_{$display}_isVoiceMailEnabled() && isEmpty()", "failvalidationmsg" => $msgInvalidVMContext);
        $currentcomponent->addguielem($section, new $tb(array_merge($guidefaults, $el)), $category);
        voicemail_draw_vmxgui($extdisplay, $disable);
    }
}
Example #27
0
<?php

global $db;
global $amp_conf;
// Add Feature Codes for Toggle Queues - Using *45
$fcc = new featurecode('queues', 'que_toggle');
$fcc->setDescription('Queue Toggle');
$fcc->setDefault('*45');
$fcc->update();
unset($fcc);
if (!function_exists("out")) {
    function out($text)
    {
        echo $text . "<br />";
    }
}
if (!function_exists("outn")) {
    function outn($text)
    {
        echo $text;
    }
}
$results = array();
$sql = "SELECT args, extension, priority FROM extensions WHERE context = 'ext-queues' AND descr = 'jump'";
$results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
if (!DB::IsError($results)) {
    // error - table must not be there
    foreach ($results as $result) {
        $old_dest = $result['args'];
        $extension = $result['extension'];
        $priority = $result['priority'];
Example #28
0
function findmefollow_get_config($engine)
{
    global $ext;
    // is this the best way to pass this?
    global $amp_conf;
    switch ($engine) {
        case "asterisk":
            if ($amp_conf['USEDEVSTATE']) {
                $ext->addGlobal('FMDEVSTATE', 'TRUE');
            }
            $fcc = new featurecode('findmefollow', 'fmf_toggle');
            $fmf_code = $fcc->getCodeActive();
            unset($fcc);
            if ($fmf_code != '') {
                findmefollow_fmf_toggle($fmf_code);
            }
            $ext->addInclude('from-internal-additional', 'ext-findmefollow');
            $ext->addInclude('from-internal-additional', 'fmgrps');
            $contextname = 'ext-findmefollow';
            // Before creating all the contexts, let's make a list of hints if needed
            //
            if ($amp_conf['USEDEVSTATE'] && $fmf_code != '') {
                $device_list = core_devices_list("all", 'full', true);
                foreach ($device_list as $device) {
                    if ($device['tech'] == 'sip' || $device['tech'] == 'iax2') {
                        $ext->add($contextname, $fmf_code . $device['id'], '', new ext_goto("1", $fmf_code, "app-fmf-toggle"));
                        $ext->addHint($contextname, $fmf_code . $device['id'], "Custom:FOLLOWME" . $device['id']);
                    }
                }
            }
            $ringlist = findmefollow_full_list();
            if (is_array($ringlist)) {
                foreach ($ringlist as $item) {
                    $grpnum = ltrim($item['0']);
                    $grp = findmefollow_get($grpnum);
                    $strategy = $grp['strategy'];
                    $grptime = $grp['grptime'];
                    $grplist = $grp['grplist'];
                    $postdest = $grp['postdest'];
                    $grppre = isset($grp['grppre']) ? $grp['grppre'] : '';
                    $annmsg_id = $grp['annmsg_id'];
                    $dring = $grp['dring'];
                    $needsconf = $grp['needsconf'];
                    $remotealert_id = $grp['remotealert_id'];
                    $toolate_id = $grp['toolate_id'];
                    $ringing = $grp['ringing'];
                    $pre_ring = $grp['pre_ring'];
                    if ($ringing == 'Ring' || empty($ringing)) {
                        $dialopts = '${DIAL_OPTIONS}';
                    } else {
                        // We need the DIAL_OPTIONS variable
                        $sops = sql("SELECT value from globals where variable='DIAL_OPTIONS'", "getRow");
                        $dialopts = "m({$ringing})" . str_replace('r', '', $sops[0]);
                    }
                    // Direct target to Follow-Me come here bypassing the followme/ddial conditional check
                    //
                    $ext->add($contextname, 'FM' . $grpnum, '', new ext_goto("FM{$grpnum}", "{$grpnum}"));
                    //
                    // If the followme is configured for extension dialing to go to the the extension and not followme then
                    // go there. This is often used in VmX Locater functionality when the user does not want the followme
                    // to automatically be called but only if chosen by the caller as an alternative to going to voicemail
                    //
                    $ext->add($contextname, $grpnum, '', new ext_gotoif('$[ "${DB(AMPUSER/' . $grpnum . '/followme/ddial)}" = "EXTENSION" ]', 'ext-local,' . $grpnum . ',1'));
                    $ext->add($contextname, $grpnum, 'FM' . $grpnum, new ext_macro('user-callerid'));
                    $ext->add($contextname, $grpnum, '', new ext_set('__EXTTOCALL', '${EXTEN}'));
                    // block voicemail until phone is answered at which point a macro should be called on the answering
                    // line to clear this flag so that subsequent transfers can occur, if already set by a the caller
                    // then don't change.
                    //
                    $ext->add($contextname, $grpnum, '', new ext_gotoif('$["foo${BLKVM_OVERRIDE}" = "foo"]', 'skipdb'));
                    $ext->add($contextname, $grpnum, '', new ext_gotoif('$["${DB(${BLKVM_OVERRIDE})}" = "TRUE"]', 'skipov'));
                    $ext->add($contextname, $grpnum, 'skipdb', new ext_setvar('__NODEST', ''));
                    $ext->add($contextname, $grpnum, '', new ext_setvar('__BLKVM_OVERRIDE', 'BLKVM/${EXTEN}/${CHANNEL}'));
                    $ext->add($contextname, $grpnum, '', new ext_setvar('__BLKVM_BASE', '${EXTEN}'));
                    $ext->add($contextname, $grpnum, '', new ext_setvar('DB(${BLKVM_OVERRIDE})', 'TRUE'));
                    // Remember if NODEST was set later, but clear it in case the call is answered so that subsequent
                    // transfers work.
                    //
                    $ext->add($contextname, $grpnum, 'skipov', new ext_setvar('RRNODEST', '${NODEST}'));
                    $ext->add($contextname, $grpnum, 'skipvmblk', new ext_setvar('__NODEST', '${EXTEN}'));
                    $ext->add($contextname, $grpnum, '', new ext_gosubif('$[${DB_EXISTS(AMPUSER/' . $grpnum . '/followme/changecid)} = 1 & "${DB(AMPUSER/' . $grpnum . '/followme/changecid)}" != "default" & "${DB(AMPUSER/' . $grpnum . '/followme/changecid)}" != ""]', 'sub-fmsetcid,s,1'));
                    // deal with group CID prefix
                    // but strip only if you plan on setting a new one
                    if ($grppre != '') {
                        $ext->add($contextname, $grpnum, '', new ext_gotoif('$["foo${RGPREFIX}" = "foo"]', 'REPCID'));
                        $ext->add($contextname, $grpnum, '', new ext_gotoif('$["${RGPREFIX}" != "${CALLERID(name):0:${LEN(${RGPREFIX})}}"]', 'REPCID'));
                        $ext->add($contextname, $grpnum, '', new ext_noop('Current RGPREFIX is ${RGPREFIX}....stripping from Caller ID'));
                        $ext->add($contextname, $grpnum, '', new ext_setvar('CALLERID(name)', '${CALLERID(name):${LEN(${RGPREFIX})}}'));
                        $ext->add($contextname, $grpnum, '', new ext_setvar('_RGPREFIX', ''));
                        $ext->add($contextname, $grpnum, 'REPCID', new ext_noop('CALLERID(name) is ${CALLERID(name)}'));
                        $ext->add($contextname, $grpnum, '', new ext_setvar('_RGPREFIX', $grppre));
                        $ext->add($contextname, $grpnum, '', new ext_setvar('CALLERID(name)', '${RGPREFIX}${CALLERID(name)}'));
                    }
                    // recording stuff
                    $ext->add($contextname, $grpnum, '', new ext_setvar('RecordMethod', 'Group'));
                    // append the followme's extension to the grouplist. This may be redundant but will ensure recording if the extension itself is not part of
                    // the list
                    $ext->add($contextname, $grpnum, '', new ext_macro('record-enable', '${DB(AMPUSER/' . "{$grpnum}/followme/grplist)}-{$grpnum}" . ',${RecordMethod}'));
                    // MODIFIED (PL)
                    // Add Alert Info if set but don't override and already set value (could be from ringgroup, directdid, etc.)
                    //
                    if ((isset($dring) ? $dring : '') != '') {
                        // If ALERTINFO is set, then skip to the next set command. This was modified to two lines because the previous
                        // IF() couldn't handle ':' as part of the string. The jump to PRIORITY+2 allows for now destination label
                        // which is needed in the 2.3 version.
                        $ext->add($contextname, $grpnum, '', new ext_gotoif('$["x${ALERT_INFO}"!="x"]', '$[${PRIORITY}+2])}'));
                        $ext->add($contextname, $grpnum, '', new ext_setvar("__ALERT_INFO", str_replace(';', '\\;', $dring)));
                    }
                    // If pre_ring is set, then ring this number of seconds prior to moving on
                    if ((isset($strategy) ? substr($strategy, 0, strlen('ringallv2')) : '') != 'ringallv2') {
                        $ext->add($contextname, $grpnum, '', new ext_gotoif('$[$[ "${DB(AMPUSER/' . $grpnum . '/followme/prering)}" = "0" ] | $[ "${DB(AMPUSER/' . $grpnum . '/followme/prering)}" = "" ]] ', 'skipsimple'));
                        $ext->add($contextname, $grpnum, '', new ext_macro('simple-dial', $grpnum . ',${DB(AMPUSER/' . "{$grpnum}/followme/prering)}"));
                    }
                    // group dial
                    $ext->add($contextname, $grpnum, 'skipsimple', new ext_setvar('RingGroupMethod', $strategy));
                    $ext->add($contextname, $grpnum, '', new ext_setvar('_FMGRP', $grpnum));
                    if (isset($annmsg_id) ? $annmsg_id : '') {
                        $annmsg = recordings_get_file($annmsg_id);
                        // should always answer before playing anything, shouldn't we ?
                        $ext->add($contextname, $grpnum, '', new ext_gotoif('$[$["${DIALSTATUS}" = "ANSWER"] | $["foo${RRNODEST}" != "foo"]]', 'DIALGRP'));
                        $ext->add($contextname, $grpnum, '', new ext_answer(''));
                        $ext->add($contextname, $grpnum, '', new ext_wait(1));
                        $ext->add($contextname, $grpnum, '', new ext_playback($annmsg));
                    }
                    // Create the confirm target
                    $len = strlen($grpnum) + 4;
                    $remotealert = recordings_get_file($remotealert_id);
                    $toolate = recordings_get_file($toolate_id);
                    $ext->add("fmgrps", "_RG-{$grpnum}-.", '', new ext_macro('dial', '${DB(AMPUSER/' . "{$grpnum}/followme/grptime)}," . "M(confirm^{$remotealert}^{$toolate}^{$grpnum}){$dialopts}" . ',${EXTEN:' . $len . '}'));
                    // If grpconf == ENABLED call with confirmation ELSE call normal
                    $ext->add($contextname, $grpnum, 'DIALGRP', new ext_gotoif('$[ "${DB(AMPUSER/' . $grpnum . '/followme/grpconf)}" = "ENABLED" ]', 'doconfirm'));
                    // Normal call
                    if ((isset($strategy) ? substr($strategy, 0, strlen('ringallv2')) : '') != 'ringallv2') {
                        $ext->add($contextname, $grpnum, '', new ext_macro('dial', '${DB(AMPUSER/' . "{$grpnum}/followme/grptime)},{$dialopts}," . '${DB(AMPUSER/' . "{$grpnum}/followme/grplist)}"));
                    } else {
                        $ext->add($contextname, $grpnum, '', new ext_macro('dial', '$[ ${DB(AMPUSER/' . $grpnum . '/followme/grptime)} + ${DB(AMPUSER/' . $grpnum . '/followme/prering)} ],' . $dialopts . ',${DB(AMPUSER/' . $grpnum . '/followme/grplist)}'));
                    }
                    $ext->add($contextname, $grpnum, '', new ext_goto('nextstep'));
                    // Call Confirm call
                    if ((isset($strategy) ? substr($strategy, 0, strlen('ringallv2')) : '') != 'ringallv2') {
                        $ext->add($contextname, $grpnum, 'doconfirm', new ext_macro('dial-confirm', '${DB(AMPUSER/' . "{$grpnum}/followme/grptime)},{$dialopts}," . '${DB(AMPUSER/' . "{$grpnum}/followme/grplist)}," . $grpnum));
                    } else {
                        $ext->add($contextname, $grpnum, 'doconfirm', new ext_macro('dial-confirm', '$[ ${DB(AMPUSER/' . $grpnum . '/followme/grptime)} + ${DB(AMPUSER/' . $grpnum . '/followme/prering)} ],' . $dialopts . ',${DB(AMPUSER/' . $grpnum . '/followme/grplist)},' . $grpnum));
                    }
                    $ext->add($contextname, $grpnum, 'nextstep', new ext_setvar('RingGroupMethod', ''));
                    // Did the call come from a queue or ringgroup, if so, don't go to the destination, just end and let
                    // the queue or ringgroup decide what to do next
                    //
                    $ext->add($contextname, $grpnum, '', new ext_gotoif('$["foo${RRNODEST}" != "foo"]', 'nodest'));
                    $ext->add($contextname, $grpnum, '', new ext_setvar('__NODEST', ''));
                    $ext->add($contextname, $grpnum, '', new ext_dbdel('${BLKVM_OVERRIDE}'));
                    // where next?
                    if ((isset($postdest) ? $postdest : '') != '') {
                        $ext->add($contextname, $grpnum, '', new ext_goto($postdest));
                    } else {
                        $ext->add($contextname, $grpnum, '', new ext_hangup(''));
                    }
                    $ext->add($contextname, $grpnum, 'nodest', new ext_noop('SKIPPING DEST, CALL CAME FROM Q/RG: ${RRNODEST}'));
                }
                /*
                  ASTDB Settings:
                  AMPUSER/nnn/followme/changecid default | did | fixed | extern
                  AMPUSER/nnn/followme/fixedcid XXXXXXXX
                
                  changecid:
                    default   - works as always, same as if not present
                    fixed     - set to the fixedcid
                    extern    - set to the fixedcid if the call is from the outside only
                    did       - set to the DID that the call came in on or leave alone, treated as foreign
                    forcedid  - set to the DID that the call came in on or leave alone, not treated as foreign
                  
                  EXTTOCALL   - has the exten num called, hoaky if that goes away but for now use it
                */
                if (count($ringlist)) {
                    $contextname = 'sub-fmsetcid';
                    $exten = 's';
                    $ext->add($contextname, $exten, '', new ext_goto('1', 's-${DB(AMPUSER/${EXTTOCALL}/followme/changecid)}'));
                    $exten = 's-fixed';
                    $ext->add($contextname, $exten, '', new ext_execif('$["${REGEX("^[\\+]?[0-9]+$" ${DB(AMPUSER/${EXTTOCALL}/followme/fixedcid)})}" = "1"]', 'Set', '__TRUNKCIDOVERRIDE=${DB(AMPUSER/${EXTTOCALL}/followme/fixedcid)}'));
                    $ext->add($contextname, $exten, '', new ext_return(''));
                    $exten = 's-extern';
                    $ext->add($contextname, $exten, '', new ext_execif('$["${REGEX("^[\\+]?[0-9]+$" ${DB(AMPUSER/${EXTTOCALL}/followme/fixedcid)})}" == "1" & "${FROM_DID}" != ""]', 'Set', '__TRUNKCIDOVERRIDE=${DB(AMPUSER/${EXTTOCALL}/followme/fixedcid)}'));
                    $ext->add($contextname, $exten, '', new ext_return(''));
                    $exten = 's-did';
                    $ext->add($contextname, $exten, '', new ext_execif('$["${REGEX("^[\\+]?[0-9]+$" ${FROM_DID})}" = "1"]', 'Set', '__REALCALLERIDNUM=${FROM_DID}'));
                    $ext->add($contextname, $exten, '', new ext_return(''));
                    $exten = 's-forcedid';
                    $ext->add($contextname, $exten, '', new ext_execif('$["${REGEX("^[\\+]?[0-9]+$" ${FROM_DID})}" = "1"]', 'Set', '__TRUNKCIDOVERRIDE=${FROM_DID}'));
                    $ext->add($contextname, $exten, '', new ext_return(''));
                    $exten = '_s-.';
                    $ext->add($contextname, $exten, '', new ext_noop('Unknown value for AMPUSER/${EXTTOCALL}/followme/changecid of ${DB(AMPUSER/${EXTTOCALL}/followme/changecid)} set to "default"'));
                    $ext->add($contextname, $exten, '', new ext_setvar('DB(AMPUSER/${EXTTOCALL}/followme/changecid)', 'default'));
                    $ext->add($contextname, $exten, '', new ext_return(''));
                }
            }
            break;
    }
}
Example #29
0
//    the Free Software Foundation, either version 2 of the License, or
//    (at your option) any later version.
//
//    FreePBX 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.
//
//    You should have received a copy of the GNU General Public License
//    along with FreePBX.  If not, see <http://www.gnu.org/licenses/>.
//
// Copyright (C) 2005 mheydon1973
//
//for translation only
if (false) {
    _("Call Waiting");
    _("Call Waiting - Activate");
    _("Call Waiting - Deactivate");
}
// Register FeatureCode - Activate
$fcc = new featurecode('callwaiting', 'cwon');
$fcc->setDescription('Call Waiting - Activate');
$fcc->setDefault('*70');
$fcc->update();
unset($fcc);
// Register FeatureCode - Deactivate
$fcc = new featurecode('callwaiting', 'cwoff');
$fcc->setDescription('Call Waiting - Deactivate');
$fcc->setDefault('*71');
$fcc->update();
unset($fcc);
Example #30
0
$fcc = new featurecode('core', 'blindxfer');
$fcc->setDescription('In-Call Asterisk Blind Transfer');
$fcc->setDefault('##');
$fcc->update();
unset($fcc);
$fcc = new featurecode('core', 'atxfer');
$fcc->setDescription('In-Call Asterisk Attended Transfer');
$fcc->setDefault('*2');
$fcc->update();
unset($fcc);
$fcc = new featurecode('core', 'automon');
$fcc->setDescription('In-Call Asterisk Toggle Call Recording');
$fcc->setDefault('*1');
$fcc->update();
unset($fcc);
$fcc = new featurecode('core', 'disconnect');
$fcc->setDescription('In-Call Asterisk Disconnect Code');
$fcc->setDefault('**');
$fcc->update();
unset($fcc);
// Version 2.5 Upgrade needs to migrate directdid user info to incoming table
//
outn(_("Checking if directdids need migrating.."));
$sql = "SELECT `directdid` FROM `users`";
$check = $db->getRow($sql, DB_FETCHMODE_ASSOC);
if (!DB::IsError($check)) {
    out(_("starting migration"));
    $errors = 0;
    $sql = "SELECT * FROM `users` WHERE `directdid` != '' AND `directdid` IS NOT NULL";
    $direct_dids_arr = $db->getAll($sql, DB_FETCHMODE_ASSOC);
    if (!DB::IsError($direct_dids_arr)) {