/** * Destruct the builder */ public function __destruct() { // Close all the packages if ($this->stk_build instanceof compress) { $this->stk_build->close(); } foreach ($this->lang_builders as $lang_builder) { if ($lang_builder instanceof compress) { $lang_builder->close(); } } }
/** * Gets missing language directories for an extension from a specified zip file. * @param string $ext_name The name of the extension. * @param string $zip_file The name of zip file. * @return null|bool */ public static function restore_languages($ext_name, $zip_file) { $ext_tmp = objects::$phpbb_root_path . 'ext/' . objects::$upload_ext_name . '/tmp/' . (int) objects::$user->data['user_id']; // Ensure that we don't have any previous files in the working directory. if (is_dir($ext_tmp)) { if (!files::catch_errors(files::rrmdir($ext_tmp))) { files::catch_errors(objects::$user->lang['ERROR_DIRECTORIES_NOT_RESTORED']); return false; } } if (!class_exists('\\compress_zip')) { include objects::$phpbb_root_path . 'includes/functions_compress.' . objects::$phpEx; } $zip = new \compress_zip('r', objects::$zip_dir . '/' . $zip_file); $zip->extract($ext_tmp . '/'); $zip->close(); $composery = files::getComposer($ext_tmp); if (!$composery) { files::catch_errors(files::rrmdir($ext_tmp)); files::catch_errors(objects::$user->lang['ERROR_ZIP_NO_COMPOSER']); files::catch_errors(objects::$user->lang['ERROR_DIRECTORIES_NOT_RESTORED']); return false; } $source = substr($composery, 0, -14); // Check languages missing in the new version. $ext_path = objects::$phpbb_root_path . 'ext/' . $ext_name; $old_langs = files::get_languages($source . '/language'); $new_langs = files::get_languages($ext_path . '/language'); $old_langs = array_diff($old_langs, $new_langs); if (sizeof($old_langs)) { foreach ($old_langs as $lang) { files::catch_errors(files::rcopy($source . '/language/' . $lang, $ext_path . '/language/' . $lang)); } objects::$template->assign_var('EXT_LANGUAGES_RESTORED', true); } files::catch_errors(files::rrmdir($ext_tmp)); }
/** * The function that uploads the specified language package for the extension. * * @param string $action Requested action. * @param string $ext_name The name of the extension. * @param string $lang_name The ISO code of the language. * @return bool */ public function upload_lang($action, $ext_name, $lang_name) { global $phpbb_root_path, $phpEx, $user; if (empty($ext_name)) { files::catch_errors(objects::$user->lang('ERROR_LANGUAGE_NO_EXTENSION')); return false; } if (empty($lang_name)) { files::catch_errors(objects::$user->lang('ERROR_LANGUAGE_NOT_DEFINED')); return false; } $file = $this->proceed_upload($action); if (!$file) { return false; } $dest_file = $this->get_dest_file($action, $file, objects::$zip_dir); if (!$dest_file) { return false; } // We need to use the user ID and the time to escape from problems with simultaneous uploads. // We suppose that one user can upload only one extension per session. $ext_tmp = $phpbb_root_path . 'ext/' . objects::$upload_ext_name . '/tmp/' . (int) $user->data['user_id']; // Ensure that we don't have any previous files in the working directory. if (is_dir($ext_tmp)) { if (!files::catch_errors(files::rrmdir($ext_tmp))) { if ($action != 'upload_local') { $file->remove(); } return false; } } if (!class_exists('\\compress_zip')) { include $phpbb_root_path . 'includes/functions_compress.' . $phpEx; } $zip = new \compress_zip('r', $dest_file); $zip->extract($ext_tmp . '/'); $zip->close(); if ($action != 'upload_local') { $file->remove(); } // The files can be stored inside the $ext_tmp directory or up to two levels lower in the file tree. $lang_dir = ''; // First level (the highest one). $files = @scandir($ext_tmp); if ($files === false) { files::catch_errors(objects::$user->lang('ERROR_LANGUAGE_UNKNOWN_STRUCTURE')); return false; } $files = array_diff($files, array('.', '..')); $last_file = array_pop($files); // Continue searching if we have a single directory. if (!sizeof($files) && !is_null($last_file) && @is_dir($ext_tmp . $lang_dir . '/' . $last_file)) { $lang_dir .= '/' . $last_file; // Second level. $files = @scandir($ext_tmp . $lang_dir); if ($files === false) { files::catch_errors(objects::$user->lang('ERROR_LANGUAGE_UNKNOWN_STRUCTURE')); return false; } $files = array_diff($files, array('.', '..')); // Search for a directory with language ISO code (to escape from problems with unnecessary readme files). if (array_search($lang_name, $files) !== false && @is_dir($ext_tmp . $lang_dir . '/' . $lang_name)) { $lang_dir .= '/' . $lang_name; } } $source = $ext_tmp . $lang_dir; if (!files::catch_errors(files::rcopy($source, $phpbb_root_path . 'ext/' . $ext_name . '/language/' . $lang_name))) { files::catch_errors(files::rrmdir($ext_tmp)); return false; } if (!files::catch_errors(files::rrmdir($ext_tmp))) { return false; } if (objects::$is_ajax && $ext_name === objects::$upload_ext_name && $lang_name === objects::$user->lang_name) { /* * Refresh the page if the uploaded language package * is currently used by the user of Upload Extensions. * Only for Ajax requests. */ $response_object = new \phpbb\json_response(); $response_object->send(array("LANGUAGE" => urlencode($lang_name), "REFRESH" => true)); } objects::$template->assign_var('EXT_LANGUAGE_UPLOADED', objects::$user->lang('EXT_LANGUAGE_UPLOADED', $lang_name)); return true; }
/** * Saves the contents of a file or a directory in a zip archive file. * @param string $dest_file The path to the contents for adding to the zip file. * @param string $dest_name The name of the zip file. * @param string $zip_dir The directory for saving zip files. */ public static function save_zip_archive($dest_file, $dest_name, $zip_dir) { if (!class_exists('\\compress_zip')) { include objects::$phpbb_root_path . 'includes/functions_compress.' . objects::$phpEx; } // Remove additional ext/ prefix. $src_rm_prefix = strpos($dest_file, 'ext/') === 0 ? substr($dest_file, 0, 4) : ''; $zip = new \compress_zip('w', $zip_dir . '/' . $dest_name . '.zip'); $zip->add_file($dest_file, $src_rm_prefix); $zip->close(); }
/** * Extract a zip file * * @param string $filename Path to zip file * @param string $destination Path to destination */ public static function extract_zip($filename, $destination) { // create dir if it doesn't exist if (!is_dir($destination)) { mkdir($destination, 0777, true); } // extract files $zip = new compress_zip('r', $filename); $zip->extract($destination); $zip->close(); }
/** * Save the previous version of the extension that is being updated in a zip archive file */ function save_zip_archive($dest_file, $dest_name) { global $phpbb_root_path, $phpEx; if (!class_exists('\\compress_zip')) { include $phpbb_root_path . 'includes/functions_compress.' . $phpEx; } $zip = new \compress_zip('w', $this->zip_dir . '/' . $dest_name . '.zip'); $zip->add_file($dest_file); $zip->close(); }
function upload_mod() { global $phpbb_root_path, $phpEx, $template, $user; if (!isset($_POST['submit'])) { return false; } if (check_form_key('acp_mods_upload') && isset($_FILES['modupload'])) { $user->add_lang('posting'); // For error messages include $phpbb_root_path . 'includes/functions_upload.' . $phpEx; $upload = new fileupload(); // Only allow ZIP files $upload->set_allowed_extensions(array('zip')); // Let's make sure the mods directory exists and if it doesn't then create it if (!is_dir($this->mods_dir)) { mkdir($this->mods_dir, octdec($config['am_dir_perms'])); } $file = $upload->form_upload('modupload'); if (empty($file->filename)) { trigger_error($user->lang['NO_UPLOAD_FILE'] . adm_back_link($this->u_action), E_USER_WARNING); } else { if (!$file->init_error && !sizeof($file->error)) { $file->clean_filename('real'); $file->move_file(str_replace($phpbb_root_path, '', $this->mods_dir), true, true); if (!sizeof($file->error)) { include $phpbb_root_path . 'includes/functions_compress.' . $phpEx; $mod_dir = $this->mods_dir . '/' . str_replace('.zip', '', $file->get('realname')); $compress = new compress_zip('r', $file->destination_file); $compress->extract($mod_dir . '_tmp/'); $compress->close(); $folder_contents = scandir($mod_dir . '_tmp/', 1); // This ensures dir is at index 0 // We need to check if there's a main directory inside the temp MOD directory if (sizeof($folder_contents) == 3) { // We need to move that directory then $this->directory_move($mod_dir . '_tmp/' . $folder_contents[0], $this->mods_dir . '/' . $folder_contents[0]); } else { if (!is_dir($mod_dir)) { // Change the name of the directory by moving to directory without _tmp in it $this->directory_move($mod_dir . '_tmp/', $mod_dir); } } $this->directory_delete($mod_dir . '_tmp/'); if (!sizeof($file->error)) { $template->assign_vars(array('S_MOD_SUCCESSBOX' => true, 'MESSAGE' => $user->lang['MOD_UPLOAD_SUCCESS'], 'U_RETURN' => $this->u_action)); } } } $file->remove(); if ($file->init_error || sizeof($file->error)) { trigger_error((sizeof($file->error) ? implode('<br />', $file->error) : $user->lang['MOD_UPLOAD_INIT_FAIL']) . adm_back_link($this->u_action), E_USER_WARNING); } } } else { trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } return true; }
/** * Original copyright information for the function from AutoMOD. * The function was almost totally changed by the authors of Upload Extensions. * @package automod * @copyright (c) 2008 phpBB Group * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License * * @param string $action Requested action. * @return bool */ function upload_ext($action) { global $phpbb_root_path, $phpEx, $phpbb_log, $phpbb_extension_manager, $template, $user, $request; //$can_upload = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !@extension_loaded('zlib')) ? false : true; $user->add_lang('posting'); // For error messages if (!class_exists('\\fileupload')) { include $phpbb_root_path . 'includes/functions_upload.' . $phpEx; } $upload = new \fileupload(); $upload->set_allowed_extensions(array('zip')); // Only allow ZIP files $upload_dir = $phpbb_root_path . 'ext'; // Make sure the ext/ directory exists and if it doesn't, create it if (!is_dir($phpbb_root_path . 'ext')) { files::catch_errors(files::recursive_mkdir($phpbb_root_path . 'ext')); } if (!is_writable($phpbb_root_path . 'ext')) { files::catch_errors($user->lang['EXT_NOT_WRITABLE']); return false; } // Proceed with the upload $file = files::remote_upload($upload, $request->variable('remote_upload', '')); // What is a safe limit of execution time? Half the max execution time should be safe. $safe_time_limit = ini_get('max_execution_time') / 2; $start_time = time(); // We skip working with a zip file if we are enabling/restarting the extension. if ($action != 'force_update') { if (empty($file->filename)) { files::catch_errors(sizeof($file->error) ? implode('<br />', $file->error) : $user->lang['NO_UPLOAD_FILE']); return false; } else { if ($file->init_error || sizeof($file->error)) { $file->remove(); files::catch_errors(sizeof($file->error) ? implode('<br />', $file->error) : $user->lang['EXT_UPLOAD_INIT_FAIL']); return false; } } $file->clean_filename('real'); $file->move_file(str_replace($phpbb_root_path, '', $upload_dir), true, true); if (sizeof($file->error)) { $file->remove(); files::catch_errors(implode('<br />', $file->error)); return false; } $dest_file = $file->destination_file; if (!class_exists('\\compress_zip')) { include $phpbb_root_path . 'includes/functions_compress.' . $phpEx; } // We need to use the user ID and the time to escape from problems with simultaneous uploads. // We suppose that one user can upload only one extension per session. $ext_tmp = $this->updater_ext_name . '/tmp/' . (int) $user->data['user_id']; // Ensure that we don't have any previous files in the working directory. if (is_dir($phpbb_root_path . 'ext/' . $ext_tmp)) { if (!files::catch_errors(files::rrmdir($phpbb_root_path . 'ext/' . $ext_tmp))) { $file->remove(); return false; } } $zip = new \compress_zip('r', $dest_file); $zip->extract($phpbb_root_path . 'ext/' . $ext_tmp . '/'); $zip->close(); $composery = files::getComposer($phpbb_root_path . 'ext/' . $ext_tmp); if (!$composery) { files::catch_errors(files::rrmdir($phpbb_root_path . 'ext/' . $ext_tmp)); $file->remove(); files::catch_errors($user->lang['ACP_UPLOAD_EXT_ERROR_COMP']); return false; } $string = @file_get_contents($composery); if ($string === false) { files::catch_errors(files::rrmdir($phpbb_root_path . 'ext/' . $ext_tmp)); $file->remove(); files::catch_errors($user->lang['EXT_UPLOAD_ERROR']); return false; } $json_a = json_decode($string, true); $destination = isset($json_a['name']) ? $json_a['name'] : ''; $ext_version = isset($json_a['version']) ? $json_a['version'] : '0.0.0'; if (strpos($destination, '/') === false) { files::catch_errors(files::rrmdir($phpbb_root_path . 'ext/' . $ext_tmp)); $file->remove(); files::catch_errors($user->lang['ACP_UPLOAD_EXT_ERROR_DEST']); return false; } else { if (strpos($destination, objects::$upload_ext_name) === false) { files::catch_errors(files::rrmdir($phpbb_root_path . 'ext/' . $ext_tmp)); $file->remove(); files::catch_errors($user->lang['ACP_UPLOAD_EXT_NOT_COMPATIBLE']); return false; } } $display_name = isset($json_a['extra']['display-name']) ? $json_a['extra']['display-name'] : $destination; if (!isset($json_a['type']) || $json_a['type'] != "phpbb-extension") { files::catch_errors(files::rrmdir($phpbb_root_path . 'ext/' . $ext_tmp)); $file->remove(); files::catch_errors($user->lang['NOT_AN_EXTENSION']); return false; } $source = substr($composery, 0, -14); $source_for_check = $ext_tmp . '/' . $destination; // At first we need to change the directory structure to something like ext/tmp/vendor/extension. // We need it to escape from problems with dots on validation. if ($source != $phpbb_root_path . 'ext/' . $source_for_check) { if (!files::catch_errors(files::rcopy($source, $phpbb_root_path . 'ext/' . $source_for_check))) { files::catch_errors(files::rrmdir($phpbb_root_path . 'ext/' . $ext_tmp)); $file->remove(); return false; } $source = $phpbb_root_path . 'ext/' . $source_for_check; } // Validate the extension to check if it can be used on the board. $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($source_for_check, $template); try { if ($md_manager->get_metadata() === false || $md_manager->validate_require_phpbb() === false || $md_manager->validate_require_php() === false) { files::catch_errors(files::rrmdir($phpbb_root_path . 'ext/' . $ext_tmp)); $file->remove(); files::catch_errors($user->lang['EXTENSION_NOT_AVAILABLE']); return false; } } catch (\phpbb\extension\exception $e) { files::catch_errors(files::rrmdir($phpbb_root_path . 'ext/' . $ext_tmp)); $file->remove(); files::catch_errors($e . ' ' . $user->lang['ACP_UPLOAD_EXT_ERROR_NOT_SAVED']); return false; } // Here we can assume that all checks are done. // Now we are able to install the uploaded extension to the correct path. } else { // All checks were done previously. Now we only need to restore the variables. // We try to restore the data of the current upload. $ext_tmp = $this->updater_ext_name . '/tmp/' . (int) $user->data['user_id']; if (!is_dir($phpbb_root_path . 'ext/' . $ext_tmp) || !($composery = files::getComposer($phpbb_root_path . 'ext/' . $ext_tmp)) || !($string = @file_get_contents($composery))) { files::catch_errors($user->lang['ACP_UPLOAD_EXT_WRONG_RESTORE']); return false; } $json_a = json_decode($string, true); $destination = isset($json_a['name']) ? $json_a['name'] : ''; if (strpos($destination, '/') === false) { files::catch_errors($user->lang['ACP_UPLOAD_EXT_WRONG_RESTORE']); return false; } $source = substr($composery, 0, -14); $display_name = isset($json_a['extra']['display-name']) ? $json_a['extra']['display-name'] : $destination; } $made_update = false; // Delete the previous version of extension files - we're able to update them. if (is_dir($phpbb_root_path . 'ext/' . $destination)) { // At first we need to disable the extension if it is enabled. if ($phpbb_extension_manager->is_enabled($destination)) { while ($phpbb_extension_manager->disable_step($destination)) { // Are we approaching the time limit? If so, we want to pause the update and continue after refreshing. if (time() - $start_time >= $safe_time_limit) { $template->assign_var('S_NEXT_STEP', objects::$user->lang['EXTENSION_DISABLE_IN_PROGRESS']); // No need to specify the name of the extension. We suppose that it is the one in ext/tmp/USER_ID folder. meta_refresh(0, objects::$u_action . '&action=force_update'); return false; } } $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_EXT_DISABLE', time(), array($destination)); $made_update = true; } if (!files::catch_errors(files::rrmdir($phpbb_root_path . 'ext/' . $destination))) { return false; } } if (!files::catch_errors(files::rcopy($source, $phpbb_root_path . 'ext/' . $destination))) { files::catch_errors(files::rrmdir($phpbb_root_path . 'ext/' . $ext_tmp)); return false; } // No enabling at this stage. Admins should have a chance to revise the uploaded scripts. if (!files::catch_errors(files::rrmdir($phpbb_root_path . 'ext/' . $ext_tmp))) { return false; } if ($made_update) { // We have updated Upload Extensions - let's enable it again. redirect(objects::$u_action . '&action=enable'); } else { $template->assign_var('EXT_UPLOADED', true); } return true; }
/** * Upload a zip file and save the images into the import/ directory. */ public function upload_zip() { global $phpbb_ext_gallery, $phpbb_root_path, $phpEx; if (!class_exists('compress_zip')) { include_once $phpbb_root_path . 'includes/functions_compress.' . $phpEx; } global $user; $tmp_dir = $phpbb_ext_gallery->url->path('import') . 'tmp_' . md5(unique_id()) . '/'; $this->zip_file->clean_filename('unique_ext'); $this->zip_file->move_file(substr($phpbb_ext_gallery->url->path('import_noroot'), 0, -1), false, false, CHMOD_ALL); if (!empty($this->zip_file->error)) { $this->zip_file->remove(); $this->new_error($user->lang('UPLOAD_ERROR', $this->zip_file->uploadname, implode('<br />» ', $this->zip_file->error))); return false; } $compress = new \compress_zip('r', $this->zip_file->destination_file); $compress->extract($tmp_dir); $compress->close(); $this->zip_file->remove(); // Remove zip from allowed extensions $this->upload->set_allowed_extensions(self::get_allowed_types(false, true)); $this->read_zip_folder($tmp_dir); // Read zip from allowed extensions $this->upload->set_allowed_extensions(self::get_allowed_types()); }
/** * Merge MOD and the according language pack together * * @param bool $test Whether to generate the MOD package or just test the language pack */ public function merge_packs($test = false) { global $phpbb_root_path, $config; /** * Unzip both packages */ $mod = new compress_zip('r', $phpbb_root_path . $config['mods_tmp_dir_path'] . 'mods/' . $this->filename . '.zip'); $mod->extract($phpbb_root_path . $config['mods_tmp_dir_path'] . 'mods/'); /* ZipArchive is not currently supported on the server - leave this here for possible later use $mod = new ZipArchive(); $mod->open($config['mods_tmp_dir_path'] . 'mods/' . $this->filename . '.zip'); $mod->extractTo($config['mods_tmp_dir_path'] . 'mods/');*/ // If no localisation pack exists then we just check the original MOD package to make sure all Hungarian translation files are included if (file_exists($phpbb_root_path . $config['mods_tmp_dir_path'] . 'localisations/' . $this->filename . '.zip')) { $loc = new compress_zip('r', $phpbb_root_path . $config['mods_tmp_dir_path'] . 'localisations/' . $this->filename . '.zip'); $loc->extract($phpbb_root_path . $config['mods_tmp_dir_path'] . 'localisations/'); } /** * Merge packages */ $errors = array(); // Introduce variables with short names for frequently used file paths $mod_dir = $phpbb_root_path . $config['mods_tmp_dir_path'] . 'mods/' . $this->filename; $loc_dir = $phpbb_root_path . $config['mods_tmp_dir_path'] . 'localisations/' . $this->filename; // First look at the language files in the mods directory if (file_exists($mod_dir . '/root/language/en/') && !file_exists($mod_dir . '/root/language/hu/')) { $files = scandir_rec($mod_dir . '/root/language/en/'); foreach ($files as $file) { if (!file_exists($loc_dir . '/root/language/hu/' . $file)) { $errors[] = array('MISSING_LANGUAGE_FILE', 'root/language/hu/' . $file); } else { // Check PHP syntax (assume we are on a unix-based system) if (substr(shell_exec('php -l ' . $loc_dir . '/root/language/hu/' . $file), 0, 11) == 'Parse error') { $errors[] = array('SYNTAX_ERROR', 'root/language/hu/' . $file); } else { $dir_name = $mod_dir . '/root/language/hu/' . site_dirname($file); if (!file_exists($dir_name)) { mkdir($dir_name, 0755, true); } rename($loc_dir . '/root/language/hu/' . $file, $mod_dir . '/root/language/hu/' . $file); } } } } // Next the styles directory if (file_exists($mod_dir . '/root/styles/prosilver/imageset/en/') && !file_exists($mod_dir . '/root/styles/prosilver/imageset/hu/')) { // Check whether prosilver images are in place $files = scandir_rec($mod_dir . '/root/styles/prosilver/imageset/en/'); foreach ($files as $file) { if (!file_exists($loc_dir . '/root/styles/prosilver/imageset/hu/' . $file)) { $errors[] = array('MISSING_STYLE_IMAGE', '/root/styles/prosilver/imageset/hu/' . $file); } } // Copy all image files $files = scandir_rec($loc_dir . '/root/styles/'); foreach ($files as $file) { if (substr($file, -4) == '.gif' && !file_exists($loc_dir . '/root/styles/' . $file)) { $dir_name = $mod_dir . '/root/styles/' . site_dirname($file); if (!file_exists($dir_name)) { mkdir($dir_name, 0755, true); } rename($loc_dir . '/root/styles/' . $file, $mod_dir . '/root/styles/' . $file); } } } // Copy the entire contrib directory if (file_exists($loc_dir . '/contrib/')) { $files = scandir_rec($loc_dir . '/contrib/'); foreach ($files as $file) { if (!file_exists($mod_dir . '/contrib/' . $file)) { $dir_name = $mod_dir . '/contrib/' . site_dirname($file) . '/'; if (!file_exists($dir_name)) { mkdir($dir_name, 0755, true); } rename($loc_dir . '/contrib/' . $file, $mod_dir . '/contrib/' . $file); } } } // Now the Hungarian MODX file if (file_exists($loc_dir . '/languages/hu.xml') && !file_exists($mod_dir . '/languages/hu.xml')) { if (!file_exists($mod_dir . '/languages/')) { mkdir($mod_dir . '/languages/', 0755); } rename($loc_dir . '/languages/hu.xml', $mod_dir . '/languages/hu.xml'); } // Style localisations if (file_exists($loc_dir . '/templates/')) { $files = scandir_rec($loc_dir . '/templates/'); foreach ($files as $file) { if (preg_match('#^([^/]+)\\/hu\\.xml$#is', $file, $match) && !file_exists($mod_dir . '/templates/' . $file)) { mkdir($mod_dir . '/templates/' . $match[1], 0755, true); rename($loc_dir . '/templates/' . $file, $mod_dir . '/templates/' . $file); } } } // And finally merge the translation and the original version of install.xml (or alternatively MOD_NAME.xml) // @todo implement the merge /** * "Zip everything back" */ if (!empty($errors)) { throw new ModException($errors); } if ($test) { return true; } // Remove old file? if (file_exists($phpbb_root_path . $config['downloads_path'] . '/mods/' . $this->filename . '.zip')) { unlink($phpbb_root_path . $config['downloads_path'] . '/mods/' . $this->filename . '.zip'); } /* ZipArchive is not supported on the server - but leave this here for possible later use $final = new DirZipArchive(); $final->open('$config['downloads_path'] . '/mods/' . $this->filename . '.zip', ZIPARCHIVE::CREATE); $final->addDir($mod_dir . '/', $this->filename); $final->close();*/ // Generate final MOD pack $final = new compress_zip('w', $phpbb_root_path . $config['downloads_path'] . '/mods/' . $this->filename . '.zip'); $filelist = scandir_rec($mod_dir . '/'); foreach ($filelist as $file) { // Add file to archive $final->add_custom_file($mod_dir . '/' . $file, $this->filename . '/' . $file); } $final->close(); $this->data['size'] = filesize($phpbb_root_path . $config['downloads_path'] . '/mods/' . $this->filename . '.zip'); return true; }
/** * upload module zip */ private function upload_file() { global $user, $phpbb_root_path, $phpEx, $phpbb_admin_path, $template; // Upload part $user->add_lang('posting'); // For error messages include($phpbb_root_path . 'includes/functions_upload.' . $phpEx); $upload = new fileupload(); // Only allow ZIP files $upload->set_allowed_extensions(array('zip')); $file = $upload->form_upload('modupload'); // this is for module zips so don't allow anything else if (empty($file->filename) || !preg_match('.zip.', $file->get('realname'))) { trigger_error($user->lang['NO_FILE_B3P'] . adm_back_link($this->u_action), E_USER_WARNING); } else { if (!$file->init_error && !sizeof($file->error)) { $file->clean_filename('real'); $file->move_file(str_replace($phpbb_root_path, '', $this->upload_path), true, true); if (!sizeof($file->error)) { include($phpbb_root_path . 'includes/functions_compress.' . $phpEx); $mod_dir = $this->upload_path . str_replace('.zip', '', $file->get('realname')); // make sure we don't already have the new folder if(is_dir($mod_dir)) { $this->directory_delete($mod_dir); } $compress = new compress_zip('r', $file->destination_file); $compress->extract($mod_dir . '_tmp/'); $compress->close(); $folder_contents = $this->cut_folder(scandir($mod_dir . '_tmp/', 1)); // This ensures dir is at index 0 // We need to check if there's a main directory inside the temp MOD directory if (sizeof($folder_contents) == 1) { // We need to move that directory then $this->directory_move($mod_dir . '_tmp/' . $folder_contents[0], $this->upload_path . $folder_contents[0]); $new_mod_dir = $this->upload_path . $folder_contents[0]; } else if (!is_dir($mod_dir)) { // Change the name of the directory by moving to directory without _tmp in it $this->directory_move($mod_dir . '_tmp/', $mod_dir); $new_mod_dir = $mod_dir; } $this->directory_delete($mod_dir . '_tmp/'); // make sure we set $mod_dir to the correct folder after the above step $mod_dir = (isset($new_mod_dir)) ? $new_mod_dir : $mod_dir; // if we got until here set $actions['NEW_FILES'] $actions['NEW_FILES'] = array(); // Now we need to get the files inside the folders //$folder_contents = $this->cut_folder(scandir($mod_dir)); $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($mod_dir)); // requires PHP 5 foreach($iterator as $cur_file) { $cur_path = $cur_file->getPathname(); $cur_path = str_replace('\\', '/', $cur_path); // we want unix-like paths $cur_path = str_replace($mod_dir . '/', '', $cur_path); $cut_pos = strpos($cur_path, '/'); /* * We only copy files. The recursive iterator might grab paths depending on * the PHP version. This will trigger our error handle with trigger_error() * though. If we are trying to copy a directory just move on. */ if (is_dir($cur_path)) { continue; } // Only allow files in adm, language, portal and styles folder and a license.txt if(!in_array(substr($cur_path, 0, $cut_pos), array('adm', 'language', 'portal', 'styles')) && $cur_file->getFilename() != 'license.txt') { $file->remove(); $this->directory_delete($mod_dir); trigger_error($user->lang['MODULE_CORRUPTED'] . adm_back_link(append_sid("{$phpbb_admin_path}index.$phpEx", 'i=portal&mode=modules')), E_USER_WARNING); } else { $actions['NEW_FILES'][$mod_dir . '/' . $cur_path] = $phpbb_root_path . $cur_path; } } if (!sizeof($file->error)) { // Let's start moving our files where they belong foreach ($actions['NEW_FILES'] as $source => $target) { /* * make sure we don't try to copy folders * folders will be created if necessary in copy_content */ if(is_dir($source)) { continue; } $status = $this->copy_content($source, $target); if ($status !== true && !is_null($status)) { $module_installed = false; } $template->assign_block_vars('new_files', array( 'S_SUCCESS' => ($status === true) ? true : false, 'S_NO_COPY_ATTEMPT' => (is_null($status)) ? true : false, 'SOURCE' => $source, 'TARGET' => $target, )); } $template->assign_vars(array( 'S_MOD_SUCCESSBOX' => true, 'MESSAGE' => $user->lang['MODULE_UPLOADED'], 'U_RETURN' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=portal&mode=modules'), 'S_INSTALL' => true, )); } } } $file->remove(); $this->directory_delete($mod_dir); if ($file->init_error || sizeof($file->error)) { trigger_error((sizeof($file->error) ? implode('<br />', $file->error) : $user->lang['MOD_UPLOAD_INIT_FAIL']) . adm_back_link($this->u_action), E_USER_WARNING); } $this->tpl_name = 'portal/acp_portal_upload_module'; $this->page_title = $user->lang['ACP_PORTAL_UPLOAD']; $template->assign_vars(array( 'L_TITLE' => $user->lang['ACP_PORTAL_UPLOAD'], 'L_TITLE_EXPLAIN' => '', 'S_ERROR' => false, // if we get here, there was no error or we can ignore it 'ERROR_MSG' => '', 'U_ACTION' => $this->u_action, )); } }
function upload_mod($action) { global $phpbb_root_path, $phpEx, $template, $user; $can_upload = @ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !@extension_loaded('zlib') ? false : true; // get FTP information if we need it $hidden_ary = get_connection_info(false); if (!isset($_FILES['modupload']) || $action != 'upload_mod') { $template->assign_vars(array('S_FRONTEND' => true, 'S_MOD_UPLOAD' => $can_upload ? true : false, 'U_UPLOAD' => $this->u_action . '&action=upload_mod', 'S_FORM_ENCTYPE' => $can_upload ? ' enctype="multipart/form-data"' : '', 'S_HIDDEN_FIELDS' => build_hidden_fields($hidden_ary))); add_form_key('acp_mods_upload'); return false; } // end pre_upload_mod if (!check_form_key('acp_mods_upload')) { trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } $user->add_lang('posting'); // For error messages include $phpbb_root_path . 'includes/functions_upload.' . $phpEx; $upload = new fileupload(); $upload->set_allowed_extensions(array('zip')); // Only allow ZIP files $write_method = 'editor_' . determine_write_method(false); // For Direct & Manual write methods, make sure store/mods/ directory is writable if ($write_method == 'editor_direct' || $write_method == 'editor_manual') { if (!is_writable($this->mods_dir)) { trigger_error($user->lang['MODS_NOT_WRITABLE'] . adm_back_link($this->u_action), E_USER_WARNING); } $write_method = 'editor_direct'; // Force Direct method, in the case of manual $upload_dir = $this->mods_dir; } else { if (is_writable($this->store_dir)) { $upload_dir = $this->store_dir; } else { trigger_error($user->lang['STORE_NOT_WRITABLE'] . adm_back_link($this->u_action), E_USER_WARNING); } } $editor = new $write_method(); // Make sure the store/mods/ directory exists and if it doesn't, create it if (!is_dir($this->mods_dir)) { $editor->recursive_mkdir($this->mods_dir); } // Proceed with the upload $file = $upload->form_upload('modupload'); if (empty($file->filename)) { trigger_error($user->lang['NO_UPLOAD_FILE'] . adm_back_link($this->u_action), E_USER_WARNING); } else { if ($file->init_error || sizeof($file->error)) { $file->remove(); trigger_error((sizeof($file->error) ? implode('<br />', $file->error) : $user->lang['MOD_UPLOAD_INIT_FAIL']) . adm_back_link($this->u_action), E_USER_WARNING); } } $file->clean_filename('real'); $file->move_file(str_replace($phpbb_root_path, '', $upload_dir), true, true); if (sizeof($file->error)) { $file->remove(); trigger_error(implode('<br />', $file->error) . adm_back_link($this->u_action), E_USER_WARNING); } include $phpbb_root_path . 'includes/functions_compress.' . $phpEx; $mod_dir = $upload_dir . '/' . str_replace('.zip', '', $file->get('realname')); $compress = new compress_zip('r', $file->destination_file); $compress->extract($mod_dir . '_tmp/'); $compress->close(); $folder_contents = scandir($mod_dir . '_tmp/', 1); // This ensures dir is at index 0 $folder_contents = array_diff($folder_contents, array('.', '..')); // We need to check if there's only one (main) directory inside the temp MOD directory if (sizeof($folder_contents) == 1) { $folder_contents = implode(null, $folder_contents); $from_dir = $mod_dir . '_tmp/' . $folder_contents; $to_dir = $this->mods_dir . '/' . $folder_contents; } else { if (!is_dir($mod_dir)) { $from_dir = $mod_dir . '_tmp/'; $to_dir = $mod_dir . '/'; } else { trigger_error($user->lang['MOD_UPLOAD_UNRECOGNIZED'] . adm_back_link($this->u_action), E_USER_WARNING); } } // Copy that directory to the new path $editor->copy_content($from_dir, $to_dir); // Finally remove the main tmp extraction directory, directly, just like we created it recursive_unlink($mod_dir . '_tmp/'); $template->assign_vars(array('S_MOD_SUCCESSBOX' => true, 'MESSAGE' => $user->lang['MOD_UPLOAD_SUCCESS'], 'U_RETURN' => $this->u_action)); // Remove the uploaded archive file $file->remove(); return true; }