Source for file phpagi_1.php

Documentation is available at phpagi_1.php

  1. <?php
  2. /**
  3. * phpagi-asmanager.php : PHP Asterisk Manager functions
  4. * Website: http://phpagi.sourceforge.net
  5. *
  6. * $Id: phpagi-asmanager.php,v 1.9 2005/03/14 18:29:38 masham Exp $
  7. *
  8. * Copyright (c) 2004, 2005 Matthew Asham <matthewa@bcwireless.net>, David Eder <david@eder.us>
  9. * All Rights Reserved.
  10. *
  11. * This software is released under the terms of the GNU Lesser General Public License v2.1
  12. * A copy of which is available from http://www.gnu.org/copyleft/lesser.html
  13. *
  14. * We would be happy to list your phpagi based application on the phpagi
  15. * website. Drop me an Email if you'd like us to list your program.
  16. *
  17. * @package phpAGI
  18. * @version 2.0
  19. */
  20.  
  21.  
  22. /**
  23. * Written for PHP 4.3.4, should work with older PHP 4.x versions.
  24. * Please submit bug reports, patches, etc to http://sourceforge.net/projects/phpagi/
  25. * Gracias. :)
  26. *
  27. */
  28.  
  29. if(!class_exists('AGI'))
  30. {
  31. require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'phpagi.php');
  32. }
  33.  
  34. /**
  35. * Asterisk Manager class
  36. *
  37. * @link http://www.voip-info.org/wiki-Asterisk+config+manager.conf
  38. * @link http://www.voip-info.org/wiki-Asterisk+manager+API
  39. * @example examples/sip_show_peer.php Get information about a sip peer
  40. * @package phpAGI
  41. */
  42. class AGI_1 extends AGI
  43. {
  44. /**
  45. * Response structure
  46. *
  47. * array('code'=>$code, 'result'=>$result, 'data'=>$data)
  48. *
  49. * @var array
  50. * @access public
  51. */
  52. var $response;
  53.  
  54. /**
  55. * Constructor
  56. *
  57. * @param string $config is the name of the config file to parse
  58. * @param array $optconfig is an array of configuration vars and vals, stuffed into $this->config['phpagi']
  59. */
  60. function AGI_1($config=false, $optconfig=false)
  61. {
  62. if(!$config) $config = NULL;
  63. if(!$optconfig) $optconfig = array();
  64. parent::AGI($config, $optconfig);
  65. }
  66.  
  67. /**
  68. * Evaluate an AGI command
  69. *
  70. * @access private
  71. * @param string $command
  72. * @return array ('code'=>$code, 'result'=>$result, 'data'=>$data)
  73. */
  74. function evalutate($command)
  75. {
  76. $this->response = parent::evalute($command);
  77. return $this->response;
  78. }
  79.  
  80. /**
  81. * Execute an AGI command
  82. *
  83. * @access private
  84. * @param string $str
  85. * @return array ('code'=>$code, 'result'=>$result, 'data'=>$data)
  86. */
  87. function agi_exec($str)
  88. {
  89. return $this->evaluate($str);
  90. }
  91.  
  92. /**
  93. * Check for error in result structure
  94. *
  95. * @param array $retarr
  96. * @return boolean true on error
  97. */
  98. function agi_is_error($retarr)
  99. {
  100. // Returns TRUE if the command returned an error.
  101.  
  102. if($retarr['code'] != AGIRES_OK)
  103. {
  104. $this->conlog("DEBUG: Bad command? Returned code is {$retarr['code']} result={$retarr['result']}");
  105. return true;
  106. }
  107.  
  108. if(!isset($retarr['result']))
  109. {
  110. $this->conlog("DEBUG: No 'result' value returned from asterisk! Eww!");
  111. return true;
  112. }
  113.  
  114. if($retarr['result'] == -1)
  115. return true;
  116.  
  117. return false;
  118. }
  119.  
  120. /**
  121. * Read the result from Asterisk
  122. *
  123. * @return array
  124. */
  125. function agi_readresult()
  126. {
  127. return $this->response;
  128. }
  129.  
  130. /**
  131. * Sends $message to the Asterisk console via the 'verbose' message system.
  132. *
  133. * If the Asterisk verbosity level is $vbl or greater, send $str to the console.
  134. *
  135. * The Asterisk verbosity system works as follows. The Asterisk user gets to set the desired verbosity at startup time or later
  136. * using the console 'set verbose' command. Messages are displayed on the console if their verbose level is less than or equal
  137. * to desired verbosity set by the user. More important messages should have a low verbose level; less important messages
  138. * should have a high verbose level.
  139. *
  140. * @link http://www.voip-info.org/wiki-verbose
  141. * @param string $str
  142. * @param integer $vbl from 1 to 4
  143. */
  144. function agi_verbose($str, $vbl=1)
  145. {
  146. $this->verbose($str, $vbl);
  147. }
  148.  
  149. /**
  150. * Get the response code from the last command
  151. *
  152. * @return integer
  153. */
  154. function agi_response_code()
  155. {
  156. return $this->response['code'];
  157. }
  158.  
  159. /**
  160. * Get the result code from the last command
  161. *
  162. * @return integer
  163. */
  164. function agi_response_result()
  165. {
  166. $this->conlog("result is {$this->response['result']}");
  167. return $this->response['result'];
  168. }
  169.  
  170. /**
  171. * Get the response data from the last command
  172. *
  173. * @return string
  174. */
  175. function agi_response_data()
  176. {
  177. return $this->response['data'];
  178. }
  179.  
  180. /**
  181. * Get the response variable from the last command
  182. *
  183. * @param string $var
  184. * @return mixed
  185. */
  186. function agi_response_var($var)
  187. {
  188. if(!isset($this->response[$var]))
  189. return false;
  190. return $this->response[$var];
  191. }
  192.  
  193. /**
  194. * Check for error in response
  195. *
  196. * @return boolean true on error
  197. */
  198. function agi_response_is_error()
  199. {
  200. return $this->agi_is_error($this->response);
  201. }
  202.  
  203. /**
  204. * Log to console if debug mode
  205. *
  206. * @param array $arr to print
  207. * @param string $label
  208. * @param integer $vbl verbose level
  209. */
  210. function con_print_r($arr, $label='', $lvl=0)
  211. {
  212. if($lvl == 0 && $label != '')
  213. $this->conlog("debug: $label");
  214.  
  215. $this->conlog(print_r($arr, true), $lvl);
  216. }
  217.  
  218.  
  219. /**
  220. * Plays the given file and receives DTMF data.
  221. *
  222. * This is similar to STREAM FILE, but this command can accept and return many DTMF digits,
  223. * while STREAM FILE returns immediately after the first DTMF digit is detected.
  224. *
  225. * Asterisk looks for the file to play in /var/lib/asterisk/sounds by default.
  226. *
  227. * If the user doesn't press any keys when the message plays, there is $timeout milliseconds
  228. * of silence then the command ends.
  229. *
  230. * The user has the opportunity to press a key at any time during the message or the
  231. * post-message silence. If the user presses a key while the message is playing, the
  232. * message stops playing. When the first key is pressed a timer starts counting for
  233. * $timeout milliseconds. Every time the user presses another key the timer is restarted.
  234. * The command ends when the counter goes to zero or the maximum number of digits is entered,
  235. * whichever happens first.
  236. *
  237. * Pressing the # key has the same effect as the timer running out: the command ends and
  238. * any previously keyed digits are returned. A side effect of this is that there is no
  239. * way to read a # key using this command.
  240. *
  241. * @link http://www.voip-info.org/wiki-get+data
  242. * @param integer $len number of digits to read
  243. * @param integer $timeout milliseconds
  244. * @param string $terminator character on which to quit
  245. * @param string $prompt file to play. Do not include file extension.
  246. * @return array of characters
  247. */
  248. function agi_getdtmf($len, $timeout, $terminator=false, $prompt=false)
  249. {
  250. if($prompt)
  251. {
  252. if(!is_array($prompt)) $prompt = array($prompt);
  253.  
  254. foreach($prompt as $p)
  255. {
  256. if($p[0] == '$')
  257. {
  258. $this->text2wav(substr($p, 1));
  259. }
  260. else
  261. {
  262. $this->stream_file($p, '#');
  263. }
  264. }
  265. }
  266.  
  267. $ret = array();
  268. for($i = 0; $i < $len; $i++)
  269. {
  270. $res = $this->wait_for_digit($timeout);
  271. $this->con_print_r($res);
  272. if($this->agi_response_is_error())
  273. {
  274. $this->conlog('error?');
  275. return false;
  276. }
  277. $ch = chr($res['result']);
  278. $this->conlog("got $ch");
  279. if($terminator && $ch == $terminator)
  280. return $ret;
  281.  
  282. $ret[$i] = $ch;
  283. }
  284. return($ret);
  285. }
  286.  
  287. /**
  288. * Read $len characters as DTMF codes
  289. *
  290. * @param integer $len
  291. * @return string
  292. */
  293. function agi_dtmf2text($len)
  294. {
  295. $numbers=array('1'=>'1', '2'=>'2abc', '3'=>'3def', '4'=>'4ghi', '5'=>'5jkl', '6'=>'6mno',
  296. '7'=>'7pqrs', '8'=>'8tuv', '9'=>'9wxyz', '0'=>'0');
  297.  
  298. $last = false;
  299. $i = $times = 0;
  300. $abort = 0;
  301.  
  302. $char = '';
  303. do
  304. {
  305. $res = $this->agi_getdtmf(1, 4000);
  306. $res = $res[0];
  307.  
  308. if($res == false) break;
  309.  
  310. if($last == false)
  311. $last = $res;
  312. elseif($last != $res || $res == false)
  313. {
  314. $ret[$i] = $char;
  315. $this->conlog("Character $i is $char");
  316. // $this->text2wav($char);
  317. $times = 0;
  318. $i++;
  319. }
  320.  
  321. $char = $numbers[$res][$times++];
  322. $this->conlog("Number $res is '$char'");
  323.  
  324. if(strlen($numbers[$res]) == $times) $times = 0;
  325.  
  326. $last = $res;
  327. } while($i < $len && !$abort);
  328.  
  329. $str = '';
  330. foreach($ret as $k) $str .= $k . ' ';
  331.  
  332. $this->text2wav($str);
  333. return($str);
  334. }
  335.  
  336. /**
  337. * Alias of PHP join function
  338. *
  339. * @param array $arr
  340. * @return string
  341. */
  342. function arr2str($arr)
  343. {
  344. return trim(join(' ', $arr));
  345. }
  346.  
  347. /**
  348. * Retrieves an entry in the Asterisk database for a given family and key.
  349. *
  350. * @link http://www.voip-info.org/wiki-database+get
  351. * @param string $family
  352. * @param string $key
  353. * @return string
  354. */
  355. function db_get($family, $key)
  356. {
  357. $res = $this->database_get($family, $key);
  358. if($res['code'] != AGIRES_OK || $res['result'] == 0) return false;
  359. return $res['data'];
  360. }
  361.  
  362. /**
  363. * Adds or updates an entry in the Asterisk database for a given family, key, and value.
  364. *
  365. * @param string $family
  366. * @param string $key
  367. * @param string $val
  368. * @return integer result code
  369. */
  370. function db_put($family, $key, $val)
  371. {
  372. $res = $this->database_put($family, $key, $val);
  373. return $res['code'];
  374. }
  375.  
  376. /**
  377. * Deletes an entry in the Asterisk database for a given family and key.
  378. *
  379. * @link http://www.voip-info.org/wiki-database+del
  380. * @param string $family
  381. * @param string $key
  382. * @return integer result code
  383. */
  384. function db_del($family, $key)
  385. {
  386. $res = $this->database_del($family, $key);
  387. return $res['code'];
  388. }
  389.  
  390. /**
  391. * Fetch the value of a variable.
  392. *
  393. * Does not work with global variables. Does not work with some variables that are generated by modules.
  394. *
  395. * @link http://www.voip-info.org/wiki-get+variable
  396. * @link http://www.voip-info.org/wiki-Asterisk+variables
  397. * @param string $var variable name
  398. * @return string
  399. */
  400. function get_var($var)
  401. {
  402. $res = $this->get_variable($var);
  403. if($res['code'] != AGIRES_OK || $res['result'] == 0) return false;
  404. return $res['data'];
  405. }
  406.  
  407. /**
  408. * Sets a variable to the specified value. The variables so created can later be used by later using ${<variablename>}
  409. * in the dialplan.
  410. *
  411. * These variables live in the channel Asterisk creates when you pickup a phone and as such they are both local and temporary.
  412. * Variables created in one channel can not be accessed by another channel. When you hang up the phone, the channel is deleted
  413. * and any variables in that channel are deleted as well.
  414. *
  415. * @link http://www.voip-info.org/wiki-set+variable
  416. * @param string $var is case sensitive
  417. * @param string $val
  418. * @return integer result code
  419. */
  420. function set_var($var, $val)
  421. {
  422. $res = $this->set_variable($var, $val);
  423. return $res['code'];
  424. }
  425.  
  426. /**
  427. * Hangup the current channel.
  428. *
  429. * @link http://www.voip-info.org/wiki-hangup
  430. * @param string $channel
  431. */
  432. function agi_hangup()
  433. {
  434. $this->hangup();
  435. }
  436.  
  437. /**
  438. * Get the status of the specified channel.
  439. *
  440. * @link http://www.voip-info.org/wiki-channel+status
  441. * @param string $channel
  442. * @return array, ('status'=>$res['result'], 'description'=>$res['data'])
  443. */
  444. function agi_channel_status($channel)
  445. {
  446. $res = $this->channel_status($channel);
  447. return array('status'=>$res['result'], 'description'=>$res['data']);
  448. }
  449.  
  450. /**
  451. * Record sound to a file until an acceptable DTMF digit is received or a specified amount of
  452. * time has passed. Optionally the file BEEP is played before recording begins.
  453. *
  454. * @link http://www.voip-info.org/wiki-record+file
  455. * @param string $file to record, without extension, often created in /var/lib/asterisk/sounds
  456. * @param string $format of the file. GSM and WAV are commonly used formats. MP3 is read-only and thus cannot be used.
  457. * @param integer $timeout is the maximum record time in milliseconds, or -1 for no timeout.
  458. * @param string $prompt to play
  459. */
  460. function agi_recordfile($file, $format, $timeout=5000, $prompt=FALSE)
  461. {
  462. if($prompt) $this->stream_file($prompt);
  463. $this->record_file($file, $format, '#', $timeout, true);
  464. }
  465.  
  466. /**
  467. * Play the given audio file, allowing playback to be interrupted by a #. This command is similar to the GET DATA
  468. * command but this command returns after the first DTMF digit has been pressed while GET DATA can accumulated any number of
  469. * digits before returning.
  470. *
  471. * @link http://www.voip-info.org/wiki-stream+file
  472. * @param string $file filename without extension, often in /var/lib/asterisk/sounds
  473. */
  474. function agi_play($file)
  475. {
  476. $this->stream_file($file, '#');
  477. }
  478.  
  479. /**
  480. * Goto - Set context, extension and priority
  481. *
  482. * @param string $con context
  483. * @param string $ext extension
  484. * @param string $pri priority
  485. */
  486. function agi_goto($con,$ext='s',$pri=1)
  487. {
  488. $this->goto($con, $ext, $pri);
  489. }
  490.  
  491. /**
  492. * Say the given digit string, returning early if # is received on the channel.
  493. *
  494. * @link http://www.voip-info.org/wiki-say+digits
  495. * @param integer $digits
  496. */
  497. function agi_saydigits($digits)
  498. {
  499. $this->say_digits($digits, '#');
  500. }
  501.  
  502. /**
  503. * Say the given number, returning early if # is received on the channel.
  504. *
  505. * @link http://www.voip-info.org/wiki-say+number
  506. * @param integer $number
  507. */
  508. function agi_saynumber($number)
  509. {
  510. $this->say_number($number, '#');
  511. }
  512.  
  513. /**
  514. * Say a given time, returning early if # is received on the channel.
  515. *
  516. * @link http://www.voip-info.org/wiki-say+time
  517. * @param integer $time number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC).
  518. */
  519. function agi_saytime($time='')
  520. {
  521. if($time == '') $time = time();
  522. $this->say_time($time, '#');
  523. }
  524.  
  525. /**
  526. * Set Language
  527. *
  528. * @param string $language code
  529. */
  530. function agi_setlanguage($language='en')
  531. {
  532. $this->exec_setlanguage($language);
  533. }
  534.  
  535. /**
  536. * Perform enum lookup
  537. *
  538. * @param string $telnumber
  539. * @param string $rDNS
  540. * @return array
  541. */
  542. function enum_lookup($telnumber, $rDNS='e164.org')
  543. {
  544. // returns a sorted array of enum records
  545.  
  546. if($telnumber[0] == '+')
  547. $telnumber = substr($telnumber, 1);
  548.  
  549. for($i = 0; $i < strlen($telnumber); $i++)
  550. $rDNS = $telnumber[$i] . '.' . $rDNS;
  551.  
  552. if(!isset($this->config['phpagi']['dig'])) $this->config['phpagi']['dig'] = $this->which('dig');
  553. $dig=trim($this->config['phpagi']['dig']);
  554.  
  555. $execstr= $dig . " +short " . escapeshellarg($rDNS) . " NAPTR";
  556. $lines = trim(`$execstr`);
  557.  
  558. $lines = explode("\n", $lines);
  559. $arr = array();
  560. foreach($lines as $line)
  561. {
  562. $line = trim($line);
  563. $line = str_replace("\t", ' ', $line);
  564. while(strstr($line, ' '))
  565. $line = str_replace(' ', ' ', $line);
  566. $line = str_replace("\"", '', $line);
  567. $line = str_replace("\'", '', $line);
  568. $line = str_replace(' ', '|', $line);
  569. $bits = explode('|', $line);
  570. $bit = explode('!', stripslashes($bits[4]));
  571. $URI = @ereg_replace($bit[1], $bit[2], '+' . $telnumber);
  572. if($URI[3] == ':') $URI[3] = '/';
  573. if($URI[4] == ':') $URI[4] = '/';
  574. $arr[] = array('order'=>$bits[0], 'prio'=>$bits[1], 'tech'=>$bits[3], 'URI'=>$URI);
  575. }
  576.  
  577. foreach($arr as $key=>$row)
  578. {
  579. $order[$key] = $row['order'];
  580. $prio[$key] = $row['prio'];
  581. }
  582.  
  583. array_multisort($order, SORT_ASC, $prio, SORT_ASC, $arr);
  584. return($arr);
  585. }
  586.  
  587. /**
  588. * Perform enum txt lookup
  589. *
  590. * @param string $telnumber
  591. * @param string $rDNS
  592. * @return string
  593. */
  594. function enum_txtlookup($telnumber, $rDNS='e164.org')
  595. {
  596. // returns the contents of a TXT record associated with an ENUM dns record.
  597. // ala reverse caller ID lookup.
  598. if($telnumber[0] == '+')
  599. $telnumber = substr($telnumber, 1);
  600.  
  601. for($i = 0; $i < strlen($telnumber); $i++)
  602. $rDNS = $telnumber[$i] . '.' . $rDNS;
  603.  
  604. if(!isset($this->config['phpagi']['dig'])) $this->config['phpagi']['dig'] = $this->which('dig');
  605. $dig=trim($this->config['phpagi']['dig']);
  606.  
  607. $execstr = $dig . ' +short ' . escapeshellarg($rDNS) . ' TXT';
  608. $lines = trim(`$execstr`);
  609.  
  610. $lines = explode("\n", $lines);
  611. foreach($lines as $line)
  612. {
  613. $line = str_replace("\t", ' ', trim($line));
  614. while(strstr($line, ' ')) $line = str_replace(' ', ' ', $line);
  615. $line = str_replace("\"", '', $line);
  616. $line = str_replace("\'", '', $line);
  617. $ret .= $line;
  618. }
  619. $ret = trim($ret);
  620. if($ret == '') return false;
  621. return $ret;
  622. }
  623.  
  624. /**
  625. * Send the given text to the connected channel.
  626. *
  627. * Most channels do not support transmission of text.
  628. *
  629. * @link http://www.voip-info.org/wiki-send+text
  630. * @param $text
  631. * @return boolean true on success
  632. */
  633. function send_text($txt)
  634. {
  635. $res = parent::send_text($txt);
  636. if($res['code'] != AGIRES_OK || $res['result'] == -1) return false;
  637. return true;
  638. }
  639.  
  640. /**
  641. * Send the specified image on a channel.
  642. *
  643. * Most channels do not support the transmission of images.
  644. *
  645. * @link http://www.voip-info.org/wiki-send+image
  646. * @param string $image without extension, often in /var/lib/asterisk/images
  647. * @return boolean true on success
  648. */
  649. function send_image($image)
  650. {
  651. $res = parent::send_image($image);
  652. if($res['code'] != AGIRES_OK || $res['result'] == -1) return false;
  653. return true;
  654. }
  655. }
  656. ?>

Documentation generated on Wed, 16 Nov 2005 12:49:28 -0700 by phpDocumentor 1.3.0RC3