diff --git a/admin/include/languages.class.php b/admin/include/languages.class.php index 6f6780592..fcf1cbda8 100644 --- a/admin/include/languages.class.php +++ b/admin/include/languages.class.php @@ -306,6 +306,8 @@ UPDATE '.USER_INFOS_TABLE.' */ function extract_language_files($action, $revision, $dest='') { + global $logger; + if ($archive = tempnam( PHPWG_ROOT_PATH.'language', 'zip')) { $url = PEM_URL . '/download.php'; @@ -331,6 +333,9 @@ UPDATE '.USER_INFOS_TABLE.' $main_filepath = $file['filename']; } } + + $logger->debug(__FUNCTION__.', $main_filepath = '.$main_filepath); + if (isset($main_filepath)) { $root = basename(dirname($main_filepath)); // common.lang.php path in archive @@ -341,6 +346,9 @@ UPDATE '.USER_INFOS_TABLE.' $dest = $root; } $extract_path = PHPWG_ROOT_PATH.'language/'.$dest; + + $logger->debug(__FUNCTION__.', $extract_path = '.$extract_path); + if ( $result = $zip->extract( PCLZIP_OPT_PATH, $extract_path, @@ -370,9 +378,31 @@ UPDATE '.USER_INFOS_TABLE.' and !empty($old_files)) { $old_files[] = 'obsolete.list'; + $logger->debug(__FUNCTION__.', $old_files = {'.join('},{', $old_files).'}'); + + $extract_path_realpath = realpath($extract_path); + foreach($old_files as $old_file) { + $old_file = trim($old_file); + $old_file = trim($old_file, '/'); // prevent path starting with a "/" + + if (empty($old_file)) // empty here means the extension itself + { + continue; + } + $path = $extract_path.'/'.$old_file; + + // make sure the obsolete file is withing the extension directory, prevent traversal path + $realpath = realpath($path); + if ($realpath === false or strpos($realpath, $extract_path_realpath) !== 0) + { + continue; + } + + $logger->debug(__FUNCTION__.', to delete = '.$path); + if (is_file($path)) { @unlink($path); diff --git a/admin/include/plugins.class.php b/admin/include/plugins.class.php index 8b4b82b75..12e7fd140 100644 --- a/admin/include/plugins.class.php +++ b/admin/include/plugins.class.php @@ -558,6 +558,8 @@ DELETE FROM '. PLUGINS_TABLE .' */ function extract_plugin_files($action, $revision, $dest, &$plugin_id=null) { + global $logger; + if ($archive = tempnam( PHPWG_PLUGINS_PATH, 'zip')) { $url = PEM_URL . '/download.php'; @@ -583,6 +585,9 @@ DELETE FROM '. PLUGINS_TABLE .' $main_filepath = $file['filename']; } } + + $logger->debug(__FUNCTION__.', $main_filepath = '.$main_filepath); + if (isset($main_filepath)) { $root = dirname($main_filepath); // main.inc.php path in archive @@ -595,6 +600,7 @@ DELETE FROM '. PLUGINS_TABLE .' $plugin_id = ($root == '.' ? 'extension_' . $dest : basename($root)); } $extract_path = PHPWG_PLUGINS_PATH . $plugin_id; + $logger->debug(__FUNCTION__.', $extract_path = '.$extract_path); if($result = $zip->extract(PCLZIP_OPT_PATH, $extract_path, PCLZIP_OPT_REMOVE_PATH, $root, @@ -613,9 +619,31 @@ DELETE FROM '. PLUGINS_TABLE .' and !empty($old_files)) { $old_files[] = 'obsolete.list'; + $logger->debug(__FUNCTION__.', $old_files = {'.join('},{', $old_files).'}'); + + $extract_path_realpath = realpath($extract_path); + foreach($old_files as $old_file) { + $old_file = trim($old_file); + $old_file = trim($old_file, '/'); // prevent path starting with a "/" + + if (empty($old_file)) // empty here means the extension itself + { + continue; + } + $path = $extract_path.'/'.$old_file; + + // make sure the obsolete file is withing the extension directory, prevent traversal path + $realpath = realpath($path); + if ($realpath === false or strpos($realpath, $extract_path_realpath) !== 0) + { + continue; + } + + $logger->debug(__FUNCTION__.', to delete = '.$path); + if (is_file($path)) { @unlink($path); diff --git a/admin/include/themes.class.php b/admin/include/themes.class.php index d38352dfa..8819b7e7d 100644 --- a/admin/include/themes.class.php +++ b/admin/include/themes.class.php @@ -594,6 +594,8 @@ SELECT */ function extract_theme_files($action, $revision, $dest) { + global $logger; + if ($archive = tempnam( PHPWG_THEMES_PATH, 'zip')) { $url = PEM_URL . '/download.php'; @@ -619,6 +621,9 @@ SELECT $main_filepath = $file['filename']; } } + + $logger->debug(__FUNCTION__.', $main_filepath = '.$main_filepath); + if (isset($main_filepath)) { $root = dirname($main_filepath); // main.inc.php path in archive @@ -630,6 +635,9 @@ SELECT { $extract_path = PHPWG_THEMES_PATH . ($root == '.' ? 'extension_' . $dest : basename($root)); } + + $logger->debug(__FUNCTION__.', $extract_path = '.$extract_path); + if ( $result = $zip->extract( PCLZIP_OPT_PATH, $extract_path, @@ -651,9 +659,32 @@ SELECT and !empty($old_files)) { $old_files[] = 'obsolete.list'; + + $logger->debug(__FUNCTION__.', $old_files = {'.join('},{', $old_files).'}'); + + $extract_path_realpath = realpath($extract_path); + foreach($old_files as $old_file) { + $old_file = trim($old_file); + $old_file = trim($old_file, '/'); // prevent path starting with a "/" + + if (empty($old_file)) // empty here means the extension itself + { + continue; + } + $path = $extract_path.'/'.$old_file; + + // make sure the obsolete file is withing the extension directory, prevent traversal path + $realpath = realpath($path); + if ($realpath === false or strpos($realpath, $extract_path_realpath) !== 0) + { + continue; + } + + $logger->debug(__FUNCTION__.', to delete = '.$path); + if (is_file($path)) { @unlink($path);