return result;
}
+struct magic_entry {
+ unsigned char *magic;
+ size_t magic_size;
+ char *name;
+ unsigned char *mask;
+};
+
+static int
+test_magic(unsigned char *buffer, size_t length, struct magic_entry const *magic) {
+ int c;
+
+ if (length < magic->magic_size)
+ return 0;
+ if (magic->mask) {
+ int i;
+ unsigned char *bufp = buffer,
+ *maskp = magic->mask,
+ *magicp = magic->magic;
+ for (i = 0; i < magic->magic_size; ++i) {
+ int mask = *maskp == 'x' ? 0xFF : *maskp == ' ' ? 0 : *maskp;
+ ++maskp;
+
+ if ((*bufp++ & mask) != (*magicp++ & mask))
+ return 0;
+ }
+
+ return 1;
+ }
+ else {
+ return !memcmp(magic->magic, buffer, magic->magic_size);
+ }
+}
/*
=item i_test_format_probe(io_glue *data, int length)
#define FORMAT_ENTRY(magic, type) \
{ (unsigned char *)(magic ""), sizeof(magic)-1, type }
-
-struct magic_entry {
- unsigned char *magic;
- size_t magic_size;
- char *name;
-};
+#define FORMAT_ENTRY2(magic, type, mask) \
+ { (unsigned char *)(magic ""), sizeof(magic)-1, type, mask }
const char *
i_test_format_probe(io_glue *data, int length) {
- static struct magic_entry formats[] = {
+ static const struct magic_entry formats[] = {
FORMAT_ENTRY("\xFF\xD8", "jpeg"),
FORMAT_ENTRY("GIF87a", "gif"),
FORMAT_ENTRY("GIF89a", "gif"),
FORMAT_ENTRY("P4", "pnm"),
FORMAT_ENTRY("P5", "pnm"),
FORMAT_ENTRY("P6", "pnm"),
+ FORMAT_ENTRY("/* XPM", "xpm"),
+ FORMAT_ENTRY("\x8aMNG", "mng"),
+ FORMAT_ENTRY("\x8aJNG", "jng"),
+ /* SGI RGB - with various possible parameters to avoid false positives
+ on similar files
+ values are: 2 byte magic, rle flags (0 or 1), bytes/sample (1 or 2)
+ */
+ FORMAT_ENTRY("\x01\xDA\x00\x01", "rgb"),
+ FORMAT_ENTRY("\x01\xDA\x00\x02", "rgb"),
+ FORMAT_ENTRY("\x01\xDA\x01\x01", "rgb"),
+ FORMAT_ENTRY("\x01\xDA\x01\x02", "rgb"),
+
+ FORMAT_ENTRY2("FORM ILBM", "ilbm", "xxxx xxxx"),
+
+ /* different versions of PCX format
+ http://www.fileformat.info/format/pcx/
+ */
+ FORMAT_ENTRY("\x0A\x00\x01", "pcx"),
+ FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
+ FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
+ FORMAT_ENTRY("\x0A\x04\x01", "pcx"),
+ FORMAT_ENTRY("\x0A\x05\x01", "pcx"),
+
+ /* FITS - http://fits.gsfc.nasa.gov/ */
+ FORMAT_ENTRY("SIMPLE =", "fits"),
+
+ /* PSD - Photoshop */
+ FORMAT_ENTRY("8BPS\x00\x01", "psd"),
+
+ /* EPS - Encapsulated Postscript */
+ /* only reading 18 chars, so we don't include the F in EPSF */
+ FORMAT_ENTRY("%!PS-Adobe-2.0 EPS", "eps"),
};
- static struct magic_entry more_formats[] = {
+ static const struct magic_entry more_formats[] = {
FORMAT_ENTRY("\x00\x00\x01\x00", "ico"),
FORMAT_ENTRY("\x00\x00\x02\x00", "ico"), /* cursor */
};
data->seekcb(data, -rc, SEEK_CUR);
for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) {
- int c;
- if (rc < formats[i].magic_size)
- continue;
- c = !memcmp(formats[i].magic, head, formats[i].magic_size);
- if (c) {
- return formats[i].name;
- }
+ struct magic_entry const *entry = formats + i;
+
+ if (test_magic(head, rc, entry))
+ return entry->name;
}
if ((rc == 18) &&
return "tga";
for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) {
- int c;
- if (rc < more_formats[i].magic_size)
- continue;
- c = !memcmp(more_formats[i].magic, head, more_formats[i].magic_size);
- if (c) {
- return more_formats[i].name;
- }
+ struct magic_entry const *entry = more_formats + i;
+
+ if (test_magic(head, rc, entry))
+ return entry->name;
}
return NULL;
use strict;
use lib 't';
-use Test::More tests => 20;
+use Test::More tests => 27;
use Imager;
Imager::init_log("testout/t1000files.log", 1);
00 00 0E 03 00 00 28 00 00 00 20 00 00 00 40 00
ICO
+probe_ok(<<RGB, "rgb", "SGI RGB");
+01 DA 01 01 00 03 00 96 00 96 00 03 00 00 00 00
+00 00 00 FF 00 00 00 00 6E 6F 20 6E 61 6D 65 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+RGB
+
+probe_ok(<<ILBM, "ilbm", "ILBM");
+46 4F 52 4D 00 00 60 7A 49 4C 42 4D 42 4D 48 44
+00 00 00 14 00 96 00 96 00 00 00 00 18 00 01 80
+00 00 0A 0A 00 96 00 96 42 4F 44 59 00 00 60 51
+ILBM
+
+probe_ok(<<XPM, "xpm", "XPM");
+2F 2A 20 58 50 4D 20 2A 2F 0A 73 74 61 74 69 63
+20 63 68 61 72 20 2A 6E 6F 6E 61 6D 65 5B 5D 20
+3D 20 7B 0A 2F 2A 20 77 69 64 74 68 20 68 65 69
+XPM
+
+probe_ok(<<PCX, "pcx", 'PCX');
+0A 05 01 08 00 00 00 00 95 00 95 00 96 00 96 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCX
+
+probe_ok(<<FITS, "fits", "FITS");
+53 49 4D 50 4C 45 20 20 3D 20 20 20 20 20 20 20
+20 20 20 20 20 20 20 20 20 20 20 20 20 54 20 20
+20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+FITS
+
+probe_ok(<<PSD, "psd", "Photoshop");
+38 42 50 53 00 01 00 00 00 00 00 00 00 06 00 00
+00 3C 00 00 00 96 00 08 00 03 00 00 00 00 00 00
+0B E6 38 42 49 4D 03 ED 00 00 00 00 00 10 00 90
+PSD
+
+probe_ok(<<EPS, "eps", "Encapsulated Postscript");
+25 21 50 53 2D 41 64 6F 62 65 2D 32 2E 30 20 45
+50 53 46 2D 32 2E 30 0A 25 25 43 72 65 61 74 6F
+72 3A 20 70 6E 6D 74 6F 70 73 0A 25 25 54 69 74
+EPS
+
sub probe_ok {
my ($packed, $exp_type, $name) = @_;