Req #79874 [Opn->Nab]: procedural API of ext/zip depercated without replacement
| From: | remi@php.net | 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