Total Complexity | 237 |
Total Lines | 1746 |
Duplicated Lines | 0 % |
Changes | 2 | ||
Bugs | 0 | Features | 0 |
Complex classes like AGI often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use AGI, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
64 | class AGI |
||
65 | { |
||
66 | /** |
||
67 | * Request variables read in on initialization. |
||
68 | * |
||
69 | * Often contains any/all of the following: |
||
70 | * agi_request - name of agi script |
||
71 | * agi_channel - current channel |
||
72 | * agi_language - current language |
||
73 | * agi_type - channel type (SIP, ZAP, IAX, ...) |
||
74 | * agi_uniqueid - unique id based on unix time |
||
75 | * agi_callerid - callerID string |
||
76 | * agi_dnid - dialed number id |
||
77 | * agi_rdnis - referring DNIS number |
||
78 | * agi_context - current context |
||
79 | * agi_extension - extension dialed |
||
80 | * agi_priority - current priority |
||
81 | * agi_enhanced - value is 1.0 if started as an EAGI script |
||
82 | * agi_accountcode - set by SetAccount in the dialplan |
||
83 | * agi_network - value is yes if this is a fastagi |
||
84 | * agi_network_script - name of the script to execute |
||
85 | * |
||
86 | * NOTE: program arguments are still in $_SERVER['argv']. |
||
87 | * |
||
88 | * @var array |
||
89 | * @access public |
||
90 | */ |
||
91 | public $request; |
||
92 | |||
93 | /** |
||
94 | * Config variables |
||
95 | * |
||
96 | * @var array |
||
97 | * @access public |
||
98 | */ |
||
99 | public $config; |
||
100 | |||
101 | /** |
||
102 | * Asterisk Manager |
||
103 | * |
||
104 | * @var AGI_AsteriskManager |
||
105 | * @access public |
||
106 | */ |
||
107 | public $asm; |
||
108 | |||
109 | /** |
||
110 | * Input Stream |
||
111 | * |
||
112 | * @access private |
||
113 | */ |
||
114 | private $in = null; |
||
115 | |||
116 | /** |
||
117 | * Output Stream |
||
118 | * |
||
119 | * @access private |
||
120 | */ |
||
121 | private $out = null; |
||
122 | |||
123 | /** |
||
124 | * Audio Stream |
||
125 | * |
||
126 | * @access public |
||
127 | */ |
||
128 | public $audio = null; |
||
129 | |||
130 | |||
131 | /** |
||
132 | * Application option delimiter |
||
133 | * |
||
134 | * @access public |
||
135 | */ |
||
136 | public $option_delim = ","; |
||
137 | |||
138 | private $defaultConfig = ["error_handler" => true, |
||
139 | "debug" => false, |
||
140 | "admin" => null, |
||
141 | "tempdir" => AST_TMP_DIR]; |
||
142 | |||
143 | /** |
||
144 | * Constructor |
||
145 | * |
||
146 | * @param string $config is the name of the config file to parse |
||
147 | * @param array $optconfig is an array of configuration vars and values, stuffed into $this->config['phpagi'] |
||
148 | */ |
||
149 | function __construct($config = null, array $optconfig = []) { |
||
150 | // load config |
||
151 | if (!is_null($config) && file_exists($config)) { |
||
152 | $this->config = parse_ini_file($config, true); |
||
153 | } elseif (file_exists(DEFAULT_PHPAGI_CONFIG)) { |
||
154 | $this->config = parse_ini_file(DEFAULT_PHPAGI_CONFIG, true); |
||
155 | } |
||
156 | |||
157 | // If optconfig is specified, stuff values and vars into 'phpagi' config array. |
||
158 | foreach ($optconfig as $var => $val) { |
||
159 | $this->config['phpagi'][$var] = $val; |
||
160 | } |
||
161 | |||
162 | // add default values to config for uninitialized values |
||
163 | foreach ($this->defaultConfig as $name => $value) { |
||
164 | $this->config["phpagi"][$name] = $this->config["phpagi"][$name] ?? $value; |
||
165 | } |
||
166 | |||
167 | // festival TTS config |
||
168 | $this->config['festival']['text2wave'] = $this->config['festival']['text2wave'] ?? $this->which('text2wave'); |
||
169 | |||
170 | // swift TTS config |
||
171 | $this->config['cepstral']['swift'] = $this->config['cepstral']['swift'] ?? $this->which('swift'); |
||
172 | |||
173 | ob_implicit_flush(); |
||
174 | |||
175 | // open stdin & stdout |
||
176 | $this->in = defined('STDIN') ? STDIN : fopen('php://stdin', 'r'); |
||
177 | $this->out = defined('STDOUT') ? STDOUT : fopen('php://stdout', 'w'); |
||
178 | |||
179 | // initialize error handler |
||
180 | if ($this->config['phpagi']['error_handler']) { |
||
181 | set_error_handler('phpagi_error_handler'); |
||
182 | global $phpagi_error_handler_email; |
||
183 | $phpagi_error_handler_email = $this->config['phpagi']['admin']; |
||
184 | error_reporting(E_ALL); |
||
185 | } |
||
186 | |||
187 | // make sure temp folder exists |
||
188 | $this->make_folder($this->config['phpagi']['tempdir']); |
||
189 | |||
190 | // read the request |
||
191 | $str = fgets($this->in); |
||
192 | while ($str != "\n") { |
||
193 | $this->request[substr($str, 0, strpos($str, ':'))] = trim(substr($str, strpos($str, ':') + 1)); |
||
194 | $str = fgets($this->in); |
||
195 | } |
||
196 | |||
197 | // open audio if eagi detected |
||
198 | if ($this->request['agi_enhanced'] == '1.0') { |
||
199 | if (file_exists('/proc/' . getmypid() . '/fd/3')) { |
||
200 | $this->audio = fopen('/proc/' . getmypid() . '/fd/3', 'r'); |
||
201 | } elseif (file_exists('/dev/fd/3')) { |
||
202 | // may need to mount fdescfs |
||
203 | $this->audio = fopen('/dev/fd/3', 'r'); |
||
204 | } else { |
||
205 | $this->conlog('Unable to open audio stream'); |
||
206 | } |
||
207 | |||
208 | if ($this->audio) { |
||
209 | stream_set_blocking($this->audio, 0); |
||
210 | } |
||
211 | } |
||
212 | |||
213 | $this->conlog('AGI Request:'); |
||
214 | $this->conlog(print_r($this->request, true)); |
||
|
|||
215 | $this->conlog('PHPAGI internal configuration:'); |
||
216 | $this->conlog(print_r($this->config, true)); |
||
217 | } |
||
218 | |||
219 | // ********************************************************************************************************* |
||
220 | // ** COMMANDS ** |
||
221 | // ********************************************************************************************************* |
||
222 | |||
223 | /** |
||
224 | * Answer channel if not already in answer state. |
||
225 | * |
||
226 | * @link http://www.voip-info.org/wiki-answer |
||
227 | * @example examples/dtmf.php Get DTMF tones from the user and say the digits |
||
228 | * @example examples/input.php Get text input from the user and say it back |
||
229 | * @example examples/ping.php Ping an IP address |
||
230 | * |
||
231 | * @return array, see evaluate for return information. ['result'] is 0 on success, -1 on failure. |
||
232 | */ |
||
233 | function answer(): array { |
||
234 | return $this->evaluate('ANSWER'); |
||
235 | } |
||
236 | |||
237 | /** |
||
238 | * Get the status of the specified channel. If no channel name is specified, return the status of the current channel. |
||
239 | * |
||
240 | * @link http://www.voip-info.org/wiki-channel+status |
||
241 | * @param string $channel |
||
242 | * @return array, see evaluate for return information. ['data'] contains description. |
||
243 | */ |
||
244 | function channel_status(string $channel = ''): array { |
||
245 | $ret = $this->evaluate("CHANNEL STATUS $channel"); |
||
246 | switch ($ret['result']) { |
||
247 | case -1: |
||
248 | $ret['data'] = trim("There is no channel that matches $channel"); |
||
249 | break; |
||
250 | case AST_STATE_DOWN: |
||
251 | $ret['data'] = 'Channel is down and available'; |
||
252 | break; |
||
253 | case AST_STATE_RESERVED: |
||
254 | $ret['data'] = 'Channel is down, but reserved'; |
||
255 | break; |
||
256 | case AST_STATE_OFFHOOK: |
||
257 | $ret['data'] = 'Channel is off hook'; |
||
258 | break; |
||
259 | case AST_STATE_DIALING: |
||
260 | $ret['data'] = 'Digits (or equivalent) have been dialed'; |
||
261 | break; |
||
262 | case AST_STATE_RING: |
||
263 | $ret['data'] = 'Line is ringing'; |
||
264 | break; |
||
265 | case AST_STATE_RINGING: |
||
266 | $ret['data'] = 'Remote end is ringing'; |
||
267 | break; |
||
268 | case AST_STATE_UP: |
||
269 | $ret['data'] = 'Line is up'; |
||
270 | break; |
||
271 | case AST_STATE_BUSY: |
||
272 | $ret['data'] = 'Line is busy'; |
||
273 | break; |
||
274 | case AST_STATE_DIALING_OFFHOOK: |
||
275 | $ret['data'] = 'Digits (or equivalent) have been dialed while offhook'; |
||
276 | break; |
||
277 | case AST_STATE_PRERING: |
||
278 | $ret['data'] = 'Channel has detected an incoming call and is waiting for ring'; |
||
279 | break; |
||
280 | default: |
||
281 | $ret['data'] = "Unknown ({$ret['result']})"; |
||
282 | break; |
||
283 | } |
||
284 | return $ret; |
||
285 | } |
||
286 | |||
287 | /** |
||
288 | * Deletes an entry in the Asterisk database for a given family and key. |
||
289 | * |
||
290 | * @link http://www.voip-info.org/wiki-database+del |
||
291 | * @param string $family |
||
292 | * @param string $key |
||
293 | * @return array, see evaluate for return information. ['result'] is 1 on success, 0 otherwise. |
||
294 | */ |
||
295 | function database_del(string $family, string $key): array { |
||
296 | return $this->evaluate("DATABASE DEL \"$family\" \"$key\""); |
||
297 | } |
||
298 | |||
299 | /** |
||
300 | * Deletes a family or specific keytree within a family in the Asterisk database. |
||
301 | * |
||
302 | * @link http://www.voip-info.org/wiki-database+deltree |
||
303 | * @param string $family |
||
304 | * @param string $keytree |
||
305 | * @return array, see evaluate for return information. ['result'] is 1 on success, 0 otherwise. |
||
306 | */ |
||
307 | function database_deltree(string $family, string $keytree = ''): array { |
||
308 | $cmd = "DATABASE DELTREE \"$family\""; |
||
309 | if ($keytree != '') { |
||
310 | $cmd .= " \"$keytree\""; |
||
311 | } |
||
312 | return $this->evaluate($cmd); |
||
313 | } |
||
314 | |||
315 | /** |
||
316 | * Retrieves an entry in the Asterisk database for a given family and key. |
||
317 | * |
||
318 | * @link http://www.voip-info.org/wiki-database+get |
||
319 | * @param string $family |
||
320 | * @param string $key |
||
321 | * @return array, see evaluate for return information. ['result'] is 1 on success, 0 failure. ['data'] holds the value |
||
322 | */ |
||
323 | function database_get(string $family, string $key): array { |
||
324 | return $this->evaluate("DATABASE GET \"$family\" \"$key\""); |
||
325 | } |
||
326 | |||
327 | /** |
||
328 | * Adds or updates an entry in the Asterisk database for a given family, key, and value. |
||
329 | * |
||
330 | * @param string $family |
||
331 | * @param string $key |
||
332 | * @param string $value |
||
333 | * @return array, see evaluate for return information. ['result'] is 1 on success, 0 otherwise |
||
334 | */ |
||
335 | function database_put(string $family, string $key, string $value): array { |
||
336 | $value = str_replace("\n", '\n', addslashes($value)); |
||
337 | return $this->evaluate("DATABASE PUT \"$family\" \"$key\" \"$value\""); |
||
338 | } |
||
339 | |||
340 | |||
341 | /** |
||
342 | * Sets a global variable, using Asterisk 1.6 syntax. |
||
343 | * |
||
344 | * @link http://www.voip-info.org/wiki/view/Asterisk+cmd+Set |
||
345 | * |
||
346 | * @param string $pVariable |
||
347 | * @param string|int|float $pValue |
||
348 | * @return array, see evaluate for return information. ['result'] is 1 on success, 0 otherwise |
||
349 | */ |
||
350 | function set_global_var(string $pVariable, $pValue): array { |
||
351 | if (is_numeric($pValue)) { |
||
352 | return $this->evaluate("Set({$pVariable}={$pValue},g);"); |
||
353 | } |
||
354 | return $this->evaluate("Set({$pVariable}=\"{$pValue}\",g);"); |
||
355 | } |
||
356 | |||
357 | |||
358 | /** |
||
359 | * Sets a variable, using Asterisk 1.6 syntax. |
||
360 | * |
||
361 | * @link http://www.voip-info.org/wiki/view/Asterisk+cmd+Set |
||
362 | * |
||
363 | * @param string $pVariable |
||
364 | * @param string|int|float $pValue |
||
365 | * @return array, see evaluate for return information. ['result'] is 1 on success, 0 otherwise |
||
366 | */ |
||
367 | function set_var(string $pVariable, $pValue): array { |
||
368 | if (is_numeric($pValue)) { |
||
369 | return $this->evaluate("Set({$pVariable}={$pValue});"); |
||
370 | } |
||
371 | return $this->evaluate("Set({$pVariable}=\"{$pValue}\");"); |
||
372 | } |
||
373 | |||
374 | |||
375 | /** |
||
376 | * Executes the specified Asterisk application with given options. |
||
377 | * |
||
378 | * @link http://www.voip-info.org/wiki-exec |
||
379 | * @link http://www.voip-info.org/wiki-Asterisk+-+documentation+of+application+commands |
||
380 | * @param string $application |
||
381 | * @param mixed $options |
||
382 | * @return array, see evaluate for return information. ['result'] is whatever the application returns, or -2 on failure to find application |
||
383 | */ |
||
384 | function exec(string $application, $options): array { |
||
385 | if (is_array($options)) { |
||
386 | $options = join('|', $options); |
||
387 | } |
||
388 | return $this->evaluate("EXEC $application $options"); |
||
389 | } |
||
390 | |||
391 | /** |
||
392 | * Plays the given file and receives DTMF data. |
||
393 | * |
||
394 | * This is similar to STREAM FILE, but this command can accept and return many DTMF digits, |
||
395 | * while STREAM FILE returns immediately after the first DTMF digit is detected. |
||
396 | * |
||
397 | * Asterisk looks for the file to play in /var/lib/asterisk/sounds by default. |
||
398 | * |
||
399 | * If the user doesn't press any keys when the message plays, there is $timeout milliseconds |
||
400 | * of silence then the command ends. |
||
401 | * |
||
402 | * The user has the opportunity to press a key at any time during the message or the |
||
403 | * post-message silence. If the user presses a key while the message is playing, the |
||
404 | * message stops playing. When the first key is pressed a timer starts counting for |
||
405 | * $timeout milliseconds. Every time the user presses another key the timer is restarted. |
||
406 | * The command ends when the counter goes to zero or the maximum number of digits is entered, |
||
407 | * whichever happens first. |
||
408 | * |
||
409 | * If you don't specify a time out then a default timeout of 2000 is used following a pressed |
||
410 | * digit. If no digits are pressed then 6 seconds of silence follow the message. |
||
411 | * |
||
412 | * If you don't specify $max_digits then the user can enter as many digits as they want. |
||
413 | * |
||
414 | * Pressing the # key has the same effect as the timer running out: the command ends and |
||
415 | * any previously keyed digits are returned. A side effect of this is that there is no |
||
416 | * way to read a # key using this command. |
||
417 | * |
||
418 | * @param string $filename file to play. Do not include file extension. |
||
419 | * @param integer $timeout milliseconds |
||
420 | * @param integer $max_digits |
||
421 | * @return array, see evaluate for return information. ['result'] holds the digits and ['data'] holds the timeout if present. |
||
422 | * |
||
423 | * This differs from other commands with return DTMF as numbers representing ASCII characters. |
||
424 | * @example examples/ping.php Ping an IP address |
||
425 | * |
||
426 | * @link http://www.voip-info.org/wiki-get+data |
||
427 | */ |
||
428 | function get_data(string $filename, $timeout = null, $max_digits = null): array { |
||
429 | return $this->evaluate(rtrim("GET DATA $filename $timeout $max_digits")); |
||
430 | } |
||
431 | |||
432 | /** |
||
433 | * Fetch the value of a variable. |
||
434 | * |
||
435 | * Does not work with global variables. Does not work with some variables that are generated by modules. |
||
436 | * |
||
437 | * @link http://www.voip-info.org/wiki-get+variable |
||
438 | * @link http://www.voip-info.org/wiki-Asterisk+variables |
||
439 | * @param string $variable name |
||
440 | * @param boolean $getvalue return the value only |
||
441 | * @return mixed, see evaluate for return information. ['result'] is 0 if variable hasn't been set, 1 if it has. ['data'] holds the value. returns value if $getvalue is TRUE |
||
442 | */ |
||
443 | function get_variable(string $variable, bool $getvalue = false) { |
||
444 | $res = $this->evaluate("GET VARIABLE $variable"); |
||
445 | return $getvalue ? $res['data'] : $res; |
||
446 | } |
||
447 | |||
448 | |||
449 | /** |
||
450 | * Fetch the value of a full variable. |
||
451 | * |
||
452 | * |
||
453 | * @link http://www.voip-info.org/wiki/view/get+full+variable |
||
454 | * @link http://www.voip-info.org/wiki-Asterisk+variables |
||
455 | * @param string $variable name |
||
456 | * @param string $channel channel |
||
457 | * @param boolean $getvalue return the value only |
||
458 | * @return mixed, see evaluate for return information. ['result'] is 0 if variable hasn't been set, 1 if it has. ['data'] holds the value. returns value if $getvalue is TRUE |
||
459 | */ |
||
460 | function get_fullvariable(string $variable, $channel = false, bool $getvalue = false) { |
||
461 | $req = ($channel == false) ? $variable : $variable . ' ' . $channel; |
||
462 | $res = $this->evaluate('GET FULL VARIABLE ' . $req); |
||
463 | return $getvalue ? $res['data'] : $res; |
||
464 | |||
465 | } |
||
466 | |||
467 | /** |
||
468 | * Hangup the specified channel. If no channel name is given, hang up the current channel. |
||
469 | * |
||
470 | * With power comes responsibility. Hanging up channels other than your own isn't something |
||
471 | * that is done routinely. If you are not sure why you are doing so, then don't. |
||
472 | * |
||
473 | * @link http://www.voip-info.org/wiki-hangup |
||
474 | * @example examples/dtmf.php Get DTMF tones from the user and say the digits |
||
475 | * @example examples/input.php Get text input from the user and say it back |
||
476 | * @example examples/ping.php Ping an IP address |
||
477 | * |
||
478 | * @param string $channel |
||
479 | * @return array, see evaluate for return information. ['result'] is 1 on success, -1 on failure. |
||
480 | */ |
||
481 | function hangup(string $channel = ''): array { |
||
483 | } |
||
484 | |||
485 | /** |
||
486 | * Does nothing. |
||
487 | * |
||
488 | * @link http://www.voip-info.org/wiki-noop |
||
489 | * @param string $string |
||
490 | * @return array, see evaluate for return information. |
||
491 | */ |
||
492 | function noop(string $string = ""): array { |
||
493 | return $this->evaluate("NOOP \"$string\""); |
||
494 | } |
||
495 | |||
496 | /** |
||
497 | * Receive a character of text from a connected channel. Waits up to $timeout milliseconds for |
||
498 | * a character to arrive, or infinitely if $timeout is zero. |
||
499 | * |
||
500 | * @link http://www.voip-info.org/wiki-receive+char |
||
501 | * @param integer $timeout milliseconds |
||
502 | * @return array, see evaluate for return information. ['result'] is 0 on timeout or not supported, -1 on failure. Otherwise |
||
503 | * it is the decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
504 | */ |
||
505 | function receive_char(int $timeout = -1): array { |
||
506 | return $this->evaluate("RECEIVE CHAR $timeout"); |
||
507 | } |
||
508 | |||
509 | /** |
||
510 | * Record sound to a file until an acceptable DTMF digit is received or a specified amount of |
||
511 | * time has passed. Optionally the file BEEP is played before recording begins. |
||
512 | * |
||
513 | * @link http://www.voip-info.org/wiki-record+file |
||
514 | * @param string $file to record, without extension, often created in /var/lib/asterisk/sounds |
||
515 | * @param string $format of the file. GSM and WAV are commonly used formats. MP3 is read-only and thus cannot be used. |
||
516 | * @param string $escape_digits |
||
517 | * @param integer $timeout is the maximum record time in milliseconds, or -1 for no timeout. |
||
518 | * @param integer $offset to seek to without exceeding the end of the file. |
||
519 | * @param boolean $beep |
||
520 | * @param integer $silence number of seconds of silence allowed before the function returns despite the |
||
521 | * lack of dtmf digits or reaching timeout. |
||
522 | * @return array, see evaluate for return information. ['result'] is -1 on error, 0 on hangup, otherwise a decimal value of the |
||
523 | * DTMF tone. Use chr() to convert to ASCII. |
||
524 | */ |
||
525 | function record_file(string $file, string $format, string $escape_digits = '', int $timeout = -1, |
||
526 | $offset = null, bool $beep = false, $silence = null): array { |
||
527 | $cmd = trim("RECORD FILE $file $format \"$escape_digits\" $timeout $offset"); |
||
528 | if ($beep) { |
||
529 | $cmd .= ' BEEP'; |
||
530 | } |
||
531 | if (!is_null($silence)) { |
||
532 | $cmd .= " s=$silence"; |
||
533 | } |
||
534 | return $this->evaluate($cmd); |
||
535 | } |
||
536 | |||
537 | /** |
||
538 | * Say a given character string, returning early if any of the given DTMF digits are received on the channel. |
||
539 | * |
||
540 | * @link https://www.voip-info.org/say-alpha |
||
541 | * @param string $text |
||
542 | * @param string $escape_digits |
||
543 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if playback completes with no |
||
544 | * digit received, otherwise a decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
545 | */ |
||
546 | function say_alpha(string $text, string $escape_digits = ''): array { |
||
547 | return $this->evaluate("SAY ALPHA $text \"$escape_digits\""); |
||
548 | } |
||
549 | |||
550 | /** |
||
551 | * Say the given digit string, returning early if any of the given DTMF escape digits are received on the channel. |
||
552 | * |
||
553 | * @link http://www.voip-info.org/wiki-say+digits |
||
554 | * @param integer $digits |
||
555 | * @param string $escape_digits |
||
556 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if playback completes with no |
||
557 | * digit received, otherwise a decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
558 | */ |
||
559 | function say_digits(int $digits, string $escape_digits = ''): array { |
||
560 | return $this->evaluate("SAY DIGITS $digits \"$escape_digits\""); |
||
561 | } |
||
562 | |||
563 | /** |
||
564 | * Say the given number, returning early if any of the given DTMF escape digits are received on the channel. |
||
565 | * |
||
566 | * @link http://www.voip-info.org/wiki-say+number |
||
567 | * @param integer $number |
||
568 | * @param string $escape_digits |
||
569 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if playback completes with no |
||
570 | * digit received, otherwise a decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
571 | */ |
||
572 | function say_number(int $number, string $escape_digits = ''): array { |
||
574 | } |
||
575 | |||
576 | /** |
||
577 | * Say the given character string, returning early if any of the given DTMF escape digits are received on the channel. |
||
578 | * |
||
579 | * @link http://www.voip-info.org/wiki-say+phonetic |
||
580 | * @param string $text |
||
581 | * @param string $escape_digits |
||
582 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if playback completes with no |
||
583 | * digit received, otherwise a decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
584 | */ |
||
585 | function say_phonetic(string $text, string $escape_digits = ''): array { |
||
586 | return $this->evaluate("SAY PHONETIC $text \"$escape_digits\""); |
||
587 | } |
||
588 | |||
589 | /** |
||
590 | * Say a given time, returning early if any of the given DTMF escape digits are received on the channel. |
||
591 | * |
||
592 | * @link http://www.voip-info.org/wiki-say+time |
||
593 | * @param integer $time number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC). |
||
594 | * @param string $escape_digits |
||
595 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if playback completes with no |
||
596 | * digit received, otherwise a decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
597 | */ |
||
598 | function say_time($time = null, string $escape_digits = ''): array { |
||
599 | if (is_null($time)) { |
||
600 | $time = time(); |
||
601 | } |
||
602 | return $this->evaluate("SAY TIME $time \"$escape_digits\""); |
||
603 | } |
||
604 | |||
605 | /** |
||
606 | * Send the specified image on a channel. |
||
607 | * |
||
608 | * Most channels do not support the transmission of images. |
||
609 | * |
||
610 | * @link http://www.voip-info.org/wiki-send+image |
||
611 | * @param string $image without extension, often in /var/lib/asterisk/images |
||
612 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if the image is sent or |
||
613 | * channel does not support image transmission. |
||
614 | */ |
||
615 | function send_image(string $image): array { |
||
616 | return $this->evaluate("SEND IMAGE $image"); |
||
617 | } |
||
618 | |||
619 | /** |
||
620 | * Send the given text to the connected channel. |
||
621 | * |
||
622 | * Most channels do not support transmission of text. |
||
623 | * |
||
624 | * @link http://www.voip-info.org/wiki-send+text |
||
625 | * @param $text |
||
626 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if the text is sent or |
||
627 | * channel does not support text transmission. |
||
628 | */ |
||
629 | function send_text($text): array { |
||
630 | return $this->evaluate("SEND TEXT \"$text\""); |
||
631 | } |
||
632 | |||
633 | /** |
||
634 | * Cause the channel to automatically hangup at $time seconds in the future. |
||
635 | * If $time is 0 then the auto hangup feature is disabled on this channel. |
||
636 | * |
||
637 | * If the channel is hangup prior to $time seconds, this setting has no effect. |
||
638 | * |
||
639 | * @link http://www.voip-info.org/wiki-set+autohangup |
||
640 | * @param integer $time until automatic hangup |
||
641 | * @return array, see evaluate for return information. |
||
642 | */ |
||
643 | function set_autohangup(int $time = 0): array { |
||
644 | return $this->evaluate("SET AUTOHANGUP $time"); |
||
645 | } |
||
646 | |||
647 | /** |
||
648 | * Changes the caller ID of the current channel. |
||
649 | * |
||
650 | * @link http://www.voip-info.org/wiki-set+callerid |
||
651 | * @param string $cid example: "John Smith"<1234567> |
||
652 | * This command will let you take liberties with the <caller ID specification> but the format shown in the example above works |
||
653 | * well: the name enclosed in double quotes followed immediately by the number inside angle brackets. If there is no name then |
||
654 | * you can omit it. If the name contains no spaces you can omit the double quotes around it. The number must follow the name |
||
655 | * immediately; don't put a space between them. The angle brackets around the number are necessary; if you omit them the |
||
656 | * number will be considered to be part of the name. |
||
657 | * @return array, see evaluate for return information. |
||
658 | */ |
||
659 | function set_callerid(string $cid): array { |
||
660 | return $this->evaluate("SET CALLERID $cid"); |
||
661 | } |
||
662 | |||
663 | /** |
||
664 | * Sets the context for continuation upon exiting the application. |
||
665 | * |
||
666 | * Setting the context does NOT automatically reset the extension and the priority; if you want to start at the top of the new |
||
667 | * context you should set extension and priority yourself. |
||
668 | * |
||
669 | * If you specify a non-existent context you receive no error indication (['result'] is still 0) but you do get a |
||
670 | * warning message on the Asterisk console. |
||
671 | * |
||
672 | * @link http://www.voip-info.org/wiki-set+context |
||
673 | * @param string $context |
||
674 | * @return array, see evaluate for return information. |
||
675 | */ |
||
676 | function set_context(string $context): array { |
||
677 | return $this->evaluate("SET CONTEXT $context"); |
||
678 | } |
||
679 | |||
680 | /** |
||
681 | * Set the extension to be used for continuation upon exiting the application. |
||
682 | * |
||
683 | * Setting the extension does NOT automatically reset the priority. If you want to start with the first priority of the |
||
684 | * extension you should set the priority yourself. |
||
685 | * |
||
686 | * If you specify a non-existent extension you receive no error indication (['result'] is still 0) but you do |
||
687 | * get a warning message on the Asterisk console. |
||
688 | * |
||
689 | * @link http://www.voip-info.org/wiki-set+extension |
||
690 | * @param string $extension |
||
691 | * @return array, see evaluate for return information. |
||
692 | */ |
||
693 | function set_extension(string $extension): array { |
||
694 | return $this->evaluate("SET EXTENSION $extension"); |
||
695 | } |
||
696 | |||
697 | /** |
||
698 | * Enable/Disable Music on hold generator. |
||
699 | * |
||
700 | * @link http://www.voip-info.org/wiki-set+music |
||
701 | * @param boolean $enabled |
||
702 | * @param string $class |
||
703 | * @return array, see evaluate for return information. |
||
704 | */ |
||
705 | function set_music(bool $enabled = true, string $class = ''): array { |
||
706 | $enabled = ($enabled) ? 'ON' : 'OFF'; |
||
707 | return $this->evaluate("SET MUSIC $enabled $class"); |
||
708 | } |
||
709 | |||
710 | /** |
||
711 | * Set the priority to be used for continuation upon exiting the application. |
||
712 | * |
||
713 | * If you specify a non-existent priority you receive no error indication (['result'] is still 0) |
||
714 | * and no warning is issued on the Asterisk console. |
||
715 | * |
||
716 | * @link http://www.voip-info.org/wiki-set+priority |
||
717 | * @param integer $priority |
||
718 | * @return array, see evaluate for return information. |
||
719 | */ |
||
720 | function set_priority(int $priority): array { |
||
721 | return $this->evaluate("SET PRIORITY $priority"); |
||
722 | } |
||
723 | |||
724 | /** |
||
725 | * Sets a variable to the specified value. The variables so created can later be used by later using ${<variablename>} |
||
726 | * in the dialplan. |
||
727 | * |
||
728 | * These variables live in the channel Asterisk creates when you pickup a phone and as such they are both local and temporary. |
||
729 | * Variables created in one channel can not be accessed by another channel. When you hang up the phone, the channel is deleted |
||
730 | * and any variables in that channel are deleted as well. |
||
731 | * |
||
732 | * @link http://www.voip-info.org/wiki-set+variable |
||
733 | * @param string $variable is case sensitive |
||
734 | * @param string $value |
||
735 | * @return array, see evaluate for return information. |
||
736 | */ |
||
737 | function set_variable(string $variable, string $value): array { |
||
738 | $value = str_replace("\n", '\n', addslashes($value)); |
||
739 | return $this->evaluate("SET VARIABLE $variable \"$value\""); |
||
740 | } |
||
741 | |||
742 | /** |
||
743 | * Play the given audio file, allowing playback to be interrupted by a DTMF digit. This command is similar to the GET DATA |
||
744 | * command but this command returns after the first DTMF digit has been pressed while GET DATA can accumulated any number of |
||
745 | * digits before returning. |
||
746 | * |
||
747 | * @param string $filename without extension, often in /var/lib/asterisk/sounds |
||
748 | * @param string $escape_digits |
||
749 | * @param integer $offset |
||
750 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if playback completes with no |
||
751 | * digit received, otherwise a decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
752 | * @example examples/ping.php Ping an IP address |
||
753 | * |
||
754 | * @link http://www.voip-info.org/wiki-stream+file |
||
755 | */ |
||
756 | function stream_file(string $filename, string $escape_digits = '', int $offset = 0): array { |
||
757 | return $this->evaluate("STREAM FILE $filename \"$escape_digits\" $offset"); |
||
758 | } |
||
759 | |||
760 | /** |
||
761 | * Enable or disable TDD transmission/reception on the current channel. |
||
762 | * |
||
763 | * @link http://www.voip-info.org/wiki-tdd+mode |
||
764 | * @param string $setting can be on, off or mate |
||
765 | * @return array, see evaluate for return information. ['result'] is 1 on success, 0 if the channel is not TDD capable. |
||
766 | */ |
||
767 | function tdd_mode(string $setting): array { |
||
768 | return $this->evaluate("TDD MODE $setting"); |
||
769 | } |
||
770 | |||
771 | /** |
||
772 | * Sends $message to the Asterisk console via the 'verbose' message system. |
||
773 | * |
||
774 | * If the Asterisk verbosity level is $level or greater, send $message to the console. |
||
775 | * |
||
776 | * The Asterisk verbosity system works as follows. The Asterisk user gets to set the desired verbosity at startup time or later |
||
777 | * using the console 'set verbose' command. Messages are displayed on the console if their verbose level is less than or equal |
||
778 | * to desired verbosity set by the user. More important messages should have a low verbose level; less important messages |
||
779 | * should have a high verbose level. |
||
780 | * |
||
781 | * @link http://www.voip-info.org/wiki-verbose |
||
782 | * @param string $message |
||
783 | * @param integer $level from 1 to 4 |
||
784 | * @return array, see evaluate for return information. |
||
785 | */ |
||
786 | function verbose(string $message, int $level = 1): array { |
||
787 | $ret = []; |
||
788 | foreach (explode("\n", str_replace("\r\n", "\n", print_r($message, true))) as $msg) { |
||
789 | @syslog(LOG_WARNING, $msg); |
||
790 | $ret = $this->evaluate("VERBOSE \"$msg\" $level"); |
||
791 | } |
||
792 | return $ret; |
||
793 | } |
||
794 | |||
795 | /** |
||
796 | * Waits up to $timeout milliseconds for channel to receive a DTMF digit. |
||
797 | * |
||
798 | * @link http://www.voip-info.org/wiki-wait+for+digit |
||
799 | * @param integer $timeout in milliseconds. Use -1 for the timeout value if you want the call to wait indefinitely. |
||
800 | * @return array, see evaluate for return information. ['result'] is 0 if wait completes with no |
||
801 | * digit received, otherwise a decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
802 | */ |
||
803 | function wait_for_digit(int $timeout = -1): array { |
||
804 | return $this->evaluate("WAIT FOR DIGIT $timeout"); |
||
805 | } |
||
806 | |||
807 | |||
808 | // ********************************************************************************************************* |
||
809 | // ** APPLICATIONS ** |
||
810 | // ********************************************************************************************************* |
||
811 | |||
812 | /** |
||
813 | * Set absolute maximum time of call. |
||
814 | * |
||
815 | * Note that the timeout is set from the current time forward, not counting the number of seconds the call has already been up. |
||
816 | * Each time you call AbsoluteTimeout(), all previous absolute timeouts are cancelled. |
||
817 | * Will return the call to the T extension so that you can playback an explanatory note to the calling party (the called party |
||
818 | * will not hear that) |
||
819 | * |
||
820 | * @link http://www.voip-info.org/wiki-Asterisk+-+documentation+of+application+commands |
||
821 | * @link http://www.dynx.net/ASTERISK/AGI/ccard/agi-ccard.agi |
||
822 | * @param integer $seconds allowed, 0 disables timeout |
||
823 | * @return array, see evaluate for return information. |
||
824 | */ |
||
825 | function exec_absolutetimeout(int $seconds = 0): array { |
||
826 | return $this->exec('AbsoluteTimeout', $seconds); |
||
827 | } |
||
828 | |||
829 | /** |
||
830 | * Executes an AGI compliant application. |
||
831 | * |
||
832 | * @param string $command |
||
833 | * @param string $args |
||
834 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or if application requested hangup, or 0 on non-hangup exit. |
||
835 | */ |
||
836 | function exec_agi(string $command, string $args): array { |
||
837 | return $this->exec("AGI $command", $args); |
||
838 | } |
||
839 | |||
840 | /** |
||
841 | * Set Language. |
||
842 | * |
||
843 | * @param string $language code |
||
844 | * @return array, see evaluate for return information. |
||
845 | */ |
||
846 | function exec_setlanguage(string $language = 'en'): array { |
||
847 | return $this->exec('Set', 'CHANNEL(language)=' . $language); |
||
848 | } |
||
849 | |||
850 | /** |
||
851 | * Do ENUM Lookup. |
||
852 | * |
||
853 | * Note: to retrieve the result, use |
||
854 | * get_variable('ENUM'); |
||
855 | * |
||
856 | * @param $exten |
||
857 | * @return array, see evaluate for return information. |
||
858 | */ |
||
859 | function exec_enumlookup($exten): array { |
||
860 | return $this->exec('EnumLookup', $exten); |
||
861 | } |
||
862 | |||
863 | /** |
||
864 | * Dial. |
||
865 | * |
||
866 | * Dial takes input from ${VXML_URL} to send XML Url to Cisco 7960 |
||
867 | * Dial takes input from ${ALERT_INFO} to set ring cadence for Cisco phones |
||
868 | * Dial returns ${CAUSECODE}: If the dial failed, this is the errormessage. |
||
869 | * Dial returns ${DIALSTATUS}: Text code returning status of last dial attempt. |
||
870 | * |
||
871 | * @link http://www.voip-info.org/wiki-Asterisk+cmd+Dial |
||
872 | * @param string $type |
||
873 | * @param string $identifier |
||
874 | * @param integer $timeout |
||
875 | * @param string $options |
||
876 | * @param string $url |
||
877 | * @return array, see evaluate for return information. |
||
878 | */ |
||
879 | function exec_dial(string $type, string $identifier, $timeout = null, $options = null, $url = null): array { |
||
880 | return $this->exec( |
||
881 | 'Dial', trim("$type/$identifier" . $this->option_delim . $timeout . $this->option_delim . $options . $this->option_delim . $url, $this->option_delim)); |
||
882 | } |
||
883 | |||
884 | /** |
||
885 | * Goto. |
||
886 | * |
||
887 | * This function takes three arguments: context,extension, and priority, but the leading arguments |
||
888 | * are optional, not the trailing arguments. Those goto($z) sets the priority to $z. |
||
889 | * |
||
890 | * @param string $a |
||
891 | * @param string $b ; |
||
892 | * @param string $c ; |
||
893 | * @return array, see evaluate for return information. |
||
894 | */ |
||
895 | function exec_goto(string $a, $b = null, $c = null): array { |
||
896 | return $this->exec('Goto', trim($a . $this->option_delim . $b . $this->option_delim . $c, $this->option_delim)); |
||
897 | } |
||
898 | |||
899 | |||
900 | // ********************************************************************************************************* |
||
901 | // ** FAST PASSING ** |
||
902 | // ********************************************************************************************************* |
||
903 | |||
904 | /** |
||
905 | * Say the given digit string, returning early if any of the given DTMF escape digits are received on the channel. |
||
906 | * Return early if $buffer is adequate for request. |
||
907 | * |
||
908 | * @link http://www.voip-info.org/wiki-say+digits |
||
909 | * @param string $buffer |
||
910 | * @param integer $digits |
||
911 | * @param string $escape_digits |
||
912 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if playback completes with no |
||
913 | * digit received, otherwise a decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
914 | */ |
||
915 | function fastpass_say_digits(string &$buffer, int $digits, string $escape_digits = ''): array { |
||
916 | if ($buffer == '' || $this->proceedDigits($buffer, $escape_digits)) { |
||
917 | $res = $this->say_digits($digits, $escape_digits); |
||
918 | $this->appendBuffer($buffer, $res); |
||
919 | return $res; |
||
920 | } |
||
921 | return ['code' => AGIRES_OK, |
||
922 | 'result' => $this->ordBuffer($buffer)]; |
||
923 | } |
||
924 | |||
925 | /** |
||
926 | * Say the given number, returning early if any of the given DTMF escape digits are received on the channel. |
||
927 | * Return early if $buffer is adequate for request. |
||
928 | * |
||
929 | * @link http://www.voip-info.org/wiki-say+number |
||
930 | * @param string $buffer |
||
931 | * @param integer $number |
||
932 | * @param string $escape_digits |
||
933 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if playback completes with no |
||
934 | * digit received, otherwise a decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
935 | */ |
||
936 | function fastpass_say_number(string &$buffer, int $number, string $escape_digits = ''): array { |
||
937 | if ($buffer == '' || $this->proceedDigits($buffer, $escape_digits)) { |
||
938 | $res = $this->say_number($number, $escape_digits); |
||
939 | $this->appendBuffer($buffer, $res); |
||
940 | return $res; |
||
941 | } |
||
942 | return ['code' => AGIRES_OK, |
||
943 | 'result' => $this->ordBuffer($buffer)]; |
||
944 | } |
||
945 | |||
946 | /** |
||
947 | * Say the given character string, returning early if any of the given DTMF escape digits are received on the channel. |
||
948 | * Return early if $buffer is adequate for request. |
||
949 | * |
||
950 | * @link http://www.voip-info.org/wiki-say+phonetic |
||
951 | * @param string $buffer |
||
952 | * @param string $text |
||
953 | * @param string $escape_digits |
||
954 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if playback completes with no |
||
955 | * digit received, otherwise a decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
956 | */ |
||
957 | function fastpass_say_phonetic(string &$buffer, string $text, string $escape_digits = ''): array { |
||
958 | if ($buffer == '' || $this->proceedDigits($buffer, $escape_digits)) { |
||
959 | $res = $this->say_phonetic($text, $escape_digits); |
||
960 | $this->appendBuffer($buffer, $res); |
||
961 | return $res; |
||
962 | } |
||
963 | return ['code' => AGIRES_OK, |
||
964 | 'result' => $this->ordBuffer($buffer)]; |
||
965 | } |
||
966 | |||
967 | /** |
||
968 | * Say a given time, returning early if any of the given DTMF escape digits are received on the channel. |
||
969 | * Return early if $buffer is adequate for request. |
||
970 | * |
||
971 | * @link http://www.voip-info.org/wiki-say+time |
||
972 | * @param string $buffer |
||
973 | * @param integer $time number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC). |
||
974 | * @param string $escape_digits |
||
975 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if playback completes with no |
||
976 | * digit received, otherwise a decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
977 | */ |
||
978 | function fastpass_say_time(string &$buffer, $time = null, string $escape_digits = ''): array { |
||
979 | if ($buffer == '' || $this->proceedDigits($buffer, $escape_digits)) { |
||
980 | $res = $this->say_time($time, $escape_digits); |
||
981 | $this->appendBuffer($buffer, $res); |
||
982 | return $res; |
||
983 | } |
||
984 | return ['code' => AGIRES_OK, |
||
985 | 'result' => $this->ordBuffer($buffer)]; |
||
986 | } |
||
987 | |||
988 | /** |
||
989 | * Play the given audio file, allowing playback to be interrupted by a DTMF digit. This command is similar to the GET DATA |
||
990 | * command but this command returns after the first DTMF digit has been pressed while GET DATA can accumulated any number of |
||
991 | * digits before returning. |
||
992 | * Return early if $buffer is adequate for request. |
||
993 | * |
||
994 | * @link http://www.voip-info.org/wiki-stream+file |
||
995 | * @param string $buffer |
||
996 | * @param string $filename without extension, often in /var/lib/asterisk/sounds |
||
997 | * @param string $escape_digits |
||
998 | * @param integer $offset |
||
999 | * @return array, see evaluate for return information. ['result'] is -1 on hangup or error, 0 if playback completes with no |
||
1000 | * digit received, otherwise a decimal value of the DTMF tone. Use chr() to convert to ASCII. |
||
1001 | */ |
||
1002 | function fastpass_stream_file(string &$buffer, string $filename, string $escape_digits = '', int $offset = 0): array { |
||
1003 | if ($buffer == '' || $this->proceedDigits($buffer, $escape_digits)) { |
||
1004 | $res = $this->stream_file($filename, $escape_digits, $offset); |
||
1005 | $this->appendBuffer($buffer, $res); |
||
1006 | return $res; |
||
1007 | } |
||
1008 | return ['code' => AGIRES_OK, |
||
1009 | 'result' => $this->ordBuffer($buffer), |
||
1010 | 'endpos' => 0]; |
||
1011 | } |
||
1012 | |||
1013 | /** |
||
1014 | * Use festival to read text. |
||
1015 | * Return early if $buffer is adequate for request. |
||
1016 | * |
||
1017 | * @link http://www.cstr.ed.ac.uk/projects/festival/ |
||
1018 | * @param string $buffer |
||
1019 | * @param string $text |
||
1020 | * @param string $escape_digits |
||
1021 | * @param integer $frequency |
||
1022 | * @return array, see evaluate for return information. |
||
1023 | */ |
||
1024 | function fastpass_text2wav(string &$buffer, string $text, string $escape_digits = '', int $frequency = 8000): array { |
||
1025 | if ($buffer == '' || $this->proceedDigits($buffer, $escape_digits)) { |
||
1026 | $res = $this->text2wav($text, $escape_digits, $frequency); |
||
1027 | $this->appendBuffer($buffer, $res); |
||
1028 | return $res; |
||
1029 | } |
||
1030 | return ['code' => AGIRES_OK, |
||
1031 | 'result' => $this->ordBuffer($buffer), |
||
1032 | 'endpos' => 0]; |
||
1033 | } |
||
1034 | |||
1035 | /** |
||
1036 | * Use Cepstral Swift to read text. |
||
1037 | * Return early if $buffer is adequate for request. |
||
1038 | * |
||
1039 | * @link http://www.cepstral.com/ |
||
1040 | * @param string $buffer |
||
1041 | * @param string $text |
||
1042 | * @param string $escape_digits |
||
1043 | * @param integer $frequency |
||
1044 | * @param $voice |
||
1045 | * @return array, see evaluate for return information. |
||
1046 | */ |
||
1047 | function fastpass_swift(string &$buffer, string $text, string $escape_digits = '', int $frequency = 8000, $voice = null): array { |
||
1048 | if ($buffer == '' || $this->proceedDigits($buffer, $escape_digits)) { |
||
1049 | $res = $this->swift($text, $escape_digits, $frequency, $voice); |
||
1050 | $this->appendBuffer($buffer, $res); |
||
1051 | return $res; |
||
1052 | } |
||
1053 | return ['code' => AGIRES_OK, |
||
1054 | 'result' => $this->ordBuffer($buffer), |
||
1055 | 'endpos' => 0]; |
||
1056 | } |
||
1057 | |||
1058 | /** |
||
1059 | * Say Punctuation in a string. |
||
1060 | * Return early if $buffer is adequate for request. |
||
1061 | * |
||
1062 | * @param string $buffer |
||
1063 | * @param string $text |
||
1064 | * @param string $escape_digits |
||
1065 | * @param integer $frequency |
||
1066 | * @return array, see evaluate for return information. |
||
1067 | */ |
||
1068 | function fastpass_say_punctuation(string &$buffer, string $text, string $escape_digits = '', int $frequency = 8000): array { |
||
1069 | if ($buffer == '' || $this->proceedDigits($buffer, $escape_digits)) { |
||
1070 | $res = $this->say_punctuation($text, $escape_digits, $frequency); |
||
1071 | $this->appendBuffer($buffer, $res); |
||
1072 | return $res; |
||
1073 | } |
||
1074 | return ['code' => AGIRES_OK, |
||
1075 | 'result' => $this->ordBuffer($buffer)]; |
||
1076 | } |
||
1077 | |||
1078 | /** |
||
1079 | * Plays the given file and receives DTMF data. |
||
1080 | * Return early if $buffer is adequate for request. |
||
1081 | * |
||
1082 | * This is similar to STREAM FILE, but this command can accept and return many DTMF digits, |
||
1083 | * while STREAM FILE returns immediately after the first DTMF digit is detected. |
||
1084 | * |
||
1085 | * Asterisk looks for the file to play in /var/lib/asterisk/sounds by default. |
||
1086 | * |
||
1087 | * If the user doesn't press any keys when the message plays, there is $timeout milliseconds |
||
1088 | * of silence then the command ends. |
||
1089 | * |
||
1090 | * The user has the opportunity to press a key at any time during the message or the |
||
1091 | * post-message silence. If the user presses a key while the message is playing, the |
||
1092 | * message stops playing. When the first key is pressed a timer starts counting for |
||
1093 | * $timeout milliseconds. Every time the user presses another key the timer is restarted. |
||
1094 | * The command ends when the counter goes to zero or the maximum number of digits is entered, |
||
1095 | * whichever happens first. |
||
1096 | * |
||
1097 | * If you don't specify a time out then a default timeout of 2000 is used following a pressed |
||
1098 | * digit. If no digits are pressed then 6 seconds of silence follow the message. |
||
1099 | * |
||
1100 | * If you don't specify $max_digits then the user can enter as many digits as they want. |
||
1101 | * |
||
1102 | * Pressing the # key has the same effect as the timer running out: the command ends and |
||
1103 | * any previously keyed digits are returned. A side effect of this is that there is no |
||
1104 | * way to read a # key using this command. |
||
1105 | * |
||
1106 | * @link http://www.voip-info.org/wiki-get+data |
||
1107 | * @param string $buffer |
||
1108 | * @param string $filename file to play. Do not include file extension. |
||
1109 | * @param integer $timeout milliseconds |
||
1110 | * @param integer $max_digits |
||
1111 | * @return array, see evaluate for return information. ['result'] holds the digits and ['data'] holds the timeout if present. |
||
1112 | * |
||
1113 | * This differs from other commands with return DTMF as numbers representing ASCII characters. |
||
1114 | */ |
||
1115 | function fastpass_get_data(string &$buffer, string $filename, $timeout = null, $max_digits = null): array { |
||
1116 | if (is_null($max_digits) || strlen($buffer) < $max_digits) { |
||
1117 | if ($buffer == '') { |
||
1118 | $res = $this->get_data($filename, $timeout, $max_digits); |
||
1119 | if ($res['code'] == AGIRES_OK) { |
||
1120 | $buffer .= $res['result']; |
||
1121 | } |
||
1122 | return $res; |
||
1123 | } |
||
1124 | while (is_null($max_digits) || strlen($buffer) < $max_digits) { |
||
1125 | $res = $this->wait_for_digit(); |
||
1126 | if ($res['code'] != AGIRES_OK) { |
||
1127 | return $res; |
||
1128 | } |
||
1129 | if ($res['result'] == ord('#')) { |
||
1130 | break; |
||
1131 | } |
||
1132 | $buffer .= chr($res['result']); |
||
1133 | } |
||
1134 | } |
||
1135 | return ['code' => AGIRES_OK, |
||
1136 | 'result' => $buffer]; |
||
1137 | } |
||
1138 | |||
1139 | // ********************************************************************************************************* |
||
1140 | // ** DERIVED ** |
||
1141 | // ********************************************************************************************************* |
||
1142 | |||
1143 | /** |
||
1144 | * Menu. |
||
1145 | * |
||
1146 | * This function presents the user with a menu and reads the response |
||
1147 | * |
||
1148 | * @param array $choices has the following structure: |
||
1149 | * array('1'=>'*Press 1 for this', // festival reads if prompt starts with * |
||
1150 | * '2'=>'some-gsm-without-extension', |
||
1151 | * '*'=>'*Press star for help'); |
||
1152 | * @param int $timeout |
||
1153 | * @return mixed key pressed on success, -1 on failure |
||
1154 | */ |
||
1155 | function menu(array $choices, int $timeout = 2000) { |
||
1156 | $keys = join('', array_keys($choices)); |
||
1157 | $choice = null; |
||
1158 | while (is_null($choice)) { |
||
1159 | foreach ($choices as $prompt) { |
||
1160 | if ($prompt[0] == '*') { |
||
1161 | $ret = $this->text2wav(substr($prompt, 1), $keys); |
||
1162 | } else { |
||
1163 | $ret = $this->stream_file($prompt, $keys); |
||
1164 | } |
||
1165 | |||
1166 | if ($ret['code'] != AGIRES_OK || $ret['result'] == -1) { |
||
1167 | $choice = -1; |
||
1168 | break; |
||
1169 | } |
||
1170 | |||
1171 | if ($ret['result'] != 0) { |
||
1172 | $choice = chr($ret['result']); |
||
1173 | break; |
||
1174 | } |
||
1175 | } |
||
1176 | |||
1177 | if (is_null($choice)) { |
||
1178 | $ret = $this->get_data('beep', $timeout, 1); |
||
1179 | if ($ret['code'] != AGIRES_OK || $ret['result'] == -1) { |
||
1180 | $choice = -1; |
||
1181 | } elseif ($ret['result'] != '' && strpos(' ' . $keys, $ret['result'])) { |
||
1182 | $choice = $ret['result']; |
||
1183 | } |
||
1184 | } |
||
1185 | } |
||
1186 | return $choice; |
||
1187 | } |
||
1188 | |||
1189 | /** |
||
1190 | * setContext - Set context, extension and priority. |
||
1191 | * |
||
1192 | * @param string $context |
||
1193 | * @param string $extension |
||
1194 | * @param string $priority |
||
1195 | */ |
||
1196 | function setContext(string $context, string $extension = 's', $priority = 1) { |
||
1197 | $this->set_context($context); |
||
1198 | $this->set_extension($extension); |
||
1199 | $this->set_priority($priority); |
||
1200 | } |
||
1201 | |||
1202 | /** |
||
1203 | * Parse caller id. |
||
1204 | * |
||
1205 | * @param string $callerid |
||
1206 | * @return array('Name'=>$name, 'Number'=>$number) |
||
1207 | * @example examples/dtmf.php Get DTMF tones from the user and say the digits |
||
1208 | * @example examples/input.php Get text input from the user and say it back |
||
1209 | * |
||
1210 | * "name" <proto:user@server:port> |
||
1211 | * |
||
1212 | */ |
||
1213 | function parse_callerid($callerid = null): array { |
||
1214 | if (is_null($callerid)) { |
||
1215 | $callerid = $this->request['agi_callerid']; |
||
1216 | } |
||
1217 | |||
1218 | $ret = ['name' => '', |
||
1219 | 'protocol' => '', |
||
1220 | 'username' => '', |
||
1221 | 'host' => '', |
||
1222 | 'port' => '']; |
||
1223 | $callerid = trim($callerid); |
||
1224 | |||
1225 | if ($callerid[0] == '"' || $callerid[0] == "'") { |
||
1226 | $d = $callerid[0]; |
||
1227 | $callerid = explode($d, substr($callerid, 1)); |
||
1228 | $ret['name'] = array_shift($callerid); |
||
1229 | $callerid = join($d, $callerid); |
||
1230 | } |
||
1231 | |||
1232 | $callerid = explode('@', trim($callerid, '<> ')); |
||
1233 | $username = explode(':', array_shift($callerid)); |
||
1234 | if (count($username) == 1) { |
||
1235 | $ret['username'] = $username[0]; |
||
1236 | } else { |
||
1237 | $ret['protocol'] = array_shift($username); |
||
1238 | $ret['username'] = join(':', $username); |
||
1239 | } |
||
1240 | |||
1241 | $callerid = join('@', $callerid); |
||
1242 | $host = explode(':', $callerid); |
||
1243 | if (count($host) == 1) { |
||
1244 | $ret['host'] = $host[0]; |
||
1245 | } else { |
||
1246 | $ret['host'] = array_shift($host); |
||
1247 | $ret['port'] = join(':', $host); |
||
1248 | } |
||
1249 | |||
1250 | return $ret; |
||
1251 | } |
||
1252 | |||
1253 | /** |
||
1254 | * Use festival to read text. |
||
1255 | * |
||
1256 | * @param string $text |
||
1257 | * @param string $escape_digits |
||
1258 | * @param integer $frequency |
||
1259 | * @return array | bool, see evaluate for return information. |
||
1260 | * @example examples/dtmf.php Get DTMF tones from the user and say the digits |
||
1261 | * @example examples/input.php Get text input from the user and say it back |
||
1262 | * @example examples/ping.php Ping an IP address |
||
1263 | * |
||
1264 | * @link http://www.cstr.ed.ac.uk/projects/festival/ |
||
1265 | */ |
||
1266 | function text2wav(string $text, string $escape_digits = '', int $frequency = 8000) { |
||
1267 | $text = trim($text); |
||
1268 | if ($text == '') { |
||
1269 | return true; |
||
1270 | } |
||
1271 | |||
1272 | $hash = md5($text); |
||
1273 | $fname = $this->config['phpagi']['tempdir'] . DIRECTORY_SEPARATOR; |
||
1274 | $fname .= 'text2wav_' . $hash; |
||
1275 | |||
1276 | // create wave file |
||
1277 | if (!file_exists("$fname.wav")) { |
||
1278 | // write text file |
||
1279 | if (!file_exists("$fname.txt")) { |
||
1280 | $fp = fopen("$fname.txt", 'w'); |
||
1281 | fputs($fp, $text); |
||
1282 | fclose($fp); |
||
1283 | } |
||
1284 | |||
1285 | shell_exec("{$this->config['festival']['text2wave']} -F $frequency -o $fname.wav $fname.txt"); |
||
1286 | } else { |
||
1287 | touch("$fname.txt"); |
||
1288 | touch("$fname.wav"); |
||
1289 | } |
||
1290 | |||
1291 | // stream it |
||
1292 | $ret = $this->stream_file($fname, $escape_digits); |
||
1293 | |||
1294 | // clean up old files |
||
1295 | $delete = time() - 2592000; // 1 month |
||
1296 | foreach (glob($this->config['phpagi']['tempdir'] . DIRECTORY_SEPARATOR . 'text2wav_*') as $file) |
||
1297 | if (filemtime($file) < $delete) { |
||
1298 | unlink($file); |
||
1299 | } |
||
1300 | |||
1301 | return $ret; |
||
1302 | } |
||
1303 | |||
1304 | /** |
||
1305 | * Use Cepstral Swift to read text. |
||
1306 | * |
||
1307 | * @link http://www.cepstral.com/ |
||
1308 | * @param string $text |
||
1309 | * @param string $escape_digits |
||
1310 | * @param integer $frequency |
||
1311 | * @param $voice |
||
1312 | * @return array | bool, see evaluate for return information. |
||
1313 | */ |
||
1314 | function swift(string $text, string $escape_digits = '', int $frequency = 8000, $voice = null) { |
||
1315 | if (!is_null($voice)) { |
||
1316 | $voice = "-n $voice"; |
||
1317 | } elseif (isset($this->config['cepstral']['voice'])) { |
||
1318 | $voice = "-n {$this->config['cepstral']['voice']}"; |
||
1319 | } |
||
1320 | |||
1321 | $text = trim($text); |
||
1322 | if ($text == '') { |
||
1323 | return true; |
||
1324 | } |
||
1325 | |||
1326 | $hash = md5($text); |
||
1327 | $fname = $this->config['phpagi']['tempdir'] . DIRECTORY_SEPARATOR; |
||
1328 | $fname .= 'swift_' . $hash; |
||
1329 | |||
1330 | // create wave file |
||
1331 | if (!file_exists("$fname.wav")) { |
||
1332 | // write text file |
||
1333 | if (!file_exists("$fname.txt")) { |
||
1334 | $fp = fopen("$fname.txt", 'w'); |
||
1335 | fputs($fp, $text); |
||
1336 | fclose($fp); |
||
1337 | } |
||
1338 | |||
1339 | shell_exec("{$this->config['cepstral']['swift']} -p audio/channels=1,audio/sampling-rate=$frequency $voice -o $fname.wav -f $fname.txt"); |
||
1340 | } |
||
1341 | |||
1342 | // stream it |
||
1343 | $ret = $this->stream_file($fname, $escape_digits); |
||
1344 | |||
1345 | // clean up old files |
||
1346 | $delete = time() - 2592000; // 1 month |
||
1347 | foreach (glob($this->config['phpagi']['tempdir'] . DIRECTORY_SEPARATOR . 'swift_*') as $file) |
||
1348 | if (filemtime($file) < $delete) { |
||
1349 | unlink($file); |
||
1350 | } |
||
1351 | |||
1352 | return $ret; |
||
1353 | } |
||
1354 | |||
1355 | /** |
||
1356 | * Text Input. |
||
1357 | * |
||
1358 | * Based on ideas found at http://www.voip-info.org/wiki-Asterisk+cmd+DTMFToText |
||
1359 | * |
||
1360 | * Example: |
||
1361 | * UC H LC i , SP h o w SP a r e SP y o u ? |
||
1362 | * $string = '*8'.'44*'.'*5'.'444*'.'00*'.'0*'.'44*'.'666*'.'9*'.'0*'.'2*'.'777*'.'33*'.'0*'.'999*'.'666*'.'88*'.'0000*'; |
||
1363 | * |
||
1364 | * @link http://www.voip-info.org/wiki-Asterisk+cmd+DTMFToText |
||
1365 | * @example examples/input.php Get text input from the user and say it back |
||
1366 | * |
||
1367 | * @param string $mode |
||
1368 | * @return string |
||
1369 | */ |
||
1370 | function text_input(string $mode = 'NUMERIC'): string { |
||
1371 | $alpha = ['k0' => ' ', |
||
1372 | 'k00' => ',', |
||
1373 | 'k000' => '.', |
||
1374 | 'k0000' => '?', |
||
1375 | 'k00000' => '0', |
||
1376 | 'k1' => '!', |
||
1377 | 'k11' => ':', |
||
1378 | 'k111' => ';', |
||
1379 | 'k1111' => '#', |
||
1380 | 'k11111' => '1', |
||
1381 | 'k2' => 'A', |
||
1382 | 'k22' => 'B', |
||
1383 | 'k222' => 'C', |
||
1384 | 'k2222' => '2', |
||
1385 | 'k3' => 'D', |
||
1386 | 'k33' => 'E', |
||
1387 | 'k333' => 'F', |
||
1388 | 'k3333' => '3', |
||
1389 | 'k4' => 'G', |
||
1390 | 'k44' => 'H', |
||
1391 | 'k444' => 'I', |
||
1392 | 'k4444' => '4', |
||
1393 | 'k5' => 'J', |
||
1394 | 'k55' => 'K', |
||
1395 | 'k555' => 'L', |
||
1396 | 'k5555' => '5', |
||
1397 | 'k6' => 'M', |
||
1398 | 'k66' => 'N', |
||
1399 | 'k666' => 'O', |
||
1400 | 'k6666' => '6', |
||
1401 | 'k7' => 'P', |
||
1402 | 'k77' => 'Q', |
||
1403 | 'k777' => 'R', |
||
1404 | 'k7777' => 'S', |
||
1405 | 'k77777' => '7', |
||
1406 | 'k8' => 'T', |
||
1407 | 'k88' => 'U', |
||
1408 | 'k888' => 'V', |
||
1409 | 'k8888' => '8', |
||
1410 | 'k9' => 'W', |
||
1411 | 'k99' => 'X', |
||
1412 | 'k999' => 'Y', |
||
1413 | 'k9999' => 'Z', |
||
1414 | 'k99999' => '9']; |
||
1415 | $symbol = ['k0' => '=', |
||
1416 | 'k1' => '<', |
||
1417 | 'k11' => '(', |
||
1418 | 'k111' => '[', |
||
1419 | 'k1111' => '{', |
||
1420 | 'k11111' => '1', |
||
1421 | 'k2' => '@', |
||
1422 | 'k22' => '$', |
||
1423 | 'k222' => '&', |
||
1424 | 'k2222' => '%', |
||
1425 | 'k22222' => '2', |
||
1426 | 'k3' => '>', |
||
1427 | 'k33' => ')', |
||
1428 | 'k333' => ']', |
||
1429 | 'k3333' => '}', |
||
1430 | 'k33333' => '3', |
||
1431 | 'k4' => '+', |
||
1432 | 'k44' => '-', |
||
1433 | 'k444' => '*', |
||
1434 | 'k4444' => '/', |
||
1435 | 'k44444' => '4', |
||
1436 | 'k5' => "'", |
||
1437 | 'k55' => '`', |
||
1438 | 'k555' => '5', |
||
1439 | 'k6' => '"', |
||
1440 | 'k66' => '6', |
||
1441 | 'k7' => '^', |
||
1442 | 'k77' => '7', |
||
1443 | 'k8' => "\\", |
||
1444 | 'k88' => '|', |
||
1445 | 'k888' => '8', |
||
1446 | 'k9' => '_', |
||
1447 | 'k99' => '~', |
||
1448 | 'k999' => '9']; |
||
1449 | $text = ''; |
||
1450 | do { |
||
1451 | $command = false; |
||
1452 | $result = $this->get_data('beep'); |
||
1453 | foreach (explode('*', $result['result']) as $code) { |
||
1454 | if ($command) { |
||
1455 | switch ($code[0]) { |
||
1456 | case '2': |
||
1457 | $text = substr($text, 0, strlen($text) - 1); |
||
1458 | break; // backspace |
||
1459 | case '5': |
||
1460 | $mode = 'LOWERCASE'; |
||
1461 | break; |
||
1462 | case '6': |
||
1463 | $mode = 'NUMERIC'; |
||
1464 | break; |
||
1465 | case '7': |
||
1466 | $mode = 'SYMBOL'; |
||
1467 | break; |
||
1468 | case '8': |
||
1469 | $mode = 'UPPERCASE'; |
||
1470 | break; |
||
1471 | case '9': |
||
1472 | $text = explode(' ', $text); |
||
1473 | unset($text[count($text) - 1]); |
||
1474 | $text = join(' ', $text); |
||
1475 | break; // backspace a word |
||
1476 | } |
||
1477 | $code = substr($code, 1); |
||
1478 | $command = false; |
||
1479 | } |
||
1480 | if ($code == '') { |
||
1481 | $command = true; |
||
1482 | } elseif ($mode == 'NUMERIC') { |
||
1483 | $text .= $code; |
||
1484 | } elseif ($mode == 'UPPERCASE' && isset($alpha['k' . $code])) { |
||
1485 | $text .= $alpha['k' . $code]; |
||
1486 | } elseif ($mode == 'LOWERCASE' && isset($alpha['k' . $code])) { |
||
1487 | $text .= strtolower($alpha['k' . $code]); |
||
1488 | } elseif ($mode == 'SYMBOL' && isset($symbol['k' . $code])) { |
||
1489 | $text .= $symbol['k' . $code]; |
||
1490 | } |
||
1491 | } |
||
1492 | $this->say_punctuation($text); |
||
1493 | } while (substr($result['result'], -2) == '**'); |
||
1494 | return $text; |
||
1495 | } |
||
1496 | |||
1497 | /** |
||
1498 | * Say Punctuation in a string. |
||
1499 | * |
||
1500 | * @param string $text |
||
1501 | * @param string $escape_digits |
||
1502 | * @param integer $frequency |
||
1503 | * @return array, see evaluate for return information. |
||
1504 | */ |
||
1505 | function say_punctuation(string $text, string $escape_digits = '', int $frequency = 8000): array { |
||
1506 | $ret = ""; |
||
1507 | for ($i = 0; $i < strlen($text); $i++) { |
||
1508 | switch ($text[$i]) { |
||
1509 | case ' ': |
||
1510 | $ret .= 'SPACE '; |
||
1511 | break; |
||
1512 | case ',': |
||
1513 | $ret .= 'COMMA '; |
||
1514 | break; |
||
1515 | case '.': |
||
1516 | $ret .= 'PERIOD '; |
||
1517 | break; |
||
1518 | case '?': |
||
1519 | $ret .= 'QUESTION MARK '; |
||
1520 | break; |
||
1521 | case '!': |
||
1522 | $ret .= 'EXPLANATION POINT '; |
||
1523 | break; |
||
1524 | case ':': |
||
1525 | $ret .= 'COLON '; |
||
1526 | break; |
||
1527 | case ';': |
||
1528 | $ret .= 'SEMICOLON '; |
||
1529 | break; |
||
1530 | case '#': |
||
1531 | $ret .= 'POUND '; |
||
1532 | break; |
||
1533 | case '=': |
||
1534 | $ret .= 'EQUALS '; |
||
1535 | break; |
||
1536 | case '<': |
||
1537 | $ret .= 'LESS THAN '; |
||
1538 | break; |
||
1539 | case '(': |
||
1540 | $ret .= 'LEFT PARENTHESIS '; |
||
1541 | break; |
||
1542 | case '[': |
||
1543 | $ret .= 'LEFT BRACKET '; |
||
1544 | break; |
||
1545 | case '{': |
||
1546 | $ret .= 'LEFT BRACE '; |
||
1547 | break; |
||
1548 | case '@': |
||
1549 | $ret .= 'AT '; |
||
1550 | break; |
||
1551 | case '$': |
||
1552 | $ret .= 'DOLLAR SIGN '; |
||
1553 | break; |
||
1554 | case '&': |
||
1555 | $ret .= 'AMPERSAND '; |
||
1556 | break; |
||
1557 | case '%': |
||
1558 | $ret .= 'PERCENT '; |
||
1559 | break; |
||
1560 | case '>': |
||
1561 | $ret .= 'GREATER THAN '; |
||
1562 | break; |
||
1563 | case ')': |
||
1564 | $ret .= 'RIGHT PARENTHESIS '; |
||
1565 | break; |
||
1566 | case ']': |
||
1567 | $ret .= 'RIGHT BRACKET '; |
||
1568 | break; |
||
1569 | case '}': |
||
1570 | $ret .= 'RIGHT BRACE '; |
||
1571 | break; |
||
1572 | case '+': |
||
1573 | $ret .= 'PLUS '; |
||
1574 | break; |
||
1575 | case '-': |
||
1576 | $ret .= 'MINUS '; |
||
1577 | break; |
||
1578 | case '*': |
||
1579 | $ret .= 'ASTERISK '; |
||
1580 | break; |
||
1581 | case '/': |
||
1582 | $ret .= 'SLASH '; |
||
1583 | break; |
||
1584 | case "'": |
||
1585 | $ret .= 'SINGLE QUOTE '; |
||
1586 | break; |
||
1587 | case '`': |
||
1588 | $ret .= 'BACK TICK '; |
||
1589 | break; |
||
1590 | case '"': |
||
1591 | $ret .= 'QUOTE '; |
||
1592 | break; |
||
1593 | case '^': |
||
1594 | $ret .= 'CAROT '; |
||
1595 | break; |
||
1596 | case "\\": |
||
1597 | $ret .= 'BACK SLASH '; |
||
1598 | break; |
||
1599 | case '|': |
||
1600 | $ret .= 'BAR '; |
||
1601 | break; |
||
1602 | case '_': |
||
1603 | $ret .= 'UNDERSCORE '; |
||
1604 | break; |
||
1605 | case '~': |
||
1606 | $ret .= 'TILDE '; |
||
1607 | break; |
||
1608 | default: |
||
1609 | $ret .= $text[$i] . ' '; |
||
1610 | break; |
||
1611 | } |
||
1612 | } |
||
1613 | return $this->text2wav($ret, $escape_digits, $frequency); |
||
1614 | } |
||
1615 | |||
1616 | /** |
||
1617 | * Create a new AGI_AsteriskManager. |
||
1618 | */ |
||
1619 | function &new_AsteriskManager(): AGI_AsteriskManager { |
||
1620 | $this->asm = new AGI_AsteriskManager(null, $this->config['asmanager']); |
||
1621 | $this->asm->setPagi($this); |
||
1622 | $this->config['asmanager'] =& $this->asm->config['asmanager']; |
||
1623 | return $this->asm; |
||
1624 | } |
||
1625 | |||
1626 | |||
1627 | // ********************************************************************************************************* |
||
1628 | // ** PRIVATE ** |
||
1629 | // ********************************************************************************************************* |
||
1630 | |||
1631 | |||
1632 | /** |
||
1633 | * Evaluate an AGI command. |
||
1634 | * |
||
1635 | * @access private |
||
1636 | * @param string $command |
||
1637 | * @return array ('code'=>$code, 'result'=>$result, 'data'=>$data) |
||
1638 | */ |
||
1639 | private function evaluate(string $command): array { |
||
1721 | } |
||
1722 | |||
1723 | /** |
||
1724 | * Log to console if debug mode. |
||
1725 | * |
||
1726 | * @param string $str |
||
1727 | * @param integer $vbl verbose level |
||
1728 | * @example examples/ping.php Ping an IP address |
||
1729 | * |
||
1730 | */ |
||
1731 | function conlog(string $str, int $vbl = 1) { |
||
1739 | } |
||
1740 | } |
||
1741 | } |
||
1742 | |||
1743 | /** |
||
1744 | * Find an executable in the path. |
||
1745 | * |
||
1746 | * @access private |
||
1747 | * @param string $cmd command to find |
||
1748 | * @param string $checkpath path to check |
||
1749 | * @return string the path to the command |
||
1750 | */ |
||
1751 | private function which(string $cmd, $checkpath = null) { |
||
1752 | if (is_null($checkpath)) { |
||
1753 | $chpath = getenv('PATH'); |
||
1754 | if ($chpath === false) { |
||
1755 | $chpath = '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:' . |
||
1756 | '/usr/X11R6/bin:/usr/local/apache/bin:/usr/local/mysql/bin'; |
||
1757 | } |
||
1758 | } else { |
||
1759 | $chpath = $checkpath; |
||
1760 | } |
||
1761 | |||
1762 | foreach (explode(':', $chpath) as $path) { |
||
1763 | if (is_executable("$path/$cmd")) { |
||
1764 | return "$path/$cmd"; |
||
1765 | } |
||
1766 | } |
||
1767 | |||
1768 | return false; |
||
1769 | } |
||
1770 | |||
1771 | /** |
||
1772 | * Make a folder recursively. |
||
1773 | * |
||
1774 | * @access private |
||
1775 | * @param string $folder |
||
1776 | * @param integer $perms |
||
1777 | * @return boolean |
||
1778 | */ |
||
1779 | private function make_folder(string $folder, int $perms = 0755): bool { |
||
1780 | $f = explode(DIRECTORY_SEPARATOR, $folder); |
||
1781 | $base = ''; |
||
1782 | for ($i = 0; $i < count($f); $i++) { |
||
1783 | $base .= $f[$i]; |
||
1784 | if ($f[$i] != '' && !file_exists($base)) { |
||
1785 | if (mkdir($base, $perms) == false) { |
||
1786 | return (false); |
||
1787 | } |
||
1788 | } |
||
1789 | $base .= DIRECTORY_SEPARATOR; |
||
1790 | } |
||
1791 | return (true); |
||
1792 | } |
||
1793 | |||
1794 | private function proceedDigits(string $buffer, string $escapeDigits): bool { |
||
1795 | if ($escapeDigits != "" && $buffer != "") { |
||
1796 | if (!strpos(chr(255) . $escapeDigits, $buffer[strlen($buffer) - 1])) { |
||
1797 | return true; |
||
1798 | } |
||
1799 | } |
||
1800 | return false; |
||
1801 | } |
||
1802 | |||
1803 | private function ordBuffer(string $buffer): int { |
||
1805 | } |
||
1806 | |||
1807 | private function appendBuffer(string &$buffer, array $res) { |
||
1808 | if ($res['code'] == AGIRES_OK && $res['result'] > 0) { |
||
1809 | $buffer .= chr($res['result']); |
||
1810 | } |
||
1811 | } |
||
1812 | } |
||
1813 | |||
1814 | |||
1815 | /** |
||
1816 | * error handler for phpagi. |
||
1817 | * |
||
1818 | * @param integer $level PHP error level |
||
1819 | * @param string $message error message |
||
1820 | * @param string $file path to file |
||
1821 | * @param integer $line line number of error |
||
1822 | * @param array $context variables in the current scope |
||
1823 | */ |
||
1824 | function phpagi_error_handler(int $level, string $message, string $file, int $line, array $context) { |
||
1825 | if (ini_get('error_reporting') == 0) { |
||
1826 | return; // this happens with an @ |
||
1827 | } |
||
1828 | |||
1829 | @syslog(LOG_WARNING, $file . '[' . $line . ']: ' . $message); |
||
1830 | |||
1831 | global $phpagi_error_handler_email; |
||
1832 | if (function_exists('mail') && !is_null($phpagi_error_handler_email)) { // generate email debugging information |
||
1833 | // decode error level |
||
1834 | switch ($level) { |
||
1835 | case E_WARNING: |
||
1836 | case E_USER_WARNING: |
||
1837 | $level = "Warning"; |
||
1838 | break; |
||
1839 | case E_NOTICE: |
||
1840 | case E_USER_NOTICE: |
||
1841 | $level = "Notice"; |
||
1842 | break; |
||
1843 | case E_USER_ERROR: |
||
1844 | $level = "Error"; |
||
1845 | break; |
||
1846 | } |
||
1847 | |||
1848 | // build message |
||
1849 | $basefile = basename($file); |
||
1850 | $subject = "$basefile/$line/$level: $message"; |
||
1851 | $message = "$level: $message in $file on line $line\n\n"; |
||
1852 | |||
1853 | // TODO: OLD |
||
1854 | /*if (strpos(' ' . strtolower($message), 'mysql')) { |
||
1855 | if (function_exists('mysql_errno')) { |
||
1856 | $message .= 'MySQL error ' . mysql_errno() . ": " . mysql_error() . "\n\n"; |
||
1857 | } else if (function_exists('mysqli_errno')) { |
||
1858 | $message .= 'MySQL error ' . mysqli_errno() . ": " . mysqli_error() . "\n\n"; |
||
1859 | } |
||
1914 |