· 10 years ago · Mar 18, 2016, 05:11 AM
1<?php /* $id$ */
2//Copyright (C) 2004 Coalescent Systems Inc. (info@coalescentsystems.ca)
3//
4//This program is free software; you can redistribute it and/or
5//modify it under the terms of the GNU General Public License
6//as published by the Free Software Foundation; either version 2
7//of the License, or (at your option) any later version.
8//
9//This program is distributed in the hope that it will be useful,
10//but WITHOUT ANY WARRANTY; without even the implied warranty of
11//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12//GNU General Public License for more details.
13
14require_once('featurecodes.class.php');
15
16function parse_amportal_conf($filename) {
17 $file = file($filename);
18 foreach ($file as $line) {
19 if (preg_match("/^\s*([a-zA-Z0-9]+)=([a-zA-Z0-9 .&-@=_<>\"\']+)\s*$/",$line,$matches)) {
20 $conf[ $matches[1] ] = $matches[2];
21 }
22 }
23
24 if ( !isset($conf["AMPDBENGINE"]) || ($conf["AMPDBENGINE"] == ""))
25 {
26 $conf["AMPDBENGINE"] = "mysql";
27 }
28
29/*
30 if (($amp_conf["AMPDBENGINE"] == "sqlite") && (!isset($amp_conf["AMPDBENGINE"])))
31 $amp_conf["AMPDBFILE"] = "/var/lib/freepbx/freepbx.sqlite";
32*/
33
34 return $conf;
35}
36
37function parse_asterisk_conf($filename) {
38 $file = file($filename);
39 foreach ($file as $line) {
40 if (preg_match("/^\s*([a-zA-Z0-9]+)\s* => \s*(.*)\s*([;#].*)?/",$line,$matches)) {
41 $conf[ $matches[1] ] = $matches[2];
42 }
43 }
44 return $conf;
45}
46
47function getAmpAdminUsers() {
48 global $db;
49
50 $sql = "SELECT username FROM ampusers WHERE sections='*'";
51 $results = $db->getAll($sql);
52 if(DB::IsError($results)) {
53 die($results->getMessage());
54 }
55 return $results;
56}
57
58function getAmpUser($username) {
59 global $db;
60
61 $sql = "SELECT username, password, extension_low, extension_high, deptname, sections FROM ampusers WHERE username = '".$username."'";
62 $results = $db->getAll($sql);
63 if(DB::IsError($results)) {
64 die($results->getMessage());
65 }
66
67 if (count($results) > 0) {
68 $user = array();
69 $user["username"] = $results[0][0];
70 $user["password"] = $results[0][1];
71 $user["extension_low"] = $results[0][2];
72 $user["extension_high"] = $results[0][3];
73 $user["deptname"] = $results[0][4];
74 $user["sections"] = explode(";",$results[0][5]);
75 return $user;
76 } else {
77 return false;
78 }
79}
80
81class ampuser {
82 var $username;
83 var $_password;
84 var $_extension_high;
85 var $_extension_low;
86 var $_deptname;
87 var $_sections;
88
89 function ampuser($username) {
90 $this->username = $username;
91 if ($user = getAmpUser($username)) {
92 $this->_password = $user["password"];
93 $this->_extension_high = $user["extension_high"];
94 $this->_extension_low = $user["extension_low"];
95 $this->_deptname = $user["deptname"];
96 $this->_sections = $user["sections"];
97 } else {
98 // user doesn't exist
99 $this->_password = false;
100 $this->_extension_high = "";
101 $this->_extension_low = "";
102 $this->_deptname = "";
103 $this->_sections = array();
104 }
105 }
106
107 /** Give this user full admin access
108 */
109 function setAdmin() {
110 $this->_extension_high = "";
111 $this->_extension_low = "";
112 $this->_deptname = "";
113 $this->_sections = array("*");
114 }
115
116 function checkPassword($password) {
117 // strict checking so false will never match
118 return ($this->_password === $password);
119 }
120
121 function checkSection($section) {
122 // if they have * then it means all sections
123 return in_array("*", $this->_sections) || in_array($section, $this->_sections);
124 }
125}
126
127// returns true if extension is within allowed range
128function checkRange($extension){
129 $low = isset($_SESSION["AMP_user"]->_extension_low)?$_SESSION["AMP_user"]->_extension_low:'';
130 $high = isset($_SESSION["AMP_user"]->_extension_high)?$_SESSION["AMP_user"]->_extension_high:'';
131
132 if ((($extension >= $low) && ($extension <= $high)) || ($low == '' && $high == ''))
133 return true;
134 else
135 return false;
136}
137
138// returns true if department string matches dept for this user
139function checkDept($dept){
140 $deptname = isset($_SESSION["AMP_user"])?$_SESSION["AMP_user"]:null;
141
142 if ( ($dept == null) || ($dept == $deptname) )
143 return true;
144 else
145 return false;
146}
147
148/* look for all modules in modules dir.
149** returns array:
150** array['module']['displayName']
151** array['module']['version']
152** array['module']['type']
153** array['module']['status']
154** array['module']['items'][array(items)]
155** Use find_modules() to return only specific type or status
156*/
157
158/*
159function find_allmodules() {
160 global $db;
161 global $amp_conf;
162
163 $dir = opendir($amp_conf['AMPWEBROOT'].'/admin/modules');
164 //loop through each module directory, ensure there is a module.ini file
165 while ($file = readdir($dir)) {
166 if (($file != ".") && ($file != "..") && ($file != "CVS") && ($file != ".svn") && is_dir($amp_conf['AMPWEBROOT'].'/admin/modules/'.$file) && is_file($amp_conf['AMPWEBROOT'].'/admin/modules/'.$file.'/module.ini')) {
167 //open module.ini and read contents
168 $inifile = file($amp_conf['AMPWEBROOT'].'/admin/modules/'.$file.'/module.ini');
169 foreach ($inifile as $line) {
170 // parse the module display name and version from module.ini
171 if (preg_match("/^\s*([a-zA-Z0-9]+)=([a-zA-Z0-9 .&-@=_<>\"\']+)\s*$/",$line,$matches)) {
172 if (trim($matches[1]) == "name")
173 $mod[ $file ]['displayName'] = $matches[2];
174 else if (trim($matches[1]) == "version")
175 $mod[ $file ]['version'] = $matches[2];
176 else if (trim($matches[1]) == "type")
177 $mod[ $file ]['type'] = $matches[2];
178 else if (trim($matches[1]) == "category")
179 $mod[ $file ]['category'] = $matches[2];
180 else
181 $mod[ $file ]['items'][ $matches[1] ] = $matches[2];
182 }
183 // determine details about this module from database
184 // modulename should match the directory name
185 $sql = "SELECT * FROM modules WHERE modulename = '".$file."'";
186 $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
187 if(DB::IsError($results)) {
188 die($results->getMessage());
189 }
190 //set status key based on results (0=not installed, 1=disabled, 2=enabled)
191 if ($results) {
192 if ($results['enabled'] != 0)
193 $mod[ $file ]["status"] = 2;
194 else
195 $mod[ $file ]["status"] = 1;
196 } else {
197 $mod[ $file ]["status"] = 0;
198 }
199 }
200 }
201 }
202 return $mod;
203} */
204
205
206/* look for all modules in modules dir.
207** returns array:
208** array['module']['displayName']
209** array['module']['version']
210** array['module']['type']
211** array['module']['status']
212** array['module']['items'][array(items)]
213** Use find_modules() to return only specific type or status
214*/
215function find_allmodules() {
216 global $db;
217 global $amp_conf;
218 $dir = opendir($amp_conf['AMPWEBROOT'].'/admin/modules');
219 $data = "<xml>";
220 //loop through each module directory, ensure there is a module.ini file
221 while ($file = readdir($dir)) {
222 if (($file != ".") && ($file != "..") && ($file != "CVS") && ($file != ".svn") && is_dir($amp_conf['AMPWEBROOT'].'/admin/modules/'.$file) && is_file($amp_conf['AMPWEBROOT'].'/admin/modules/'.$file.'/module.xml')) {
223 //open module.xml and read contents
224 if(is_file($amp_conf['AMPWEBROOT'].'/admin/modules/'.$file.'/module.xml')){
225 $data .=file_get_contents($amp_conf['AMPWEBROOT'].'/admin/modules/'.$file.'/module.xml');
226
227 }
228 }
229 }
230 $data .= "</xml>";
231 $parser = new xml2ModuleArray($data);
232 $xmlarray = $parser->parseModulesXML($data);
233
234 // determine details about this module from database
235 // modulename should match the directory name
236 $sql = "SELECT * FROM modules";
237 $results = $db->getAll($sql,DB_FETCHMODE_ASSOC);
238 if(DB::IsError($results)) {
239 die($results->getMessage());
240 }
241
242 if (is_array($results)) {
243 foreach($results as $result) {
244 /*
245 set status key based on results
246 -1=broken (in table, not not on filesystem)
247 0 or null=not installed
248 1=disabled
249 2=enabled
250 3=enabled and needs upgrade
251 */
252 if(isset($xmlarray[ $result['modulename'] ] ) && is_array($xmlarray[ $result['modulename'] ])) {
253 if ($result['enabled'] != 0) {
254 // check if file and registered versions are the same
255 // version_compare returns 0 if no difference
256 if (version_compare($result['version'],$xmlarray[ $result['modulename'] ]["version"]) === 0)
257 $xmlarray[ $result['modulename'] ]["status"] = 2;
258 else
259 $xmlarray[ $result['modulename'] ]["status"] = 3;
260 } else {
261 $xmlarray[ $result['modulename'] ]["status"] = 1;
262 }
263 } else {
264 $xmlarray[ $result['modulename'] ]["status"] = -1;
265 }
266
267 }
268 }
269
270 //echo "<pre>"; print_r($xmlarray); echo "</pre>";
271 return $xmlarray;
272}
273
274/* finds modules of the specified status and type
275** $status can be 0 (not installed), 1 (disabled), 2 (enabled)
276** $type can be 'setup' or 'tool'
277**
278** returns array:
279** array['module']['displayName']
280** array['module']['version']
281** array['module']['type']
282** array['module']['status']
283** array['module']['items'][array(items)]
284*/
285function find_modules($status,$type) {
286 $modules = find_allmodules();
287 //$return_modules = $modules;
288 // add only modules of type=$status
289 foreach(array_keys($modules) as $key) {
290 //remove modules not matching status or type
291 if(isset($modules[$key]['status']) && $modules[$key]['status'] == $status && isset($modules[$key]['type']) && $modules[$key]['type'] == $type) {
292 $return_modules[$key] = $modules[$key];
293 }
294 }
295 return $return_modules;
296}
297
298
299// This returns the version of a module
300function modules_getversion($modname) {
301 global $db;
302
303 $sql = "SELECT version FROM modules WHERE modulename = '$modname'";
304 $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
305 if (isset($results['version']))
306 return $results['version'];
307 else
308 return null;
309}
310
311// I bet you can't guess what this one does.
312function modules_setversion($modname, $vers) {
313 global $db;
314
315 return sql("UPDATE modules SET version='$vers' WHERE modulename = '$modname'");
316}
317
318
319/* queries database using PEAR.
320* $type can be query, getAll, getRow, getCol, getOne, etc
321* $fetchmode can be DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC, DB_FETCHMODE_OBJECT
322* returns array, unless using getOne
323*/
324function sql($sql,$type="query",$fetchmode=null) {
325 global $db;
326 $results = $db->$type($sql,$fetchmode);
327 if(DB::IsError($results)) {
328 die($results->getDebugInfo());
329 }
330 return $results;
331}
332
333// sql text formatting -- couldn't see that one was available already
334function sql_formattext($txt) {
335 if (isset($txt)) {
336 $fmt = str_replace("'", "''", $txt);
337 $fmt = "'" . $fmt . "'";
338 } else {
339 $fmt = 'null';
340 }
341
342 return $fmt;
343}
344
345//tell application we need to reload asterisk
346function needreload() {
347 global $db;
348 $sql = "UPDATE admin SET value = 'true' WHERE variable = 'need_reload'";
349 $result = $db->query($sql);
350 if(DB::IsError($result)) {
351 die($result->getMessage());
352 }
353}
354
355//get the version number
356function getversion() {
357 global $db;
358 $sql = "SELECT value FROM admin WHERE variable = 'version'";
359 $results = $db->getAll($sql);
360 if(DB::IsError($results)) {
361 die($results->getMessage());
362 }
363 return $results;
364}
365
366// draw list for users and devices with paging
367function drawListMenu($results, $skip, $dispnum, $extdisplay, $description) {
368 $perpage=20;
369
370 $skipped = 0;
371 $index = 0;
372 if ($skip == "") $skip = 0;
373 echo "<li><a id=\"".($extdisplay=='' ? 'current':'')."\" href=\"config.php?display=".$dispnum."\">"._("Add")." ".$description."</a></li>";
374
375 if (isset($results)) {
376
377 foreach ($results AS $key=>$result) {
378 if ($index >= $perpage) {
379 $shownext= 1;
380 break;
381 }
382 if ($skipped<$skip && $skip!= 0) {
383 $skipped= $skipped + 1;
384 continue;
385 }
386 $index= $index + 1;
387
388 echo "<li><a id=\"".($extdisplay==$result[0] ? 'current':'')."\" href=\"config.php?display=".$dispnum."&extdisplay={$result[0]}&skip={$skip}\">{$result[1]} <{$result[0]}></a></li>";
389
390 }
391 }
392
393 if ($index >= $perpage) {
394
395 print "<li><center>";
396
397 }
398
399 if ($skip) {
400
401 $prevskip= $skip - $perpage;
402 if ($prevskip<0) $prevskip= 0;
403 $prevtag_pre= "<a href='?display=".$dispnum."&skip=$prevskip'>[PREVIOUS]</a>";
404 print "$prevtag_pre";
405 }
406 if (isset($shownext)) {
407
408 $nextskip= $skip + $index;
409 if ($prevtag_pre) $prevtag .= " | ";
410 print "$prevtag <a href='?display=".$dispnum."&skip=$nextskip'>[NEXT]</a>";
411 }
412 elseif ($skip) {
413 print "$prevtag";
414 }
415
416 print "</center></li>";
417
418}
419
420// this function simply makes a connection to the asterisk manager, and should be called by modules that require it (ie: dbput/dbget)
421function checkAstMan() {
422 require_once('common/php-asmanager.php');
423 global $amp_conf;
424 $astman = new AGI_AsteriskManager();
425 if ($res = $astman->connect("127.0.0.1", $amp_conf["AMPMGRUSER"] , $amp_conf["AMPMGRPASS"])) {
426 return $astman->disconnect();
427 } else {
428 echo "<h3>Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]."</h3>This module requires access to the Asterisk Manager. Please ensure Asterisk is running and access to the manager is available.</div>";
429 exit;
430 }
431}
432
433
434/** Recursively read voicemail.conf (and any included files)
435 * This function is called by getVoicemailConf()
436 */
437function parse_voicemailconf($filename, &$vmconf, &$section) {
438 if (is_null($vmconf)) {
439 $vmconf = array();
440 }
441 if (is_null($section)) {
442 $section = "general";
443 }
444
445 if (file_exists($filename)) {
446 $fd = fopen($filename, "r");
447 while ($line = fgets($fd, 1024)) {
448 if (preg_match("/^\s*(\d+)\s*=>\s*(\d*),(.*),(.*),(.*),(.*)\s*([;#].*)?/",$line,$matches)) {
449 // "mailbox=>password,name,email,pager,options"
450 // this is a voicemail line
451 $vmconf[$section][ $matches[1] ] = array("mailbox"=>$matches[1],
452 "pwd"=>$matches[2],
453 "name"=>$matches[3],
454 "email"=>$matches[4],
455 "pager"=>$matches[5],
456 "options"=>array(),
457 );
458
459 // parse options
460 //output($matches);
461 foreach (explode("|",$matches[6]) as $opt) {
462 $temp = explode("=",$opt);
463 //output($temp);
464 if (isset($temp[1])) {
465 list($key,$value) = $temp;
466 $vmconf[$section][ $matches[1] ]["options"][$key] = $value;
467 }
468 }
469 } else if (preg_match("/^\s*(\d+)\s*=>\s*dup,(.*)\s*([;#].*)?/",$line,$matches)) {
470 // "mailbox=>dup,name"
471 // duplace name line
472 $vmconf[$section][ $matches[1] ]["dups"][] = $matches[2];
473 } else if (preg_match("/^\s*#include\s+(.*)\s*([;#].*)?/",$line,$matches)) {
474 // include another file
475
476 if ($matches[1][0] == "/") {
477 // absolute path
478 $filename = $matches[1];
479 } else {
480 // relative path
481 $filename = dirname($filename)."/".$matches[1];
482 }
483
484 parse_voicemailconf($filename, $vmconf, $section);
485
486 } else if (preg_match("/^\s*\[(.+)\]/",$line,$matches)) {
487 // section name
488 $section = strtolower($matches[1]);
489 } else if (preg_match("/^\s*([a-zA-Z0-9-_]+)\s*=\s*(.*?)\s*([;#].*)?$/",$line,$matches)) {
490 // name = value
491 // option line
492 $vmconf[$section][ $matches[1] ] = $matches[2];
493 }
494 }
495 fclose($fd);
496 }
497}
498
499function getVoicemail() {
500 $vmconf = null;
501 $section = null;
502
503 // yes, this is hardcoded.. is this a bad thing?
504 parse_voicemailconf("/etc/asterisk/voicemail.conf", $vmconf, $section);
505
506 return $vmconf;
507}
508
509/** Write the voicemail.conf file
510 * This is called by saveVoicemail()
511 * It's important to make a copy of $vmconf before passing it. Since this is a recursive function, has to
512 * pass by reference. At the same time, it removes entries as it writes them to the file, so if you don't have
513 * a copy, by the time it's done $vmconf will be empty.
514*/
515function write_voicemailconf($filename, &$vmconf, &$section, $iteration = 0) {
516 if ($iteration == 0) {
517 $section = null;
518 }
519
520 $output = array();
521
522 if (file_exists($filename)) {
523 $fd = fopen($filename, "r");
524 while ($line = fgets($fd, 1024)) {
525 if (preg_match("/^(\s*)(\d+)(\s*)=>(\s*)(\d*),(.*),(.*),(.*),(.*)(\s*[;#].*)?$/",$line,$matches)) {
526 // "mailbox=>password,name,email,pager,options"
527 // this is a voicemail line
528 //DEBUG echo "\nmailbox";
529
530 // make sure we have something as a comment
531 if (!isset($matches[10])) {
532 $matches[10] = "";
533 }
534
535 // $matches[1] [3] and [4] are to preserve indents/whitespace, we add these back in
536
537 if (isset($vmconf[$section][ $matches[2] ])) {
538 // we have this one loaded
539 // repopulate from our version
540 $temp = & $vmconf[$section][ $matches[2] ];
541
542 $options = array();
543 foreach ($temp["options"] as $key=>$value) {
544 $options[] = $key."=".$value;
545 }
546
547 $output[] = $matches[1].$temp["mailbox"].$matches[3]."=>".$matches[4].$temp["pwd"].",".$temp["name"].",".$temp["email"].",".$temp["pager"].",". implode("|",$options).$matches[10];
548
549 // remove this one from $vmconf
550 unset($vmconf[$section][ $matches[2] ]);
551 } else {
552 // we don't know about this mailbox, so it must be deleted
553 // (and hopefully not JUST added since we did read_voiceamilconf)
554
555 // do nothing
556 }
557
558 } else if (preg_match("/^(\s*)(\d+)(\s*)=>(\s*)dup,(.*)(\s*[;#].*)?$/",$line,$matches)) {
559 // "mailbox=>dup,name"
560 // duplace name line
561 // leave it as-is (for now)
562 //DEBUG echo "\ndup mailbox";
563 $output[] = $line;
564 } else if (preg_match("/^(\s*)#include(\s+)(.*)(\s*[;#].*)?$/",$line,$matches)) {
565 // include another file
566 //DEBUG echo "\ninclude ".$matches[3]."<blockquote>";
567
568 // make sure we have something as a comment
569 if (!isset($matches[4])) {
570 $matches[4] = "";
571 }
572
573 if ($matches[3][0] == "/") {
574 // absolute path
575 $include_filename = $matches[3];
576 } else {
577 // relative path
578 $include_filename = dirname($filename)."/".$matches[3];
579 }
580
581 $output[] = $matches[1]."#include".$matches[2].$matches[3].$matches[4];
582 write_voicemailconf($include_filename, $vmconf, $section, $iteration+1);
583
584 //DEBUG echo "</blockquote>";
585
586 } else if (preg_match("/^(\s*)\[(.+)\](\s*[;#].*)?$/",$line,$matches)) {
587 // section name
588 //DEBUG echo "\nsection";
589
590 // make sure we have something as a comment
591 if (!isset($matches[3])) {
592 $matches[3] = "";
593 }
594
595 // check if this is the first run (section is null)
596 if ($section !== null) {
597 // we need to add any new entries here, before the section changes
598 //DEBUG echo "<blockquote><i>";
599 //DEBUG var_dump($vmconf[$section]);
600 if (isset($vmconf[$section])){ //need this, or we get an error if we unset the last items in this section - should probably automatically remove the section/context from voicemail.conf
601 foreach ($vmconf[$section] as $key=>$value) {
602 if (is_array($value)) {
603 // mailbox line
604
605 $temp = & $vmconf[$section][ $key ];
606
607 $options = array();
608 foreach ($temp["options"] as $key1=>$value) {
609 $options[] = $key1."=".$value;
610 }
611
612 $output[] = $temp["mailbox"]." => ".$temp["pwd"].",".$temp["name"].",".$temp["email"].",".$temp["pager"].",". implode("|",$options);
613
614 // remove this one from $vmconf
615 unset($vmconf[$section][ $key ]);
616
617 } else {
618 // option line
619
620 $output[] = $key."=".$vmconf[$section][ $key ];
621
622 // remove this one from $vmconf
623 unset($vmconf[$section][ $key ]);
624 }
625 }
626 }
627 //DEBUG echo "</i></blockquote>";
628 }
629
630 $section = strtolower($matches[2]);
631 $output[] = $matches[1]."[".$section."]".$matches[3];
632 $existing_sections[] = $section; //remember that this section exists
633
634 } else if (preg_match("/^(\s*)([a-zA-Z0-9-_]+)(\s*)=(\s*)(.*?)(\s*[;#].*)?$/",$line,$matches)) {
635 // name = value
636 // option line
637 //DEBUG echo "\noption line";
638
639
640 // make sure we have something as a comment
641 if (!isset($matches[6])) {
642 $matches[6] = "";
643 }
644
645 if (isset($vmconf[$section][ $matches[2] ])) {
646 $output[] = $matches[1].$matches[2].$matches[3]."=".$matches[4].$vmconf[$section][ $matches[2] ].$matches[6];
647
648 // remove this one from $vmconf
649 unset($vmconf[$section][ $matches[2] ]);
650 }
651 // else it's been deleted, so we don't write it in
652
653 } else {
654 // unknown other line -- probably a comment or whitespace
655 //DEBUG echo "\nother: ".$line;
656
657 $output[] = str_replace(array("\n","\r"),"",$line); // str_replace so we don't double-space
658 }
659 }
660
661 if ($iteration == 0) {
662 // we need to add any new entries here, since it's the end of the file
663 //DEBUG echo "END OF FILE!! <blockquote><i>";
664 //DEBUG var_dump($vmconf);
665 foreach (array_keys($vmconf) as $section) {
666 if (!in_array($section,$existing_sections)) // If this is a new section, write the context label
667 $output[] = "[".$section."]";
668 foreach ($vmconf[$section] as $key=>$value) {
669 if (is_array($value)) {
670 // mailbox line
671
672 $temp = & $vmconf[$section][ $key ];
673
674 $options = array();
675 foreach ($temp["options"] as $key=>$value) {
676 $options[] = $key."=".$value;
677 }
678
679 $output[] = $temp["mailbox"]." => ".$temp["pwd"].",".$temp["name"].",".$temp["email"].",".$temp["pager"].",". implode("|",$options);
680
681 // remove this one from $vmconf
682 unset($vmconf[$section][ $key ]);
683
684 } else {
685 // option line
686
687 $output[] = $key."=".$vmconf[$section][ $key ];
688
689 // remove this one from $vmconf
690 unset($vmconf[$section][$key ]);
691 }
692 }
693 }
694 //DEBUG echo "</i></blockquote>";
695 }
696
697 fclose($fd);
698
699 //DEBUG echo "\n\nwriting ".$filename;
700 //DEBUG echo "\n-----------\n";
701 //DEBUG echo implode("\n",$output);
702 //DEBUG echo "\n-----------\n";
703
704 // write this file back out
705
706 if ($fd = fopen($filename, "w")) {
707 fwrite($fd, implode("\n",$output)."\n");
708 fclose($fd);
709 }
710
711 }
712}
713
714function saveVoicemail($vmconf) {
715 // yes, this is hardcoded.. is this a bad thing?
716 write_voicemailconf("/etc/asterisk/voicemail.conf", $vmconf, $section);
717}
718
719
720// $goto is the current goto destination setting
721// $i is the destination set number (used when drawing multiple destination sets in a single form ie: digital receptionist)
722// esnure that any form that includes this calls the setDestinations() javascript function on submit.
723// ie: if the form name is "edit", and drawselects has been called with $i=2 then use onsubmit="setDestinations(edit,2)"
724function drawselects($goto,$i) {
725
726 /* --- MODULES BEGIN --- */
727 global $active_modules;
728
729 // This is purely to remove a warning.
730 if (!isset($selectHtml)) { $selectHtml=''; }
731 $selectHtml .= '<tr><td colspan=2>';
732
733 //check for module-specific destination functions
734 foreach ($active_modules as $mod => $displayname) {
735 $funct = strtolower($mod.'_destinations');
736
737 //if the modulename_destinations() function exits, run it and display selections for it
738 if (function_exists($funct)) {
739 $options = "";
740 $destArray = $funct(); //returns an array with 'destination' and 'description'.
741 $checked = false;
742 if (isset($destArray)) {
743 //loop through each option returned by the module
744 foreach ($destArray as $dest) {
745 // check to see if the currently selected goto matches one these destinations
746 if ($dest['destination'] == $goto)
747 $checked = true; //there is a match, so we select the radio for this group
748
749 // create an select option for each destination
750 $options .= '<option value="'.$dest['destination'].'" '.(strpos($goto,$dest['destination']) === false ? '' : 'SELECTED').'>'.($dest['description'] ? $dest['description'] : $dest['destination']);
751 }
752 $selectHtml .= '<input type="radio" name="goto_indicate'.$i.'" value="'.$mod.'" onclick="javascript:this.form.goto'.$i.'.value=\''.$mod.'\';" onkeypress="javascript:if (event.keyCode == 0 || (document.all && event.keyCode == 13)) this.form.goto'.$i.'.value=\''.$mod.'\';" '.($checked? 'CHECKED=CHECKED' : '').' /> '._($displayname['displayName']).': ';
753 if ($checked) { $goto = $mod; }
754 $selectHtml .= '<select name="'.$mod.$i.'"/>';
755 $selectHtml .= $options;
756 $selectHtml .= "</select><br>\n";
757 }
758
759 }
760 }
761 /* --- MODULES END --- */
762
763 //display a custom goto field
764 $selectHtml .= '<input type="radio" name="goto_indicate'.$i.'" value="custom" onclick="javascript:this.form.goto'.$i.'.value=\'custom\';" onkeypress="javascript:if (event.keyCode == 0 || (document.all && event.keyCode == 13)) this.form.goto'.$i.'.value=\'custom\';" '.(strpos($goto,'custom') === false ? '' : 'CHECKED=CHECKED').' />';
765 $selectHtml .= '<a href="#" class="info"> '._("Custom App<span><br>ADVANCED USERS ONLY<br><br>Uses Goto() to send caller to a custom context.<br><br>The context name <b>MUST</b> contain the word 'custom' and should be in the format custom-context , extension , priority. Example entry:<br><br><b>custom-myapp,s,1</b><br><br>The <b>[custom-myapp]</b> context would need to be created and included in extensions_custom.conf</span>").'</a>:';
766 $selectHtml .= '<input type="text" size="15" name="custom'.$i.'" value="'.(strpos($goto,'custom') === false ? '' : $goto).'" />';
767 $selectHtml .= "\n<input type='hidden' name='goto$i' value='$goto'>";
768
769 //close off our row
770 $selectHtml .= '</td></tr>';
771
772 return $selectHtml;
773}
774
775
776/* below are legacy functions required to allow pre 2.0 modules to function (ie: interact with 'extensions' table) */
777
778 //add to extensions table - used in callgroups.php
779 function legacy_extensions_add($addarray) {
780 global $db;
781 $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr, flags) VALUES ('".$addarray[0]."', '".$addarray[1]."', '".$addarray[2]."', '".$addarray[3]."', '".$addarray[4]."', '".$addarray[5]."' , '".$addarray[6]."')";
782 $result = $db->query($sql);
783 if(DB::IsError($result)) {
784 die($result->getMessage().$sql);
785 }
786 return $result;
787 }
788
789 //delete extension from extensions table
790 function legacy_extensions_del($context,$exten) {
791 global $db;
792 $sql = "DELETE FROM extensions WHERE context = '".$context."' AND `extension` = '".$exten."'";
793 $result = $db->query($sql);
794 if(DB::IsError($result)) {
795 die($result->getMessage());
796 }
797 return $result;
798 }
799
800
801 //get args for specified exten and priority - primarily used to grab goto destination
802 function legacy_args_get($exten,$priority,$context) {
803 global $db;
804 $sql = "SELECT args FROM extensions WHERE extension = '".$exten."' AND priority = '".$priority."' AND context = '".$context."'";
805 list($args) = $db->getRow($sql);
806 return $args;
807 }
808
809/* end legacy functions */
810
811/* Usage
812Grab some XML data, either from a file, URL, etc. however you want. Assume storage in $strYourXML;
813
814$objXML = new xml2Array();
815$arrOutput = $objXML->parse($strYourXML);
816print_r($arrOutput); //print it out, or do whatever!
817
818*/
819
820class xml2Array {
821
822 var $arrOutput = array();
823 var $resParser;
824 var $strXmlData;
825
826 function parse($strInputXML) {
827
828 $this->resParser = xml_parser_create ();
829 xml_set_object($this->resParser,$this);
830 xml_set_element_handler($this->resParser, "tagOpen", "tagClosed");
831
832 xml_set_character_data_handler($this->resParser, "tagData");
833
834 $this->strXmlData = xml_parse($this->resParser,$strInputXML );
835 if(!$this->strXmlData) {
836 die(sprintf("XML error: %s at line %d",
837 xml_error_string(xml_get_error_code($this->resParser)),
838 xml_get_current_line_number($this->resParser)));
839 }
840
841 xml_parser_free($this->resParser);
842
843 return $this->arrOutput;
844 }
845 function tagOpen($parser, $name, $attrs) {
846 $tag=array("name"=>$name,"attrs"=>$attrs);
847 array_push($this->arrOutput,$tag);
848 }
849
850 function tagData($parser, $tagData) {
851 if(trim($tagData)) {
852 if(isset($this->arrOutput[count($this->arrOutput)-1]['tagData'])) {
853 $this->arrOutput[count($this->arrOutput)-1]['tagData'] .= $tagData;
854 }
855 else {
856 $this->arrOutput[count($this->arrOutput)-1]['tagData'] = $tagData;
857 }
858 }
859 }
860
861 function tagClosed($parser, $name) {
862 $this->arrOutput[count($this->arrOutput)-2]['children'][] = $this->arrOutput[count($this->arrOutput)-1];
863 array_pop($this->arrOutput);
864 }
865}
866
867/*
868 Return a much more manageable assoc array with module data.
869*/
870class xml2ModuleArray extends xml2Array {
871 function parseModulesXML($strInputXML) {
872 $arrOutput = $this->parse($strInputXML);
873 // if you are confused about what's happening below, uncomment this why we do it
874 // echo "<pre>"; print_r($arrOutput); echo "</pre>";
875
876 // ignore the regular xml garbage ([0]['children']) & loop through each module
877 if(!is_array($arrOutput[0]['children'])) return false;
878 foreach($arrOutput[0]['children'] as $module) {
879 if(!is_array($module['children'])) return false;
880 // loop through each modules's tags
881 foreach($module['children'] as $modTags) {
882 if(isset($modTags['children']) && is_array($modTags['children'])) {
883 $$modTags['name'] = $modTags['children'];
884 // loop if there are children (menuitems and requirements)
885 foreach($modTags['children'] as $subTag) {
886 $subTags[strtolower($subTag['name'])] = $subTag['tagData'];
887 }
888 $$modTags['name'] = $subTags;
889 unset($subTags);
890 } else {
891 // create a variable for each tag we find
892 $$modTags['name'] = $modTags['tagData'];
893 }
894
895 }
896 // now build our return array
897 $arrModules[$RAWNAME]['rawname'] = $RAWNAME; // This has to be set
898 $arrModules[$RAWNAME]['displayName'] = $NAME; // This has to be set
899 $arrModules[$RAWNAME]['version'] = $VERSION; // This has to be set
900 $arrModules[$RAWNAME]['type'] = isset($TYPE)?$TYPE:'setup';
901 $arrModules[$RAWNAME]['category'] = isset($CATEGORY)?$CATEGORY:'Unknown';
902 $arrModules[$RAWNAME]['info'] = isset($INFO)?$INFO:'http://www.freepbx.org/wiki/'.$RAWNAME;
903 $arrModules[$RAWNAME]['location'] = isset($LOCATION)?$LOCATION:'local';
904 $arrModules[$RAWNAME]['items'] = isset($MENUITEMS)?$MENUITEMS:null;
905 $arrModules[$RAWNAME]['requirements'] = isset($REQUIREMENTS)?$REQUIREMENTS:null;
906 $arrModules[$RAWNAME]['md5sum'] = isset($MD5SUM)?$MD5SUM:null;
907 //print_r($arrModules);
908 //unset our variables
909 unset($NAME);
910 unset($VERSION);
911 unset($TYPE);
912 unset($CATEGORY);
913 unset($AUTHOR);
914 unset($EMAIL);
915 unset($LOCATION);
916 unset($MENUITEMS);
917 unset($REQUIREMENTS);
918 unset($MD5SUM);
919 }
920 //echo "<pre>"; print_r($arrModules); echo "</pre>";
921
922 return $arrModules;
923 }
924}
925
926
927
928class moduleHook {
929 var $hookHtml = '';
930 var $arrHooks = array();
931
932 function install_hooks($viewing_itemid,$target_module,$target_menuid = '') {
933 global $active_modules;
934 // loop through all active modules
935 foreach($active_modules as $this_module) {
936 // look for requested hooks for $module
937 // ie: findme_hook_extensions()
938 $funct = $this_module['rawname'] . '_hook_' . $target_module;
939 if( function_exists( $funct ) ) {
940 // execute the function, appending the
941 // html output to that of other hooking modules
942 if ($hookReturn = $funct($viewing_itemid,$target_menuid))
943 $this->hookHtml .= $hookReturn;
944 // remember who installed hooks
945 // we need to know this for processing form vars
946 $this->arrHooks[] = $this_module['rawname'];
947 }
948 }
949 }
950
951 // process the request from the module we hooked
952 function process_hooks($viewing_itemid, $target_module, $target_menuid, $request) {
953 if(is_array($this->arrHooks)) {
954 foreach($this->arrHooks as $hookingMod) {
955 // check if there is a processing function
956 $funct = $hookingMod . '_hookProcess_' . $target_module;
957 if( function_exists( $funct ) ) {
958 $funct($viewing_itemid, $request);
959 }
960 }
961 }
962 }
963}
964
965/*
966// just for testing hooks, i'll delete it later
967function queues_hook_core($viewing_itemid, $target_menuid) {
968 switch ($target_menuid) {
969 case 'did':
970 //get the current setting for this display (if any)
971 $alertinfo = $viewing_itemid;
972 return '
973 <tr>
974 <td><a href="#" class="info">'._("Alert Info").'<span>'._('ALERT_INFO can be used for distinctive ring with SIP devices.').'</span></a>:</td>
975 <td><input type="text" name="alertinfo" size="10" value="'.(($alertinfo) ? $alertinfo : "") .'"></td>
976 </tr>
977 ';
978 break;
979 default:
980 return false;
981 break;
982 }
983}
984
985function queues_hookProcess_core($viewing_itemid, $request) {
986 switch ($request['action']) {
987 case 'edtIncoming':
988 echo "<h1>HI</h1>";
989 return '
990 <tr>
991 <td><a href="#" class="info">'._("Alert Info").'<span>'._('ALERT_INFO can be used for distinctive ring with SIP devices.').'</span></a>:</td>
992 <td><input type="text" name="alertinfo" size="10" value="'.(($alertinfo) ? $alertinfo : "") .'"></td>
993 </tr>
994 ';
995 break;
996 default:
997 return false;
998 break;
999 }
1000}
1001*/
1002
1003?>
1004