2 <?php /* $Id: build_exten.php,v 1.1 2010-03-26 02:19:16 ivan Exp $ */
3 //Copyright (C) 2008 Astrogen LLC
5 //This program is free software; you can redistribute it and/or
6 //modify it under the terms of the GNU General Public License
7 //as published by the Free Software Foundation; either version 2
8 //of the License, or (at your option) any later version.
10 //This program is distributed in the hope that it will be useful,
11 //but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 //GNU General Public License for more details.
19 function outn($text) {
23 function error($text) {
24 echo "[ERROR] ".$text."\n";
27 function warning($text) {
28 echo "[WARNING] ".$text."\n";
31 function fatal($text) {
32 echo "[FATAL] ".$text."\n";
36 function debug($text) {
39 if ($param_debug) echo "[DEBUG] ".$text."\n";
42 if (! @ include("Console/Getopt.php")) {
43 fatal("PEAR must be installed (requires Console/Getopt.php). Include path: ".ini_get("include_path"));
47 ini_set('error_reporting', E_ALL & ~E_NOTICE);
52 out(" ".$argv[0]." --create|delete --exten <extension> [optional parameters]");
55 out("OPERATIONS (exactly one must be specified):");
57 out(" Create a new extension");
59 out(" Modify an existing extension, the extension must exist and all values execept");
60 out(" those specified will remain the same");
62 out(" Delete an extension");
65 out(" --exten extension_number");
66 out(" Extension number to create or delete. Must be specified.");
68 out("OPTIONAL PARAMETERS:");
70 out(" Display Name, defaults to specified extension number.");
71 out(" --outboundcid cid_number");
72 out(" Outbound CID Number, defaults to specified extension number.");
73 out(" --directdid did_number");
74 out(" Direct DID Number, defaults to extension number.");
75 out(" --vm-password password");
76 out(" Voicemail Password, defaults to specified extension number.");
77 out(" --sip-secret secret");
78 out(" SIP Secret, defaults to md5 hash of specified extension number.");
80 out(" Display debug messages.");
81 out(" --no-warnings");
82 out(" Do Not display warning messages.");
84 out(" --help, -h, -? Show this help");
87 // **** Parse out command-line options
104 $args = Console_Getopt::getopt(Console_Getopt::readPHPArgv(), $shortopts, $longopts);
105 if (is_object($args)) {
106 // assume it's PEAR_ERROR
107 fatal($args->message);
113 $param_debug = false;
114 $param_warnings = true;
115 $param_create = false;
116 $param_modify = false;
117 $param_delete = false;
118 $param_exten = false;
120 $param_outboundcid = false;
121 $param_directdid = false;
122 $param_sip_secret = false;
123 $param_vm_password = false;
125 foreach ($args[0] as $arg) {
138 debug("debug mode is enabled");
141 case "--no-warnings":
142 $param_warnings = false;
147 $param_create = true;
152 $param_modify = true;
157 $param_delete = true;
162 $new_exten = $arg[1];
165 case "--outboundcid":
166 $param_outboundcid = true;
167 $new_outboundcid = $arg[1];
171 $param_directdid = true;
172 $new_directdid = $arg[1];
181 $param_sip_secret = true;
182 $new_sip_secret = $arg[1];
185 case "--vm-password":
186 $param_vm_password = true;
187 $new_vm_password = $arg[1];
191 error("unhandled argument supplied: ".$arg[0].", aborting");
200 if ($param_create && $param_modify) {
201 error("Incompatible combination of options, create and modify");
204 if (!(($param_create || $param_modify) XOR $param_delete)) {
205 error("Invalid Parameter combination, you must include create or delete and can not do both in one call");
209 error("You must provide an extension number to create or delete an extension");
213 if ($param_warnings && $param_create) {
214 if (!$param_outboundcid) {
215 $new_outboundcid = $new_exten;
216 warning("WARNING: No outboundcid specified for extenion, using $new_outboundcid as outboundcid");
218 if (!$param_directdid) {
219 $new_directdid = $new_exten;
220 warning("WARNING: No outboundcid specified for extenion, using $new_outboundcid as outboundcid");
223 $new_name = $new_exten;
224 warning("WARNING: No name specified for extenion, using $new_name as name");
226 if (!$param_sip_secret) {
227 $new_sip_secret = md5($new_exten);
228 warning("WARNING: No sip-secret specified for extenion, using $new_sip_secret as secret");
230 if (!$param_vm_password) {
231 $new_vm_password = $new_exten;
232 warning("WARNING: No vm-password specified for extenion, using $new_vm_password as password");
236 // Now setup actions and exten how leveraged code expected it
240 $actions = "addext/addvm";
241 } else if ($param_modify) {
243 } else if ($param_delete) {
247 /* I don't think I need these but ???
253 // determine module type to show, default to 'setup'
257 'cdrcost'=>'Call Cost',
260 define("AMP_CONF", "/etc/amportal.conf");
261 $amportalconf = AMP_CONF;
263 // bootstrap retrieve_conf by getting the AMPWEBROOT since that is currently where the necessary
264 // functions.inc.php resides, and then use that parser to properly parse the file and get all
265 // the defaults as needed.
267 function parse_amportal_conf_bootstrap($filename) {
268 $file = file($filename);
269 foreach ($file as $line) {
270 if (preg_match("/^\s*([\w]+)\s*=\s*\"?([\w\/\:\.\*\%-]*)\"?\s*([;#].*)?/",$line,$matches)) {
271 $conf[ $matches[1] ] = $matches[2];
274 if ( !isset($conf["AMPWEBROOT"]) || ($conf["AMPWEBROOT"] == "")) {
275 $conf["AMPWEBROOT"] = "/var/www/html";
277 $conf["AMPWEBROOT"] = rtrim($conf["AMPWEBROOT"],'/');
283 $amp_conf = parse_amportal_conf_bootstrap($amportalconf);
284 if (count($amp_conf) == 0) {
289 // Emulate gettext extension functions if gettext is not available
290 if (!function_exists('_')) {
295 if (!function_exists('gettext')) {
296 function gettext($message) {
300 if (!function_exists('dgettext')) {
301 function dgettext($domain, $message) {
307 function set_language() {
308 if (extension_loaded('gettext')) {
309 if (isset($_COOKIE['lang'])) {
310 setlocale(LC_ALL, $_COOKIE['lang']);
311 putenv("LANGUAGE=".$_COOKIE['lang']);
313 setlocale(LC_ALL, 'en_US');
315 bindtextdomain('amp','./i18n');
316 bind_textdomain_codeset('amp', 'utf8');
322 // systems running on sqlite3 (or pgsql) this function is not available
323 // instead of changing the whole code, lets hack our own version of this function.
324 // according to the documentation found here: http://il2.php.net/mysql_real_escape_string
325 // this shold be enough.
326 // Fixes ticket: http://freepbx.org/trac/ticket/1963
327 if (!function_exists('mysql_real_escape_string')) {
328 function mysql_real_escape_string($str) {
329 $str = str_replace( "\x00", "\\" . "\x00", $str );
330 $str = str_replace( "\x1a", "\\" . "\x1a", $str );
331 $str = str_replace( "\n" , "\\". "\n" , $str );
332 $str = str_replace( "\r" , "\\". "\r" , $str );
333 $str = str_replace( "\\" , "\\". "\\" , $str );
334 $str = str_replace( "'" , "''" , $str );
335 $str = str_replace( '"' , '""' , $str );
340 // include base functions
342 require_once($amp_conf['AMPWEBROOT']."/admin/functions.inc.php");
343 require_once($amp_conf['AMPWEBROOT']."/admin/common/php-asmanager.php");
344 $amp_conf = parse_amportal_conf($amportalconf);
345 if (count($amp_conf) == 0) {
348 $asterisk_conf_file = $amp_conf["ASTETCDIR"]."/asterisk.conf";
349 $asterisk_conf = parse_asterisk_conf($asterisk_conf_file);
351 ini_set('include_path',ini_get('include_path').':'.$amp_conf['AMPWEBROOT'].'/admin/:');
353 $astman = new AGI_AsteriskManager();
355 // attempt to connect to asterisk manager proxy
356 if (!isset($amp_conf["ASTMANAGERPROXYPORT"]) || !$res = $astman->connect("127.0.0.1:".$amp_conf["ASTMANAGERPROXYPORT"], $amp_conf["AMPMGRUSER"] , $amp_conf["AMPMGRPASS"])) {
357 // attempt to connect directly to asterisk, if no proxy or if proxy failed
358 if (!$res = $astman->connect("127.0.0.1:".$amp_conf["ASTMANAGERPORT"], $amp_conf["AMPMGRUSER"] , $amp_conf["AMPMGRPASS"])) {
359 // couldn't connect at all
363 // connect to database
364 require_once($amp_conf['AMPWEBROOT']."/admin/common/db_connect.php");
366 $nt = notifications::create($db);
368 $framework_asterisk_running = checkAstMan();
370 // get all enabled modules
371 // active_modules array used below and in drawselects function and genConf function
372 $active_modules = module_getinfo(false, MODULE_STATUS_ENABLED);
374 $fpbx_menu = array();
376 // pointer to current item in $fpbx_menu, if applicable
377 $cur_menuitem = null;
379 // add module sections to $fpbx_menu
381 if(is_array($active_modules)){
382 foreach($active_modules as $key => $module) {
383 //include module functions
384 if (is_file($amp_conf['AMPWEBROOT']."/admin/modules/{$key}/functions.inc.php")) {
385 require_once($amp_conf['AMPWEBROOT']."/admin/modules/{$key}/functions.inc.php");
388 // create an array of module sections to display
389 // stored as [items][$type][$category][$name] = $displayvalue
390 if (isset($module['items']) && is_array($module['items'])) {
391 // loop through the types
392 foreach($module['items'] as $itemKey => $item) {
394 if (!$framework_asterisk_running &&
395 ((isset($item['needsenginedb']) && strtolower($item['needsenginedb'] == 'yes')) ||
396 (isset($item['needsenginerunning']) && strtolower($item['needsenginerunning'] == 'yes')))
399 $item['disabled'] = true;
401 $item['disabled'] = false;
404 if (!in_array($item['type'], $types)) {
405 $types[] = $item['type'];
408 if (!isset($item['display'])) {
409 $item['display'] = $itemKey;
412 // reference to the actual module
413 $item['module'] =& $active_modules[$key];
415 // item is an assoc array, with at least array(module=> name=>, category=>, type=>, display=>)
416 $fpbx_menu[$itemKey] = $item;
418 // allow a module to replace our main index page
419 if (($item['display'] == 'index') && ($display == '')) {
423 // check current item
424 if ($display == $item['display']) {
425 // found current menuitem, make a reference to it
426 $cur_menuitem =& $fpbx_menu[$itemKey];
435 if(is_array($active_modules)){
436 foreach($active_modules as $key => $module) {
437 if (isset($module['items']) && is_array($module['items'])) {
438 foreach($module['items'] as $itemKey => $itemName) {
439 //list of potential _configpageinit functions
440 $initfuncname = $key . '_' . $itemKey . '_configpageinit';
441 if ( function_exists($initfuncname) ) {
442 $configpageinits[] = $initfuncname;
446 //check for module level (rather than item as above) _configpageinit function
447 $initfuncname = $key . '_configpageinit';
448 if ( function_exists($initfuncname) ) {
449 $configpageinits[] = $initfuncname;
454 // extensions vs device/users ... this is a bad design, but hey, it works
455 if (isset($amp_conf["AMPEXTENSIONS"]) && ($amp_conf["AMPEXTENSIONS"] == "deviceanduser")) {
456 unset($fpbx_menu["extensions"]);
458 unset($fpbx_menu["devices"]);
459 unset($fpbx_menu["users"]);
463 // Here we process the action and create the exten, mailbox or delete it.
466 $EXTEN_REQUEST = array (
467 'actions' => $actions,
469 'displayname' => $new_name,
470 'emergencycid' => '',
471 'outboundcid' => $new_outboundcid,
473 'dtmfmode' => 'auto',
474 'devicesecret' => $new_sip_secret,
475 'directdid' => $new_directdid,
478 $actions = explode('/',$EXTEN_REQUEST['actions']);
480 $actions_taken = false;
490 $dcontext = 'from-internal';
493 foreach ($EXTEN_REQUEST as $key => $value) {
514 echo "\nDumping core_users_get:";
515 $user_list = core_users_get($ext);
516 var_dump($user_list);
518 echo "\nDumping core_devices_get:";
519 $device_list = core_devices_get($ext);
520 var_dump($device_list);
522 echo "\nDumping voicemail_mailbox_get:";
523 $vm_list = voicemail_mailbox_get($ext);
530 fatal("No Extension provided (this should have been caught above, may be a bug");
539 if (in_array('addext', $actions) || in_array('addvm',$actions)) {
540 if ($displayname == '') {
543 if (isset($accountcode)) {
544 $_REQUEST['devinfo_accountcode'] = $accountcode;
546 if (!isset($devicesecret)) {
547 $devicesecret = $ext;
549 if ($mailbox == '') {
550 $mailbox = $ext.'@default';
552 $user_add_arr = array(
555 'name' => $displayname,
556 'directdid' => $directdid,
557 'outboundcid' => $outboundcid,
559 'record_out' => 'Never',
560 'record_in' => 'Never',
561 'callwaiting' => 'enabled',
564 'vmcontext' => 'default',
566 'vmpwd' => $new_vm_password,
569 'attach' => 'attach=no',
570 'saycid' => 'saycid=no',
571 'envelope' => 'envelope=no',
572 'delete' => 'delete=no',
575 // archaic code expects these in the REQUEST array ...
577 $_REQUEST['devinfo_secret'] = $devicesecret;
578 $_REQUEST['devinfo_dtmfmode'] = $dtmfmode;
579 $_REQUEST['devinfo_canreinvite'] = 'no';
580 $_REQUEST['devinfo_context'] = $dcontext;
581 $_REQUEST['devinfo_host'] = 'dynamic';
582 $_REQUEST['devinfo_type'] = 'friend';
583 $_REQUEST['devinfo_nat'] = 'yes';
584 $_REQUEST['devinfo_port'] = '5060';
585 $_REQUEST['devinfo_dial'] = 'SIP/'.$ext;
586 $_REQUEST['devinfo_mailbox'] = $mailbox;
588 } else if (in_array('modext', $actions)) {
589 $user_list = core_users_get($ext);
590 //var_dump($user_list);
591 if (!isset($user_list['extension'])) {
592 error("No such extension found: $ext");
595 $device_list = core_devices_get($ext);
596 //var_dump($device_list);
597 if (count($device_list) == 0) {
598 error("No such device found: $ext");
601 $vm_list = voicemail_mailbox_get($ext);
602 //var_dump($vm_list);
603 if (count($vm_list) == 0) {
604 error("No voicemail found for: $ext");
609 $user_list['name'] = $new_name;
610 $device_list['description'] = $new_name;
611 $vm_list['name'] = $new_name;
613 if ($param_sip_secret) {
614 $device_list['secret'] = $new_sip_secret;
616 if ($param_vm_password) {
617 $vm_list['pwd'] = $new_vm_password;
619 if ($param_directdid) {
620 $user_list['directdid'] = $new_directdid;
622 if ($param_outboundcid) {
623 $user_list['outboundcid'] = $new_outboundcid;
625 $user_mod_arr = array(
628 'name' => $user_list['name'],
629 'directdid' => $user_list['directdid'],
630 'outboundcid' => $user_list['outboundcid'],
631 'sipname' => $user_list['sipname'],
632 'record_out' => $user_list['record_out'],
633 'record_in' => $user_list['record_in'],
634 'callwaiting' => $user_list['callwaiting'],
637 'vmcontext' => $vm_list['vmcontext'],
638 'vmpwd' => $vm_list['pwd'],
639 'email' => $vm_list['email'],
640 'pager' => $vm_list['pager'],
642 'attach' => $vm_list['options']['attach'],
643 'saycid' => $vm_list['options']['saycid'],
644 'envelope' => $vm_list['options']['envelope'],
645 'delete' => $vm_list['options']['delete'],
648 // archaic code expects these in the REQUEST array ...
650 $_REQUEST['devinfo_secret'] = $device_list['secret'];
651 $_REQUEST['devinfo_dtmfmode'] = $device_list['dtmfmode'];
652 $_REQUEST['devinfo_canreinvite'] = $device_list['canreinvite'];
653 $_REQUEST['devinfo_context'] = $device_list['context'];
654 $_REQUEST['devinfo_host'] = $device_list['host'];
655 $_REQUEST['devinfo_type'] = $device_list['type'];
656 $_REQUEST['devinfo_nat'] = $device_list['nat'];
657 $_REQUEST['devinfo_port'] = $device_list['port'];
658 $_REQUEST['devinfo_dial'] = $device_list['dial'];
659 $_REQUEST['devinfo_mailbox'] = $device_list['mailbox'];
660 $_REQUEST['devinfo_accountcode'] = $device_list['accountcode'];
661 $_REQUEST['devinfo_username'] = $ext;
662 //$_REQUEST['devinfo_callerid'] = $device_list['callerid'];
663 //$_REQUEST['devinfo_record_in'] = $device_list['record_in'];
664 //$_REQUEST['devinfo_record_out'] = $device_list['record_out'];
666 if (isset($device_list['qualify'])) {
667 $_REQUEST['devinfo_qualify'] = $device_list['qualify'];
669 if (isset($device_list['callgroup'])) {
670 $_REQUEST['devinfo_callgroup'] = $device_list['callgroup'];
672 if (isset($device_list['pickupgroup'])) {
673 $_REQUEST['devinfo_pickupgroup'] = $device_list['pickupgroup'];
675 if (isset($device_list['allow'])) {
676 $_REQUEST['devinfo_allow'] = $device_list['allow'];
678 if (isset($device_list['disallow'])) {
679 $_REQUEST['devinfo_disallow'] = $device_list['disallow'];
682 $actions_taken = true;
683 debug("core_users_edit($ext, $user_add_arr)");
684 core_users_edit($ext, $user_mod_arr);
685 // doesn't return a return code, so hope it worked:-)
687 debug("core_devices_del($ext, true)");
688 debug("core_devices_add($ext,'sip',".$device_list['dial'].",'fixed',$ext,".$device_list['description'].",".$device_list['emergency_cid'].",true)");
689 core_devices_del($ext,true);
690 core_devices_add($ext,'sip',$device_list['dial'],'fixed',$ext,$device_list['description'],$device_list['emergency_cid'],true);
691 // doesn't return a return code, so hope it worked:-)
693 debug("voicemail_mailbox_del($ext)");
694 debug("voicemail_mailbox_add($ext, $user_mod_arr)");
695 voicemail_mailbox_del($ext);
696 voicemail_mailbox_add($ext, $user_mod_arr);
699 if (in_array('addvm', $actions)) {
700 $actions_taken = true;
701 if (($existing_vmbox = voicemail_mailbox_get($ext)) == null ) {
702 debug("voicemail_mailbox_add($ext, $user_add_arr)");
703 voicemail_mailbox_add($ext, $user_add_arr);
705 debug(print_r($existing_vmbox,true));
706 fatal("voicemail_mailbox_get($ext) indicates the box already exists, aborting");
710 // check if we need to create symlink if if addext is not being called
711 if (!in_array('addext', $actions)) {
713 $thisUser = core_users_get($ext);
715 // This is a bit kludgey, the other way is to reformat the core_users_get() info and do a core_users_add() in edit mode
717 if (!empty($thisUser)) {
718 $this_vmcontext = $user_add_arr['vmcontext'];
719 sql("UPDATE `users` SET `voicemail` = '$this_vmcontext' WHERE `extension` = '$ext'");
722 $astman->database_put("AMPUSER",$ext."/voicemail","\"".isset($this_vmcontext)?$this_vmcontext:''."\"");
726 if(isset($this_vmcontext) && $this_vmcontext != "novm") {
727 if(empty($this_vmcontext)) {
728 $vmcontext = "default";
730 $vmcontext = $this_vmcontext;
734 exec("rm -f /var/spool/asterisk/voicemail/device/".$ext,$output,$return_val);
735 exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$ext."/ /var/spool/asterisk/voicemail/device/".$ext,$output,$return_val);
736 if ($return_val != 0) {
737 error("Error code $return_val when sym-linking vmail context $vmcontext to device directory for $ext. Trying to carry on but you should investigate.");
743 if (in_array('addext', $actions)) {
744 $actions_taken = true;
745 $any_users = core_users_get($ext);
746 debug("core_users_add($user_add_arr)");
747 if (isset($any_users['extension']) || !core_users_add($user_add_arr)) {
748 var_dump($any_users);
749 fatal("Attempt to add user failed, aborting");
754 if (in_array('addext', $actions)) {
755 $actions_taken = true;
756 debug("core_devices_add($ext, $tech, '', 'fixed', $ext, $displayname, $emergencycid)");
757 $any_devices = core_devices_get($ext);
758 if (count($any_devices) > 0 || !core_devices_add($ext, $tech, '', 'fixed', $ext, $displayname, $emergencycid)) {
759 var_dump($any_devices);
760 fatal("Attempt to add device failed, aborting");
765 if (in_array('remext', $actions)) {
766 $actions_taken = true;
767 if (core_users_get($ext) != null) {
768 debug("removing user $ext");
769 core_users_del($ext);
770 core_devices_del($ext);
772 debug("not removing user $ext");
774 if (voicemail_mailbox_get($ext) != null) {
775 debug("removing vm $ext");
776 voicemail_mailbox_del($ext);
778 debug("not removing vm $ext");
782 if ($actions_taken) {
783 debug("Request completed successfully");
786 warning("No actions were performed");