root/modules/branches/2.10/sipsettings/functions.inc.php

Revision 13091, 17.4 kB (checked in by p_lindheimer, 1 year ago)

adds FREEPBX_IS_AUTH checking to most module files re #5478

Line 
1 <?php
2 /* $Id:$ */
3 if (!defined('FREEPBX_IS_AUTH')) { die('No direct script access allowed'); }
4
5 // Original Release by Philippe Lindheimer
6 // Copyright Philippe Lindheimer (2009)
7 // Copyright Bandwidth.com (2009)
8 /*
9     This program is free software: you can redistribute it and/or modify
10     it under the terms of the GNU Affero General Public License as
11     published by the Free Software Foundation, either version 3 of the
12     License, or (at your option) any later version.
13
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU Affero General Public License for more details.
18
19     You should have received a copy of the GNU Affero General Public License
20     along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 // Use hookGet_config so that everyone (like core) will have written their
24 // SIP settings and then we can remove any that we are going to override
25 //
26
27 /* Field Values for type field */
28 define('SIP_NORMAL','0');
29 define('SIP_CODEC','1');
30 define('SIP_VIDEO_CODEC','2');
31 define('SIP_CUSTOM','9');
32
33 class sipsettings_validate {
34   var $errors = array();
35
36   /* checks if value is an integer */
37   function is_int($value, $item, $message, $negative=false) {
38     $value = trim($value);
39     if ($value != '' && $negative) {
40       $tmp_value = substr($value,0,1) == '-' ? substr($value,1) : $value;
41       if (!ctype_digit($tmp_value)) {
42         $this->errors[] = array('id' => $item, 'value' => $value, 'message' => $message);
43       }
44     } elseif (!$negative) {
45       if (!ctype_digit($value) || ($value < 0 )) {
46         $this->errors[] = array('id' => $item, 'value' => $value, 'message' => $message);
47       }
48     }
49     return $value;
50   }
51
52   /* checks if value is valid port between 1024 - 6 65535 */
53   function is_ip_port($value, $item, $message) {
54     $value = trim($value);
55     if ($value != '' && (!ctype_digit($value) || $value < 1024 || $value > 65535)) {
56       $this->errors[] = array('id' => $item, 'value' => $value, 'message' => $message);
57     }
58     return $value;
59   }
60
61   /* checks if value is valid ip format */
62   function is_ip($value, $item, $message, $ipv6_ok=false) {
63     $value = trim($value);
64     if ($value != '' && !preg_match('|^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$|',$value,$matches)) {
65       $regex = '/^\s*((?=.*::.*)(::)?([0-9A-F]{1,4}(:(?=[0-9A-F])|(?!\2)(?!\5)(::)|\z)){0,7}|((?=.*::.*)(::)?([0-9A-F]{1,4}(:(?=[0-9A-F])|(?!\7)(?!\10)(::))){0,5}|([0-9A-F]{1,4}:){6})((25[0-5]|(2[0-4]|1[0-9]|[1-9]?)[0-9])(\.(?=.)|\z)){4}|([0-9A-F]{1,4}:){7}[0-9A-F]{1,4})\s*$/i';
66       if ($ipv6_ok && ($value == '::' || preg_match($regex,$value, $matches))) {
67         return $value;
68       } else {
69         $this->errors[] = array('id' => $item, 'value' => $value, 'message' => $message);
70       }
71     }
72     return $value;
73   }
74
75   /* checks if value is valid ip netmask format */
76   function is_netmask($value, $item, $message) {
77     $value = trim($value);
78     if ($value != '' && !(preg_match('|^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$|',$value,$matches) || (ctype_digit($value) && $value >= 0 && $value <= 24))) {
79       $this->errors[] = array('id' => $item, 'value' => $value, 'message' => $message);
80     }
81     return $value;
82   }
83
84   /* checks if value is valid alpha numeric format */
85   function is_alphanumeric($value, $item, $message) {
86     $value = trim($value);
87       if ($value != '' && !preg_match("/^\s*([a-zA-Z0-9.&\-@_!<>!\"\']+)\s*$/",$value,$matches)) {
88       $this->errors[] = array('id' => $item, 'value' => $value, 'message' => $message);
89     }
90     return $value;
91   }
92
93   /* trigger a validation error to be appended to this class */
94   function log_error($value, $item, $message) {
95     $this->errors[] = array('id' => $item, 'value' => $value, 'message' => $message);
96     return $value;
97   }
98 }
99
100 function sipsettings_hookGet_config($engine) {
101   global $core_conf;
102     global $ext// is this the best way to pass this?
103
104   switch($engine) {
105     case "asterisk":
106       if (isset($core_conf) && is_a($core_conf, "core_conf")) {
107         $raw_settings = sipsettings_get(true);
108
109         /* TODO: This is example concept code
110
111            The only real conflicts are codecs (mainly cause
112            it will look ugly. So we should strip those but
113            leave the rest. If we overrite it, oh well
114
115                  */
116         $idx = 0;
117         foreach ($core_conf->_sip_general as $entry) {
118           switch (strtolower($entry['key'])) {
119             case 'allow':
120             case 'disallow':
121               unset($core_conf->_sip_general[$idx]);
122             break;
123           default:
124             // do nothing
125           }
126           $idx++;
127         }
128
129         foreach ($raw_settings as $var) {
130           switch ($var['type']) {
131             case SIP_NORMAL:
132               $interim_settings[$var['keyword']] = $var['data'];
133             break;
134
135             case SIP_CODEC:
136               $codecs[$var['keyword']] = $var['data'];
137             break;
138
139             case SIP_VIDEO_CODEC:
140               $video_codecs[$var['keyword']] = $var['data'];
141             break;
142
143             case SIP_CUSTOM:
144               $sip_settings[] = array($var['keyword'], $var['data']);
145             break;
146           default:
147             // Error should be above
148           }
149         }
150         unset($raw_settings);
151
152         /* Codecs First */
153         $core_conf->addSipGeneral('disallow','all');
154         asort($codecs);
155         foreach ($codecs as $codec => $enabled) {
156           if ($enabled != '') {
157             $core_conf->addSipGeneral('allow',$codec);
158           }
159         }
160         unset($codecs);
161
162         if ($interim_settings['videosupport'] == 'yes') {
163           asort($video_codecs);
164           foreach ($video_codecs as $codec => $enabled) {
165             if ($enabled != '') {
166               $core_conf->addSipGeneral('allow',$codec);
167             }
168           }
169         }
170         unset($video_codecs);
171
172         /* next figure out what we need to write out (deal with things like nat combos, etc. */
173
174         $nat_mode = $interim_settings['nat_mode'];
175         $jbenable = $interim_settings['jbenable'];
176         if (is_array($interim_settings)) foreach ($interim_settings as $key => $value) {
177           switch ($key) {
178             case 'nat_mode':
179             break;
180
181             case 'externhost_val':
182               if ($nat_mode == 'externhost' && $value != '') {
183                 $sip_settings[] = array('externhost', $value);
184               }
185             break;
186
187             case 'externrefresh':
188               if ($nat_mode == 'externhost' && $value != '') {
189                 $sip_settings[] = array($key, $value);
190               }
191             break;
192
193             case 'externip_val':
194               if ($nat_mode == 'externip' && $value != '') {
195                 $sip_settings[] = array('externip', $value);
196               }
197             break;
198
199             case 'jbforce':
200             case 'jbimpl':
201             case 'jbmaxsize':
202             case 'jbresyncthreshold':
203             case 'jblog':
204               if ($jbenable == 'yes' && $value != '') {
205                 $sip_settings[] = array($key, $value);
206               }
207             break;
208
209             case 'sip_language':
210               if ($key != '') {
211                 $sip_settings[] = array('language', $value);
212                 $ext->addGlobal('SIPLANG',$value);
213               }
214             break;
215
216             default:
217               if (substr($key,0,9) == "localnet_" && $value != '') {
218                 if ($nat_mode != 'public') {
219                   $seq = substr($key,9);
220                   $network = "$value/".$interim_settings["netmask_$seq"];
221                   $sip_settings[] = array('localnet', $network);
222                 }
223               } else if (substr($key,0,8) == "netmask_") {
224                 // do nothing, handled above
225               } else {
226                 $sip_settings[] = array($key, $value);
227               }
228             }
229           }
230           unset($interim_settings);
231           if (is_array($sip_settings)) foreach ($sip_settings as $entry) {
232             if ($entry[1] != '') {
233               $core_conf->addSipGeneral($entry[0],$entry[1]);
234             }
235           }
236       }
237     break;
238   }
239
240   return true;
241 }
242
243 function sipsettings_get($raw=false) {
244
245   $sql = "SELECT `keyword`, `data`, `type`, `seq` FROM `sipsettings` ORDER BY `type`, `seq`";
246   $raw_settings = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
247
248   /* Just give the SQL table if more convenient (such as in hookGet_config */
249   if ($raw) {
250     return $raw_settings;
251   }
252
253   /* Initialize first, then replace with DB, to make sure we have defaults */
254
255   $sip_settings['nat']               = 'yes';
256   $sip_settings['nat_mode']          = 'externip';
257   $sip_settings['externip_val']      = '';
258   $sip_settings['externhost_val']    = '';
259   $sip_settings['externrefresh']     = '120';
260   $sip_settings['localnet_0']        = '';
261   $sip_settings['netmask_0']         = '255.255.255.0';
262
263   $sip_settings['codecs']            =  array(
264     'ulaw'     => '1',
265     'alaw'     => '2',
266     'slin'     => '',
267     'g726'     => '',
268     'gsm'      => '3',
269     'g729'     => '',
270     'ilbc'     => '',
271     'g723'     => '',
272     'g726aal2' => '',
273     'adpcm'    => '',
274     'lpc10'    => '',
275     'speex'    => '',
276     'g722'     => '',
277     'siren7'   => '',
278     'siren14'  => '',
279     );
280
281   $sip_settings['g726nonstandard']   = 'no';
282   $sip_settings['t38pt_udptl']       = 'no';
283
284   $sip_settings['video_codecs']      = array(
285     'h261'  => '',
286     'h263'  => '',
287     'h263p' => '',
288     'h264'  => '',
289     );
290
291   $sip_settings['videosupport']      = 'no';
292   $sip_settings['maxcallbitrate']    = '384';
293
294   $sip_settings['canreinvite']       = 'no';
295   $sip_settings['rtptimeout']        = '30';
296   $sip_settings['rtpholdtimeout']    = '300';
297   $sip_settings['rtpkeepalive']      = '0';
298
299   $sip_settings['checkmwi']          = '10';
300   $sip_settings['notifyringing']     = 'yes';
301   $sip_settings['notifyhold']        = 'yes';
302
303   $sip_settings['registertimeout']   = '20';
304   $sip_settings['registerattempts']  = '0';
305   $sip_settings['maxexpiry']         = '3600';
306   $sip_settings['minexpiry']         = '60';
307   $sip_settings['defaultexpiry']     = '120';
308
309   $sip_settings['jbenable']          = 'no';
310   $sip_settings['jbforce']           = 'no';
311   $sip_settings['jbimpl']            = 'fixed';
312   $sip_settings['jbmaxsize']         = '200';
313   $sip_settings['jbresyncthreshold'] = '1000';
314   $sip_settings['jblog']             = 'no';
315
316   $sip_settings['sip_language']      = '';
317   $sip_settings['context']           = '';
318   $sip_settings['bindaddr']          = '';
319   $sip_settings['bindport']          = '';
320   $sip_settings['allowguest']        = 'yes';
321   $sip_settings['srvlookup']         = 'no';
322   $sip_settings['callevents']        = 'no';
323
324   $sip_settings['sip_custom_key_0']  = '';
325   $sip_settings['sip_custom_val_0']  = '';
326
327   foreach ($raw_settings as $var) {
328     switch ($var['type']) {
329       case SIP_NORMAL:
330         $sip_settings[$var['keyword']]                 = $var['data'];
331       break;
332
333       case SIP_CODEC:
334         $sip_settings['codecs'][$var['keyword']]       = $var['data'];
335       break;
336
337       case SIP_VIDEO_CODEC:
338         $sip_settings['video_codecs'][$var['keyword']] = $var['data'];
339       break;
340
341       case SIP_CUSTOM:
342         $sip_settings['sip_custom_key_'.$var['seq']]   = $var['keyword'];
343         $sip_settings['sip_custom_val_'.$var['seq']]   = $var['data'];
344       break;
345
346     default:
347       // Error should be above
348     }
349   }
350   unset($raw_settings);
351
352   return $sip_settings;
353 }
354
355 // Add a sipsettings
356 function sipsettings_edit($sip_settings) {
357   global $db;
358   global $amp_conf;
359   $save_settings = array();
360   $vd = new  sipsettings_validate();
361
362   $codecs = $sip_settings['codecs'];
363   $video_codecs = $sip_settings['video_codecs'];
364   unset($sip_settings['codecs']);
365   unset($sip_settings['video_codecs']);
366
367   // TODO: this is where I will build validation before saving
368     //
369   $integer_msg = _("%s must be a non-negative integer");
370   foreach ($sip_settings as $key => $val) {
371     switch ($key) {
372       case 'bindaddr':
373         $msg = _("Bind Address (bindaddr) must be an IP address.");
374         $ipv6_ok = version_compare($amp_conf['ASTVERSION'],'1.8','ge');
375         $save_settings[] = array($key,$db->escapeSimple($vd->is_ip($val,$key,$msg,$ipv6_ok)),'2',SIP_NORMAL);
376       break;
377
378       case 'bindport':
379         $msg = _("Bind Port (bindport) must be between 1024..65535, default 5060");
380         $save_settings[] = array($key,$db->escapeSimple($vd->is_ip_port($val, $key, $msg)),'1',SIP_NORMAL);
381       break;
382
383       case 'rtpholdtimeout':
384         // validation: must be > $sip_settings['rtptimeout'] (and of course a proper number)
385         //$vd->log_error();
386         if ($val < $sip_settings['rtptimeout']) {
387           $msg = _("rtpholdtimeout must be higher than rtptimeout");
388           $vd->log_error($val, $key, $msg);
389         }
390         $msg = sprintf($integer_msg,$key);
391         $save_settings[] = array($key,$db->escapeSimple($vd->is_int($val, $key, $msg)),'10',SIP_NORMAL);
392       break;
393
394       case 'rtptimeout':
395       case 'rtpkeepalive':
396       case 'checkmwi':
397       case 'registertimeout':
398       case 'minexpiry':
399       case 'maxexpiry':
400       case 'defaultexpiry':
401         $msg = sprintf($integer_msg,$key);
402         $save_settings[] = array($key,$db->escapeSimple($vd->is_int($val,$key,$msg)),'10',SIP_NORMAL);
403       break;
404
405       case 'maxcallbitrate':
406       case 'registerattempts':
407         $msg = sprintf($integer_msg,$key);
408         $save_settings[] = array($key,$db->escapeSimple($vd->is_int($val,$key,$msg)),'10',SIP_NORMAL);
409       break;
410
411
412       case 'sip_language':
413         $msg = ("Language must be alphanumeric and installed");
414         $save_settings[] = array($key,$db->escapeSimple($vd->is_alphanumeric($val,$key,$msg)),'0',SIP_NORMAL);
415       break;
416
417       case 'context':
418         $msg = sprintf(_("%s must be alphanumeric"),$key);
419         $save_settings[] = array($key,$db->escapeSimple($vd->is_alphanumeric($val,$key,$msg)),'0',SIP_NORMAL);
420       break;
421
422       case 'externrefresh':
423         $msg = sprintf($integer_msg,$key);
424         $save_settings[] = array($key,$db->escapeSimple($vd->is_int($val,$key,$msg)),'41',SIP_NORMAL);
425       break;
426
427       case 'nat':
428         $save_settings[] = array($key,$val,'39',SIP_NORMAL);
429       break;
430
431       case 'externip_val':
432         if (trim($val) == '' && $sip_settings['nat_mode'] == 'externip') {
433           $msg = _("External IP can not be blank");
434           $vd->log_error($val, $key, $msg);
435          }
436         $save_settings[] = array($key,$val,'40',SIP_NORMAL);
437       break;
438
439       case 'externhost_val':
440         if (trim($val) == '' && $sip_settings['nat_mode'] == 'externhost') {
441           $msg = _("Dynamic Host can not be blank");
442           $vd->log_error($val, $key, $msg);
443          }
444         $save_settings[] = array($key,$val,'40',SIP_NORMAL);
445       break;
446
447       case 'jbenable':
448         $save_settings[] = array($key,$val,'4',SIP_NORMAL);
449       break;
450
451       case 'jbforce':
452       case 'jbimpl':
453       case 'jblog':
454         $save_settings[] = array($key,$val,'5',SIP_NORMAL);
455       break;
456
457       case 'jbmaxsize':
458       case 'jbresyncthreshold':
459         $msg = sprintf($integer_msg,$key);
460         $save_settings[] = array($key,$db->escapeSimple($vd->is_int($val,$key,$msg)),'5',SIP_NORMAL);
461       break;
462
463       case 'nat_mode':
464       case 'g726nonstandard':
465       case 't38pt_udptl':
466       case 'videosupport':
467       case 'canreinvite':
468       case 'notifyringing':
469       case 'notifyhold':
470       case 'allowguest':
471       case 'srvlookup':
472         $save_settings[] = array($key,$val,'10',SIP_NORMAL);
473       break;
474
475     default:
476       if (substr($key,0,9) == "localnet_") {
477         // ip validate this and store
478         $seq = substr($key,9);
479         $msg = _("Localnet setting must be an IP address");
480         $save_settings[] = array($key,$db->escapeSimple($vd->is_ip($val,$key,$msg)),(42+$seq),SIP_NORMAL);
481       } else if (substr($key,0,8) == "netmask_") {
482         // ip validate this and store
483         $seq = substr($key,8);
484         $msg = _("Localnet netmask must be formatted properly (e.g. 255.255.255.0 or 24)");
485         $save_settings[] = array($key,$db->escapeSimple($vd->is_netmask($val,$key,$msg)),$seq,SIP_NORMAL);
486       } else if (substr($key,0,15) == "sip_custom_key_") {
487         $seq = substr($key,15);
488         $save_settings[] = array($db->escapeSimple($val),$db->escapeSimple($sip_settings["sip_custom_val_$seq"]),($seq),SIP_CUSTOM);
489       } else if (substr($key,0,15) == "sip_custom_val_") {
490         // skip it, we will seek it out when we see the sip_custom_key
491       } else {
492         $save_settings[] = array($key,$val,'0',SIP_NORMAL);
493       }
494     }
495   }
496
497   /* if there were any validation errors, we will return them and not proceed with saving */
498   if (count($vd->errors)) {
499     return $vd->errors;
500   } else {
501     $seq = 0;
502     foreach ($codecs as $key => $val) {
503       $save_settings[] = array($db->escapeSimple($key),$db->escapeSimple($val),$seq++,SIP_CODEC);
504     }
505     $seq = 0;
506     foreach ($video_codecs as $key => $val) {
507       $save_settings[] = array($db->escapeSimple($key),$db->escapeSimple($val),$seq++,SIP_VIDEO_CODEC);
508     }
509
510     // TODO: normally don't like doing delete/insert but otherwise we would have do update for each
511     //       individual setting and then an insert if there was nothing to update. So this is cleaner
512     //       this time around.
513       //
514     sql("DELETE FROM `sipsettings` WHERE 1");
515     $compiled = $db->prepare('INSERT INTO `sipsettings` (`keyword`, `data`, `seq`, `type`) VALUES (?,?,?,?)');
516     $result = $db->executeMultiple($compiled,$save_settings);
517     if(DB::IsError($result)) {
518       die_freepbx($result->getDebugInfo()."<br><br>".'error adding to sipsettings table');    }
519     return true;
520   }
521 }
522
523
Note: See TracBrowser for help on using the browser.