/** * Disables all plugins with unresolved dependencies * and resolves the load order for all enabled plugins. * * @return bool True or False, depending on whether it was * necessary to alter the load order of a plugin * @since Geeklog 1.8.0 */ function PLG_resolveDependencies() { global $_PLUGINS, $_TABLES; $retval = ''; $flag = true; // false means that all dependencies are resolved while ($flag) { // loop until ALL dependencies are satisfied $flag = false; // set this if any plugin has been disabled during the loop foreach ($_PLUGINS as $key => $pi_name) { if (!PLG_checkDependencies($pi_name)) { // plugin has unresolved dependencies // disable plugin; $flag = true; // disabling a plugin can break the dependencies of a plugin that has already been checked, remember to loop again PLG_enableStateChange($pi_name, false); DB_change($_TABLES['plugins'], 'pi_enabled', 0, 'pi_name', $pi_name); PLG_pluginStateChange($pi_name, 'disabled'); unset($_PLUGINS[$key]); } } } // automatically resolve load order for enabled plugins $index = 2000; // how far through the load order to push back plugins $maxqueries = 50; // just in case... $globalflag = false; // remember if we change the load order of any plugin $flag = true; // set true if we need another pass in the while loop while ($flag && $maxqueries) { // Now check if the load order is correct $flag = false; // get the load orders of all enabled plugins $q = DB_query("SELECT pi_name, pi_load FROM {$_TABLES['plugins']} WHERE pi_enabled='1'"); $plo = array(); // Plugins Load Order while ($a = DB_fetchArray($q)) { $plo[] = $a; } $params = array(); foreach ($plo as $key => $value) { // for each available plugin $maxqueries--; $params = PLG_getParams($value['pi_name']); // get dependencies if (isset($params['requires']) && is_array($params['requires'])) { // if any foreach ($params['requires'] as $rkey => $rvalue) { // process each dependency if (isset($rvalue['plugin'])) { // get the load order of the required plugin foreach ($plo as $new_key => $new_value) { if ($new_value['pi_name'] == $rvalue['plugin']) { $dep_load = $new_value['pi_load']; break; } } if ($dep_load > $value['pi_load']) { // incorrect load order // move down the order DB_query("UPDATE {$_TABLES['plugins']} SET pi_load = '{$index}' WHERE pi_name = '{$value['pi_name']}'"); $index++; $flag = true; $globalflag = true; } } } } } } reorderplugins(); if ($globalflag == false) { return true; // no change } else { return false; // something changed } }
/** * Continue a plugin upgrade that started in plugin_upload() * * @param string $plugin plugin name * @param string $pi_version current plugin version * @param string $code_version plugin version to be upgraded to * @return string HTML refresh * @see function plugin_upload * */ function continue_upgrade($plugin, $pi_version, $code_version) { global $_CONF, $_TABLES; $retval = ''; $msg_with_plugin_name = false; // simple sanity checks if (empty($plugin) || empty($pi_version) || empty($code_version) || $pi_version == $code_version) { $msg = 72; } else { // more sanity checks $result = DB_query("SELECT pi_version, pi_enabled FROM {$_TABLES['plugins']} WHERE pi_name = '" . addslashes($plugin) . "'"); $A = DB_fetchArray($result); if (!empty($A['pi_version']) && $A['pi_enabled'] == 1 && $A['pi_version'] == $pi_version && $A['pi_version'] != $code_version) { // continue upgrade process that started in plugin_upload() $result = PLG_upgrade($plugin); if ($result === true) { PLG_pluginStateChange($plugin, 'upgraded'); $msg = 60; // successfully updated } else { $msg_with_plugin_name = true; $msg = $result; // message provided by the plugin } } else { $msg = 72; } } $url = $_CONF['site_admin_url'] . '/plugins.php?msg=' . $msg; if ($msg_with_plugin_name) { $url .= '&plugin=' . $plugin; } $retval = COM_refresh($url); return $retval; }
/** * Handle uploaded plugin * * @return string HTML: redirect or main plugin screen + error message * */ function plugin_upload() { global $_CONF, $_TABLES; $retval = ''; $path_admin = $_CONF['path_html'] . substr($_CONF['site_admin_url'], strlen($_CONF['site_url']) + 1) . '/'; $upload_success = false; // If an error occured while uploading the file. $error_msg = plugin_getUploadError($_FILES['plugin']); if (!empty($error_msg)) { $retval .= plugin_main($error_msg); } else { require_once $_CONF['path_system'] . 'classes/unpacker.class.php'; $plugin_file = $_CONF['path_data'] . $_FILES['plugin']['name']; // Name the plugin file $archive = new unpacker($_FILES['plugin']['tmp_name'], $_FILES['plugin']['type']); $tmp = $archive->getlist(); // Grab the contents of the tarball to see what the plugin name is $dirname = preg_replace('/\\/.*$/', '', $tmp[0]['filename']); if (empty($dirname)) { // If $dirname is blank it's probably because the user uploaded a non Tarball file. $retval = COM_refresh($_CONF['site_admin_url'] . '/plugins.php?msg=100'); } else { $pi_did_exist = false; // plugin directory already existed $pi_had_entry = false; // plugin had an entry in the database $pi_was_enabled = false; // plugin was enabled if (file_exists($_CONF['path'] . 'plugins/' . $dirname)) { $pi_did_exist = true; // plugin directory already exists $pstatus = DB_query("SELECT pi_name, pi_enabled FROM {$_TABLES['plugins']} WHERE pi_name = '{$dirname}'"); $A = DB_fetchArray($pstatus); if (isset($A['pi_name'])) { $pi_had_entry = true; $pi_was_enabled = $A['pi_enabled'] == 1; } if ($pi_was_enabled) { // disable temporarily while we move the files around DB_change($_TABLES['plugins'], 'pi_enabled', 0, 'pi_name', $dirname); } require_once 'System.php'; $plugin_dir = $_CONF['path'] . 'plugins/' . $dirname; if (file_exists($plugin_dir . '.previous')) { @System::rm('-rf ' . $plugin_dir . '.previous'); } if (file_exists($plugin_dir)) { rename($plugin_dir, $plugin_dir . '.previous'); } $public_dir = $_CONF['path_html'] . $dirname; if (file_exists($public_dir . '.previous')) { @System::rm('-rf ' . $public_dir . '.previous'); } if (file_exists($public_dir)) { rename($public_dir, $public_dir . '.previous'); } $admin_dir = $path_admin . 'plugins/' . $dirname; if (file_exists($admin_dir . '.previous')) { @System::rm('-rf ' . $admin_dir . '.previous'); } if (file_exists($admin_dir)) { rename($admin_dir, $admin_dir . '.previous'); } } /** * Install the plugin * This doesn't work if the public_html & public_html/admin/plugins directories aren't 777 */ // Extract the tarball to data so we can get the $pi_name name from admin/install.php $archive->unpack($_CONF['path'] . 'data/', array($dirname . '/admin/install.php')); $plugin_inst = $_CONF['path'] . 'data/' . $dirname . '/admin/install.php'; $fdata = ''; $fhandle = @fopen($plugin_inst, 'r'); if ($fhandle) { $fdata = fread($fhandle, filesize($plugin_inst)); fclose($fhandle); } // Remove the plugin from data/ require_once 'System.php'; @System::rm('-rf ' . $_CONF['path'] . 'data/' . $dirname); /** * One time I wanted to install a muffler on my car and * needed to match up the outside diameter of the car's * exhaust pipe to the inside diameter of the muffler. * Unfortunately, when I went to the auto parts store they * didn't have a coupling adapter that would perfectly * match the two pipes, only a bunch of smaller adapters. * I ended up using about 4 small adapters to step down * one size at a time to the size of the muffler's input. * * It's kind of like this regular expression: * */ $fdata = preg_replace('/\\n/', '', $fdata); $fdata = preg_replace('/ /', '', $fdata); $pi_name = preg_replace('/^.*\\$pi\\_name=\'/', '', $fdata); $pi_name = preg_replace('/\'.*$/', '', $pi_name); // Some plugins don't have $pi_name set in their install.php file, // This means our regex won't work and we should just use $dirname if (preg_match('/\\<\\?php/', $pi_name) || preg_match('/--/', $pi_name)) { $pi_name = $dirname; } elseif (empty($pi_name)) { $pi_name = $dirname; } // Extract the uploaded archive to the plugins directory $upload_success = $archive->unpack($_CONF['path'] . 'plugins/'); $plg_path = $_CONF['path'] . 'plugins/' . $pi_name . '/'; if ($upload_success) { if (file_exists($plg_path . 'public_html')) { rename($plg_path . 'public_html', $_CONF['path_html'] . $pi_name); } if (file_exists($plg_path . 'admin')) { rename($plg_path . 'admin', $path_admin . 'plugins/' . $pi_name); } } unset($archive); // Collect some garbage // cleanup when uploading a new version if ($pi_did_exist) { $plugin_dir = $_CONF['path'] . 'plugins/' . $dirname; if (file_exists($plugin_dir . '.previous')) { @System::rm('-rf ' . $plugin_dir . '.previous'); } $public_dir = $_CONF['path_html'] . $dirname; if (file_exists($public_dir . '.previous')) { @System::rm('-rf ' . $public_dir . '.previous'); } $admin_dir = $path_admin . 'plugins/' . $dirname; if (file_exists($admin_dir . '.previous')) { @System::rm('-rf ' . $admin_dir . '.previous'); } if ($pi_was_enabled) { DB_change($_TABLES['plugins'], 'pi_enabled', 1, 'pi_name', $dirname); } } $msg_with_plugin_name = false; if ($pi_did_exist) { if ($pi_was_enabled) { // check if we have to perform an update $pi_version = DB_getItem($_TABLES['plugins'], 'pi_version', "pi_name = '{$dirname}'"); $code_version = PLG_chkVersion($dirname); if (!empty($code_version) && $code_version != $pi_version) { $result = PLG_upgrade($dirname); if ($result === true) { PLG_pluginStateChange($dirname, 'upgraded'); $msg = 60; // successfully updated } else { $msg_with_plugin_name = true; $msg = $result; // message provided by the plugin } } else { $msg = 98; // successfully uploaded } } else { $msg = 98; // successfully uploaded } } elseif (file_exists($plg_path . 'autoinstall.php')) { // if the plugin has an autoinstall.php, install it now if (plugin_autoinstall($pi_name)) { PLG_pluginStateChange($pi_name, 'installed'); $msg = 44; // successfully installed } else { $msg = 72; // an error occured while installing the plugin } } else { $msg = 98; // successfully uploaded } $url = $_CONF['site_admin_url'] . '/plugins.php?msg=' . $msg; if ($msg_with_plugin_name) { $url .= '&plugin=' . $dirname; } $retval = COM_refresh($url); } } return $retval; }