/** * This function is used to install a module (addon); requires an * already existing ZIP file. Use installUploaded() to handle uploads. * * @access public * @param **/ public static function installModule($zipfile, $silent = false, $remove_zip_on_error = false) { // keep old modules happy global $wb, $admin, $database, $backend; if (!is_object($admin) && is_object($backend)) { $admin =& $backend; } // keep old modules happy $self = self::getInstance(); $self->log()->LogDebug('installModule'); $extension = pathinfo($zipfile, PATHINFO_EXTENSION); $sourcedir = pathinfo($zipfile, PATHINFO_DIRNAME); // Set temp vars $temp_dir = CAT_PATH . '/temp/'; $temp_unzip = $temp_dir . '/unzip_' . pathinfo($zipfile, PATHINFO_FILENAME) . '/'; $self->log()->LogDebug(sprintf('file extension [%s], source dir [%s], remove zip [%s]', $extension, $sourcedir, $remove_zip_on_error)); $self->log()->LogDebug(sprintf('temp dir [%s], unzip dir [%s]', $temp_dir, $temp_unzip)); // Check for language or template/module if ($extension == 'php') { $temp_unzip = $zipfile; } elseif ($extension == 'zip') { $self->log()->LogDebug(sprintf('creating temp. unzip dir [%s]', $temp_unzip)); CAT_Helper_Directory::createDirectory($temp_unzip); $self->log()->LogDebug(sprintf('zip file [%s], output dir [%s]', $zipfile, $temp_unzip)); // Setup the PclZip object and unzip the files to the temp unzip folder $list = CAT_Helper_Zip::getInstance($zipfile)->config('Path', CAT_Helper_Directory::sanitizePath($temp_unzip))->extract(); // check if anything was extracted if (!$list) { $self->log()->LogDebug(sprintf('No $list from ZIP-Helper, removing [%s]', $temp_unzip)); CAT_Helper_Directory::removeDirectory($temp_unzip); if ($remove_zip_on_error) { CAT_Helper_Directory::removeDirectory($zipfile); } if (!$silent) { self::printError('Unable to extract the file. Please check the ZIP format.'); } return false; } // check for info.php if (!file_exists($temp_unzip . '/info.php')) { // check subfolders for info.php $info = CAT_Helper_Directory::getInstance(1)->maxRecursionDepth(4)->findFile('info.php', $temp_unzip); if (!$info) { $self->log()->LogDebug(sprintf('No info.php found, removing [%s]', $temp_unzip)); CAT_Helper_Directory::removeDirectory($temp_unzip); if ($remove_zip_on_error) { CAT_Helper_Directory::removeDirectory($zipfile); } if (!$silent) { self::printError('Invalid installation file. No info.php found. Please check the ZIP format.'); } return false; } else { $temp_infofile = pathinfo($info, PATHINFO_DIRNAME); $self->log()->LogDebug(sprintf('set $temp_infofile to [%s]', $temp_infofile)); } } else { $temp_infofile = $temp_unzip; } } else { $self->log()->LogDebug(sprintf('Unknown extension [%s], "php" or "zip" expected, removing [%s]', $extension, $temp_unzip)); CAT_Helper_Directory::removeDirectory($temp_unzip); if ($remove_zip_on_error) { CAT_Helper_Directory::removeDirectory($zipfile); } if (!$silent) { self::printError('Invalid installation file. Wrong extension. Please check the ZIP format.'); } return false; } // Check the info.php file / language file $precheck_errors = NULL; if ($addon_info = self::checkInfo($temp_infofile)) { $precheck_errors = self::preCheckAddon($zipfile, $temp_infofile, false); } else { $self->log()->LogDebug(sprintf('Unable to load info file [%s], removing [%s]', $temp_infofile, $temp_unzip)); CAT_Helper_Directory::removeDirectory($temp_unzip); if ($remove_zip_on_error) { CAT_Helper_Directory::removeDirectory($zipfile); } if (!$silent) { self::printError($self->lang()->translate('Invalid installation file. {{error}}', array('error' => $self->lang()->translate('Unable to find info.php')))); } return false; } // precheck failed if ($precheck_errors != '' && !is_bool($precheck_errors)) { $self->log()->LogDebug(sprintf('Pre-installation check(s) failed, removing [%s]', $temp_unzip)); CAT_Helper_Directory::removeDirectory($temp_unzip); if (!$silent) { self::printError($precheck_errors, $_SERVER['SCRIPT_NAME'], false); } return false; } // So, now we have done all preinstall checks, lets see what to do next $addon_directory = $addon_info['addon_function'] == 'language' ? $addon_info['module_code'] . '.php' : $addon_info['module_directory']; // Set module directory $addon_dir = CAT_PATH . '/' . $addon_info['addon_function'] . 's/' . $addon_directory; $action = 'install'; if (file_exists($addon_dir) && $addon_info['addon_function'] != 'language') { $action = 'upgrade'; // look for old info.php $previous_info = self::checkInfo($addon_dir); if ($previous_info) { // compare versions if (self::versionCompare($previous_info['module_version'], $addon_info['module_version'], '>=')) { $self->log()->LogDebug(sprintf('Version check found no difference between installed and uploaded version, removing [%s]', $temp_unzip)); CAT_Helper_Directory::removeDirectory($temp_unzip); if ($remove_zip_on_error) { CAT_Helper_Directory::removeDirectory($zipfile); } if (!$silent) { self::printError('Already installed'); } else { self::$error = 'already installed'; } return false; } } } // Make sure the module dir exists, and chmod if needed if ($addon_info['addon_function'] != 'language') { $self->log()->LogDebug(sprintf('Creating addon directory [%s]', $addon_dir)); CAT_Helper_Directory::createDirectory($addon_dir); // copy files from temp folder // we use $temp_infofile here as source as it is the folder the // info.php file resides if (CAT_Helper_Directory::copyRecursive($temp_infofile, $addon_dir) !== true) { $self->log()->LogDebug(sprintf('Copy failed, removing [%s]', $temp_unzip)); CAT_Helper_Directory::removeDirectory($temp_unzip); if ($remove_zip_on_error) { CAT_Helper_Directory::removeDirectory($zipfile); } if (!$silent) { self::printError('Unable to install - error copying files'); } return false; } // remove temp $self->log()->LogDebug(sprintf('removing [%s]', $temp_unzip)); CAT_Helper_Directory::removeDirectory($temp_unzip); if ($remove_zip_on_error) { CAT_Helper_Directory::removeDirectory($zipfile); } } // load the module info into the database if (!self::loadModuleIntoDB($addon_dir, $action, self::checkInfo($addon_dir))) { $self->log()->LogDebug(sprintf('Loading module into DB failed, removing [%s]', $temp_unzip)); CAT_Helper_Directory::removeDirectory($temp_unzip); CAT_Helper_Directory::removeDirectory($addon_dir); if (!$silent) { self::printError($self->db()->getError()); } return false; } // Run the modules install // upgrade script if there is one if (file_exists($addon_dir . '/' . $action . '.php')) { $self->log()->LogDebug(sprintf('Running [%s]', $addon_dir . '/' . $action . '.php')); require $addon_dir . '/' . $action . '.php'; } if ($action == 'install' && $addon_info['addon_function'] == 'language') { $target = CAT_Helper_Directory::sanitizePath($addon_dir); // for manual install... if ($zipfile !== $target) { rename($zipfile, $addon_directory); CAT_Helper_Directory::setPerms($addon_directory); } } // set module permissions if ($addon_info['addon_function'] == 'module' && ($addon_info['module_function'] == 'page' || $addon_info['module_function'] == 'tool') || $addon_info['addon_function'] == 'template') { self::setModulePermissions($addon_info); } return true; }
/** * Install a Droplet from a ZIP file (the ZIP may contain more than one * Droplet) * * @access public * @param string $temp_file - name of the ZIP file * @return array see droplets_import() method * **/ public static function installDroplet($temp_file) { $self = self::getInstance(); $temp_unzip = CAT_PATH . '/temp/droplets_unzip/'; CAT_Helper_Directory::createDirectory($temp_unzip); $errors = array(); $imports = array(); $count = 0; // extract file $list = CAT_Helper_Zip::getInstance($temp_file)->config('Path', $temp_unzip)->extract(); // get .php files $files = CAT_Helper_Directory::getPHPFiles($temp_unzip, $temp_unzip . '/'); // now, open all *.php files and search for the header; // an exported droplet starts with "//:" foreach ($files as $file) { if (pathinfo($file, PATHINFO_FILENAME) !== 'index' && pathinfo($file, PATHINFO_EXTENSION) == 'php') { $description = NULL; $usage = NULL; $code = NULL; // Name of the Droplet = Filename $name = pathinfo($file, PATHINFO_FILENAME); // Slurp file contents $lines = file($temp_unzip . '/' . $file); // First line: Description if (preg_match('#^//\\:(.*)$#', $lines[0], $match)) { $description = addslashes($match[1]); array_shift($lines); } // Second line: Usage instructions if (preg_match('#^//\\:(.*)$#', $lines[0], $match)) { $usage = addslashes($match[1]); array_shift($lines); } // there may be more comment lines; they will be added to the usage instructions while (preg_match('#^//(.*)$#', $lines[0], $match)) { $usage .= addslashes(trim($match[1])); array_shift($lines); } if (!$description && !$usage) { // invalid file $errors[$file] = CAT_Helper_Directory::getInstance()->lang()->translate('No valid Droplet file (missing description and/or usage instructions)'); continue; } // Remaining: Droplet code $code = implode('', $lines); // replace 'evil' chars in code $tags = array('<?php', '?>', '<?'); //$code = addslashes(str_replace($tags, '', $code)); $code = str_replace($tags, '', $code); // Already in the DB? $stmt = 'INSERT'; $id = NULL; $found = $self->db()->query("SELECT * FROM `:prefix:mod_droplets` WHERE name=:name", array('name' => $name)); if ($found->rowCount()) { $stmt = 'REPLACE'; $id = $found->fetchColumn(); } // execute $q = "{$stmt} INTO `:prefix:mod_droplets` SET " . ($id ? 'id=' . $id . ', ' : '') . '`name`=:name, `code`=:code, `description`=:desc, ' . '`modified_when`=:when, `modified_by`=:userid, ' . '`active`=:active, `comments`=:usage'; $params = array('name' => $name, 'code' => $code, 'desc' => $description, 'when' => time(), 'userid' => CAT_Users::get_user_id(), 'active' => 1, 'usage' => $usage); $result = $self->db()->query($q, $params); if (!$self->db()->isError()) { $count++; $imports[$name] = 1; } else { $errors[$name] = $self->db()->getError(); } } // check for data directory if (file_exists($temp_unzip . '/data')) { // copy all files CAT_Helper_Directory::copyRecursive($temp_unzip . '/data', dirname(__FILE__) . '/data/'); } } // cleanup; ignore errors here CAT_Helper_Directory::removeDirectory($temp_unzip); return array('count' => $count, 'errors' => $errors, 'imported' => $imports); }