Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   PHP (https://www.clubdelphi.com/foros/forumdisplay.php?f=15)
-   -   imagecreatefromstring detiene el script (https://www.clubdelphi.com/foros/showthread.php?t=94161)

bucanero 04-09-2019 18:04:21

imagecreatefromstring detiene el script
 
Hola buenas tardes,

Aquí vengo con un BUGS esta vez en PHP, que suerte todos los voy encontrando yo :confused: ...,
en particular se trata de un BUGS en la librería GD que lo que hace es elevar a error desconocido cualquier error que encuentra la propia librería y deteniendo totalmente el script que se esta ejecutando.

Aquí se comenta el BUGS que también tiene ya su tiempo
https://bugs.php.net/bug.php?id=70315

El problema en particular me afecta en PRESTASHOP que utiliza estas librerías para procesar las imágenes/miniaturas. Y en particular en el proceso de generación de miniaturas, donde siempre se detiene (debido al BUGS) en la misma imagen, sin llegar a finalizar ni a procesar el resto de las miniaturas que tiene la tienda, por lo que nunca avanza.

Intente solventarlo, antes de conocer que el problema es debido a este bug, creando un script alternativo que detecte y elimine las imágenes no validas para lo que cree una función que las chequea en el servidor para comprobar si son correctas, pero en cuanto llega a analizar la primera imagen con error en particular cuando llega al comando imagecreatefromstring() que es un comando de la librería GD el script se detiene y se acaba el proceso... no haciendo caso por mas que lo he intentado de los bloques try ... catch ... finally

Este es mi código:
Código PHP:

    function GetImageInfo($filename, &$errorMsg) {
        
        
/* Abrimos el archivo según su contenido */
        
$result false;
        try {
            
$finfo finfo_open(FILEINFO_MIME_TYPE);
            
$result finfo_file($finfo$filename);
        } catch (
Exception $e) {
            
$errorMsg .= $e->getMessage();              
        } 
finally {
            
finfo_close($finfo);        
        }         
        return 
$result;
    }
    
    function 
checkImage($filename, &$errorMsg) {
      
        
$result false;
        
$errorMsg '';
        try {    
            
$image false;    
            if (
$filename == "") {
                
$errorMsg .= "El nombre de fichero esta vacio";                                        
            } elseif ( !
file_exists($filename) ) {
                
$errorMsg .= "La ruta del fichero no es correcta";                                                    
            } elseif ( !
$infoFile GetImageInfo($filename$errorMsg) ) {
                
$errorMsg .= "{$filename}: No se ha podido obtener informacion del fichero";                            
            }elseif (( 
$infoFile != 'image/jpeg' ) && ( $infoFile != 'image/png' )) {
                
$errorMsg .= "{$filename}: Formato de imagen no soportado";            
            } elseif (!
$image_data file_get_contents($filename)) {
                
$errorMsg .= "{$filename}: Contenido no disponible";                        
            } elseif(!
$image imagecreatefromstring($image_data)) {
                
$errorMsg .= error_get_last()['message'];                  
            } else {
                unset(
$image);
                
$result true;
            } 
// if        
        
} catch (Exception $e) {
            
$errorMsg $e->getMessage();              
        } 
finally {            
            return 
$result;                    
        }  
    } 
// function 

- ¿Alguien mas que haya tenido este problema?
- ¿Alguna otra alternativa o solución para determinar si una imagen es correcta o no en PHP?

Gracias por su tiempo y colaboración
saludos

Ñuño Martínez 05-09-2019 11:34:22

Me parece muy raro que un error tan antiguo (2.015) no haya sido corregido todavía, y menos en una biblioteca tan usada como esta.

De todas formas, ¿seguro que para el programa sin más? ¿Estás ejecutando con todas las opciones de depuración activadas para que te muestre toda la información posible? [edit] ¿Qué versión de PHP estás usando? Porque dice que el error está arreglado y sólo afecta a un par de versiones viejas.

bucanero 05-09-2019 13:26:50

Cita:

Empezado por Ñuño Martínez (Mensaje 533367)
Me parece muy raro que un error tan antiguo (2.015) no haya sido corregido todavía, y menos en una biblioteca tan usada como esta.

De todas formas, ¿seguro que para el programa sin más? ¿Estás ejecutando con todas las opciones de depuración activadas para que te muestre toda la información posible? [edit] ¿Qué versión de PHP estás usando? Porque dice que el error está arreglado y sólo afecta a un par de versiones viejas.

Gracias Ñuño Martínez por responder!!

La versión de PHP de mi servidor es la 5.6.32 de fecha 26/10/2017, es verdad que no es la ultima, pero se supone que dicho BUGS esta ya solventado en esa versión, pues según la documentación se aplico a partir de la versión 5.6.25 de fecha 18/08/2016. De todas formas ya he abierto tickets para que actualicen la versión del hosting.

En cualquier caso ejecuto con todas las opciones de depuración, y se sigue deteniendo.
La solución que he aplicado momentáneamente es capturar cuando finaliza el script y analizar si se ha producido una excepción de tipo E_ERROR y en tal caso borrar el fichero. Este es el método:

Código PHP:

    register_shutdown_function('fatalErrorShutdownHandler');
    
    function 
fatalErrorShutdownHandler() {
        
        global 
$filename;
        
        
$last_error error_get_last();
        if (
$last_error['type'] === E_ERROR && ($filename != '') ) {
            if ( !
unlink $filename ) ) {
                echo 
"{$filename} no se ha podido eliminar";
            } else {
                echo 
"{$filename} eliminado";                
            }
        }
    } 

No es la solución mas optima, pero al menos para la siguiente vez que se ejecute el script ya no se volverá a detenerse en el mismo fichero.

dec 06-09-2019 08:42:39

Hola a todos,

Supongo que sí... pero... ¿estás mostrando los posibles errores de PHP? Esto es, al comienzo del script, prueba a añadir las siguientes líneas de código:

Código PHP:


error_reporting
(E_ALL);

ini_set('display_errors'1); 


bucanero 06-09-2019 11:02:55

1 Archivos Adjunto(s)
Cita:

Empezado por dec (Mensaje 533381)
Hola a todos,

Supongo que sí... pero... ¿estás mostrando los posibles errores de PHP? Esto es, al comienzo del script, prueba a añadir las siguientes líneas de código:

Código PHP:


error_reporting
(E_ALL);

ini_set('display_errors'1); 


David gracias por responder!!!

Si, esta activo el modo de depuración. De echo la librería GD devuelve exactamente el error que encuentra. El error en particular es:

Código:

Fatal error: imagecreatefromstring(): gd-jpeg: JPEG library reports unrecoverable error: Bogus marker length in itest.php on line 53
El error es correcto es de la propia imagen por estar corrupta (parece ser que el tamaño de los datos contenidos en la imagen es distinto al definido por las dimensiones de la imagen). Y ese mismo error también lo obtengo al intentar leer esa imagen con cualquier programa externo de imagenes en windows.
El problema es de la libreria GD y de PHP que detiene la ejecución ...

Este es mi código completo que utilizo para hacer la prueba de comprobación y en donde ya se da el fallo:
Código PHP:

<?php
  
// https://bugs.php.net/bug.php?id=73986
  
  
error_reporting(E_ALL);  
  
ini_set('display_errors'1);
  
ini_set('display_startup_errors'1);
  
  
ini_set ('gd.jpeg_ignore_warning'1);
  
  
register_shutdown_function('fatalErrorShutdownHandler');
    
    function 
fatalErrorShutdownHandler() {
        
        global 
$filename;
        
        
$last_error error_get_last();
        if (
$last_error['type'] === E_ERROR && ($filename != '') ) {
            echo 
"<BR/>\r\r(" __LINE__ ") ERROR: {$filename}. Ejecución detenida."
        }
    }
    
    function 
GetImageInfo($filename, &$errorMsg) {
        
        
/* Abrimos el archivo según su contenido */
        
$result false;
        try {
            
$finfo finfo_open(FILEINFO_MIME_TYPE);
            
$result finfo_file($finfo$filename);
        } catch (
Exception $e) {
            
$errorMsg .= $e->getMessage();              
        } 
finally {
            
finfo_close($finfo);        
        }         
        return 
$result;
    }
    
    function 
checkImage($filename, &$errorMsg) {
      
        
$result false;
        
$errorMsg '';
        try {    
            
$image false;    
            if (
$filename == "") {
                
$errorMsg .= "El nombre de fichero esta vacio";                                        
            } elseif ( !
file_exists($filename) ) {
                
$errorMsg .= "La ruta del fichero no es correcta";                                                    
            } elseif ( !
$infoFile GetImageInfo($filename$errorMsg) ) {
                
$errorMsg .= "{$filename}: No se ha podido obtener informacion del fichero";                            
            }elseif (( 
$infoFile != 'image/jpeg' ) && ( $infoFile != 'image/png' )) {
                
$errorMsg .= "{$filename}: Formato de imagen no soportado";            
            } elseif (!
$image_data file_get_contents($filename)) {
                
$errorMsg .= "{$filename}: Contenido no disponible";                        
            } elseif(!
$image imagecreatefromstring($image_data)) {
                
$errorMsg .= error_get_last()['message'];                  
            } else {
                unset(
$image);
                
$result true;
            } 
// if        
        
} catch (Exception $e) {
            
$errorMsg .= $e->getMessage();              
        } 
finally {        
            return 
$result;                    
        }  
    } 
// function

  
$errorMsg ''
  
$filename '3612272.jpg';      
  if ( !
checkImage($filename$errorMsg) ) {
    echo 
"<BR/>\r\r(" __LINE__ ") ERROR: {$filename} {$errorMsg}";
  } else {
    echo 
"{$filename} OK";
  }
?>

y dejo enlace a la imagen corrupta por si alguien quiere hacer pruebas en su propio equipo

dec 06-09-2019 11:41:23

Hola a todos,

¿Se detiene la ejecución incluso con el "try...catch"? Sea como sea... claro, lo primero que se le ocurre a uno es, ¿por qué no se usa una imagen "incorrupta"? ¿Es obligatorio usar esa imagen? Pero siempre podría convertirse, ¿no? ... porque el error pinta malamente así a bote pronto...

bucanero 06-09-2019 13:04:35

Cita:

Empezado por dec (Mensaje 533383)
Hola a todos,

¿Se detiene la ejecución incluso con el "try...catch"? Sea como sea...

Si, se detiene sin mas y finaliza, el try ... catch hace caso omiso, cosa que también a mi me ha sorprendido mucho....

Cita:

Empezado por dec (Mensaje 533383)
Hola a todos,
claro, lo primero que se le ocurre a uno es, ¿por qué no se usa una imagen "incorrupta"? ¿Es obligatorio usar esa imagen? Pero siempre podría convertirse, ¿no? ...

Esta imagen procede de un proceso automático donde las recoge de diversos catálogos de precios de varios proveedores y en distintos servidores y monta un catalogo propio de productos (dropshipping). La imagen puede venir ya corrupta incluso desde el propio servidor web del proveedor, o corromperse a lo largo del proceso de descarga, o simplemente no ser un formato de imagen valido... por tanto el objetivo de este código es simplemente detectar las imágenes problemáticas y eliminarlas, por lo menos para que no interfieran en el resto de procesos.

Hasta ahora con la medio solución de register_shutdown_function(); he conseguido a base de ejecutar muchas veces el script, ir eliminando de una en una cada imagen problemática. Pero esta solución es como matar moscas a cañonazos...

Cita:

Empezado por dec (Mensaje 533383)
porque el error pinta malamente así a bote pronto...

Pues parece que si...


La franja horaria es GMT +2. Ahora son las 02:19:31.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi