Chequear si un archivo .PNG es realmente un .PNG

Iniciado por extreme69, 9 Julio 2013, 20:39 PM

0 Miembros y 2 Visitantes están viendo este tema.

extreme69

Tengo un problema...

El usuario tiene un archivo .GIF y como mi web no se lo deja subir porque sólo acepta imágenes .PNG, ¿qué hace el usuario? renombra la extensión. Esto me trae complicaciones, ya que se tranca el código y me da errores.

La pregunta es... ¿hay manera de chequear que el archivo que está subiendo el usuario realmente sea .PNG? leyendo los headers de los archivos o algo así?

La misma pregunta va para chequear otros formatos de imágenes como .GIF y .JPG.

Estoy googleando hace hoooooooras, no encuentro nada, denme una pista, algo, por favor.

engel lex

te recomiendo 2 paginas para buscar eso... se llaman google y wikipedia... te dejo los links de wikipedia para que revises

http://es.wikipedia.org/wiki/Portable_Network_Graphics

CitarDetalles técnicos
Un archivo PNG empieza con una firma de 8 bytes, los valores en hexadecimal son: 89 50 4E 47 0D 0A 1A 0A, los valores decimales son: 137 80 78 71 13 10 26 10; cada valor está ahí por una razón específica.

http://en.wikipedia.org/wiki/JPEG
CitarA JPEG image consists of a sequence of segments, each beginning with a marker, each of which begins with a 0xFF byte followed by a byte indicating what kind of marker it is. Some markers consist of just those two bytes; others are followed by two bytes indicating the length of marker-specific payload data that follows. (The length includes the two bytes for the length, but not the two bytes for the marker.) Some markers are followed by entropy-coded data; the length of such a marker does not include the entropy-coded data. Note that consecutive 0xFF bytes are used as fill bytes for padding purposes, although this fill byte padding should only ever take place for markers immediately following entropy-coded scan data (see JPEG specification section B.1.1.2 and E.1.2 for details; specifically "In all cases where markers are appended after the compressed data, optional 0xFF fill bytes may precede the marker").

http://en.wikipedia.org/wiki/Graphics_Interchange_Format
CitarGIF files start with a fixed-length header ("GIF87a" or "GIF89a") giving the version, followed by a fixed-length Logical Screen Descriptor giving the size and other characteristics of the logical screen. The screen descriptor may also specify the presence and size of a Global Color Table, which follows next if present.
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

1mpuls0

No estoy seguro si con el MIME se puede hacer algo al respecto.

abc

extreme69

#3
Cita de: engelx en  9 Julio 2013, 20:55 PM
te recomiendo 2 paginas para buscar eso... se llaman google y wikipedia... te dejo los links de wikipedia para que revises

http://es.wikipedia.org/wiki/Portable_Network_Graphics

http://en.wikipedia.org/wiki/JPEG
http://en.wikipedia.org/wiki/Graphics_Interchange_Format

Gracias por la inútil información que ya tenía.

Voy a probar con exif_read_data para los JPG, aunque esto no me alienta mucho:

EXIF headers tend to be present in JPEG/TIFF images generated by digital cameras, but unfortunately each digital camera maker has a different idea of how to actually tag their images, so you can't always rely on a specific Exif header being present.

extreme69

Cita de: Darhius en  9 Julio 2013, 20:59 PM
No estoy seguro si con el MIME se puede hacer algo al respecto.



Mmmmm, voy a probar también con mime_content_type

engel lex

el mime no te sirve...

no es inutil... agarras el archivo lo subes, lees los primeros bytes y si coinciden con los bytes según el mime eso son, no hay que darle muchas vueltas... la informacion exif no es obligatoria así que no lo vas a conseguir en todos los archivos de esos formatos...
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

extreme69

#6
Cita de: engelx en 10 Julio 2013, 09:55 AM
el mime no te sirve...

no es inutil... agarras el archivo lo subes, lees los primeros bytes y si coinciden con los bytes según el mime eso son, no hay que darle muchas vueltas... la informacion exif no es obligatoria así que no lo vas a conseguir en todos los archivos de esos formatos...

Ya lo intenté, pero si probás por tus medios te das cuenta que eso sólo funciona con PNG's, bueno, en realidad probé con PNG y JPG, con GIF todavía no, dando como resultado que sólo me funciona para PNG's, los JPG no tienen los primeros bytes iguales, dependen de otros factores que desconozco.

Dejo link de un código que encontré para los PNG por si alguien estaba buscando esto:

http://codeaid.net/php/check-if-the-file-is-a-png-image-file-by-reading-its-signature

engel lex

para que no digan que no ayudo con códigos...

se puede resumir mucho está hecho para ser leído...

Código (php) [Seleccionar]
$archivo = "a1.jpg";
$f = fopen($archivo,"rb");
$largo = filesize ($archivo);

$debe_tener[] = hexdec ("ff");//inicia
$debe_tener[] = hexdec ("d8");
$debe_tener[] = hexdec ("ff");//finaliza
$debe_tener[] = hexdec ("d9");

$contenido[] = ord(fread ($f , 1));
$contenido[] = ord(fread ($f , 1));
fseek($f, $largo-2);
$contenido[] = ord(fread ($f , 1));
$contenido[] = ord(fread ($f , 1));
fclose($f);

$es_valido_jpg=true;
for($i=0;$i<count($contenido);$i++) $es_valido_jpg &= $debe_tener[$i]==$contenido[$i];

echo "valido jpg = ";
var_dump($es_valido_jpg);
var_dump($contenido);
var_dump($debe_tener);
///////////////////////////////////////////////////////
unset ($debe_tener);
unset ($contenido);

$archivo = "a2.png";
$f = fopen($archivo,"rb");
$largo = filesize ($archivo);


$debe_tener[] = hexdec ("89");
$debe_tener[] = hexdec ("50");
$debe_tener[] = hexdec ("4e");
$debe_tener[] = hexdec ("47");
$debe_tener[] = hexdec ("0d");
$debe_tener[] = hexdec ("0a");
$debe_tener[] = hexdec ("1a");
$debe_tener[] = hexdec ("0a");

for($i=0;$i<count($debe_tener);$i++)
$contenido[] = ord(fread ($f , 1));
fclose($f);

$es_valido_png=true;
for($i=0;$i<count($contenido);$i++) $es_valido_png &= $debe_tener[$i]==$contenido[$i];
echo "valido png = ";
var_dump($es_valido_png);
var_dump($contenido);
var_dump($debe_tener);

///////////////////////////////////////////////////////
unset ($debe_tener);
unset ($contenido);

$archivo = "a3.gif";
$f = fopen($archivo,"rb");
$largo = filesize ($archivo);


$debe_tener[] = ord ("G");
$debe_tener[] = ord ("I");
$debe_tener[] = ord ("F");
$debe_tener[] = ord ("8");
$debe_tener[] = ord ("9");
$debe_tener[] = ord ("a");


for($i=0;$i<count($debe_tener);$i++)
$contenido[] = ord(fread ($f , 1));
fclose($f);

$es_valido_gif89a=true;
for($i=0;$i<count($contenido);$i++) $es_valido_gif89a &= $debe_tener[$i]==$contenido[$i];

echo "valido gif89a = ";
var_dump($es_valido_gif89a);

$debe_tener[4] = ord ("7");
$es_valido_gif87a=true;
for($i=0;$i<count($contenido);$i++) $es_valido_gif87a &= $debe_tener[$i]==$contenido[$i];

echo "valido gif87a = ";
var_dump($es_valido_gif87a);

$debe_tener[4] = $es_valido_gif89a? ord("9"):ord("7");

$es_valido_gif=$es_valido_gif87a||$es_valido_gif89a;

echo "valido gif = ";

var_dump($es_valido_gif);
var_dump($contenido);
var_dump($debe_tener);


CitarGracias por la inútil información que ya tenía.

CitarJPEG
Syntax and structure
Start Of Image 0xFF, 0xD8   
End Of Image 0xFF, 0xD9

CitarGIF
File format
GIF files start with a fixed-length header ("GIF87a" or "GIF89a")

CitarPNG
Detalles técnicos
Un archivo PNG empieza con una firma de 8 bytes, los valores en hexadecimal son: 89 50 4E 47 0D 0A 1A 0A

NO es inútil ahí está todo solo con esa info hice eso...

CitarYa lo intenté, pero si probás por tus medios te das cuenta que eso sólo funciona con PNG's, bueno, en realidad probé con PNG y JPG, con GIF todavía no, dando como resultado que sólo me funciona para PNG's, los JPG no tienen los primeros bytes iguales, dependen de otros factores que desconozco.

ni leíste lo que decía en wiki -.-
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

extreme69

Pah, te la jugaste!!!

No era mi intención tampoco que me pases códigos, me gusta ir aprendiendo en el camino.

Ahora me pongo a revisarlo bien y a probarlo.

Gracias ;-)