Changeset 10244

Show
Ignore:
Timestamp:
09/06/10 17:50:08 (3 years ago)
Author:
mbrevda
Message:

closes #4527; Move classes to their own files

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • freepbx/trunk/amp_conf/htdocs/admin/functions.inc.php

    r10212 r10244  
    1212//GNU General Public License for more details. 
    1313 
    14 require_once( (defined('AMP_BASE_INCLUDE_PATH') ? AMP_BASE_INCLUDE_PATH.'/' : '').'featurecodes.class.php'); 
    15 require_once( (defined('AMP_BASE_INCLUDE_PATH') ? AMP_BASE_INCLUDE_PATH.'/' : '').'components.class.php'); 
    16  
    17 define('MODULE_STATUS_NOTINSTALLED', 0); 
    18 define('MODULE_STATUS_DISABLED', 1); 
    19 define('MODULE_STATUS_ENABLED', 2); 
    20 define('MODULE_STATUS_NEEDUPGRADE', 3); 
    21 define('MODULE_STATUS_BROKEN', -1); 
    22  
    23 class modulelist { 
    24   var $_loaded = false; 
    25   var $module_array = array(); 
    26   var $_db; 
    27  
    28   function &create(&$db) { 
    29     static $obj; 
    30     if (!isset($obj)) { 
    31       $obj = new modulelist($db); 
    32     } 
    33     return $obj; 
    34   } 
    35   function modulelist(&$db) { 
    36     $this->_db =& $db; 
    37     $module_serialized = sql("SELECT `data` FROM `module_xml` WHERE `id` = 'mod_serialized'","getOne"); 
    38     if (isset($module_serialized) && $module_serialized) { 
    39       $this->module_array = (unserialize($module_serialized)); 
    40       $this->_loaded = true; 
    41     } 
    42   } 
    43   function is_loaded() { 
    44     return $this->_loaded; 
    45   } 
    46   function initialize(&$module_list) { 
    47     $this->module_array = $module_list; 
    48     $module_serialized = $this->_db->escapeSimple(serialize($this->module_array)); 
    49     sql("DELETE FROM `module_xml` WHERE `id` = 'mod_serialized'"); 
    50     sql("INSERT INTO `module_xml` (`id`, `time`, `data`) VALUES ('mod_serialized', '".time()."','".$module_serialized."')"); 
    51     $this->_loaded = true; 
    52   } 
    53   function invalidate() { 
    54     unset($this->module_array); 
    55     sql("DELETE FROM `module_xml` WHERE `id` = 'mod_serialized'"); 
    56     $this->_loaded = false; 
    57   } 
    58 
    59  
    60 define("NOTIFICATION_TYPE_CRITICAL", 100); 
    61 define("NOTIFICATION_TYPE_SECURITY", 200); 
    62 define("NOTIFICATION_TYPE_UPDATE",  300); 
    63 define("NOTIFICATION_TYPE_ERROR",    400); 
    64 define("NOTIFICATION_TYPE_WARNING" , 500); 
    65 define("NOTIFICATION_TYPE_NOTICE",   600); 
    66  
    67 class notifications { 
    68  
    69   var $not_loaded = true; 
    70   var $notification_table = array(); 
    71   var $_db; 
    72      
    73   function &create(&$db) { 
    74     static $obj; 
    75     if (!isset($obj)) { 
    76       $obj = new notifications($db); 
    77     } 
    78     return $obj; 
    79   } 
    80  
    81   function notifications(&$db) { 
    82     $this->_db =& $db; 
    83   } 
    84  
    85  
    86   function add_critical($module, $id, $display_text, $extended_text="", $link="", $reset=true, $candelete=false) { 
    87     $this->_add_type(NOTIFICATION_TYPE_CRITICAL, $module, $id, $display_text, $extended_text, $link, $reset, $candelete); 
    88   } 
    89   function add_security($module, $id, $display_text, $extended_text="", $link="", $reset=true, $candelete=false) { 
    90     $this->_add_type(NOTIFICATION_TYPE_SECURITY, $module, $id, $display_text, $extended_text, $link, $reset, $candelete); 
    91   } 
    92   function add_update($module, $id, $display_text, $extended_text="", $link="", $reset=false, $candelete=false) { 
    93     $this->_add_type(NOTIFICATION_TYPE_UPDATE, $module, $id, $display_text, $extended_text, $link, $reset, $candelete); 
    94   } 
    95   function add_error($module, $id, $display_text, $extended_text="", $link="", $reset=false, $candelete=false) { 
    96     $this->_add_type(NOTIFICATION_TYPE_ERROR, $module, $id, $display_text, $extended_text, $link, $reset, $candelete); 
    97   } 
    98   function add_warning($module, $id, $display_text, $extended_text="", $link="", $reset=false, $candelete=false) { 
    99     $this->_add_type(NOTIFICATION_TYPE_WARNING, $module, $id, $display_text, $extended_text, $link, $reset, $candelete); 
    100   } 
    101   function add_notice($module, $id, $display_text, $extended_text="", $link="", $reset=false, $candelete=true) { 
    102     $this->_add_type(NOTIFICATION_TYPE_NOTICE, $module, $id, $display_text, $extended_text, $link, $reset, $candelete); 
    103   } 
    104  
    105  
    106   function list_critical($show_reset=false) { 
    107     return $this->_list(NOTIFICATION_TYPE_CRITICAL, $show_reset); 
    108   } 
    109   function list_security($show_reset=false) { 
    110     return $this->_list(NOTIFICATION_TYPE_SECURITY, $show_reset); 
    111   } 
    112   function list_update($show_reset=false) { 
    113     return $this->_list(NOTIFICATION_TYPE_UPDATE, $show_reset); 
    114   } 
    115   function list_error($show_reset=false) { 
    116     return $this->_list(NOTIFICATION_TYPE_ERROR, $show_reset); 
    117   } 
    118   function list_warning($show_reset=false) { 
    119     return $this->_list(NOTIFICATION_TYPE_WARNING, $show_reset); 
    120   } 
    121   function list_notice($show_reset=false) { 
    122     return $this->_list(NOTIFICATION_TYPE_NOTICE, $show_reset); 
    123   } 
    124   function list_all($show_reset=false) { 
    125     return $this->_list("", $show_reset); 
    126   } 
    127  
    128  
    129   function reset($module, $id) { 
    130     $module        = q($module); 
    131     $id            = q($id); 
    132  
    133     $sql = "UPDATE notifications SET reset = 1 WHERE module = $module AND id = $id"; 
    134     sql($sql); 
    135   } 
    136  
    137   function delete($module, $id) { 
    138     $module        = q($module); 
    139     $id            = q($id); 
    140  
    141     $sql = "DELETE FROM notifications WHERE module = $module AND id = $id"; 
    142     sql($sql); 
    143   } 
    144  
    145   function safe_delete($module, $id) { 
    146     $module        = q($module); 
    147     $id            = q($id); 
    148  
    149     $sql = "DELETE FROM notifications WHERE module = $module AND id = $id AND candelete = 1"; 
    150     sql($sql); 
    151   } 
    152  
    153   /* Internal functions 
    154    */ 
    155  
    156   function _add_type($level, $module, $id, $display_text, $extended_text="", $link="", $reset=false, $candelete=false) { 
    157     if ($this->not_loaded) { 
    158       $this->notification_table = $this->_list("",true); 
    159       $this->not_loaded = false; 
    160     } 
    161  
    162     $existing_row = false; 
    163     foreach ($this->notification_table as $row) { 
    164       if ($row['module'] == $module && $row['id'] == $id ) { 
    165         $existing_row = $row; 
    166         break; 
    167       } 
    168     } 
    169     // Found an existing row - check if anything changed or if we are suppose to reset it 
    170     // 
    171     $candelete = $candelete ? 1 : 0; 
    172     if ($existing_row) { 
    173  
    174       if (($reset && $existing_row['reset'] == 1) || $existing_row['level'] != $level || $existing_row['display_text'] != $display_text || $existing_row['extended_text'] != $extended_text || $existing_row['link'] != $link || $existing_row['candelete'] == $candelete) { 
    175  
    176         // If $reset is set to the special case of PASSIVE then the updates will not change it's value in an update 
    177         // 
    178         $reset_value = ($reset == 'PASSIVE') ? $existing_row['reset'] : 0; 
    179  
    180         $module        = q($module); 
    181         $id            = q($id); 
    182         $level         = q($level); 
    183         $display_text  = q($display_text); 
    184         $extended_text = q($extended_text); 
    185         $link          = q($link); 
    186         $now = time(); 
    187         $sql = "UPDATE notifications SET 
    188           level = $level, 
    189           display_text = $display_text, 
    190           extended_text = $extended_text, 
    191           link = $link, 
    192           reset = $reset_value, 
    193           candelete = $candelete, 
    194           timestamp = $now 
    195           WHERE module = $module AND id = $id 
    196         "; 
    197         sql($sql); 
    198  
    199         // TODO: I should really just add this to the internal cache, but really 
    200         //       how often does this get called that if is a big deal. 
    201         $this->not_loaded = true; 
    202       } 
    203     } else { 
    204       // No existing row so insert this new one 
    205       // 
    206       $now           = time(); 
    207       $module        = q($module); 
    208       $id            = q($id); 
    209       $level         = q($level); 
    210       $display_text  = q($display_text); 
    211       $extended_text = q($extended_text); 
    212       $link          = q($link); 
    213       $sql = "INSERT INTO notifications  
    214         (module, id, level, display_text, extended_text, link, reset, candelete, timestamp) 
    215         VALUES  
    216         ($module, $id, $level, $display_text, $extended_text, $link, 0, $candelete, $now) 
    217       "; 
    218       sql($sql); 
    219  
    220       // TODO: I should really just add this to the internal cache, but really 
    221       //       how often does this get called that if is a big deal. 
    222       $this->not_loaded = true; 
    223     } 
    224   } 
    225  
    226   function _list($level, $show_reset=false) { 
    227  
    228     $level = q($level); 
    229     $where = array(); 
    230  
    231     if (!$show_reset) { 
    232       $where[] = "reset = 0"; 
    233     } 
    234  
    235     switch ($level) { 
    236       case NOTIFICATION_TYPE_CRITICAL: 
    237       case NOTIFICATION_TYPE_SECURITY: 
    238       case NOTIFICATION_TYPE_UPDATE: 
    239       case NOTIFICATION_TYPE_ERROR: 
    240       case NOTIFICATION_TYPE_WARNING: 
    241       case NOTIFICATION_TYPE_NOTICE: 
    242         $where[] = "level = $level "; 
    243         break; 
    244       default: 
    245     } 
    246     $sql = "SELECT * FROM notifications "; 
    247     if (count($where)) { 
    248       $sql .= " WHERE ".implode(" AND ", $where); 
    249     } 
    250     $sql .= " ORDER BY level, module"; 
    251  
    252     $list = sql($sql,"getAll",DB_FETCHMODE_ASSOC); 
    253     return $list; 
    254   } 
    255   /* Returns the number of active notifications 
    256    */ 
    257   function get_num_active() { 
    258     $sql = "SELECT COUNT(id) FROM notifications WHERE reset = 0"; 
    259     return sql($sql,'getOne'); 
    260   } 
    261 
    262  
    263 class cronmanager { 
    264   /** 
    265    * note: time is the hour time of day a job should run, -1 indicates don't care 
    266    */ 
    267  
    268   function &create(&$db) { 
    269     static $obj; 
    270     if (!isset($obj)) { 
    271       $obj = new cronmanager($db); 
    272     } 
    273     return $obj; 
    274   } 
    275  
    276   function cronmanager(&$db) { 
    277     $this->_db =& $db; 
    278   } 
    279  
    280   function save_email($address) { 
    281     $address = q($address); 
    282     sql("DELETE FROM admin WHERE variable = 'email'"); 
    283     sql("INSERT INTO admin (variable, value) VALUES ('email', $address)"); 
    284   } 
    285  
    286   function get_email() { 
    287     $sql = "SELECT value FROM admin WHERE variable = 'email'"; 
    288     return sql($sql, 'getOne'); 
    289   } 
    290  
    291   function save_hash($id, &$string) { 
    292     $hash = md5($string); 
    293     $id = q($id); 
    294     sql("DELETE FROM admin WHERE variable = $id"); 
    295     sql("INSERT INTO admin (variable, value) VALUE ($id, '$hash')"); 
    296   } 
    297  
    298   function check_hash($id, &$string) { 
    299     $id = q($id); 
    300     $sql = "SELECT value FROM admin WHERE variable = $id LIMIT 1"; 
    301     $hash = sql($sql, "getOne"); 
    302     return ($hash == md5($string)); 
    303   } 
    304  
    305   function enable_updates($freq=24) { 
    306     global $amp_conf; 
    307  
    308     $night_time = array(19,20,21,22,23,0,1,2,3,4,5); 
    309     $run_time = $night_time[rand(0,10)]; 
    310     $command = $amp_conf['AMPBIN']."/module_admin listonline"; 
    311     $lasttime = 0; 
    312  
    313     $sql = "SELECT * FROM cronmanager WHERE module = 'module_admin' AND id = 'UPDATES'"; 
    314     $result = sql($sql, "getAll",DB_FETCHMODE_ASSOC); 
    315     if (count($result)) { 
    316       $sql = "UPDATE cronmanager SET 
    317                 freq = '$freq', 
    318                 command = '$command' 
    319               WHERE 
    320                 module = 'module_admin' AND id = 'UPDATES'   
    321              "; 
    322     } else { 
    323       $sql = "INSERT INTO cronmanager  
    324               (module, id, time, freq, lasttime, command) 
    325               VALUES 
    326               ('module_admin', 'UPDATES', '$run_time', $freq, 0, '$command') 
    327             "; 
    328     } 
    329     sql($sql); 
    330   } 
    331  
    332   function disable_updates() { 
    333     sql("DELETE FROM cronmanager WHERE module = 'module_admin' AND id = 'UPDATES'"); 
    334   } 
    335  
    336   function updates_enabled() { 
    337     $results = sql("SELECT module, id FROM cronmanager WHERE module = 'module_admin' AND id = 'UPDATES'",'getAll'); 
    338     return count($results); 
    339   } 
    340  
    341   /** run_jobs() 
    342    *  select all entries that need to be run now and run them, then update the times. 
    343    *   
    344    *  1. select all entries 
    345    *  2. foreach entry, if its paramters indicate it should be run, then run it and 
    346    *     update it was run in the time stamp. 
    347    */ 
    348   function run_jobs() { 
    349  
    350     $errors = 0; 
    351     $error_arr = array(); 
    352  
    353     $now = time(); 
    354     $jobs = sql("SELECT * FROM cronmanager","getAll", DB_FETCHMODE_ASSOC); 
    355     foreach ($jobs as $job) { 
    356       $nexttime = $job['lasttime'] + $job['freq']*3600;  
    357       if ($nexttime <= $now) { 
    358         if ($job['time'] >= 0 && $job['time'] < 24) { 
    359           $date_arr = getdate($now); 
    360           // Now if lasttime is 0, then we want this kicked off at the proper hour 
    361           // after wich the frequencey will set the pace for same time each night 
    362           // 
    363           if (($date_arr['hours'] != $job['time']) && !$job['lasttime']) { 
    364             continue; 
    365           } 
    366         }  
    367       } else { 
    368         // no need to run job, time is not up yet 
    369         continue; 
    370       } 
    371       // run the job 
    372       exec($job['command'],$job_out,$ret); 
    373       if ($ret) { 
    374         $errors++; 
    375         $error_arr[] = array($job['command'],$ret); 
    376  
    377         // If there where errors, let's print them out in case the script is being debugged or running 
    378         // from cron which will then put the errors out through the cron system. 
    379         // 
    380         foreach ($job_out as $line) { 
    381           echo $line."\n"; 
    382         } 
    383       } else { 
    384         $module = $job['module']; 
    385         $id =     $job['id']; 
    386         $sql = "UPDATE cronmanager SET lasttime = $now WHERE module = '$module' AND id = '$id'"; 
    387         sql($sql); 
    388       } 
    389     } 
    390     if ($errors) { 
    391       $nt =& notifications::create($db); 
    392       $text = sprintf(_("Cronmanager encountered %s Errors"),$errors); 
    393       $extext = _("The following commands failed with the listed error"); 
    394       foreach ($error_arr as $item) { 
    395         $extext .= "<br />".$item[0]." (".$item[1].")"; 
    396       } 
    397       $nt->add_error('cron_manager', 'EXECFAIL', $text, $extext, '', true, true); 
    398     } 
    399   } 
    400 
    401  
    402 class ampuser { 
    403   var $username; 
    404   var $_password; 
    405   var $_extension_high; 
    406   var $_extension_low; 
    407   var $_deptname; 
    408   var $_sections; 
    409    
    410   function ampuser($username) { 
    411     $this->username = $username; 
    412     if ($user = getAmpUser($username)) { 
    413       $this->_password = $user["password_sha1"]; 
    414       $this->_extension_high = $user["extension_high"]; 
    415       $this->_extension_low = $user["extension_low"]; 
    416       $this->_deptname = $user["deptname"]; 
    417       $this->_sections = $user["sections"]; 
    418     } else { 
    419       // user doesn't exist 
    420       $this->_password = false; 
    421       $this->_extension_high = ""; 
    422       $this->_extension_low = ""; 
    423       $this->_deptname = ""; 
    424       $this->_sections = array(); 
    425     } 
    426   } 
    427    
    428   /** Give this user full admin access 
    429   */ 
    430   function setAdmin() { 
    431     $this->_extension_high = ""; 
    432     $this->_extension_low = ""; 
    433     $this->_deptname = ""; 
    434     $this->_sections = array("*"); 
    435   } 
    436    
    437   function checkPassword($password) { 
    438     // strict checking so false will never match 
    439     return ($this->_password === $password); 
    440   } 
    441    
    442   function checkSection($section) { 
    443     // if they have * then it means all sections 
    444     return in_array("*", $this->_sections) || in_array($section, $this->_sections); 
    445   } 
    446 
    447  
    448 /* Usage 
    449 Grab some XML data, either from a file, URL, etc. however you want. Assume storage in $strYourXML; 
    450  
    451 $xml = new xml2Array($strYourXML); 
    452 xml array is in $xml->data; 
    453   This is basically an array version of the XML data (no attributes), striaght-up. If there are 
    454   multiple items with the same name, they are split into a numeric sub-array,  
    455   eg, <items><item test="123">foo</item><item>bar</item></items> 
    456   becomes: array('item' => array(0=>array('item'=>'foo'), 1=>array('item'=>'foo')) 
    457 attributes are in $xml->attributes; 
    458   These are stored with xpath type paths, as $xml->attributes['/items/item/0']["test"] == "123" 
    459    
    460  
    461 Other way (still works, but not as nice): 
    462  
    463 $objXML = new xml2Array(); 
    464 $arrOutput = $objXML->parse($strYourXML); 
    465 print_r($arrOutput); //print it out, or do whatever! 
    466  
    467 */ 
    468  
    469 class xml2Array { 
    470   var $arrOutput = array(); 
    471   var $resParser; 
    472   var $strXmlData; 
    473    
    474   var $attributes; 
    475   var $data; 
    476    
    477   function xml2Array($strInputXML = false) { 
    478     if (!empty($strInputXML)) { 
    479       $this->data = $this->parseAdvanced($strInputXML); 
    480     } 
    481   } 
    482    
    483   function parse($strInputXML) { 
    484    
    485       $this->resParser = xml_parser_create (); 
    486       xml_set_object($this->resParser,$this); 
    487       xml_set_element_handler($this->resParser, "tagOpen", "tagClosed"); 
    488        
    489       xml_set_character_data_handler($this->resParser, "tagData"); 
    490      
    491       $this->strXmlData = xml_parse($this->resParser,$strInputXML ); 
    492       if(!$this->strXmlData) { 
    493         die_freepbx(sprintf("XML error: %s at line %d", 
    494       xml_error_string(xml_get_error_code($this->resParser)), 
    495       xml_get_current_line_number($this->resParser))); 
    496       } 
    497                
    498       xml_parser_free($this->resParser); 
    499        
    500       return $this->arrOutput; 
    501   } 
    502   function tagOpen($parser, $name, $attrs) { 
    503     $tag=array("name"=>$name,"attrs"=>$attrs);  
    504     @array_push($this->arrOutput,$tag); 
    505   } 
    506    
    507   function tagData($parser, $tagData) { 
    508     if(trim($tagData)) { 
    509       if(isset($this->arrOutput[count($this->arrOutput)-1]['tagData'])) { 
    510         $this->arrOutput[count($this->arrOutput)-1]['tagData'] .= "\n".$tagData; 
    511       }  
    512       else { 
    513         $this->arrOutput[count($this->arrOutput)-1]['tagData'] = $tagData; 
    514       } 
    515     } 
    516   } 
    517    
    518   function tagClosed($parser, $name) { 
    519     @$this->arrOutput[count($this->arrOutput)-2]['children'][] = $this->arrOutput[count($this->arrOutput)-1]; 
    520     array_pop($this->arrOutput); 
    521   } 
    522    
    523   function recursive_parseLevel($items, &$attrs, $path = "") { 
    524     $array = array(); 
    525     foreach (array_keys($items) as $idx) { 
    526       @$items[$idx]['name'] = strtolower($items[$idx]['name']); 
    527        
    528       $multi = false; 
    529       if (isset($array[ $items[$idx]['name'] ])) { 
    530         // this child is already set, so we're adding multiple items to an array  
    531          
    532         if (!is_array($array[ $items[$idx]['name'] ]) || !isset($array[ $items[$idx]['name'] ][0])) { 
    533           // hasn't already been made into a numerically-indexed array, so do that now 
    534           // we're basically moving the current contents of this item into a 1-item array (at the  
    535           // original location) so that we can add a second item in the code below 
    536           $array[ $items[$idx]['name'] ] = array( $array[ $items[$idx]['name'] ] ); 
    537  
    538           if (isset($attrs[ $path.'/'.$items[$idx]['name'] ])) { 
    539             // move the attributes to /0 
    540             $attrs[ $path.'/'.$items[$idx]['name'].'/0' ] = $attrs[ $path.'/'.$items[$idx]['name'] ]; 
    541             unset($attrs[ $path.'/'.$items[$idx]['name'] ]); 
    542           } 
    543         } 
    544         $multi = true; 
    545       } 
    546        
    547       if ($multi) {  
    548         $newitem = &$array[ $items[$idx]['name'] ][]; 
    549       } else { 
    550         $newitem = &$array[ $items[$idx]['name'] ]; 
    551       } 
    552        
    553        
    554       if (isset($items[$idx]['children']) && is_array($items[$idx]['children'])) { 
    555         $newitem = $this->recursive_parseLevel($items[$idx]['children'], $attrs, $path.'/'.$items[$idx]['name']); 
    556       } else if (isset($items[$idx]['tagData'])) { 
    557         $newitem = $items[$idx]['tagData']; 
    558       } else { 
    559         $newitem = false; 
    560       } 
    561        
    562       if (isset($items[$idx]['attrs']) && is_array($items[$idx]['attrs']) && count($items[$idx]['attrs'])) { 
    563         $attrpath = $path.'/'.$items[$idx]['name']; 
    564         if ($multi) { 
    565           $attrpath .= '/'.(count($array[ $items[$idx]['name'] ])-1); 
    566         } 
    567         foreach ($items[$idx]['attrs'] as $name=>$value) { 
    568           $attrs[ $attrpath ][ strtolower($name) ] = $value; 
    569         } 
    570       } 
    571     } 
    572     return $array; 
    573   } 
    574    
    575   function parseAdvanced($strInputXML) { 
    576     $array = $this->parse($strInputXML); 
    577     $this->attributes = array(); 
    578     return $this->data = $this->recursive_parseLevel($array, $this->attributes); 
    579   } 
    580 
    581  
    582 /* 
    583   Return a much more manageable assoc array with module data. 
    584 */ 
    585 class xml2ModuleArray extends xml2Array { 
    586   function parseModulesXML($strInputXML) { 
    587     $array = $this->parseAdvanced($strInputXML); 
    588     if (isset($array['xml'])) { 
    589       foreach ($array['xml'] as $key=>$module) { 
    590         if ($key == 'module') { 
    591           // copy the structure verbatim 
    592           $modules[ $module['name'] ] = $module; 
    593         } 
    594       } 
    595     } 
    596      
    597     // if you are confused about what's happening below, uncomment this why we do it 
    598     // echo "<pre>"; print_r($arrOutput); echo "</pre>"; 
    599      
    600     // ignore the regular xml garbage ([0]['children']) & loop through each module 
    601     if(!is_array($arrOutput[0]['children'])) return false; 
    602     foreach($arrOutput[0]['children'] as $module) { 
    603       if(!is_array($module['children'])) return false; 
    604       // loop through each modules's tags 
    605       foreach($module['children'] as $modTags) { 
    606           if(isset($modTags['children']) && is_array($modTags['children'])) { 
    607             $$modTags['name'] = $modTags['children']; 
    608             // loop if there are children (menuitems and requirements) 
    609             foreach($modTags['children'] as $subTag) { 
    610               $subTags[strtolower($subTag['name'])] = $subTag['tagData']; 
    611             } 
    612             $$modTags['name'] = $subTags; 
    613             unset($subTags); 
    614           } else { 
    615             // create a variable for each tag we find 
    616             $$modTags['name'] = $modTags['tagData']; 
    617           } 
    618  
    619       } 
    620       // now build our return array 
    621       $arrModules[$RAWNAME]['rawname'] = $RAWNAME;    // This has to be set 
    622       $arrModules[$RAWNAME]['displayName'] = $NAME;    // This has to be set 
    623       $arrModules[$RAWNAME]['version'] = $VERSION;     // This has to be set 
    624       $arrModules[$RAWNAME]['type'] = isset($TYPE)?$TYPE:'setup'; 
    625       $arrModules[$RAWNAME]['category'] = isset($CATEGORY)?$CATEGORY:'Unknown'; 
    626       $arrModules[$RAWNAME]['info'] = isset($INFO)?$INFO:'http://www.freepbx.org/wiki/'.$RAWNAME; 
    627       $arrModules[$RAWNAME]['location'] = isset($LOCATION)?$LOCATION:'local'; 
    628       $arrModules[$RAWNAME]['items'] = isset($MENUITEMS)?$MENUITEMS:null; 
    629       $arrModules[$RAWNAME]['requirements'] = isset($REQUIREMENTS)?$REQUIREMENTS:null; 
    630       $arrModules[$RAWNAME]['md5sum'] = isset($MD5SUM)?$MD5SUM:null; 
    631       //print_r($arrModules); 
    632       //unset our variables 
    633       unset($NAME); 
    634       unset($VERSION); 
    635       unset($TYPE); 
    636       unset($CATEGORY); 
    637       unset($AUTHOR); 
    638       unset($EMAIL); 
    639       unset($LOCATION); 
    640       unset($MENUITEMS); 
    641       unset($REQUIREMENTS); 
    642       unset($MD5SUM); 
    643     } 
    644     //echo "<pre>"; print_r($arrModules); echo "</pre>"; 
    645  
    646     return $arrModules; 
    647   } 
    648 
    649  
    650 class moduleHook { 
    651   var $hookHtml = ''; 
    652   var $arrHooks = array(); 
    653    
    654   function install_hooks($viewing_itemid,$target_module,$target_menuid = '') { 
    655     global $active_modules; 
    656  
    657     /*  Loop though all active modules and find which ones have hooks. 
    658      *  Then process those hooks. Note we split this into two loops 
    659      *  because of #4057, if drawselects() is called from within a hook 
    660      *  it's interaction with the same $active_modules array renders the 
    661      *  foreach loop done after that module and execution ends. 
    662      */ 
    663     $our_hooks = array(); 
    664     foreach($active_modules as $this_module) { 
    665       // look for requested hooks for $module 
    666       // ie: findme_hook_extensions() 
    667       $funct = $this_module['rawname'] . '_hook_' . $target_module; 
    668       if( function_exists( $funct ) ) { 
    669         // remember who installed hooks 
    670         // we need to know this for processing form vars 
    671         $this->arrHooks[] = $this_module['rawname']; 
    672         $our_hooks[$this_module['rawname']] = $funct; 
    673       } 
    674     } 
    675     foreach($our_hooks as $thismod => $funct) { 
    676       if (isset($_COOKIE['lang']) && is_dir("./modules/$thismod/i18n/".$_COOKIE['lang'])) { 
    677         bindtextdomain($thismod,"./modules/$thismod/i18n"); 
    678         bind_textdomain_codeset($thismod, 'utf8'); 
    679         textdomain($thismod); 
    680         if ($hookReturn = $funct($target_menuid, $viewing_itemid)) { 
    681           $this->hookHtml .= $hookReturn; 
    682         } 
    683         textdomain('amp'); 
    684       } else { 
    685         if ($hookReturn = $funct($target_menuid, $viewing_itemid)) { 
    686           $this->hookHtml .= $hookReturn; 
    687         } 
    688       } 
    689     } 
    690   }  
    691   // process the request from the module we hooked 
    692   function process_hooks($viewing_itemid, $target_module, $target_menuid, $request) { 
    693     if(is_array($this->arrHooks)) { 
    694       foreach($this->arrHooks as $hookingMod) { 
    695         // check if there is a processing function 
    696         $funct = $hookingMod . '_hookProcess_' . $target_module; 
    697         if( function_exists( $funct ) ) { 
    698           $funct($viewing_itemid, $request); 
    699         } 
    700       } 
    701     } 
    702   } 
    703 
     14require_once( (defined('AMP_BASE_INCLUDE_PATH') ? AMP_BASE_INCLUDE_PATH.'/' : '').'libraries/featurecodes.class.php'); 
     15require_once( (defined('AMP_BASE_INCLUDE_PATH') ? AMP_BASE_INCLUDE_PATH.'/' : '').'libraries/components.class.php'); 
     16require_once( (defined('AMP_BASE_INCLUDE_PATH') ? AMP_BASE_INCLUDE_PATH.'/' : '').'libraries/notifications.class.php'); 
     17require_once( (defined('AMP_BASE_INCLUDE_PATH') ? AMP_BASE_INCLUDE_PATH.'/' : '').'libraries/moduleHook.class.php'); 
     18require_once( (defined('AMP_BASE_INCLUDE_PATH') ? AMP_BASE_INCLUDE_PATH.'/' : '').'libraries/modulelist.class.php'); 
     19require_once( (defined('AMP_BASE_INCLUDE_PATH') ? AMP_BASE_INCLUDE_PATH.'/' : '').'libraries/cronmanager.class.php'); 
     20require_once( (defined('AMP_BASE_INCLUDE_PATH') ? AMP_BASE_INCLUDE_PATH.'/' : '').'libraries/ampuser.class.php'); 
     21require_once( (defined('AMP_BASE_INCLUDE_PATH') ? AMP_BASE_INCLUDE_PATH.'/' : '').'libraries/xml2Array.class.php'); 
     22 
     23require_once( (defined('AMP_BASE_INCLUDE_PATH') ? AMP_BASE_INCLUDE_PATH.'/' : '').'libraries/module.functions.php'); 
    70424 
    70525$amp_conf_defaults = array( 
     
    21941514} 
    21951515 
    2196 /*********************************************************************************************************** 
    2197                                        Module functions  
    2198 ************************************************************************************************************/ 
    2199   
    2200 /** Get the latest module.xml file for this FreePBX version.  
    2201  * Caches in the database for 5 mintues. 
    2202  * If $module is specified, only returns the data for that module. 
    2203  * If the module is not found (or none are available for whatever reason), 
    2204  * then null is returned. 
    2205  * 
    2206  * Sets the global variable $module_getonlinexml_error to true if an error 
    2207  * occurred getting the module from the repository, false if no error occurred, 
    2208  * or null if the repository wasn't checked. Note that this may change in the  
    2209  * future if we decide we need to return more error codes, but as long as it's 
    2210  * a php zero-value (false, null, 0, etc) then no error happened. 
    2211  */ 
    2212 function module_getonlinexml($module = false, $override_xml = false) { // was getModuleXml() 
    2213   global $amp_conf; 
    2214   global $db; 
    2215   global $module_getonlinexml_error;  // okay, yeah, this sucks, but there's no other good way to do it without breaking BC 
    2216   $module_getonlinexml_error = null; 
    2217   $got_new = false; 
    2218   $skip_cache = false; 
    2219    
    2220   $result = sql("SELECT * FROM module_xml WHERE id = 'xml'",'getRow',DB_FETCHMODE_ASSOC); 
    2221   $data = $result['data']; 
    2222  
    2223   // Check if the cached module xml is for the same repo as being requested 
    2224   // if not, then we get it anyhow 
    2225   // 
    2226   $repo_url = ($override_xml === false) ? "http://mirror.freepbx.org/" : $override_xml; 
    2227   $result2 = sql("SELECT * FROM module_xml WHERE id = 'module_repo'",'getRow',DB_FETCHMODE_ASSOC); 
    2228   $last_repo = $result2['data']; 
    2229   if ($last_repo !== $repo_url) { 
    2230     sql("DELETE FROM module_xml WHERE id = 'module_repo'"); 
    2231     $data4sql = $db->escapeSimple($repo_url); 
    2232     sql("INSERT INTO module_xml (id,time,data) VALUES ('module_repo',".time().",'".$data4sql."')"); 
    2233     $skip_cache = true; 
    2234   } 
    2235  
    2236   // if the epoch in the db is more than 2 hours old, or the xml is less than 100 bytes, then regrab xml 
    2237   // Changed to 5 minutes while not in release. Change back for released version. 
    2238   // 
    2239   // used for debug, time set to 0 to always fall through 
    2240   // if((time() - $result['time']) > 0 || strlen($result['data']) < 100 ) { 
    2241   if((time() - $result['time']) > 300 || $skip_cache || strlen($data) < 100 ) { 
    2242     $version = getversion(); 
    2243     // we need to know the freepbx major version we have running (ie: 2.1.2 is 2.1) 
    2244     preg_match('/(\d+\.\d+)/',$version,$matches); 
    2245     //echo "the result is ".$matches[1]; 
    2246     if ($override_xml) { 
    2247       $fn = $override_xml."modules-".$matches[1].".xml"; 
    2248     } else { 
    2249       $fn = "http://mirror.freepbx.org/modules-".$matches[1].".xml"; 
    2250       // echo "(From default)"; //debug 
    2251     } 
    2252     //$fn = "/usr/src/freepbx-modules/modules.xml"; 
    2253     if (!$amp_conf['MODULEADMINWGET']) { 
    2254       ini_set('user_agent','Wget/1.10.2 (Red Hat modified)'); 
    2255       $data = @ file_get_contents($fn); 
    2256     } else { 
    2257       $data = ""; 
    2258     } 
    2259  
    2260     if (empty($data)) { 
    2261       exec("wget -O - $fn 2> /dev/null", $data_arr, $retcode); 
    2262       $data = implode("\n",$data_arr); 
    2263       $module_getonlinexml_error = ($retcode == 0)?false:true; 
    2264     } 
    2265      
    2266     $old_xml = array(); 
    2267     $got_new = false; 
    2268     if (!empty($data)) { 
    2269       // Compare the download to our current XML to see if anything changed for the notification system. 
    2270       // 
    2271       $sql = "SELECT data FROM module_xml WHERE id = 'xml'"; 
    2272       $old_xml = sql($sql, "getOne"); 
    2273       $got_new = true; 
    2274       // remove the old xml 
    2275       sql("DELETE FROM module_xml WHERE id = 'xml'"); 
    2276       // update the db with the new xml 
    2277       $data4sql = $db->escapeSimple($data); 
    2278       sql("INSERT INTO module_xml (id,time,data) VALUES ('xml',".time().",'".$data4sql."')"); 
    2279     } 
    2280   } 
    2281    
    2282   if (empty($data)) { 
    2283     // no data, probably couldn't connect online, and nothing cached 
    2284     return null; 
    2285   } 
    2286    
    2287   $parser = new xml2ModuleArray($data); 
    2288   $xmlarray = $parser->parseAdvanced($data); 
    2289    
    2290   if ($got_new) { 
    2291     module_update_notifications($old_xml, $xmlarray, ($old_xml == $data4sql)); 
    2292   } 
    2293  
    2294   if (isset($xmlarray['xml']['module'])) { 
    2295    
    2296     if ($module != false) { 
    2297       foreach ($xmlarray['xml']['module'] as $mod) { 
    2298         if ($module == $mod['rawname']) { 
    2299           return $mod; 
    2300         } 
    2301       } 
    2302       return null; 
    2303     } else { 
    2304       $modules = array(); 
    2305       foreach ($xmlarray['xml']['module'] as $mod) { 
    2306         $modules[ $mod['rawname'] ] = $mod; 
    2307       } 
    2308       return $modules; 
    2309     } 
    2310   } 
    2311   return null; 
    2312 } 
    2313  
    2314 /**  Determines if there are updates we don't already know about and posts to notification 
    2315  *   server about those updates. 
    2316  * 
    2317  */ 
    2318 function module_update_notifications(&$old_xml, &$xmlarray, $passive) { 
    2319   global $db; 
    2320  
    2321   $notifications =& notifications::create($db);  
    2322  
    2323   $reset_value = $passive ? 'PASSIVE' : false; 
    2324   $old_parser = new xml2ModuleArray($old_xml); 
    2325   $old_xmlarray = $old_parser->parseAdvanced($old_xml); 
    2326  
    2327   $new_modules = array(); 
    2328   if (count($xmlarray)) { 
    2329     foreach ($xmlarray['xml']['module'] as $mod) { 
    2330       $new_modules[$mod['rawname']] = $mod; 
    2331     } 
    2332   } 
    2333   $old_modules = array(); 
    2334   if (count($old_xmlarray)) { 
    2335     foreach ($old_xmlarray['xml']['module'] as $mod) { 
    2336       $old_modules[$mod['rawname']] = $mod; 
    2337     } 
    2338   } 
    2339  
    2340   // If keys (rawnames) are different then there are new modules, create a notification. 
    2341   // This will always be the case the first time it is run since the xml is empty. 
    2342   // 
    2343   // TODO: if old_modules is empty, should I populate it from getinfo to at find out what 
    2344   //       is installed or otherwise, just skip it since it is the first time? 
    2345   // 
    2346   $diff_modules = array_diff_assoc($new_modules, $old_modules); 
    2347   $cnt = count($diff_modules); 
    2348   if ($cnt) { 
    2349     $extext = _("The following new modules are available for download. Click delete icon on the right to remove this notice.")."<br />"; 
    2350     foreach ($diff_modules as $mod) { 
    2351       $extext .= $mod['rawname']." (".$mod['version'].")<br />"; 
    2352     } 
    2353     $notifications->add_notice('freepbx', 'NEWMODS', sprintf(_('%s New modules are available'),$cnt), $extext, '', $reset_value, true); 
    2354   } 
    2355  
    2356   // Now check if any of the installed modules need updating 
    2357   // 
    2358   module_upgrade_notifications($new_modules, $reset_value); 
    2359 } 
    2360  
    2361 /** Compare installed (enabled or disabled) modules against the xml to generate or 
    2362  *  update the noticiation table of which modules have available updates. If the list 
    2363  *  is empty then delete the notification. 
    2364  */ 
    2365 function module_upgrade_notifications(&$new_modules, $passive_value) { 
    2366   global $db; 
    2367   $notifications =& notifications::create($db);  
    2368  
    2369   $installed_status = array(MODULE_STATUS_ENABLED, MODULE_STATUS_DISABLED); 
    2370   $modules_local = module_getinfo(false, $installed_status); 
    2371  
    2372   $modules_upgradable = array(); 
    2373   foreach (array_keys($modules_local) as $name) { 
    2374     if (isset($new_modules[$name])) { 
    2375       if (version_compare_freepbx($modules_local[$name]['version'], $new_modules[$name]['version']) < 0) { 
    2376         $modules_upgradable[] = array( 
    2377           'name' => $name, 
    2378           'local_version' => $modules_local[$name]['version'], 
    2379           'online_version' => $new_modules[$name]['version'], 
    2380         ); 
    2381       } 
    2382     } 
    2383   } 
    2384   $cnt = count($modules_upgradable); 
    2385   if ($cnt) { 
    2386     if ($cnt == 1) { 
    2387       $text = _("There is 1 module available for online upgrade"); 
    2388     } else { 
    2389       $text = sprintf(_("There are %s modules available for online upgrades"),$cnt); 
    2390     } 
    2391     $extext = ""; 
    2392     foreach ($modules_upgradable as $mod) { 
    2393       $extext .= sprintf(_("%s (current: %s)"), $mod['name'].' '.$mod['online_version'], $mod['local_version'])."\n"; 
    2394     } 
    2395     $notifications->add_update('freepbx', 'NEWUPDATES', $text, $extext, '', $passive_value); 
    2396   } else { 
    2397     $notifications->delete('freepbx', 'NEWUPDATES'); 
    2398   } 
    2399 } 
    2400  
    2401 /** Looks through the modules directory and modules database and returns all available 
    2402  * information about one or all modules 
    2403  * @param string  (optional) The module name to query, or false for all module 
    2404  * @param mixed   (optional) The status(es) to show, using MODULE_STATUS_* constants. Can 
    2405  *                either be one value, or an array of values. 
    2406  */ 
    2407 function module_getinfo($module = false, $status = false, $forceload = false) { 
    2408  
    2409   global $amp_conf, $db; 
    2410   $modules = array(); 
    2411    
    2412   if ($module) { 
    2413     // get info on only one module 
    2414     $xml = _module_readxml($module); 
    2415     if (!is_null($xml)) { 
    2416       $modules[$module] = $xml; 
    2417       // if status is anything else, it will be updated below when we read the db 
    2418       $modules[$module]['status'] = MODULE_STATUS_NOTINSTALLED; 
    2419     } 
    2420      
    2421     // query to get just this one 
    2422     $sql = 'SELECT * FROM modules WHERE modulename = "'.$module.'"'; 
    2423   } else { 
    2424     // create the modulelist so it is static and does not need to be recreated 
    2425     // in subsequent calls 
    2426     // 
    2427     $modulelist =& modulelist::create($db); 
    2428     if ($forceload) { 
    2429       $modulelist->invalidate(); 
    2430     } 
    2431     if (!$modulelist->is_loaded()) { 
    2432       // initialize list with "builtin" module 
    2433       $module_list = array('builtin'); 
    2434  
    2435       // read modules dir for module names 
    2436       $dir = opendir($amp_conf['AMPWEBROOT'].'/admin/modules'); 
    2437       while ($file = readdir($dir)) { 
    2438         if (($file != ".") && ($file != "..") && ($file != "CVS") &&  
    2439             ($file != ".svn") && ($file != "_cache") &&  
    2440             is_dir($amp_conf['AMPWEBROOT'].'/admin/modules/'.$file)) { 
    2441           $module_list[] = $file; 
    2442         } 
    2443       } 
    2444  
    2445       // read the xml for each 
    2446       foreach ($module_list as $file) { 
    2447         $xml = _module_readxml($file); 
    2448         if (!is_null($xml)) { 
    2449           $modules[$file] = $xml; 
    2450           // if status is anything else, it will be updated below when we read the db 
    2451           $modules[$file]['status'] = MODULE_STATUS_NOTINSTALLED; 
    2452         } 
    2453       } 
    2454       closedir($dir); 
    2455  
    2456       // query to get everything 
    2457       $sql = 'SELECT * FROM modules'; 
    2458     } 
    2459   } 
    2460   // determine details about this module from database 
    2461   // modulename should match the directory name 
    2462    
    2463   if ($module || !$modulelist->is_loaded()) { 
    2464     $results = $db->getAll($sql,DB_FETCHMODE_ASSOC); 
    2465     if(DB::IsError($results)) { 
    2466       die_freepbx($sql."<br>\n".$results->getMessage()); 
    2467     } 
    2468    
    2469     if (is_array($results)) { 
    2470       foreach($results as $row) { 
    2471         if (isset($modules[ $row['modulename'] ])) { 
    2472           if ($row['enabled'] != 0) { 
    2473            
    2474             // check if file and registered versions are the same 
    2475             // version_compare returns 0 if no difference 
    2476             if (version_compare_freepbx($row['version'], $modules[ $row['modulename'] ]['version']) == 0) { 
    2477               $modules[ $row['modulename'] ]['status'] = MODULE_STATUS_ENABLED; 
    2478             } else { 
    2479               $modules[ $row['modulename'] ]['status'] = MODULE_STATUS_NEEDUPGRADE; 
    2480             } 
    2481            
    2482           } else { 
    2483             $modules[ $row['modulename'] ]['status'] = MODULE_STATUS_DISABLED; 
    2484           } 
    2485         } else { 
    2486           // no directory for this db entry 
    2487           $modules[ $row['modulename'] ]['status'] = MODULE_STATUS_BROKEN; 
    2488         } 
    2489         $modules[ $row['modulename'] ]['dbversion'] = $row['version']; 
    2490       } 
    2491     } 
    2492  
    2493     // "builtin" module is always enabled 
    2494     $modules['builtin']['status'] = MODULE_STATUS_ENABLED; 
    2495   }  
    2496   if (!$module && !$modulelist->is_loaded()) { 
    2497     $modulelist->initialize($modules); 
    2498   } 
    2499  
    2500   if ($status === false) { 
    2501     if (!$module) { 
    2502       return $modulelist->module_array; 
    2503     } else { 
    2504       return $modules; 
    2505     } 
    2506   } else { 
    2507     if (!$module) { 
    2508       $modules =  $modulelist->module_array; 
    2509     } 
    2510     if (!is_array($status)) { 
    2511       // make a one element array so we can use in_array below 
    2512       $status = array($status); 
    2513     } 
    2514     foreach (array_keys($modules) as $name) { 
    2515       if (!in_array($modules[$name]['status'], $status)) { 
    2516         // not found in the $status array, remove it 
    2517         unset($modules[$name]); 
    2518       } 
    2519     } 
    2520     return $modules; 
    2521   } 
    2522 } 
    2523  
    2524 /** Check if a module meets dependencies.  
    2525  * @param  mixed  The name of the module, or the modulexml Array 
    2526  * @return mixed  Returns true if dependencies are met, or an array  
    2527  *                containing a list of human-readable errors if not. 
    2528  *                NOTE: you must use strict type checking (===) to test 
    2529  *                for true, because  array() == true ! 
    2530  */ 
    2531 function module_checkdepends($modulename) { 
    2532    
    2533   // check if we were passed a modulexml array, or a string (name) 
    2534   // ensure $modulexml is the modules array, and $modulename is the name (as a string) 
    2535   if (is_array($modulename)) { 
    2536     $modulexml = $modulename; 
    2537     $modulename = $modulename['rawname']; 
    2538   } else { 
    2539     $modulexml = module_getinfo($modulename); 
    2540   } 
    2541    
    2542   $errors = array(); 
    2543    
    2544   // special handling for engine 
    2545   $engine_dependency = false; // if we've found ANY engine dependencies to check 
    2546   $engine_matched = false; // if an engine dependency has matched 
    2547   $engine_errors = array(); // the error strings for engines 
    2548    
    2549   if (isset($modulexml['depends'])) { 
    2550     foreach ($modulexml['depends'] as $type => $requirements) { 
    2551       // if only a single item, make it an array so we can use the same code as for multiple items 
    2552       // this is because if there is  <module>a</module><module>b</module>  we will get array('module' => array('a','b')) 
    2553       if (!is_array($requirements)) { 
    2554         $requirements = array($requirements); 
    2555       } 
    2556        
    2557       foreach ($requirements as $value) { 
    2558         switch ($type) { 
    2559           case 'version': 
    2560             if (preg_match('/^(lt|le|gt|ge|==|=|eq|!=|ne)?\s*(\d*[beta|alpha|rc|RC]?\d+(\.[^\.]+)*)$/i', $value, $matches)) { 
    2561               // matches[1] = operator, [2] = version 
    2562               $installed_ver = getversion(); 
    2563               $operator = (!empty($matches[1]) ? $matches[1] : 'ge'); // default to >= 
    2564               $compare_ver = $matches[2]; 
    2565               if (version_compare_freepbx($installed_ver, $compare_ver, $operator) ) { 
    2566                 // version is good 
    2567               } else { 
    2568                 $errors[] = _module_comparison_error_message('FreePBX', $compare_ver, $installed_ver, $operator); 
    2569               } 
    2570             } 
    2571           break; 
    2572           case 'phpversion': 
    2573             /* accepted formats 
    2574                <depends> 
    2575                  <phpversion>5.1.0<phpversion>       TRUE: if php is >= 5.1.0 
    2576                  <phpversion>gt 5.1.0<phpversion>    TRUE: if php is > 5.1.0 
    2577               </depends> 
    2578             */ 
    2579             if (preg_match('/^(lt|le|gt|ge|==|=|eq|!=|ne)?\s*(\d*[beta|alpha|rc|RC]?\d+(\.[^\.]+)*)$/i', $value, $matches)) { 
    2580               // matches[1] = operator, [2] = version 
    2581               $installed_ver = phpversion(); 
    2582               $operator = (!empty($matches[1]) ? $matches[1] : 'ge'); // default to >= 
    2583               $compare_ver = $matches[2]; 
    2584               if (version_compare($installed_ver, $compare_ver, $operator) ) { 
    2585                 // php version is good 
    2586               } else { 
    2587                 $errors[] = _module_comparison_error_message('PHP', $compare_ver, $installed_ver, $operator); 
    2588               } 
    2589             }  
    2590           break; 
    2591           case 'phpcomponent': 
    2592             /* accepted formats 
    2593                <depends> 
    2594                  <phpversion>zlib<phpversion>        TRUE: if extension zlib is loaded 
    2595                  <phpversion>zlib 1.2<phpversion>    TRUE: if extension zlib is loaded and >= 1.2 
    2596                  <phpversion>zlib gt 1.2<phpversion> TRUE: if extension zlib is loaded and > 1.2 
    2597               </depends> 
    2598             */ 
    2599             if (preg_match('/^([a-z0-9_]+)(\s+(lt|le|gt|ge|==|=|eq|!=|ne)?\s*(\d+(\.\d*[beta|alpha|rc|RC]*\d+)+))?$/i', $value, $matches)) { 
    2600               // matches[1] = extension name, [3]=comparison operator, [4] = version 
    2601               $compare_ver = isset($matches[4]) ? $matches[4] : ''; 
    2602               if (extension_loaded($matches[1])) { 
    2603                 if (empty($compare_ver)) { 
    2604                   // extension is loaded and no version specified 
    2605                 } else { 
    2606                   if (($installed_ver = phpversion($matches[1])) != '') { 
    2607                     $operator = (!empty($matches[3]) ? $matches[3] : 'ge'); // default to >= 
    2608                     if (version_compare($installed_ver, $compare_ver, $operator) ) { 
    2609                       // version is good 
    2610                     } else { 
    2611                       $errors[] = _module_comparison_error_message("PHP Component ".$matches[1], $compare_ver, $installed_ver, $operator); 
    2612                     } 
    2613                   } else { 
    2614                     $errors[] = _module_comparison_error_message("PHP Component ".$matches[1], $compare_ver, "<no version info>", $operator); 
    2615                   } 
    2616                 } 
    2617               } else { 
    2618                 if ($compare_version == '') { 
    2619                   $errors[] = sprintf(_('PHP Component %s is required but missing from you PHP installation.'), $matches[1]); 
    2620                 } else { 
    2621                   $errors[] = sprintf(_('PHP Component %s version %s is required but missing from you PHP installation.'), $matches[1], $compare_version); 
    2622                 } 
    2623               } 
    2624             }  
    2625           break; 
    2626           case 'module': 
    2627             // Modify to allow versions such as 2.3.0beta1.2 
    2628             if (preg_match('/^([a-z0-9_]+)(\s+(lt|le|gt|ge|==|=|eq|!=|ne)?\s*(\d+(\.\d*[beta|alpha|rc|RC]*\d+)+))?$/i', $value, $matches)) { 
    2629               // matches[1] = modulename, [3]=comparison operator, [4] = version 
    2630               $modules = module_getinfo($matches[1]); 
    2631               if (isset($modules[$matches[1]])) { 
    2632                 $needed_module = "<strong>".(isset($modules[$matches[1]]['name'])?$modules[$matches[1]]['name']:$matches[1])."</strong>"; 
    2633                 switch ($modules[$matches[1]]['status'] ) { 
    2634                   case MODULE_STATUS_ENABLED: 
    2635                     if (!empty($matches[4])) { 
    2636                       // also doing version checking 
    2637                       $installed_ver = $modules[$matches[1]]['dbversion']; 
    2638                       $compare_ver = $matches[4]; 
    2639                       $operator = (!empty($matches[3]) ? $matches[3] : 'ge'); // default to >= 
    2640                        
    2641                       if (version_compare_freepbx($installed_ver, $compare_ver, $operator) ) { 
    2642                         // version is good 
    2643                       } else { 
    2644                         $errors[] = _module_comparison_error_message($needed_module.' module', $compare_ver, $installed_ver, $operator); 
    2645                       } 
    2646                     } 
    2647                   break; 
    2648                   case MODULE_STATUS_BROKEN: 
    2649                     $errors[] = sprintf(_('Module %s is required, but yours is broken. You should reinstall '. 
    2650                                           'it and try again.'), $needed_module); 
    2651                   break; 
    2652                   case MODULE_STATUS_DISABLED: 
    2653                     $errors[] = sprintf(_('Module %s is required, but yours is disabled.'), $needed_module); 
    2654                   break; 
    2655                   case MODULE_STATUS_NEEDUPGRADE: 
    2656                     $errors[] = sprintf(_('Module %s is required, but yours is disabled because it needs to '. 
    2657                                           'be upgraded. Please upgrade %s first, and then try again.'),  
    2658                               $needed_module, $needed_module); 
    2659                   break; 
    2660                   default: 
    2661                   case MODULE_STATUS_NOTINSTALLED: 
    2662                     $errors[] = sprintf(_('Module %s is required, yours is not installed.'), $needed_module); 
    2663                   break; 
    2664                 } 
    2665               } else { 
    2666                 $errors[] = sprintf(_('Module %s is required.'), $matches[1]); 
    2667               } 
    2668             } 
    2669           break; 
    2670           case 'file': // file exists 
    2671             // replace embedded amp_conf %VARIABLES% in string 
    2672             $file = ampconf_string_replace($value); 
    2673              
    2674             if (!file_exists( $file )) { 
    2675               $errors[] = sprintf(_('File %s must exist.'), $file); 
    2676             } 
    2677           break; 
    2678           case 'engine': 
    2679             /**************************** 
    2680              *  NOTE: there is special handling for this check. We want to "OR" conditions, instead of 
    2681              *        "AND"ing like the rest of them.  
    2682              */ 
    2683              
    2684             // we found at least one engine, so mark that we're matching this  
    2685             $engine_dependency = true; 
    2686              
    2687             if (preg_match('/^([a-z0-9_]+)(\s+(lt|le|gt|ge|==|=|eq|!=|ne)?\s*(\d+(\.[^\.]+)*))?$/i', $value, $matches)) { 
    2688               // matches[1] = engine, [3]=comparison operator, [4] = version 
    2689               $operator = (!empty($matches[3]) ? $matches[3] : 'ge'); // default to >= 
    2690                
    2691               $engine = engine_getinfo(); 
    2692               if (($engine['engine'] == $matches[1]) && 
    2693                   (empty($matches[4]) || !version_compare($matches[4], $engine['version'], $operator)) 
    2694                  ) { 
    2695                   
    2696                 $engine_matched = true; 
    2697               } else { 
    2698                 // add it to the error messages 
    2699                 if ($matches[4]) { 
    2700                   // version specified 
    2701                   $operator_friendly = str_replace(array('gt','ge','lt','le','eq','ne'), array('>','>=','<','<=','=','not ='), $operator); 
    2702                   $engine_errors[] = $matches[1].' ('.$operator_friendly.' '.$matches[4].')'; 
    2703                 } else { 
    2704                   // no version 
    2705                   $engine_errors[] = $matches[1]; 
    2706                 } 
    2707               } 
    2708             } 
    2709           break; 
    2710         } 
    2711       } 
    2712     } 
    2713      
    2714     // special handling for engine 
    2715     // if we've had at least one engine dependency check, and no engine dependencies matched, we have an error 
    2716     if ($engine_dependency && !$engine_matched) { 
    2717      
    2718       $engineinfo = engine_getinfo(); 
    2719       $yourengine = $engineinfo['engine'].' '.$engineinfo['version']; 
    2720       // print it nicely 
    2721       if (count($engine_errors) == 1) { 
    2722         $errors[] = sprintf(_('Requires engine %s, you have: %s'),$engine_errors[0],$yourengine); 
    2723       } else { 
    2724         $errors[] = sprintf(_('Requires one of the following engines: %s; you have: %s'),implode(', ', $engine_errors),$yourengine); 
    2725       } 
    2726     } 
    2727   } 
    2728    
    2729   if (count($errors) > 0) { 
    2730     return $errors; 
    2731   } else { 
    2732     return true; 
    2733   } 
    2734 } 
    2735  
    2736 function _module_comparison_error_message($module, $reqversion, $version, $operator) { 
    2737   switch ($operator) { 
    2738     case 'lt': case '<': 
    2739       return sprintf(_('A %s version below %s is required, you have %s'), $module, $reqversion, $version); 
    2740     break; 
    2741     case 'le': case '<='; 
    2742       return sprintf(_('%s version %s or below is required, you have %s'), $module, $reqversion, $version); 
    2743     break; 
    2744     case 'gt': case '>'; 
    2745       return sprintf(_('A %s version newer than %s required, you have %s'), $module, $reqversion, $version); 
    2746     break; 
    2747     case 'ne': case '!=': case '<>': 
    2748       return sprintf(_('Your %s version (%s) is incompatible.'), $version, $reqversion); 
    2749     break; 
    2750     case 'eq': case '==': case '=':  
    2751       return sprintf(_('Only %s version %s is compatible, you have %s'), $module, $reqversion, $version); 
    2752     break; 
    2753     default: 
    2754     case 'ge': case '>=': 
    2755       return sprintf(_('%s version %s or higher is required, you have %s'), $module, $reqversion, $version); 
    2756   } 
    2757 } 
    2758  
    2759 /** Finds all the enabled modules that depend on a given module 
    2760  * @param  mixed  The name of the module, or the modulexml Array 
    2761  * @return array  Array containing the list of modules, or false if no dependencies 
    2762  */ 
    2763 function module_reversedepends($modulename) { 
    2764   // check if we were passed a modulexml array, or a string (name) 
    2765   // ensure $modulename is the name (as a string) 
    2766   if (is_array($modulename)) { 
    2767     $modulename = $modulename['rawname']; 
    2768   } 
    2769    
    2770   $modules = module_getinfo(false, MODULE_STATUS_ENABLED); 
    2771    
    2772   $depends = array(); 
    2773    
    2774   foreach (array_keys($modules) as $name) { 
    2775     if (isset($modules[$name]['depends'])) { 
    2776       foreach ($modules[$name]['depends'] as $type => $requirements) { 
    2777         if ($type == 'module') { 
    2778           // if only a single item, make it an array so we can use the same code as for multiple items 
    2779           // this is because if there is  <module>a</module><module>b</module>  we will get array('module' => array('a','b')) 
    2780           if (!is_array($requirements)) { 
    2781             $requirements = array($requirements); 
    2782           } 
    2783            
    2784           foreach ($requirements as $value) { 
    2785             if (preg_match('/^([a-z0-9_]+)(\s+(>=|>|=|<|<=|!=)?\s*(\d(\.\d)*))?$/i', $value, $matches)) { 
    2786               // matches[1] = modulename, [3]=comparison operator, [4] = version 
    2787                
    2788               // note, we're not checking version here. Normally this function is used when 
    2789               // uninstalling a module, so it doesn't really matter anyways, and version 
    2790               // dependency should have already been checked when the module was installed 
    2791               if ($matches[1] == $modulename) { 
    2792                 $depends[] = $name; 
    2793               } 
    2794             } 
    2795           } 
    2796         } 
    2797       } 
    2798     } 
    2799   } 
    2800    
    2801   return (count($depends) > 0) ? $depends : false; 
    2802 } 
    2803  
    2804 /** Enables a module 
    2805  * @param string    The name of the module to enable 
    2806  * @param bool      If true, skips status and dependency checks 
    2807  * @return  mixed   True if succesful, array of error messages if not succesful 
    2808  */ 
    2809 function module_enable($modulename, $force = false) { // was enableModule 
    2810   $modules = module_getinfo($modulename); 
    2811    
    2812   if ($modules[$modulename]['status'] == MODULE_STATUS_ENABLED) { 
    2813     return array(_("Module ".$modulename." is already enabled")); 
    2814   } 
    2815    
    2816   // doesn't make sense to skip this on $force - eg, we can't enable a non-installed or broken module 
    2817   if ($modules[$modulename]['status'] != MODULE_STATUS_DISABLED) { 
    2818     return array(_("Module ".$modulename." cannot be enabled")); 
    2819   } 
    2820    
    2821   if (!$force) {  
    2822     if (($errors = module_checkdepends($modules[$modulename])) !== true) { 
    2823       return $errors; 
    2824     } 
    2825   } 
    2826    
    2827   // disabled (but doesn't needupgrade or need install), and meets dependencies 
    2828   _module_setenabled($modulename, true); 
    2829   needreload(); 
    2830   return true; 
    2831 } 
    2832  
    2833 /** Downloads the latest version of a module 
    2834  * and extracts it to the directory 
    2835  * @param string    The name of the module to install 
    2836  * @param bool      If true, skips status and dependency checks 
    2837  * @param string    The name of a callback function to call with progress updates. 
    2838                     function($action, $params). Possible actions: 
    2839                       getinfo: while downloading modules.xml 
    2840                       downloading: while downloading file; params include 'read' and 'total' 
    2841                       untar: before untarring 
    2842                       done: when complete 
    2843  * @return  mixed   True if succesful, array of error messages if not succesful 
    2844  */ 
    2845  
    2846 // was fetchModule  
    2847 function module_download($modulename, $force = false, $progress_callback = null, $override_svn = false, $override_xml = false) {  
    2848   global $amp_conf; 
    2849  
    2850   if ($time_limit = ini_get('max_execution_time')) { 
    2851     set_time_limit($time_limit); 
    2852   } 
    2853    
    2854   // size of download blocks to fread() 
    2855   // basically, this controls how often progress_callback is called 
    2856   $download_chunk_size = 12*1024; 
    2857    
    2858   // invoke progress callback 
    2859   if (function_exists($progress_callback)) { 
    2860     $progress_callback('getinfo', array('module'=>$modulename)); 
    2861   } 
    2862        
    2863   $res = module_getonlinexml($modulename, $override_xml); 
    2864   if ($res == null) { 
    2865     return array(_("Module not found in repository")); 
    2866   } 
    2867    
    2868   $file = basename($res['location']); 
    2869   $filename = $amp_conf['AMPWEBROOT']."/admin/modules/_cache/".$file; 
    2870   // if we're not forcing the download, and a file with the target name exists.. 
    2871   if (!$force && file_exists($filename)) { 
    2872     // We might already have it! Let's check the MD5. 
    2873     $filedata = ""; 
    2874     if ( $fh = @ fopen($filename, "r") ) { 
    2875       while (!feof($fh)) { 
    2876         $filedata .= fread($fh, 8192); 
    2877       } 
    2878       fclose($fh); 
    2879     } 
    2880      
    2881     if (isset($res['md5sum']) && $res['md5sum'] == md5 ($filedata)) { 
    2882       // Note, if there's no MD5 information, it will redownload 
    2883       // every time. Otherwise theres no way to avoid a corrupt 
    2884       // download 
    2885        
    2886       // invoke progress callback 
    2887       if (function_exists($progress_callback)) { 
    2888         $progress_callback('untar', array('module'=>$modulename, 'size'=>filesize($filename))); 
    2889       } 
    2890        
    2891       /* We will explode the tarball in the cache directory and then once successful, remove the old module before before 
    2892        * moving the new one over. This way, things like removed files end up being removed instead of laying around 
    2893        * 
    2894        * TODO: save old module being replaced, if there is an old one. 
    2895        */ 
    2896       exec("rm -rf ".$amp_conf['AMPWEBROOT']."/admin/modules/_cache/$modulename", $output, $exitcode); 
    2897       if ($exitcode != 0) { 
    2898         return array(sprintf(_('Could not remove %s to install new version'), $amp_conf['AMPWEBROOT'].'/admin/modules/_cache/'.$modulenam)); 
    2899       } 
    2900       exec("tar zxf ".escapeshellarg($filename)." -C ".escapeshellarg($amp_conf['AMPWEBROOT'].'/admin/modules/_cache/'), $output, $exitcode); 
    2901       if ($exitcode != 0) { 
    2902         return array(sprintf(_('Could not untar %s to %s'), $filename, $amp_conf['AMPWEBROOT'].'/admin/modules/_cache')); 
    2903       } 
    2904       exec("rm -rf ".$amp_conf['AMPWEBROOT']."/admin/modules/$modulename", $output, $exitcode); 
    2905       if ($exitcode != 0) { 
    2906         return array(sprintf(_('Could not remove old module %s to install new version'), $amp_conf['AMPWEBROOT'].'/admin/modules/'.$modulename)); 
    2907       } 
    2908       exec("mv ".$amp_conf['AMPWEBROOT']."/admin/modules/_cache/$modulename ".$amp_conf['AMPWEBROOT']."/admin/modules/$modulename", $output, $exitcode); 
    2909       if ($exitcode != 0) { 
    2910         return array(sprintf(_('Could not move %s to %s'), $amp_conf['AMPWEBROOT']."/admin/modules/_cache/$modulename", $amp_conf['AMPWEBROOT'].'/admin/modules/')); 
    2911       } 
    2912        
    2913       // invoke progress_callback 
    2914       if (function_exists($progress_callback)) { 
    2915         $progress_callback('done', array('module'=>$modulename)); 
    2916       } 
    2917        
    2918       return true; 
    2919     } else { 
    2920       unlink($filename); 
    2921     } 
    2922   } 
    2923    
    2924   if ($override_svn) { 
    2925     $url = $override_svn.$res['location']; 
    2926   } else { 
    2927     $url = "http://mirror.freepbx.org/modules/".$res['location']; 
    2928   } 
    2929    
    2930   if (!($fp = @fopen($filename,"w"))) { 
    2931     return array(sprintf(_("Error opening %s for writing"), $filename)); 
    2932   } 
    2933    
    2934   $headers = get_headers_assoc($url); 
    2935    
    2936   $totalread = 0; 
    2937   // invoke progress_callback 
    2938   if (function_exists($progress_callback)) { 
    2939     $progress_callback('downloading', array('module'=>$modulename, 'read'=>$totalread, 'total'=>$headers['content-length'])); 
    2940   } 
    2941    
    2942   // Check MODULEADMINWGET first so we don't execute the fopen() if set 
    2943   // 
    2944   if ($amp_conf['MODULEADMINWGET'] || !$dp = @fopen($url,'r')) { 
    2945     exec("wget -O $filename $url 2> /dev/null", $filedata, $retcode); 
    2946     if ($retcode != 0) { 
    2947       return array(sprintf(_("Error opening %s for reading"), $url)); 
    2948     } else { 
    2949       if (!$dp = @fopen($filename,'r')) { 
    2950         return array(sprintf(_("Error opening %s for reading"), $url)); 
    2951       } 
    2952     } 
    2953   } 
    2954    
    2955   $filedata = ''; 
    2956   while (!feof($dp)) { 
    2957     $data = fread($dp, $download_chunk_size); 
    2958     $filedata .= $data; 
    2959     $totalread += strlen($data); 
    2960     if (function_exists($progress_callback)) { 
    2961       $progress_callback('downloading', array('module'=>$modulename, 'read'=>$totalread, 'total'=>$headers['content-length'])); 
    2962     } 
    2963   } 
    2964   fwrite($fp,$filedata); 
    2965   fclose($dp); 
    2966   fclose($fp); 
    2967    
    2968    
    2969   if (is_readable($filename) !== TRUE ) { 
    2970     return array(sprintf(_('Unable to save %s'),$filename)); 
    2971   } 
    2972    
    2973   // Check the MD5 info against what's in the module's XML 
    2974   if (!isset($res['md5sum']) || empty($res['md5sum'])) { 
    2975     //echo "<div class=\"error\">"._("Unable to Locate Integrity information for")." {$filename} - "._("Continuing Anyway")."</div>"; 
    2976   } else if ($res['md5sum'] != md5 ($filedata)) { 
    2977     unlink($filename); 
    2978     return array(sprintf(_('File Integrity failed for %s - aborting'), $filename)); 
    2979   } 
    2980    
    2981   // invoke progress callback 
    2982   if (function_exists($progress_callback)) { 
    2983     $progress_callback('untar', array('module'=>$modulename, 'size'=>filesize($filename))); 
    2984   } 
    2985  
    2986   /* We will explode the tarball in the cache directory and then once successful, remove the old module before before 
    2987    * moving the new one over. This way, things like removed files end up being removed instead of laying around 
    2988    * 
    2989    * TODO: save old module being replaced, if there is an old one. 
    2990    * 
    2991    */ 
    2992   exec("rm -rf ".$amp_conf['AMPWEBROOT']."/admin/modules/_cache/$modulename", $output, $exitcode); 
    2993   if ($exitcode != 0) { 
    2994     return array(sprintf(_('Could not remove %s to install new version'), $amp_conf['AMPWEBROOT'].'/admin/modules/_cache/'.$modulenam)); 
    2995   } 
    2996   exec("tar zxf ".escapeshellarg($filename)." -C ".escapeshellarg($amp_conf['AMPWEBROOT'].'/admin/modules/_cache/'), $output, $exitcode); 
    2997   if ($exitcode != 0) { 
    2998     return array(sprintf(_('Could not untar %s to %s'), $filename, $amp_conf['AMPWEBROOT'].'/admin/modules/_cache')); 
    2999   } 
    3000   exec("rm -rf ".$amp_conf['AMPWEBROOT']."/admin/modules/$modulename", $output, $exitcode); 
    3001   if ($exitcode != 0) { 
    3002     return array(sprintf(_('Could not remove old module %s to install new version'), $amp_conf['AMPWEBROOT'].'/admin/modules/'.$modulename)); 
    3003   } 
    3004   exec("mv ".$amp_conf['AMPWEBROOT']."/admin/modules/_cache/$modulename ".$amp_conf['AMPWEBROOT']."/admin/modules/$modulename", $output, $exitcode); 
    3005   if ($exitcode != 0) { 
    3006     return array(sprintf(_('Could not move %s to %s'), $amp_conf['AMPWEBROOT']."/admin/modules/_cache/$modulename", $amp_conf['AMPWEBROOT'].'/admin/modules/')); 
    3007   } 
    3008  
    3009   // invoke progress_callback 
    3010   if (function_exists($progress_callback)) { 
    3011     $progress_callback('done', array('module'=>$modulename)); 
    3012   } 
    3013  
    3014   return true; 
    3015 } 
    3016  
    3017  
    3018 function module_handleupload($uploaded_file) { 
    3019   global $amp_conf; 
    3020   $errors = array(); 
    3021    
    3022   if (!isset($uploaded_file['tmp_name']) || !file_exists($uploaded_file['tmp_name'])) { 
    3023     $errors[] = _("Error finding uploaded file - check your PHP and/or web server configuration"); 
    3024     return $errors; 
    3025   } 
    3026    
    3027   if (!preg_match('/\.(tar\.gz|tgz)$/', $uploaded_file['name'])) { 
    3028     $errors[] = _("File must be in tar+gzip (.tgz or .tar.gz) format"); 
    3029     return $errors; 
    3030   } 
    3031    
    3032   if (!preg_match('/^([A-Za-z][A-Za-z0-9_]+)\-([0-9a-zA-Z]+(\.[0-9a-zA-Z]+)*)\.(tar\.gz|tgz)$/', $uploaded_file['name'], $matches)) { 
    3033     $errors[] = _("Filename not in correct format: must be modulename-version.tar.gz (eg. custommodule-0.1.tar.gz)"); 
    3034     return $errors; 
    3035   } else { 
    3036     $modulename = $matches[1]; 
    3037     $moduleversion = $matches[2]; 
    3038   } 
    3039    
    3040   $temppath = $amp_conf['AMPWEBROOT'].'/admin/modules/_cache/'.uniqid("upload"); 
    3041   if (! @mkdir($temppath) ) { 
    3042     return array(sprintf(_("Error creating temporary directory: %s"), $temppath)); 
    3043   } 
    3044   $filename = $temppath.'/'.$uploaded_file['name']; 
    3045    
    3046   move_uploaded_file($uploaded_file['tmp_name'], $filename); 
    3047    
    3048   exec("tar ztf ".escapeshellarg($filename), $output, $exitcode); 
    3049   if ($exitcode != 0) { 
    3050     $errors[] = _("Error untaring uploaded file. Must be a tar+gzip file"); 
    3051     return $errors; 
    3052   } 
    3053    
    3054   foreach ($output as $line) { 
    3055     // make sure all lines start with "modulename/" 
    3056     if (!preg_match('/^'.$modulename.'\//', $line)) { 
    3057       $errors[] = 'File extracting to invalid location: '.$line; 
    3058     } 
    3059   } 
    3060   if (count($errors)) { 
    3061     return $errors; 
    3062   } 
    3063  
    3064   /* We will explode the tarball in the cache directory and then once successful, remove the old module before before 
    3065    * moving the new one over. This way, things like removed files end up being removed instead of laying around 
    3066    * 
    3067    * TODO: save old module being replaced, if there is an old one. 
    3068    * 
    3069    */ 
    3070   exec("rm -rf ".$amp_conf['AMPWEBROOT']."/admin/modules/_cache/$modulename", $output, $exitcode); 
    3071   if ($exitcode != 0) { 
    3072     return array(sprintf(_('Could not remove %s to install new version'), $amp_conf['AMPWEBROOT'].'/admin/modules/_cache/'.$modulenam)); 
    3073   } 
    3074   exec("tar zxf ".escapeshellarg($filename)." -C ".escapeshellarg($amp_conf['AMPWEBROOT'].'/admin/modules/_cache/'), $output, $exitcode); 
    3075   if ($exitcode != 0) { 
    3076     return array(sprintf(_('Could not untar %s to %s'), $filename, $amp_conf['AMPWEBROOT'].'/admin/modules/_cache')); 
    3077   } 
    3078   exec("rm -rf ".$amp_conf['AMPWEBROOT']."/admin/modules/$modulename", $output, $exitcode); 
    3079   if ($exitcode != 0) { 
    3080     return array(sprintf(_('Could not remove old module %s to install new version'), $amp_conf['AMPWEBROOT'].'/admin/modules/'.$modulename)); 
    3081   } 
    3082   exec("mv ".$amp_conf['AMPWEBROOT']."/admin/modules/_cache/$modulename ".$amp_conf['AMPWEBROOT']."/admin/modules/$modulename", $output, $exitcode); 
    3083   if ($exitcode != 0) { 
    3084     return array(sprintf(_('Could not move %s to %s'), $amp_conf['AMPWEBROOT']."/admin/modules/_cache/$modulename", $amp_conf['AMPWEBROOT'].'/admin/modules/')); 
    3085   } 
    3086  
    3087   exec("rm -rf ".$temppath, $output, $exitcode); 
    3088   if ($exitcode != 0) { 
    3089     $errors[] = sprintf(_('Error removing temporary directory: %s'), $temppath); 
    3090   } 
    3091    
    3092   if (count($errors)) { 
    3093     return $errors; 
    3094   } 
    3095    
    3096   // finally, module installation is successful 
    3097   return true; 
    3098 } 
    3099  
    3100 /** Installs or upgrades a module from it's directory 
    3101  * Checks dependencies, and enables 
    3102  * @param string   The name of the module to install 
    3103  * @param bool     If true, skips status and dependency checks 
    3104  * @return mixed   True if succesful, array of error messages if not succesful 
    3105  */ 
    3106 function module_install($modulename, $force = false) { 
    3107   global $db, $amp_conf; 
    3108  
    3109   if ($time_limit = ini_get('max_execution_time')) { 
    3110     set_time_limit($time_limit); 
    3111   } 
    3112  
    3113   $modules = module_getinfo($modulename); 
    3114    
    3115   // make sure we have a directory, to begin with 
    3116   $dir = $amp_conf['AMPWEBROOT'].'/admin/modules/'.$modulename; 
    3117   if (!is_dir($dir)) { 
    3118     return array(_("Cannot find module")); 
    3119   } 
    3120    
    3121   // read the module.xml file 
    3122   $modules = module_getinfo($modulename); 
    3123   if (!isset($modules[$modulename])) { 
    3124     return array(_("Could not read module.xml")); 
    3125   } 
    3126    
    3127   // don't force this bit - we can't install a broken module (missing files)  
    3128   if ($modules[$modulename]['status'] == MODULE_STATUS_BROKEN) { 
    3129     return array(_("Module ".$modules[$modulename]['rawname']." is broken and cannot be installed. You should try to download it again.")); 
    3130   } 
    3131    
    3132   if (!$force) { 
    3133    
    3134     if (!in_array($modules[$modulename]['status'], array(MODULE_STATUS_NOTINSTALLED, MODULE_STATUS_NEEDUPGRADE))) { 
    3135       //return array(_("This module is already installed.")); 
    3136       // This isn't really an error, we just exit 
    3137       return true; 
    3138     } 
    3139      
    3140     // check dependencies 
    3141     if (is_array($errors = module_checkdepends($modules[$modulename]))) { 
    3142       return $errors; 
    3143     } 
    3144   } 
    3145    
    3146   // run the scripts 
    3147   if (!_module_runscripts($modulename, 'install')) { 
    3148     return array(_("Failed to run installation scripts")); 
    3149   } 
    3150    
    3151   if ($modules[$modulename]['status'] == MODULE_STATUS_NOTINSTALLED) { 
    3152     // customize INSERT query 
    3153     $sql = "INSERT INTO modules (modulename, version, enabled) values ('".$db->escapeSimple($modules[$modulename]['rawname'])."','".$db->escapeSimple($modules[$modulename]['version'])."', 1);"; 
    3154   } else { 
    3155     // just need to update the version 
    3156     $sql = "UPDATE modules SET version='".$db->escapeSimple($modules[$modulename]['version'])."' WHERE modulename = '".$db->escapeSimple($modules[$modulename]['rawname'])."'"; 
    3157   } 
    3158    
    3159   // run query 
    3160   $results = $db->query($sql); 
    3161   if(DB::IsError($results)) { 
    3162     return array(sprintf(_("Error updating database. Command was: %s; error was: %s "), $sql, $results->getMessage())); 
    3163   } 
    3164    
    3165   // module is now installed & enabled, invalidate the modulelist class since it is now stale 
    3166   $modulelist =& modulelist::create($db); 
    3167   $modulelist->invalidate(); 
    3168  
    3169   // edit the notification table to list any remaining upgrades available or clear 
    3170   // it if none are left. It requres a copy of the most recent module_xml to compare 
    3171   // against the installed modules. 
    3172   // 
    3173   $sql = 'SELECT data FROM module_xml WHERE id = "xml"'; 
    3174   $data = sql($sql, "getOne"); 
    3175   $parser = new xml2ModuleArray($data); 
    3176   $xmlarray = $parser->parseAdvanced($data); 
    3177   $new_modules = array(); 
    3178   if (count($xmlarray)) { 
    3179     foreach ($xmlarray['xml']['module'] as $mod) { 
    3180       $new_modules[$mod['rawname']] = $mod; 
    3181     } 
    3182   } 
    3183   module_upgrade_notifications($new_modules, 'PASSIVE'); 
    3184   needreload(); 
    3185   return true; 
    3186 } 
    3187  
    3188 /** Disable a module, but reqmains installed 
    3189  * @param string   The name of the module to disable 
    3190  * @param bool     If true, skips status and dependency checks 
    3191  * @return mixed   True if succesful, array of error messages if not succesful 
    3192 */ 
    3193 function module_disable($modulename, $force = false) { // was disableModule 
    3194   $modules = module_getinfo($modulename); 
    3195   if (!isset($modules[$modulename])) { 
    3196     return array(_("Specified module not found")); 
    3197   } 
    3198    
    3199   if (!$force) { 
    3200     if ($modules[$modulename]['status'] != MODULE_STATUS_ENABLED) { 
    3201       return array(_("Module not enabled: cannot disable")); 
    3202     } 
    3203      
    3204     if ( ($depmods = module_reversedepends($modulename)) !== false) { 
    3205       return array(_("Cannot disable: The following modules depend on this one: ").implode(',',$depmods)); 
    3206     } 
    3207   } 
    3208    
    3209   _module_setenabled($modulename, false); 
    3210   needreload(); 
    3211   return true; 
    3212 } 
    3213  
    3214 /** Uninstall a module, but files remain 
    3215  * @param string   The name of the module to install 
    3216  * @param bool     If true, skips status and dependency checks 
    3217  * @return mixed   True if succesful, array of error messages if not succesful 
    3218  */ 
    3219 function module_uninstall($modulename, $force = false) { 
    3220   global $db; 
    3221    
    3222   $modules = module_getinfo($modulename); 
    3223   if (!isset($modules[$modulename])) { 
    3224     return array(_("Specified module not found")); 
    3225   } 
    3226    
    3227   if (!$force) { 
    3228     if ($modules[$modulename]['status'] == MODULE_STATUS_NOTINSTALLED) { 
    3229       return array(_("Module not installed: cannot uninstall")); 
    3230     } 
    3231      
    3232     if ( ($depmods = module_reversedepends($modulename)) !== false) { 
    3233       return array(_("Cannot disable: The following modules depend on this one: ").implode(',',$depmods)); 
    3234     } 
    3235   } 
    3236    
    3237   $sql = "DELETE FROM modules WHERE modulename = '".$db->escapeSimple($modulename)."'"; 
    3238   $results = $db->query($sql); 
    3239   if(DB::IsError($results)) { 
    3240     return array(_("Error updating database: ").$results->getMessage()); 
    3241   } 
    3242    
    3243   if (!_module_runscripts($modulename, 'uninstall')) { 
    3244     return array(_("Failed to run un-installation scripts")); 
    3245   } 
    3246    
    3247   needreload(); 
    3248   return true; 
    3249 } 
    3250  
    3251 /** Totally deletes a module 
    3252  * @param string   The name of the module to install 
    3253  * @param bool     If true, skips status and dependency checks 
    3254  * @return mixed   True if succesful, array of error messages if not succesful 
    3255  */ 
    3256 function module_delete($modulename, $force = false) { 
    3257   global $amp_conf; 
    3258    
    3259   $modules = module_getinfo($modulename); 
    3260   if (!isset($modules[$modulename])) { 
    3261     return array(_("Specified module not found")); 
    3262   } 
    3263    
    3264   if ($modules[$modulename]['status'] != MODULE_STATUS_NOTINSTALLED) { 
    3265     if (is_array($errors = module_uninstall($modulename, $force))) { 
    3266       return $errors; 
    3267     } 
    3268   } 
    3269    
    3270   // delete module directory 
    3271   //TODO : do this in pure php 
    3272   $dir = $amp_conf['AMPWEBROOT'].'/admin/modules/'.$modulename; 
    3273   if (!is_dir($dir)) { 
    3274     return array(sprintf(_("Cannot delete directory %s"), $dir)); 
    3275   } 
    3276   if (strpos($dir,"..") !== false) { 
    3277     die_freepbx("Security problem, denying delete"); 
    3278   } 
    3279   exec("rm -r ".escapeshellarg($dir),$output, $exitcode); 
    3280   if ($exitcode != 0) { 
    3281     return array(sprintf(_("Error deleting directory %s (code %d)"), $dir, $exitcode)); 
    3282   } 
    3283    
    3284   // uninstall will have called needreload() if necessary 
    3285   return true; 
    3286 } 
    3287  
    3288 /** Internal use only */ 
    3289 function _module_setenabled($modulename, $enabled) { 
    3290   global $db; 
    3291   $sql = 'UPDATE modules SET enabled = '.($enabled ? '1' : '0').' WHERE modulename = "'.$db->escapeSimple($modulename).'"'; 
    3292   $results = $db->query($sql); 
    3293   if(DB::IsError($results)) { 
    3294     die_freepbx($sql."<br>\n".$results->getMessage()); 
    3295   } 
    3296   $modulelist =& modulelist::create($db); 
    3297   $modulelist->invalidate(); 
    3298 } 
    3299  
    3300 function _module_readxml($modulename) { 
    3301   global $amp_conf; 
    3302   switch ($modulename) { 
    3303     case 'builtin': // special handling 
    3304       $dir = $amp_conf['AMPWEBROOT']; 
    3305       $xmlfile = $dir.'/admin/module-builtin.xml'; 
    3306     break; 
    3307     default: 
    3308       $dir = $amp_conf['AMPWEBROOT'].'/admin/modules/'.$modulename; 
    3309       $xmlfile = $dir.'/module.xml'; 
    3310     break; 
    3311   } 
    3312  
    3313   if (file_exists($xmlfile)) { 
    3314     ini_set('user_agent','Wget/1.10.2 (Red Hat modified)'); 
    3315     $data = file_get_contents($xmlfile); 
    3316     //$parser = new xml2ModuleArray($data); 
    3317     //$xmlarray = $parser->parseModulesXML($data); 
    3318     $parser = new xml2Array($data); 
    3319     $xmlarray = $parser->data; 
    3320     if (isset($xmlarray['module'])) { 
    3321       // add a couple fields first 
    3322       $xmlarray['module']['name'] = str_replace("\n&\n","&",$xmlarray['module']['name']); 
    3323       $xmlarray['module']['displayname'] = $xmlarray['module']['name']; 
    3324       if (isset($xmlarray['module']['description'])) { 
    3325         $xmlarray['module']['description'] = trim(str_replace("\n","",$xmlarray['module']['description'])); 
    3326       } 
    3327       if (isset($xmlarray['module']['menuitems'])) { 
    3328          
    3329         foreach ($xmlarray['module']['menuitems'] as $item=>$displayname) { 
    3330           $displayname = str_replace("\n&\n","&",$displayname); 
    3331           $xmlarray['module']['menuitems'][$item] = $displayname; 
    3332           $path = '/module/menuitems/'.$item; 
    3333            
    3334           // find category 
    3335           if (isset($parser->attributes[$path]['category'])) { 
    3336             $category = str_replace("\n&\n","&",$parser->attributes[$path]['category']); 
    3337           } else if (isset($xmlarray['module']['category'])) { 
    3338             $category = str_replace("\n&\n","&",$xmlarray['module']['category']); 
    3339           } else { 
    3340             $category = 'Basic'; 
    3341           } 
    3342            
    3343           // find type 
    3344           if (isset($parser->attributes[$path]['type'])) { 
    3345             $type = $parser->attributes[$path]['type']; 
    3346           } else if (isset($xmlarray['module']['type'])) { 
    3347             $type = $xmlarray['module']['type']; 
    3348           } else { 
    3349             $type = 'setup'; 
    3350           } 
    3351            
    3352           // sort priority 
    3353           if (isset($parser->attributes[$path]['sort'])) { 
    3354             // limit to -10 to 10 
    3355             if ($parser->attributes[$path]['sort'] > 10) { 
    3356               $sort = 10; 
    3357             } else if ($parser->attributes[$path]['sort'] < -10) { 
    3358               $sort = -10; 
    3359             } else { 
    3360               $sort = $parser->attributes[$path]['sort']; 
    3361             } 
    3362           } else { 
    3363             $sort = 0; 
    3364           } 
    3365  
    3366           // setup basic items array 
    3367           $xmlarray['module']['items'][$item] = array( 
    3368             'name' => $displayname, 
    3369             'type' => $type, 
    3370             'category' => $category, 
    3371             'sort' => $sort, 
    3372           ); 
    3373            
    3374           // add optional values: 
    3375           $optional_attribs = array( 
    3376             'href', // custom href 
    3377             'target', // custom target frame 
    3378             'display', // display= override 
    3379             'needsenginedb', // set to true if engine db access required (e.g. astman access) 
    3380             'needsenginerunning', // set to true if required to run 
    3381             'access', // set to all if all users should always have access 
    3382             'hidden', //keep hidden from the gui at all times - but accesable if you kknow how... 
    3383           ); 
    3384           foreach ($optional_attribs as $attrib) { 
    3385             if (isset($parser->attributes[$path][ $attrib ])) { 
    3386               $xmlarray['module']['items'][$item][ $attrib ] = $parser->attributes[$path][ $attrib ]; 
    3387             } 
    3388           } 
    3389            
    3390         } 
    3391       } 
    3392       return $xmlarray['module']; 
    3393     } 
    3394   } 
    3395   return null; 
    3396 } 
    3397  
    3398 // Temporarily copied here, for people that haven't upgraded their 
    3399 // IVR module.. 
    3400  
    3401 function modules_getversion($modname) { 
    3402   return _modules_getversion($modname);  
    3403 } 
    3404  
    3405 // This returns the version of a module 
    3406 function _modules_getversion($modname) { 
    3407   global $db; 
    3408  
    3409   $sql = "SELECT version FROM modules WHERE modulename = '".$db->escapeSimple($modname)."'"; 
    3410   $results = $db->getRow($sql,DB_FETCHMODE_ASSOC); 
    3411   if (isset($results['version']))  
    3412     return $results['version']; 
    3413   else 
    3414     return null; 
    3415 } 
    3416  
    3417 /** Updates the version field in the module table 
    3418  * Should only be called internally 
    3419  */ 
    3420 function _modules_setversion($modname, $vers) { 
    3421   global $db; 
    3422  
    3423   return ; 
    3424 } 
    3425  
    3426 /** Run the module install/uninstall scripts 
    3427  * @param string  The name of the module 
    3428  * @param string  The action to perform, either 'install' or 'uninstall' 
    3429  * @return boolean  If the action was succesful 
    3430  */ 
    3431 function _module_runscripts($modulename, $type) { 
    3432   global $amp_conf; 
    3433   $db_engine = $amp_conf["AMPDBENGINE"]; 
    3434    
    3435   $moduledir = $amp_conf["AMPWEBROOT"]."/admin/modules/".$modulename; 
    3436   if (!is_dir($moduledir)) { 
    3437     return false; 
    3438   } 
    3439    
    3440   switch ($type) {  
    3441     case 'install': 
    3442       // install sql files 
    3443       $sqlfilename = "install.sql"; 
    3444       $rc = true; 
    3445        
    3446       if (is_file($moduledir.'/'.$sqlfilename)) { 
    3447         $rc = execSQL($moduledir.'/'.$sqlfilename); 
    3448       } 
    3449        
    3450       // then run .php scripts 
    3451       return (_modules_doinclude($moduledir.'/install.php', $modulename) && $rc); 
    3452     break; 
    3453     case 'uninstall': 
    3454       // run uninstall .php scripts first 
    3455       $rc = _modules_doinclude($moduledir.'/uninstall.php', $modulename); 
    3456        
    3457       $sqlfilename = "uninstall.sql"; 
    3458        
    3459       // then uninstall sql files  
    3460       if (is_file($moduledir.'/'.$sqlfilename)) { 
    3461         return ($rc && execSQL($moduledir.'/'.$sqlfilename)); 
    3462       } else { 
    3463         return $rc; 
    3464       } 
    3465        
    3466     break; 
    3467     default: 
    3468       return false; 
    3469   } 
    3470    
    3471   return true; 
    3472 } 
    3473  
    3474 function _modules_doinclude($filename, $modulename) { 
    3475   // we provide the following variables to the included file (as well as $filename and $modulename) 
    3476   global $db, $amp_conf, $asterisk_conf; 
    3477    
    3478   if (file_exists($filename) && is_file($filename)) { 
    3479     return include_once($filename); 
    3480   } else { 
    3481     return true; 
    3482   } 
    3483 } 
    3484  
    3485 /* module_get_annoucements() 
    3486  
    3487   Get's any annoucments, security warnings, etc. that may be related to the current freepbx version. Also 
    3488   transmits a uniqueid to help track the number of installations using the online module admin system. 
    3489   The uniqueid used is completely anonymous and not trackable. 
    3490 */ 
    3491 function module_get_annoucements() { 
    3492   global $db; 
    3493   global $amp_conf; 
    3494   $firstinstall=false; 
    3495   $type=null; 
    3496  
    3497   $sql = "SELECT * FROM module_xml WHERE id = 'installid'"; 
    3498   $result = sql($sql,'getRow',DB_FETCHMODE_ASSOC); 
    3499  
    3500   // if not set so this is a first time install 
    3501   // get a new hash to account for first time install 
    3502   // 
    3503   if (!isset($result['data']) || trim($result['data']) == "") { 
    3504  
    3505     $firstinstall=true; 
    3506     $install_hash = _module_generate_unique_id(); 
    3507     $installid = $install_hash['uniqueid']; 
    3508     $type = $install_hash['type']; 
    3509  
    3510     // save the hash so we remeber this is a first time install 
    3511     // 
    3512     $data4sql = $db->escapeSimple($installid); 
    3513     sql("INSERT INTO module_xml (id,time,data) VALUES ('installid',".time().",'".$data4sql."')"); 
    3514     $data4sql = $db->escapeSimple($type); 
    3515     sql("INSERT INTO module_xml (id,time,data) VALUES ('type',".time().",'".$data4sql."')"); 
    3516  
    3517   // Not a first time so save the queried hash and check if there is a type set 
    3518   // 
    3519   } else { 
    3520     $installid=$result['data']; 
    3521     $sql = "SELECT * FROM module_xml WHERE id = 'type'"; 
    3522     $result = sql($sql,'getRow',DB_FETCHMODE_ASSOC); 
    3523  
    3524     if (isset($result['data']) && trim($result['data']) != "") { 
    3525       $type=$result['data']; 
    3526     } 
    3527   } 
    3528  
    3529   // Now we have the id and know if this is a firstime install so we can get the announcement 
    3530   // 
    3531   $options = "?installid=".urlencode($installid); 
    3532  
    3533   if (trim($type) != "") { 
    3534     $options .= "&type=".urlencode($type); 
    3535   } 
    3536   if ($firstinstall) { 
    3537     $options .= "&firstinstall=yes"; 
    3538   } 
    3539   $engver=engine_getinfo(); 
    3540   if ($engver['engine'] == 'asterisk' && trim($engver['engine']) != "") { 
    3541     $options .="&astver=".urlencode($engver['version']); 
    3542   } else { 
    3543     $options .="&astver=".urlencode($engver['raw']); 
    3544   } 
    3545  
    3546   $fn = "http://mirror.freepbx.org/version-".getversion().".html".$options; 
    3547   if (!$amp_conf['MODULEADMINWGET']) { 
    3548     ini_set('user_agent','Wget/1.10.2 (Red Hat modified)'); 
    3549     $announcement = @ file_get_contents($fn); 
    3550   } else { 
    3551     $announcement = ''; 
    3552   } 
    3553   if (empty($announcement)) { 
    3554     $fn2 = str_replace('&','\\&',$fn); 
    3555     exec("wget -O - $fn2 2>> /dev/null", $data_arr, $retcode); 
    3556     $announcement = implode("\n",$data_arr); 
    3557   } 
    3558   return $announcement; 
    3559 } 
    3560  
    3561 /* Assumes properly formated input, which is ok since 
    3562    this is a private function and error checking is done 
    3563    through proper regex scanning above 
    3564  
    3565    Returns: random md5 hash 
    3566  */ 
    3567 function _module_generate_random_id($type=null, $mac=null) { 
    3568  
    3569   if (trim($mac) == "") { 
    3570     $id['uniqueid'] = md5(mt_rand()); 
    3571   } else { 
    3572     // MD5 hash of the MAC so it is not identifiable 
    3573     // 
    3574     $id['uniqueid'] = md5($mac); 
    3575   } 
    3576   $id['type'] = $type; 
    3577  
    3578   return $id; 
    3579 } 
    3580  
    3581 /* _module_generate_unique_id 
    3582  
    3583   The purpose of this function is to generate a unique id that will try 
    3584   and regenerate the same unique id on a system if called multiple 
    3585   times. The id is unique but is not in any way identifable so that 
    3586   privacy is not compromised. 
    3587  
    3588   Returns: 
    3589  
    3590   Array: ["uniqueid"] => unique_md5_hash 
    3591          ["type"]     => type_passed_in 
    3592    
    3593 */ 
    3594 function _module_generate_unique_id($type=null) { 
    3595  
    3596   // Array of macs that require identification so we know these are not 
    3597   // 'real' systems. Either home setups or test environments 
    3598   // 
    3599   $ids = array('000C29' => 'vmware', 
    3600                '000569' => 'vmware', 
    3601                '00163E' => 'xensource' 
    3602               );  
    3603   $mac_address = array(); 
    3604   $chosen_mac = null; 
    3605  
    3606   // TODO: put proper path in places for ifconfig, try various locations where it may be if 
    3607   //       non-0 return code. 
    3608   // 
    3609   exec('/sbin/ifconfig',$output, $return); 
    3610  
    3611   if ($return != '0') { 
    3612  
    3613     // OK try another path 
    3614     // 
    3615     exec('ifconfig',$output, $return); 
    3616  
    3617     if ($return != '0') { 
    3618       // No seed available so return with random seed 
    3619       return _module_generate_random_id($type); 
    3620     } 
    3621   } 
    3622  
    3623   // parse the output of ifconfig to get list of MACs returned 
    3624   // 
    3625   foreach ($output as $str) { 
    3626     // make sure each line contains a valid MAC and IP address and then 
    3627     // 
    3628     if (preg_match("/([0-9A-Fa-f]{2}(:[0-9A-Fa-f]{2}){5})/", $str, $mac)) { 
    3629       $mac_address[] = strtoupper(preg_replace("/:/","",$mac[0])); 
    3630     } 
    3631   } 
    3632  
    3633   if (trim($type) == "") { 
    3634     foreach ($mac_address as $mac) { 
    3635       $id = substr($mac,0,6); 
    3636  
    3637       // If we care about this id, then choose it and set the type 
    3638       // we only choose the first one we see 
    3639       // 
    3640       if (array_key_exists($id,$ids)) { 
    3641         $chosen_mac = $mac; 
    3642         $type = $ids[$id]; 
    3643         break; 
    3644       } 
    3645     } 
    3646   } 
    3647  
    3648   // Now either we have a chosen_mac, we will use the first mac, or if something went wrong 
    3649   // and there is nothing in the array (couldn't find a mac) then we will make it purely random 
    3650   // 
    3651   if ($type == "vmware" || $type == "xensource") { 
    3652     // vmware, xensource machines will have repeated macs so make random 
    3653     return _module_generate_random_id($type); 
    3654   } else if ($chosen_mac != "") { 
    3655     return _module_generate_random_id($type, $chosen_mac); 
    3656   } else if (isset($mac_address[0])) { 
    3657     return _module_generate_random_id($type, $mac_address[0]); 
    3658   } else { 
    3659     return _module_generate_random_id($type); 
    3660   } 
    3661 }  
    3662  
    3663 function module_run_notification_checks() { 
    3664   global $db; 
    3665   $modules_needup = module_getinfo(false, MODULE_STATUS_NEEDUPGRADE); 
    3666   $modules_broken = module_getinfo(false, MODULE_STATUS_BROKEN); 
    3667    
    3668   $notifications =& notifications::create($db); 
    3669   if ($cnt = count($modules_needup)) { 
    3670     $text = (($cnt > 1) ? sprintf(_('You have %s disabled modules'), $cnt) : _('You have a disabled module')); 
    3671     $desc = _('The following modules are disabled because they need to be upgraded:')."\n".implode(", ",array_keys($modules_needup)); 
    3672     $desc .= "\n\n"._('You should go to the module admin page to fix these.'); 
    3673     $notifications->add_error('freepbx', 'modules_disabled', $text, $desc, '?type=tool&display=modules'); 
    3674   } else { 
    3675     $notifications->delete('freepbx', 'modules_disabled'); 
    3676   } 
    3677   if ($cnt = count($modules_broken)) { 
    3678     $text = (($cnt > 1) ? sprintf(_('You have %s broken modules'), $cnt) : _('You have a broken module')); 
    3679     $desc = _('The following modules are disabled because they are broken:')."\n".implode(", ",array_keys($modules_broken)); 
    3680     $desc .= "\n\n"._('You should go to the module admin page to fix these.'); 
    3681     $notifications->add_critical('freepbx', 'modules_broken', $text, $desc, '?type=tool&display=modules', false); 
    3682   } else { 
    3683     $notifications->delete('freepbx', 'modules_broken'); 
    3684   } 
    3685 } 
    3686  
    36871516/** Log a debug message to a debug file 
    36881517 * @param  string   debug message to be printed 
  • freepbx/trunk/amp_conf/htdocs/admin/views/freepbx.php

    r10122 r10244  
    5959  <style type="text/css"> 
    6060    body { 
    61       background-image: url(images/shadow-side-background.png); 
    62     background-repeat: repeat-y; 
    63     background-position: left; 
     61    background-image: url(images/shadow-side-background.png); 
     62    background-repeat: repeat-y; 
     63    background-position: left; 
    6464    } 
    6565  </style> 
    6666<?php } ?> 
    67   <link rel="shortcut icon" type="image/vnd.microsoft.icon" href="favicon.ico" /> 
    68   <!--[if IE]> 
    69   <link href="common/ie.css" rel="stylesheet" type="text/css" /> 
    70   <![endif]-->   
     67  <link rel="shortcut icon" href="images/favicon.ico" /> 
    7168<?php  
    7269  // check if in the amp configuration the user has set that 
  • modules/branches/2.9/blacklist/functions.inc.php

    r9619 r10244  
    1919 
    2020if( !class_exists('extension') ) { 
    21   require('extensions.class.php'); 
     21  require('libraries/extensions.class.php'); 
    2222} 
    2323function blacklist_get_config($engine) {