Bug #79874 [Com]: procedural API of ext/zip depercated without replacement
| From: | bugreports2 at gmail dot com | Date: | Sat, 18 Jul 2020 17:21:05 +0000 |
| Subject: | Bug #79874 [Com]: procedural API of ext/zip depercated without replacement | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-228114@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=79874&edit=1
ID: 79874
Comment by: bugreports2 at gmail dot com
Reported by: bugreports2 at gmail dot com
Summary: procedural API of ext/zip depercated without
replacement
Status: Open
Type: Bug
Package: *General Issues
PHP Version: 8.0Git-2020-07-18 (Git)
Block user comment: N
Private report: N
New Comment:
someone my port that code running perfectly for many years to the limited ZipArchive class.....
/**
* Lokales oder hochgeladenes ZIP-Archiv rekursiv im CMS-Temp-Folder entpacken
* Versteckte Dateien und Ordner werden ignoriert
*
* Wenn keine Dateiendungen uebergeben wurden aktuelle Systemeinstellungen benutzen
* Wenn es sich um eine hochgeladene Datei handelt implizit move_uploaded_file() benutzen
*
* @param mixed $source Pfad zum ZIP-File oder ein $_FILES-Item eines Dateiuploads
* @param array $ext Array mit erlaubten Dateiendungen oder Fallback auf CMS-defaults
wenn leer
* @param bool $normalize_names Dateinamen webkonform normalisieren, Default: Aktiv
*
* @return array [folder, files, folders]
*/
public function unpack_zip($source, array $ext=[], bool $normalize_names=TRUE): array
{
/** Abbrechen wenn kein Server-Support */
if(extension_loaded('zip') === FALSE)
{
return [];
}
/** Maximale Skript-Laufzeit erhoehen und bei Verbindungsabbruch weiterlaufen lassen */
ignore_user_abort(TRUE);
set_time_limit(0);
/** Wenn keine erlaubten Dateiendungen definiert wurden auf CMS-Defaults zurueckfallen */
if(empty($ext))
{
global $uploadtypes;
$ext = $uploadtypes;
}
/** Datei-Upload verarbeiten */
if(is_array($source) === TRUE)
{
/** Check ob es sich um einen Upload handelt */
if(empty($source['error']) && !empty($source['tmp_name']) &&
!empty($source['name']) && strtolower(substr($source['name'], -4)) ===
'.zip' && is_uploaded_file($source['tmp_name']) === TRUE)
{
/** Upload in CMS-Temp-Folder verschieben */
$zip_upload_tmp_name = "{$this->cl_api->CONTENTLOUNGE_BASEDIR}/temp/unpack_zip_"
. bin2hex(random_bytes(10)) . '.zip';
if(move_uploaded_file($source['tmp_name'], $zip_upload_tmp_name) === FALSE)
{
return [];
}
else
{
/** Ab jetzt spielen wir der Funktion eine normale Datei als Source-Angabe vor */
chmod($zip_upload_tmp_name, 0660);
clearstatcache(TRUE, $zip_upload_tmp_name);
$source = $zip_upload_tmp_name;
}
}
}
/** ZIP-Archiv oeffnen */
if(!empty($source))
{
$zip_handle = zip_open($source);
if(is_resource($zip_handle))
{
/** Eindeutigen Temp-Folder zum Entpacken */
$zip_tmp_folder = "{$this->cl_api->CONTENTLOUNGE_BASEDIR}/temp/unpack_zip_" .
bin2hex(random_bytes(10));
/** Sicherstellen dass der Temp-Pfad nicht mit einem Slash endet */
if(substr($zip_tmp_folder, -1) === '/')
{
$zip_tmp_folder = substr($zip_tmp_folder, 0, -1);
}
/** Temp-Dir anlegen */
mkdir($zip_tmp_folder, 0770);
/** ZIP-Archiv durchlaufen */
$files_created = FALSE;
while(($zip_file_handle = zip_read($zip_handle)) !== FALSE)
{
/** Nur Dateien mit der gelisteten Erweiterung verarbeiten */
$zip_file_name = utf8_decode(str_replace("\\", '/',
zip_entry_name($zip_file_handle)));
$zip_file_ext = pathinfo($zip_file_name, PATHINFO_EXTENSION);
rh_debug_in_array(strtolower($zip_file_ext), $ext);
if(in_array(strtolower($zip_file_ext), $ext, /**strict*/TRUE) === TRUE)
{
/** Sicherstellen dass wir keine versteckten und MACOSX-Meta Dateien verarbeiten */
if(substr(basename($zip_file_name), 0, 1) !== '.' && strpos($zip_file_name,
'/.') === FALSE && strpos($zip_file_name, '/__MACOSX') === FALSE)
{
/** Absoluten Pfad im Temp-Folder festlegen, einzelne Ordner-Komponenten dabei normalisieren
*/
$folder_components = explode('/', dirname($zip_file_name));
foreach($folder_components as $folder_key=>$folder_component)
{
$folder_components[$folder_key] = rh_misc::ConvertMyUploadName($folder_component);
}
/** Base-Dateinamen behandeln */
switch($normalize_names)
{
/** Kompletten Dateinamen fuer Web normalisieren */
case TRUE:
$zip_file_name = implode('/', $folder_components) . '/' .
rh_misc::ConvertMyUploadName(basename($zip_file_name));
$zip_temp_filename = "{$zip_tmp_folder}/{$zip_file_name}";
break;
/** Dateiendung in jedem Fall auf Kleinbuchstaben */
case FALSE:
$zip_file_name = implode('/', $folder_components) . '/' .
basename($zip_file_name);
$zip_temp_filename = "{$zip_tmp_folder}/" .
str_replace(".{$zip_file_ext}", '.' . strtolower($zip_file_ext),
$zip_file_name);
break;
}
/** Sicherstellen dass wir die Subfolder-Struktur beibehalten */
if(is_dir(dirname($zip_temp_filename)) === FALSE)
{
mkdir(dirname($zip_temp_filename), 0770, TRUE);
}
/** Temp-File erstellen */
if(zip_entry_filesize($zip_file_handle) > 0)
{
file_put_contents($zip_temp_filename, zip_entry_read($zip_file_handle,
zip_entry_filesize($zip_file_handle)));
$files_created = TRUE;
}
}
}
}
/** ZIP-Archiv wieder schliessen */
zip_close($zip_handle);
/** GGf. vorhandene Upload-Datei wieder loeschen */
if(!empty($zip_upload_tmp_name) && file_exists($zip_upload_tmp_name) === TRUE)
{
unlink($zip_upload_tmp_name);
}
/** Check ob verwertbare Dateien im Archiv gefunden wurden */
switch($files_created)
{
/** Keine Dateien entpackt */
case FALSE: (new rh_filesystem)->rmdir($zip_tmp_folder); return []; break;
/** Finale Verarbeitung */
case TRUE:
/** Check ob erster Ordner alleinestehend UND leer ist und alles darunter eine Ebene nach
oben schieben */
$basedir_files = $this->cl_api->folders->readdir($zip_tmp_folder);
$basedir_folders = $this->cl_api->folders->readdir_folders($zip_tmp_folder);
if(count($basedir_folders) === 1)
{
$basedir_parent_folder = $basedir_folders[0];
$basedir_folders = $this->cl_api->folders->readdir_folders($basedir_parent_folder);
/** Subfolder vorhanden */
if(!empty($basedir_folders))
{
foreach($basedir_folders as $basedir_current_folder)
{
$basedir_current_folder_new = $zip_tmp_folder . str_replace($basedir_parent_folder,
'', $basedir_current_folder);
rename($basedir_current_folder, $basedir_current_folder_new);
}
}
/** Nur Dateien im Basis-Ordner */
else
{
$basedir_files = $this->cl_api->folders->readdir($basedir_parent_folder);
if(!empty($basedir_files))
{
foreach($basedir_files as $basedir_current_file)
{
$basedir_current_file_new = $zip_tmp_folder . str_replace($basedir_parent_folder,
'', $basedir_current_file);
rename($basedir_current_file, $basedir_current_file_new);
}
}
}
}
/** Filesystem-Klasse instanzieren und Liste zurueckgeben, leere Ordner entfernen */
$rh_fs = new rh_filesystem;
$file_list = $rh_fs->ListFilesRecursive(/**path*/$zip_tmp_folder, /**details*/TRUE);
foreach($file_list['folders'] as $current_folder)
{
if($rh_fs->is_dir_empty($current_folder) === TRUE)
{
rmdir($current_folder);
}
}
$file_list = $rh_fs->ListFilesRecursive(/**path*/$zip_tmp_folder, /**details*/TRUE);
$file_list['files'] = array_keys($file_list['files']);
foreach($file_list['folders'] as $current_folder)
{
chmod($current_folder, 0770);
clearstatcache(TRUE, $current_folder);
}
foreach($file_list['files'] as $current_file)
{
chmod($current_file, 0660);
clearstatcache(TRUE, $current_file);
}
natsort($file_list['files']);
natsort($file_list['folders']);
return ['folder'=>$zip_tmp_folder,
'files'=>$file_list['files'],
'folders'=>$file_list['folders']];
break;
}
}
/** Offenbar kein ZIP-Archiv, abbrechen und ggf. Temp-File loeschen */
else
{
if(!empty($zip_upload_tmp_name) && file_exists($zip_upload_tmp_name) === TRUE)
{
unlink($zip_upload_tmp_name);
}
}
}
/** Im Zweifel leeren Array zurueckgeben */
return [];
}
Previous Comments:
------------------------------------------------------------------------
[2020-07-18 16:40:33] bugreports2 at gmail dot com
Description:
------------
http://git.php.net/?p=php-src.git;a=commitdiff;h=f3b1f342c887073012f4ca7c1bc1b5259ce4cedc
that's cool, but how do you expect switching to the object style when these is no
ZipArchive::read(), ZipArchive::entry_name, ZipArchive::entry_filesize(),
ZipArchive::entry_read()
ZipArchive::extractTo() is *no* replacement when you iterate and decide which files are supposed to
be extracted, you need to reqrite the whole code and logic to delete stuff after extract
look at mysqli - there is everything and more in the object API and so it *can* be a dropin
replacement without changing the whole program logic - and no please don#t be tempted to deprecate
tthe old APi there too just because you can
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=79874&edit=1