/** * Execute the action. */ public function execute() { // get parameters $this->currentModule = $this->getParameter('module', 'string'); // does the item exist if ($this->currentModule !== null && BackendExtensionsModel::existsModule($this->currentModule)) { // call parent, this will probably add some general CSS/JS or other required files parent::execute(); // make sure this module can be installed $this->validateInstall(); // do the actual install BackendExtensionsModel::installModule($this->currentModule); // redirect to index with a success message $this->redirect(BackendModel::createURLForAction('modules') . '&report=module-installed&var=' . $this->currentModule . '&highlight=row-module_' . $this->currentModule); } else { $this->redirect(BackendModel::createURLForAction('modules') . '&error=non-existing'); } }
/** * Process the zip-file & install the module * * @return string */ private function installModule() { // list of validated files (these files will actually be unpacked) $files = array(); // shorten field variables $fileFile = $this->frm->getField('file'); // create ziparchive instance $zip = new ZipArchive(); // try and open it if ($zip->open($fileFile->getTempFileName()) !== true) { $fileFile->addError(BL::getError('CorruptedFile')); } // zip file needs to contain some files if ($zip->numFiles == 0) { $fileFile->addError(BL::getError('FileIsEmpty')); return; } // directories we are allowed to upload to $allowedDirectories = array('backend/modules/', 'frontend/modules/', 'library/external/'); // name of the module we are trying to upload $moduleName = null; // there are some complications $warnings = array(); // check every file in the zip for ($i = 0; $i < $zip->numFiles; $i++) { // get the file name $file = $zip->statIndex($i); $fileName = $file['name']; // check if the file is in one of the valid directories foreach ($allowedDirectories as $directory) { // yay, in a valid directory if (stripos($fileName, $directory) === 0) { // we have a library file if ($directory == 'library/external/') { if (!SpoonFile::exists(PATH_WWW . '/' . $fileName)) { $files[] = $fileName; } else { $warnings[] = sprintf(BL::getError('LibraryFileAlreadyExists'), $fileName); } break; } // extract the module name from the url $tmpName = trim(str_ireplace($directory, '', $fileName), '/'); if ($tmpName == '') { break; } $chunks = explode('/', $tmpName); $tmpName = $chunks[0]; // ignore hidden files if (substr(basename($fileName), 0, 1) == '.') { break; } elseif ($moduleName === null) { $moduleName = $tmpName; } elseif ($moduleName !== $tmpName) { break; } // passed all our tests, store it for extraction $files[] = $fileName; // go to next file break; } } } // after filtering no files left (nothing useful found) if (count($files) == 0) { $fileFile->addError(BL::getError('FileContentsIsUseless')); return; } // module already exists on the filesystem if (BackendExtensionsModel::existsModule($moduleName)) { $fileFile->addError(sprintf(BL::getError('ModuleAlreadyExists'), $moduleName)); return; } // installer in array? if (!in_array('backend/modules/' . $moduleName . '/installer/installer.php', $files)) { $fileFile->addError(sprintf(BL::getError('NoInstallerFile'), $moduleName)); return; } // unpack module files $zip->extractTo(PATH_WWW, $files); // run installer BackendExtensionsModel::installModule($moduleName, $warnings); // return the files return $moduleName; }