Req #79874 [Opn->Nab]: procedural API of ext/zip depercated without replacement

From: Date: Thu, 23 Jul 2020 08:49:05 +0000
Subject: Req #79874 [Opn->Nab]: procedural API of ext/zip depercated without replacement
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-228186@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 Updated by: remi@php.net Reported by: bugreports2 at gmail dot com Summary: procedural API of ext/zip depercated without replacement -Status: Open +Status: Not a bug Type: Feature/Change Request Package: Zip Related PHP Version: 8.0Git-2020-07-18 (Git) Block user comment: N Private report: N New Comment: Sorry, but your problem does not imply a bug in PHP itself. For a list of more appropriate places to ask for help using PHP, please visit http://www.php.net/support.php as this bug system is not the appropriate forum for asking support questions. Due to the volume of reports we can not explain in detail here why your report is not a bug. The support channels will be able to provide an explanation for you. Thank you for your interest in PHP. Documentation has been updated to state about deprecation and link to methods to use. Deprecation doesn't mean the feature is removed now (only in the future, probably for PHP 9), so people have time to migrate. It also (and this is more important) means that the procedural API is not maintained, and suffers for lack of feature. Iterating is as simple as for ($idx=0 ; $s = $zip->statIndex($idx) ; $idx++) ... Previous Comments: ------------------------------------------------------------------------ [2020-07-19 09:59:53] cmb@php.net See <https://github.com/php/php-src/pull/5746#issuecomment-660619211>. ------------------------------------------------------------------------ [2020-07-18 20:59:38] requinix@php.net I'd like to see that too, but it's pretty significant. Can it be done in the next two weeks before the 8.0 feature freeze? ------------------------------------------------------------------------ [2020-07-18 20:54:25] cmb@php.net @requinix, in my opinion, that is a poor replacement for the procedural API wrt. iterating the archive entries, so I think it would be good if we made ZipArchive iteratable, yielding ZipEntry instances with methods such as ::name(), ::filesize() and ::read(). ------------------------------------------------------------------------ [2020-07-18 20:23:03] requinix@php.net The procedural API is being removed as part of a push to remove/deprecate using resources in places where other data types (mostly objects) are suitable. You're right that ext/zip does not work like mysqli where the two API styles work the same way. But ZipArchive does look like it supports the same functionality *in a different way*. Can't do an open/read loop? Use a for loop with getNameIndex/statIndex. https://www.php.net/manual/en/ziparchive.getnameindex.php ------------------------------------------------------------------------ [2020-07-18 17:21:04] bugreports2 at gmail dot com 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 []; } ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=79874 -- Edit this bug report at https://bugs.php.net/bug.php?id=79874&edit=1

« previous php.bugs (#228186) next »