/** Installs or upgrades a module from it's directory * Checks dependencies, and enables * @param string The name of the module to install * @param bool If true, skips status and dependency checks * @return mixed True if succesful, array of error messages if not succesful */ function module_install($modulename, $force = false) { global $db, $amp_conf; if ($time_limit = ini_get('max_execution_time')) { set_time_limit($time_limit); } $modules = module_getinfo($modulename); // make sure we have a directory, to begin with $dir = $amp_conf['AMPWEBROOT'] . '/admin/modules/' . $modulename; if (!is_dir($dir)) { return array(_("Cannot find module")); } // read the module.xml file $modules = module_getinfo($modulename); if (!isset($modules[$modulename])) { return array(_("Could not read module.xml")); } // don't force this bit - we can't install a broken module (missing files) if ($modules[$modulename]['status'] == MODULE_STATUS_BROKEN) { return array(_("Module " . $modules[$modulename]['rawname'] . " is broken and cannot be installed. You should try to download it again.")); } if (!$force) { if (!in_array($modules[$modulename]['status'], array(MODULE_STATUS_NOTINSTALLED, MODULE_STATUS_NEEDUPGRADE))) { //return array(_("This module is already installed.")); // This isn't really an error, we just exit return true; } // check dependencies if (is_array($errors = module_checkdepends($modules[$modulename]))) { return $errors; } } // run the scripts if (!_module_runscripts($modulename, 'install')) { return array(_("Failed to run installation scripts")); } if ($modules[$modulename]['status'] == MODULE_STATUS_NOTINSTALLED) { // customize INSERT query $sql = "INSERT INTO modules (modulename, version, enabled) values ('" . $db->escapeSimple($modules[$modulename]['rawname']) . "','" . $db->escapeSimple($modules[$modulename]['version']) . "', 1);"; } else { // just need to update the version $sql = "UPDATE modules SET version='" . $db->escapeSimple($modules[$modulename]['version']) . "' WHERE modulename = '" . $db->escapeSimple($modules[$modulename]['rawname']) . "'"; } // run query $results = $db->query($sql); if (DB::IsError($results)) { return array(sprintf(_("Error updating database. Command was: %s; error was: %s "), $sql, $results->getMessage())); } // module is now installed & enabled, invalidate the modulelist class since it is now stale $modulelist =& modulelist::create($db); $modulelist->invalidate(); // edit the notification table to list any remaining upgrades available or clear // it if none are left. It requres a copy of the most recent module_xml to compare // against the installed modules. // $sql = 'SELECT data FROM module_xml WHERE id = "xml"'; $data = sql($sql, "getOne"); $parser = new xml2ModuleArray($data); $xmlarray = $parser->parseAdvanced($data); $new_modules = array(); if (count($xmlarray)) { foreach ($xmlarray['xml']['module'] as $mod) { $new_modules[$mod['rawname']] = $mod; } } module_upgrade_notifications($new_modules, 'PASSIVE'); needreload(); return true; }
/** * Installs or upgrades a module from it's directory * Checks dependencies, and enables * @param string The name of the module to install * @param bool If true, skips status and dependency checks * @return mixed True if succesful, array of error messages if not succesful */ function install($modulename, $force = false) { $this->modDepends = array(); $this->notFound = false; global $db, $amp_conf; set_time_limit($this->maxTimeLimit); $modules = $this->getinfo($modulename); // make sure we have a directory, to begin with $dir = $amp_conf['AMPWEBROOT'] . '/admin/modules/' . $modulename; if (!is_dir($dir)) { $this->notFound = true; return array(_("Cannot find module")); } // read the module.xml file $modules = $this->getinfo($modulename); if (!isset($modules[$modulename])) { return array(_("Could not read module.xml")); } // don't force this bit - we can't install a broken module (missing files) if ($modules[$modulename]['status'] == MODULE_STATUS_BROKEN) { return array(_("Module " . $modules[$modulename]['rawname'] . " is broken and cannot be installed. You should try to download it again.")); } $mod = FreePBX::GPG()->verifyModule($modulename); $revoked = $mod['status'] & GPG::STATE_REVOKED; if ($revoked) { return array(_("Module " . $modulename . " has a revoked signature and cannot be installed")); } if (!$force) { if (!in_array($modules[$modulename]['status'], array(MODULE_STATUS_ENABLED, MODULE_STATUS_NOTINSTALLED, MODULE_STATUS_NEEDUPGRADE))) { //return array(_("This module is already installed.")); // This isn't really an error, we just exit return true; } // check dependencies if (is_array($errors = $this->checkdepends($modules[$modulename]))) { return $errors; } } // Check if another module wants this install to be rejected // The module must have a callback: [modulename]_module_install_check_callback() that takes // a single modules array from module_getinfo() about the module to be installed // and it must pass back boolean true if the installation can proceed, or a message // indicating why the installation must fail // $rejects = array(); //We need to include developer files before the callback happens during an install if (!$this->_runscripts_include($modules, 'install')) { return array(_("Failed to run installation scripts")); } foreach (mod_func_iterator('module_install_check_callback', $modules) as $mod => $res) { if ($res !== true) { $rejects[] = $res; } } if (!empty($rejects)) { return $rejects; } //Developer mode, remind them they need to run install_amp manually //run this before the install scripts below because they end up removing install.php...yup if ($modulename == 'framework' && !file_exists($dir . '/install.php')) { out(_("Framework has been detected as being in Developer mode, Please make sure to run './install_amp --update-links' manually so that any database or system settings can be updated")); } // run the scripts if (!$this->_runscripts($modulename, 'install', $modules)) { return array(_("Failed to run installation scripts")); } if ($modules[$modulename]['status'] == MODULE_STATUS_NOTINSTALLED) { // customize INSERT query $sql = "INSERT INTO modules (modulename, version, enabled) values ('" . $db->escapeSimple($modules[$modulename]['rawname']) . "','" . $db->escapeSimple($modules[$modulename]['version']) . "', 1);"; } else { // just need to update the version $sql = "UPDATE modules SET version='" . $db->escapeSimple($modules[$modulename]['version']) . "' WHERE modulename = '" . $db->escapeSimple($modules[$modulename]['rawname']) . "'"; } // run query $results = $db->query($sql); if (DB::IsError($results)) { return array(sprintf(_("Error updating database. Command was: %s; error was: %s "), $sql, $results->getMessage())); } // If module is framework then update the framework version // normally this is done inside of the funky upgrade script runner but we are changing this now as // framework and freepbx versions are the same if ($modulename == 'framework' && !empty($modules[$modulename]['version']) && getVersion() != $modules[$modulename]['version']) { out(sprintf(_("Framework Detected, Setting FreePBX Version to %s"), $modules[$modulename]['version'])); $sql = "UPDATE admin SET value = '" . $db->escapeSimple($modules[$modulename]['version']) . "' WHERE variable = 'version'"; $result = $db->query($sql); if (DB::IsError($result)) { die($result->getMessage()); } if (getVersion() != $modules[$modulename]['version']) { die(_('Internal Error. Function getVersion did not match the Framework version, even after it was suppose to be applied')); } } // module is now installed & enabled, invalidate the modulelist class since it is now stale $modulelist =& modulelist::create($db); $modulelist->invalidate(); // edit the notification table to list any remaining upgrades available or clear // it if none are left. It requres a copy of the most recent module_xml to compare // against the installed modules. // $sql = 'SELECT data FROM module_xml WHERE id = "xml"'; $data = sql($sql, "getOne"); $parser = new xml2ModuleArray($data); $xmlarray = $parser->parseAdvanced($data); $new_modules = array(); if (count($xmlarray)) { foreach ($xmlarray['xml']['module'] as $mod) { $new_modules[$mod['rawname']] = $mod; } } $this->upgrade_notifications($new_modules, 'PASSIVE'); needreload(); FreePBX::Config()->update("SIGNATURECHECK", true); $db->query("DELETE FROM admin WHERE variable = 'unsigned' LIMIT 1"); //Generate LESS on install //http://issues.freepbx.org/browse/FREEPBX-8287 outn(_("Generating CSS...")); try { if ($modulename == 'framework') { FreePBX::Less()->generateMainStyles(); } else { FreePBX::Less()->generateModuleStyles($modulename); } } catch (\Exception $e) { } out(_("Done")); return true; }
$vars['log'] = true; } fix_publisher($module); //add changelog if requested if ($vars['log'] && !$vars['debug']) { freepbx::outn("\tUpdating Changelog..."); $msg = $vars['msg'] ? $vars['msg'] : 'Packaging of ver ' . $ver; package_update_changelog($module, $msg); freepbx::out("Done"); } // Run xml script through the exact method that FreePBX currently uses. There have // been cases where XML is valid but this method still fails so it won't be caught // with the proper XML checer, better here then breaking the online repository // -Philippe L. $parser = new xml2ModuleArray(); $xmlarray = $parser->parseAdvanced(file_get_contents($mod_dir . '/module.xml')); //Check XML File one more time to be safe freepbx::outn("\tChecking Modified Module XML..."); //test xml file and get some of its values list($rawname, $ver, $supported, $license, $licenselink) = freepbx::check_xml_file($mod_dir); //dont continue if there is an issue with the xml if ($rawname == false || $ver == false || $supported == false || $license == false || $licenselink == false) { $missing = $rawname == false ? 'rawname' : ($ver == false ? 'version' : ($supported == false ? 'supported' : ($license == false ? 'license' : ($licenselink == false ? 'licenselink' : 'Unknown')))); freepbx::out('module.xml is missing ' . $missing); freepbx::out("Module " . $module . " will not be tagged!"); continue; } //sanity check if ($rawname != $xmlarray['module']['rawname'] || $ver != $xmlarray['module']['version']) { freepbx::out('simple_xml_object and xml2modulearray mismatch'); freepbx::out("Module " . $module . " will not be tagged!");