MFH Update fileinfo to libmagic 5.00 and remove dependency on dirent.h on Windows

This commit is contained in:
Scott MacVicar 2009-03-15 23:04:19 +00:00
parent 716d2c9123
commit 7a29c8f386
27 changed files with 74680 additions and 68356 deletions

View File

@ -8,9 +8,10 @@ if test "$PHP_FILEINFO" != "no"; then
libmagic_sources=" \
libmagic/apprentice.c libmagic/apptype.c libmagic/ascmagic.c \
libmagic/compress.c libmagic/fsmagic.c libmagic/funcs.c \
libmagic/cdf.c libmagic/cdf_time.c libmagic/compress.c \
libmagic/encoding.c libmagic/fsmagic.c libmagic/funcs.c \
libmagic/is_tar.c libmagic/magic.c libmagic/print.c \
libmagic/readelf.c libmagic/softmagic.c"
libmagic/readcdf.c libmagic/readelf.c libmagic/softmagic.c"
PHP_NEW_EXTENSION(fileinfo, fileinfo.c $libmagic_sources, $ext_shared,,-I@ext_srcdir@/libmagic)
PHP_ADD_BUILD_DIR($ext_builddir/libmagic)

View File

@ -5,22 +5,16 @@ ARG_ENABLE("fileinfo", "fileinfo support", "no");
if (PHP_FILEINFO != 'no') {
if (CHECK_HEADER_ADD_INCLUDE("dirent.h", "CFLAGS_FILEINFO") &&
CHECK_LIB("dirent_a.lib", "fileinfo", PHP_FILEINFO)) {
LIBMAGIC_SOURCES=" apprentice.c apptype.c ascmagic.c \
cdf.c cdf_time.c compress.c \
encoding.c fsmagic.c funcs.c \
is_tar.c magic.c print.c \
readcdf.c readelf.c softmagic.c";
LIBMAGIC_SOURCES=" apprentice.c apptype.c ascmagic.c \
compress.c fsmagic.c funcs.c is_tar.c \
magic.c print.c \
readelf.c softmagic.c";
if (VCVERS <1500) {
ADD_FLAG('CFLAGS', '/Zm1000');
}
EXTENSION('fileinfo', 'fileinfo.c', true, "/I" + configure_module_dirname + "/libmagic /I" + configure_module_dirname);
ADD_SOURCES(configure_module_dirname + '\\libmagic', LIBMAGIC_SOURCES, "fileinfo");
} else {
WARNING("fileinfo not enabled; libraries and headers not found");
PHP_FILEINFO = "no";
if (VCVERS < 1500) {
ADD_FLAG('CFLAGS', '/Zm1000');
}
EXTENSION('fileinfo', 'fileinfo.c', null, "/I" + configure_module_dirname + "/libmagic /I" + configure_module_dirname);
ADD_SOURCES(configure_module_dirname + '\\libmagic', LIBMAGIC_SOURCES, "fileinfo");
}

File diff suppressed because it is too large Load Diff

View File

@ -229,6 +229,8 @@ PHP_MINIT_FUNCTION(finfo)
REGISTER_LONG_CONSTANT("FILEINFO_NONE", MAGIC_NONE, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("FILEINFO_SYMLINK", MAGIC_SYMLINK, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("FILEINFO_MIME", MAGIC_MIME, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("FILEINFO_MIME_TYPE", MAGIC_MIME_TYPE, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("FILEINFO_MIME_ENCODING",MAGIC_MIME_ENCODING, CONST_CS|CONST_PERSISTENT);
/* REGISTER_LONG_CONSTANT("FILEINFO_COMPRESS", MAGIC_COMPRESS, CONST_CS|CONST_PERSISTENT); disabled, as it does fork now */
REGISTER_LONG_CONSTANT("FILEINFO_DEVICES", MAGIC_DEVICES, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("FILEINFO_CONTINUE", MAGIC_CONTINUE, CONST_CS|CONST_PERSISTENT);

View File

@ -32,6 +32,11 @@
#include "php.h"
#include "file.h"
#ifndef lint
FILE_RCSID("@(#)$File: apprentice.c,v 1.132 2008/03/28 18:19:30 christos Exp $")
#endif /* lint */
#include "magic.h"
#include "patchlevel.h"
#include <stdlib.h>
@ -53,19 +58,10 @@
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/stat.h>
#ifndef PHP_WIN32
#include <sys/param.h>
#endif
#include <sys/types.h>
#ifndef PHP_WIN32
#include <dirent.h>
#endif
#ifndef lint
FILE_RCSID("@(#)$File: apprentice.c,v 1.132 2008/03/28 18:19:30 christos Exp $")
#endif /* lint */
#define EATAB {while (isascii((unsigned char) *l) && \
isspace((unsigned char) *l)) ++l;}
#define LOWCASE(l) (isupper((unsigned char) (l)) ? \
@ -120,7 +116,7 @@ private void bs1(struct magic *);
private uint16_t swap2(uint16_t);
private uint32_t swap4(uint32_t);
private uint64_t swap8(uint64_t);
private void mkdbname(const char *, char **, int);
private char *mkdbname(struct magic_set *, const char *, int);
private int apprentice_map(struct magic_set *, struct magic **, uint32_t *,
const char *);
private int apprentice_compile(struct magic_set *, struct magic **, uint32_t *,
@ -129,8 +125,8 @@ private int check_format_type(const char *, int);
private int check_format(struct magic_set *, struct magic *);
private int get_op(char);
private int parse_mime(struct magic_set *, struct magic_entry *, const char *);
private int parse_strength(struct magic_set *, struct magic_entry *,
const char *);
private int parse_strength(struct magic_set *, struct magic_entry *, const char *);
private int parse_apple(struct magic_set *, struct magic_entry *, const char *);
private size_t maxmagic = 0;
private size_t magicsize = sizeof(struct magic);
@ -143,6 +139,7 @@ private struct {
} bang[] = {
#define DECLARE_FIELD(name) { # name, sizeof(# name) - 1, parse_ ## name }
DECLARE_FIELD(mime),
DECLARE_FIELD(apple),
DECLARE_FIELD(strength),
#undef DECLARE_FIELD
{ NULL, 0, NULL }
@ -196,6 +193,9 @@ static const struct type_tbl_s {
{ XX("double"), FILE_DOUBLE, FILE_FMT_DOUBLE },
{ XX("bedouble"), FILE_BEDOUBLE, FILE_FMT_DOUBLE },
{ XX("ledouble"), FILE_LEDOUBLE, FILE_FMT_DOUBLE },
{ XX("leid3"), FILE_LEID3, FILE_FMT_NUM },
{ XX("beid3"), FILE_BEID3, FILE_FMT_NUM },
{ XX("indirect"), FILE_INDIRECT, FILE_FMT_NONE },
{ XX_NULL, FILE_INVALID, FILE_FMT_NONE },
# undef XX
# undef XX_NULL
@ -569,7 +569,8 @@ set_test_type(struct magic *mstart, struct magic *m)
case FILE_REGEX:
case FILE_SEARCH:
/* binary test if pattern is not text */
if (file_looks_utf8(m->value.us, m->vallen, NULL, NULL) <= 0)
if (file_looks_utf8(m->value.us, (size_t)m->vallen, NULL,
NULL) <= 0)
mstart->flag |= BINTEST;
break;
case FILE_DEFAULT:
@ -691,6 +692,8 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
(void)fprintf(stderr, "%s\n", usg_hdr);
/* load directory or file */
/* FIXME: Read file names and sort them to prevent
non-determinism. See Debian bug #488562. */
if (php_sys_stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
dir = opendir(fn);
if (dir) {
@ -850,6 +853,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
case FILE_REGEX:
case FILE_SEARCH:
case FILE_DEFAULT:
case FILE_INDIRECT:
break;
default:
if (ms->flags & MAGIC_CHECK) {
@ -1152,6 +1156,12 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
case 'G':
m->in_type = FILE_BEDOUBLE;
break;
case 'i':
m->in_type = FILE_LEID3;
break;
case 'I':
m->in_type = FILE_BEID3;
break;
default:
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms,
@ -1435,6 +1445,38 @@ out:
return -1;
}
/*
* Parse an Apple CREATOR/TYPE annotation from magic file and put it into magic[index - 1]
*/
private int
parse_apple(struct magic_set *ms, struct magic_entry *me, const char *line)
{
size_t i;
const char *l = line;
struct magic *m = &me->mp[me->cont_count == 0 ? 0 : me->cont_count - 1];
if (m->apple[0] != '\0') {
file_magwarn(ms, "Current entry already has a APPLE type `%.8s',"
" new type `%s'", m->mimetype, l);
return -1;
}
EATAB;
for (i = 0; *l && ((isascii((unsigned char)*l) && isalnum((unsigned char)*l))
|| strchr("-+/.", *l)) && i < sizeof(m->apple); m->apple[i++] = *l++)
continue;
if (i == sizeof(m->apple) && *l) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "APPLE type `%s' truncated %zu",
line, i);
}
if (i > 0)
return 0;
else
return -1;
}
/*
* parse a MIME annotation line from magic file, put into magic[index - 1]
* if valid
@ -1453,10 +1495,8 @@ parse_mime(struct magic_set *ms, struct magic_entry *me, const char *line)
}
EATAB;
for (i = 0;
*l && ((isascii((unsigned char)*l) && isalnum((unsigned char)*l))
|| strchr("-+/.", *l)) && i < sizeof(m->mimetype);
m->mimetype[i++] = *l++)
for (i = 0; *l && ((isascii((unsigned char)*l) && isalnum((unsigned char)*l))
|| strchr("-+/.", *l)) && i < sizeof(m->mimetype); m->mimetype[i++] = *l++)
continue;
if (i == sizeof(m->mimetype)) {
m->desc[sizeof(m->mimetype) - 1] = '\0';
@ -1990,7 +2030,7 @@ apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
goto internal_loaded;
}
mkdbname(fn, &dbname, 0);
dbname = mkdbname(ms, fn, 0);
if (dbname == NULL)
goto error2;
@ -2073,7 +2113,7 @@ internal_loaded:
}
if (dbname) {
efree(dbname);
free(dbname);
}
return ret;
@ -2090,7 +2130,7 @@ error1:
}
error2:
if (dbname) {
efree(dbname);
free(dbname);
}
return -1;
}
@ -2111,7 +2151,7 @@ apprentice_compile(struct magic_set *ms, struct magic **magicp,
TSRMLS_FETCH();
mkdbname(fn, &dbname, 1);
dbname = mkdbname(ms, fn, 0);
if (dbname == NULL) {
goto out;
@ -2148,7 +2188,7 @@ apprentice_compile(struct magic_set *ms, struct magic **magicp,
rv = 0;
out:
efree(dbname);
free(dbname);
return rv;
}
@ -2156,23 +2196,45 @@ private const char ext[] = ".mgc";
/*
* make a dbname
*/
private void
mkdbname(const char *fn, char **buf, int strip)
private char *
mkdbname(struct magic_set *ms, const char *fn, int strip)
{
const char *p;
const char *p, *q;
char *buf;
if (strip) {
if ((p = strrchr(fn, '/')) != NULL)
fn = ++p;
}
if ((p = strstr(fn, ext)) != NULL && p[sizeof(ext) - 1] == '\0')
*buf = strdup(fn);
else
(void)spprintf(buf, 0, "%s%s", fn, ext);
if (buf && *buf && strlen(*buf) > MAXPATHLEN) {
efree(*buf);
*buf = NULL;
for (q = fn; *q; q++)
continue;
/* Look for .mgc */
for (p = ext + sizeof(ext) - 1; p >= ext && q >= fn; p--, q--)
if (*p != *q)
break;
/* Did not find .mgc, restore q */
if (p >= ext)
while (*q)
q++;
q++;
/* Compatibility with old code that looked in .mime */
if (ms->flags & MAGIC_MIME) {
asprintf(&buf, "%.*s.mime%s", (int)(q - fn), fn, ext);
if (access(buf, R_OK) != -1) {
ms->flags &= MAGIC_MIME_TYPE;
return buf;
}
free(buf);
}
asprintf(&buf, "%.*s%s", (int)(q - fn), fn, ext);
/* Compatibility with old code that looked in .mime */
if (strstr(p, ".mime") != NULL)
ms->flags &= MAGIC_MIME_TYPE;
return buf;
}
/*

View File

@ -26,15 +26,14 @@
#include "file.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef lint
FILE_RCSID("@(#)$File: apptype.c,v 1.7 2007/01/12 17:38:27 christos Exp $")
#endif /* lint */
#include <stdlib.h>
#include <string.h>
#ifdef __EMX__
#include <io.h>
#define INCL_DOSSESMGR

View File

@ -31,14 +31,15 @@
*
* Extensively modified by Eric Fischer <enf@pobox.com> in July, 2000,
* to handle character codes other than ASCII on a unified basis.
*
* Joerg Wunsch <joerg@freebsd.org> wrote the original support for 8-bit
* international characters, now subsumed into this file.
*/
#include "file.h"
#ifndef lint
FILE_RCSID("@(#)$File: ascmagic.c,v 1.62 2008/03/01 22:21:48 rrt Exp $")
#endif /* lint */
#include "magic.h"
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <ctype.h>
@ -48,39 +49,71 @@
#endif
#include "names.h"
#ifndef lint
FILE_RCSID("@(#)$File: ascmagic.c,v 1.62 2008/03/01 22:21:48 rrt Exp $")
#endif /* lint */
#define MAXLINELEN 300 /* longest sane line length */
#define ISSPC(x) ((x) == ' ' || (x) == '\t' || (x) == '\r' || (x) == '\n' \
|| (x) == 0x85 || (x) == '\f')
private int looks_ascii(const unsigned char *, size_t, unichar *, size_t *);
private int looks_utf8_with_BOM(const unsigned char *, size_t, unichar *,
size_t *);
private int looks_ucs16(const unsigned char *, size_t, unichar *, size_t *);
private int looks_latin1(const unsigned char *, size_t, unichar *, size_t *);
private int looks_extended(const unsigned char *, size_t, unichar *, size_t *);
private void from_ebcdic(const unsigned char *, size_t, unsigned char *);
private int ascmatch(const unsigned char *, const unichar *, size_t);
private unsigned char *encode_utf8(unsigned char *, size_t, unichar *, size_t);
private size_t trim_nuls(const unsigned char *, size_t);
/*
* Undo the NUL-termination kindly provided by process()
* but leave at least one byte to look at
*/
private size_t
trim_nuls(const unsigned char *buf, size_t nbytes)
{
while (nbytes > 1 && buf[nbytes - 1] == '\0')
nbytes--;
return nbytes;
}
protected int
file_ascmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
{
size_t i;
unsigned char *nbuf = NULL, *utf8_buf = NULL, *utf8_end;
unichar *ubuf = NULL;
size_t ulen, mlen;
const struct names *p;
int rv = -1;
int mime = ms->flags & MAGIC_MIME;
size_t ulen;
int rv = 1;
const char *code = NULL;
const char *code_mime = NULL;
const char *type = NULL;
if (ms->flags & MAGIC_APPLE)
return 0;
nbytes = trim_nuls(buf, nbytes);
/* If file doesn't look like any sort of text, give up. */
if (file_encoding(ms, buf, nbytes, &ubuf, &ulen, &code, &code_mime,
&type) == 0) {
rv = 0;
goto done;
}
rv = file_ascmagic_with_encoding(ms, buf, nbytes, ubuf, ulen, code,
type);
done:
if (ubuf)
free(ubuf);
return rv;
}
protected int
file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf,
size_t nbytes, unichar *ubuf, size_t ulen, const char *code,
const char *type)
{
unsigned char *utf8_buf = NULL, *utf8_end;
size_t mlen, i;
const struct names *p;
int rv = -1;
int mime = ms->flags & MAGIC_MIME;
const char *subtype = NULL;
const char *subtype_mime = NULL;
@ -96,88 +129,30 @@ file_ascmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
size_t last_line_end = (size_t)-1;
int has_long_lines = 0;
/*
* Undo the NUL-termination kindly provided by process()
* but leave at least one byte to look at
*/
while (nbytes > 1 && buf[nbytes - 1] == '\0') {
nbytes--;
}
if (ms->flags & MAGIC_APPLE)
return 0;
nbuf = ecalloc(1, (nbytes + 1) * sizeof(nbuf[0]));
ubuf = ecalloc(1, (nbytes + 1) * sizeof(ubuf[0]));
/*
* Then try to determine whether it's any character code we can
* identify. Each of these tests, if it succeeds, will leave
* the text converted into one-unichar-per-character Unicode in
* ubuf, and the number of characters converted in ulen.
*/
if (looks_ascii(buf, nbytes, ubuf, &ulen)) {
code = "ASCII";
code_mime = "us-ascii";
type = "text";
} else if (looks_utf8_with_BOM(buf, nbytes, ubuf, &ulen) > 0) {
code = "UTF-8 Unicode (with BOM)";
code_mime = "utf-8";
type = "text";
} else if (file_looks_utf8(buf, nbytes, ubuf, &ulen) > 1) {
code = "UTF-8 Unicode";
code_mime = "utf-8";
type = "text";
} else if ((i = looks_ucs16(buf, nbytes, ubuf, &ulen)) != 0) {
if (i == 1)
code = "Little-endian UTF-16 Unicode";
else
code = "Big-endian UTF-16 Unicode";
type = "character data";
code_mime = "utf-16"; /* is this defined? */
} else if (looks_latin1(buf, nbytes, ubuf, &ulen)) {
code = "ISO-8859";
type = "text";
code_mime = "iso-8859-1";
} else if (looks_extended(buf, nbytes, ubuf, &ulen)) {
code = "Non-ISO extended-ASCII";
type = "text";
code_mime = "unknown";
} else {
from_ebcdic(buf, nbytes, nbuf);
if (looks_ascii(nbuf, nbytes, ubuf, &ulen)) {
code = "EBCDIC";
type = "character data";
code_mime = "ebcdic";
} else if (looks_latin1(nbuf, nbytes, ubuf, &ulen)) {
code = "International EBCDIC";
type = "character data";
code_mime = "ebcdic";
} else {
rv = 0;
goto done; /* doesn't look like text at all */
}
}
nbytes = trim_nuls(buf, nbytes);
/* If we have fewer than 2 bytes, give up. */
if (nbytes <= 1) {
rv = 0;
goto done;
}
/* Convert ubuf to UTF-8 and try text soft magic */
/* If original was ASCII or UTF-8, could use nbuf instead of
re-converting. */
/* malloc size is a conservative overestimate; could be
re-converting improved, or at least realloced after
re-converting conversion. */
improved, or at least realloced after conversion. */
mlen = ulen * 6;
utf8_buf = emalloc(mlen);
if ((utf8_end = encode_utf8(utf8_buf, mlen, ubuf, ulen)) == NULL)
goto done;
if (file_softmagic(ms, utf8_buf, utf8_end - utf8_buf, TEXTTEST) != 0) {
rv = 1;
if ((rv = file_softmagic(ms, utf8_buf, (size_t)(utf8_end - utf8_buf),
TEXTTEST)) != 0)
goto done;
}
else
rv = -1;
/* look for tokens from names.h - this is expensive! */
if ((ms->flags & MAGIC_NO_CHECK_TOKENS) != 0)
@ -250,41 +225,30 @@ subtype_identified:
if (seen_cr && nbytes < HOWMANY)
n_cr++;
if (strcmp(type, "binary") == 0) {
rv = 0;
goto done;
}
if (mime) {
if (mime & MAGIC_MIME_TYPE) {
if ((mime & MAGIC_MIME_TYPE) != 0) {
if (subtype_mime) {
if (file_printf(ms, subtype_mime) == -1)
if (file_printf(ms, "%s", subtype_mime) == -1)
goto done;
} else {
if (file_printf(ms, "text/plain") == -1)
goto done;
}
}
if ((mime == 0 || mime == MAGIC_MIME) && code_mime) {
if ((mime & MAGIC_MIME_TYPE) &&
file_printf(ms, "; charset=") == -1)
goto done;
if (file_printf(ms, code_mime) == -1)
goto done;
}
if (mime == MAGIC_MIME_ENCODING)
file_printf(ms, "binary");
} else {
if (file_printf(ms, code) == -1)
if (file_printf(ms, "%s", code) == -1)
goto done;
if (subtype) {
if (file_printf(ms, " ") == -1)
goto done;
if (file_printf(ms, subtype) == -1)
if (file_printf(ms, " %s", subtype) == -1)
goto done;
}
if (file_printf(ms, " ") == -1)
goto done;
if (file_printf(ms, type) == -1)
if (file_printf(ms, " %s", type) == -1)
goto done;
if (has_long_lines)
@ -343,10 +307,6 @@ subtype_identified:
}
rv = 1;
done:
if (nbuf)
efree(nbuf);
if (ubuf)
efree(ubuf);
if (utf8_buf)
efree(utf8_buf);
@ -369,144 +329,6 @@ ascmatch(const unsigned char *s, const unichar *us, size_t ulen)
return 1;
}
/*
* This table reflects a particular philosophy about what constitutes
* "text," and there is room for disagreement about it.
*
* Version 3.31 of the file command considered a file to be ASCII if
* each of its characters was approved by either the isascii() or
* isalpha() function. On most systems, this would mean that any
* file consisting only of characters in the range 0x00 ... 0x7F
* would be called ASCII text, but many systems might reasonably
* consider some characters outside this range to be alphabetic,
* so the file command would call such characters ASCII. It might
* have been more accurate to call this "considered textual on the
* local system" than "ASCII."
*
* It considered a file to be "International language text" if each
* of its characters was either an ASCII printing character (according
* to the real ASCII standard, not the above test), a character in
* the range 0x80 ... 0xFF, or one of the following control characters:
* backspace, tab, line feed, vertical tab, form feed, carriage return,
* escape. No attempt was made to determine the language in which files
* of this type were written.
*
*
* The table below considers a file to be ASCII if all of its characters
* are either ASCII printing characters (again, according to the X3.4
* standard, not isascii()) or any of the following controls: bell,
* backspace, tab, line feed, form feed, carriage return, esc, nextline.
*
* I include bell because some programs (particularly shell scripts)
* use it literally, even though it is rare in normal text. I exclude
* vertical tab because it never seems to be used in real text. I also
* include, with hesitation, the X3.64/ECMA-43 control nextline (0x85),
* because that's what the dd EBCDIC->ASCII table maps the EBCDIC newline
* character to. It might be more appropriate to include it in the 8859
* set instead of the ASCII set, but it's got to be included in *something*
* we recognize or EBCDIC files aren't going to be considered textual.
* Some old Unix source files use SO/SI (^N/^O) to shift between Greek
* and Latin characters, so these should possibly be allowed. But they
* make a real mess on VT100-style displays if they're not paired properly,
* so we are probably better off not calling them text.
*
* A file is considered to be ISO-8859 text if its characters are all
* either ASCII, according to the above definition, or printing characters
* from the ISO-8859 8-bit extension, characters 0xA0 ... 0xFF.
*
* Finally, a file is considered to be international text from some other
* character code if its characters are all either ISO-8859 (according to
* the above definition) or characters in the range 0x80 ... 0x9F, which
* ISO-8859 considers to be control characters but the IBM PC and Macintosh
* consider to be printing characters.
*/
#define F 0 /* character never appears in text */
#define T 1 /* character appears in plain ASCII text */
#define I 2 /* character appears in ISO-8859 text */
#define X 3 /* character appears in non-ISO extended ASCII (Mac, IBM PC) */
private char text_chars[256] = {
/* BEL BS HT LF FF CR */
F, F, F, F, F, F, F, T, T, T, T, F, T, T, F, F, /* 0x0X */
/* ESC */
F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F, /* 0x1X */
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x2X */
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x3X */
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x4X */
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x5X */
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x6X */
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, /* 0x7X */
/* NEL */
X, X, X, X, X, T, X, X, X, X, X, X, X, X, X, X, /* 0x8X */
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 0x9X */
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xaX */
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xbX */
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xcX */
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xdX */
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xeX */
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I /* 0xfX */
};
private int
looks_ascii(const unsigned char *buf, size_t nbytes, unichar *ubuf,
size_t *ulen)
{
size_t i;
*ulen = 0;
for (i = 0; i < nbytes; i++) {
int t = text_chars[buf[i]];
if (t != T)
return 0;
ubuf[(*ulen)++] = buf[i];
}
return 1;
}
private int
looks_latin1(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen)
{
size_t i;
*ulen = 0;
for (i = 0; i < nbytes; i++) {
int t = text_chars[buf[i]];
if (t != T && t != I)
return 0;
ubuf[(*ulen)++] = buf[i];
}
return 1;
}
private int
looks_extended(const unsigned char *buf, size_t nbytes, unichar *ubuf,
size_t *ulen)
{
size_t i;
*ulen = 0;
for (i = 0; i < nbytes; i++) {
int t = text_chars[buf[i]];
if (t != T && t != I && t != X)
return 0;
ubuf[(*ulen)++] = buf[i];
}
return 1;
}
/*
* Encode Unicode string as UTF-8, returning pointer to character
* after end of string, or NULL if an invalid character is found.
@ -563,226 +385,3 @@ encode_utf8(unsigned char *buf, size_t len, unichar *ubuf, size_t ulen)
return buf;
}
/*
* Decide whether some text looks like UTF-8. Returns:
*
* -1: invalid UTF-8
* 0: uses odd control characters, so doesn't look like text
* 1: 7-bit text
* 2: definitely UTF-8 text (valid high-bit set bytes)
*
* If ubuf is non-NULL on entry, text is decoded into ubuf, *ulen;
* ubuf must be big enough!
*/
protected int
file_looks_utf8(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen)
{
size_t i;
int n;
unichar c;
int gotone = 0, ctrl = 0;
if (ubuf)
*ulen = 0;
for (i = 0; i < nbytes; i++) {
if ((buf[i] & 0x80) == 0) { /* 0xxxxxxx is plain ASCII */
/*
* Even if the whole file is valid UTF-8 sequences,
* still reject it if it uses weird control characters.
*/
if (text_chars[buf[i]] != T)
ctrl = 1;
if (ubuf)
ubuf[(*ulen)++] = buf[i];
} else if ((buf[i] & 0x40) == 0) { /* 10xxxxxx never 1st byte */
return -1;
} else { /* 11xxxxxx begins UTF-8 */
int following;
if ((buf[i] & 0x20) == 0) { /* 110xxxxx */
c = buf[i] & 0x1f;
following = 1;
} else if ((buf[i] & 0x10) == 0) { /* 1110xxxx */
c = buf[i] & 0x0f;
following = 2;
} else if ((buf[i] & 0x08) == 0) { /* 11110xxx */
c = buf[i] & 0x07;
following = 3;
} else if ((buf[i] & 0x04) == 0) { /* 111110xx */
c = buf[i] & 0x03;
following = 4;
} else if ((buf[i] & 0x02) == 0) { /* 1111110x */
c = buf[i] & 0x01;
following = 5;
} else
return -1;
for (n = 0; n < following; n++) {
i++;
if (i >= nbytes)
goto done;
if ((buf[i] & 0x80) == 0 || (buf[i] & 0x40))
return -1;
c = (c << 6) + (buf[i] & 0x3f);
}
if (ubuf)
ubuf[(*ulen)++] = c;
gotone = 1;
}
}
done:
return ctrl ? 0 : (gotone ? 2 : 1);
}
/*
* Decide whether some text looks like UTF-8 with BOM. If there is no
* BOM, return -1; otherwise return the result of looks_utf8 on the
* rest of the text.
*/
private int
looks_utf8_with_BOM(const unsigned char *buf, size_t nbytes, unichar *ubuf,
size_t *ulen)
{
if (nbytes > 3 && buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf)
return file_looks_utf8(buf + 3, nbytes - 3, ubuf, ulen);
else
return -1;
}
private int
looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf,
size_t *ulen)
{
int bigend;
size_t i;
if (nbytes < 2)
return 0;
if (buf[0] == 0xff && buf[1] == 0xfe)
bigend = 0;
else if (buf[0] == 0xfe && buf[1] == 0xff)
bigend = 1;
else
return 0;
*ulen = 0;
for (i = 2; i + 1 < nbytes; i += 2) {
/* XXX fix to properly handle chars > 65536 */
if (bigend)
ubuf[(*ulen)++] = buf[i + 1] + 256 * buf[i];
else
ubuf[(*ulen)++] = buf[i] + 256 * buf[i + 1];
if (ubuf[*ulen - 1] == 0xfffe)
return 0;
if (ubuf[*ulen - 1] < 128 &&
text_chars[(size_t)ubuf[*ulen - 1]] != T)
return 0;
}
return 1 + bigend;
}
#undef F
#undef T
#undef I
#undef X
/*
* This table maps each EBCDIC character to an (8-bit extended) ASCII
* character, as specified in the rationale for the dd(1) command in
* draft 11.2 (September, 1991) of the POSIX P1003.2 standard.
*
* Unfortunately it does not seem to correspond exactly to any of the
* five variants of EBCDIC documented in IBM's _Enterprise Systems
* Architecture/390: Principles of Operation_, SA22-7201-06, Seventh
* Edition, July, 1999, pp. I-1 - I-4.
*
* Fortunately, though, all versions of EBCDIC, including this one, agree
* on most of the printing characters that also appear in (7-bit) ASCII.
* Of these, only '|', '!', '~', '^', '[', and ']' are in question at all.
*
* Fortunately too, there is general agreement that codes 0x00 through
* 0x3F represent control characters, 0x41 a nonbreaking space, and the
* remainder printing characters.
*
* This is sufficient to allow us to identify EBCDIC text and to distinguish
* between old-style and internationalized examples of text.
*/
private unsigned char ebcdic_to_ascii[] = {
0, 1, 2, 3, 156, 9, 134, 127, 151, 141, 142, 11, 12, 13, 14, 15,
16, 17, 18, 19, 157, 133, 8, 135, 24, 25, 146, 143, 28, 29, 30, 31,
128, 129, 130, 131, 132, 10, 23, 27, 136, 137, 138, 139, 140, 5, 6, 7,
144, 145, 22, 147, 148, 149, 150, 4, 152, 153, 154, 155, 20, 21, 158, 26,
' ', 160, 161, 162, 163, 164, 165, 166, 167, 168, 213, '.', '<', '(', '+', '|',
'&', 169, 170, 171, 172, 173, 174, 175, 176, 177, '!', '$', '*', ')', ';', '~',
'-', '/', 178, 179, 180, 181, 182, 183, 184, 185, 203, ',', '%', '_', '>', '?',
186, 187, 188, 189, 190, 191, 192, 193, 194, '`', ':', '#', '@', '\'','=', '"',
195, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 196, 197, 198, 199, 200, 201,
202, 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', '^', 204, 205, 206, 207, 208,
209, 229, 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 210, 211, 212, '[', 214, 215,
216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, ']', 230, 231,
'{', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 232, 233, 234, 235, 236, 237,
'}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 238, 239, 240, 241, 242, 243,
'\\',159, 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 244, 245, 246, 247, 248, 249,
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 250, 251, 252, 253, 254, 255
};
#ifdef notdef
/*
* The following EBCDIC-to-ASCII table may relate more closely to reality,
* or at least to modern reality. It comes from
*
* http://ftp.s390.ibm.com/products/oe/bpxqp9.html
*
* and maps the characters of EBCDIC code page 1047 (the code used for
* Unix-derived software on IBM's 390 systems) to the corresponding
* characters from ISO 8859-1.
*
* If this table is used instead of the above one, some of the special
* cases for the NEL character can be taken out of the code.
*/
private unsigned char ebcdic_1047_to_8859[] = {
0x00,0x01,0x02,0x03,0x9C,0x09,0x86,0x7F,0x97,0x8D,0x8E,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x9D,0x0A,0x08,0x87,0x18,0x19,0x92,0x8F,0x1C,0x1D,0x1E,0x1F,
0x80,0x81,0x82,0x83,0x84,0x85,0x17,0x1B,0x88,0x89,0x8A,0x8B,0x8C,0x05,0x06,0x07,
0x90,0x91,0x16,0x93,0x94,0x95,0x96,0x04,0x98,0x99,0x9A,0x9B,0x14,0x15,0x9E,0x1A,
0x20,0xA0,0xE2,0xE4,0xE0,0xE1,0xE3,0xE5,0xE7,0xF1,0xA2,0x2E,0x3C,0x28,0x2B,0x7C,
0x26,0xE9,0xEA,0xEB,0xE8,0xED,0xEE,0xEF,0xEC,0xDF,0x21,0x24,0x2A,0x29,0x3B,0x5E,
0x2D,0x2F,0xC2,0xC4,0xC0,0xC1,0xC3,0xC5,0xC7,0xD1,0xA6,0x2C,0x25,0x5F,0x3E,0x3F,
0xF8,0xC9,0xCA,0xCB,0xC8,0xCD,0xCE,0xCF,0xCC,0x60,0x3A,0x23,0x40,0x27,0x3D,0x22,
0xD8,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0xAB,0xBB,0xF0,0xFD,0xFE,0xB1,
0xB0,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0xAA,0xBA,0xE6,0xB8,0xC6,0xA4,
0xB5,0x7E,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0xA1,0xBF,0xD0,0x5B,0xDE,0xAE,
0xAC,0xA3,0xA5,0xB7,0xA9,0xA7,0xB6,0xBC,0xBD,0xBE,0xDD,0xA8,0xAF,0x5D,0xB4,0xD7,
0x7B,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0xAD,0xF4,0xF6,0xF2,0xF3,0xF5,
0x7D,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0xB9,0xFB,0xFC,0xF9,0xFA,0xFF,
0x5C,0xF7,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0xB2,0xD4,0xD6,0xD2,0xD3,0xD5,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xB3,0xDB,0xDC,0xD9,0xDA,0x9F
};
#endif
/*
* Copy buf[0 ... nbytes-1] into out[], translating EBCDIC to ASCII.
*/
private void
from_ebcdic(const unsigned char *buf, size_t nbytes, unsigned char *out)
{
size_t i;
for (i = 0; i < nbytes; i++) {
out[i] = ebcdic_to_ascii[buf[i]];
}
}

1111
ext/fileinfo/libmagic/cdf.c Normal file

File diff suppressed because it is too large Load Diff

298
ext/fileinfo/libmagic/cdf.h Normal file
View File

@ -0,0 +1,298 @@
/*-
* Copyright (c) 2008 Christos Zoulas
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Info from: http://sc.openoffice.org/compdocfileformat.pdf
*/
#ifndef _H_CDF_
#define _H_CDF_
typedef int32_t cdf_secid_t;
#define CDF_LOOP_LIMIT 10000
#define CDF_SECID_NULL 0
#define CDF_SECID_FREE -1
#define CDF_SECID_END_OF_CHAIN -2
#define CDF_SECID_SECTOR_ALLOCATION_TABLE -3
#define CDF_SECID_MASTER_SECTOR_ALLOCATION_TABLE -4
typedef struct {
uint64_t h_magic;
#define CDF_MAGIC 0xE11AB1A1E011CFD0LL
uint64_t h_uuid[2];
uint16_t h_revision;
uint16_t h_version;
uint16_t h_byte_order;
uint16_t h_sec_size_p2;
uint16_t h_short_sec_size_p2;
uint8_t h_unused0[10];
uint32_t h_num_sectors_in_sat;
uint32_t h_secid_first_directory;
uint8_t h_unused1[4];
uint32_t h_min_size_standard_stream;
cdf_secid_t h_secid_first_sector_in_short_sat;
uint32_t h_num_sectors_in_short_sat;
cdf_secid_t h_secid_first_sector_in_master_sat;
uint32_t h_num_sectors_in_master_sat;
cdf_secid_t h_master_sat[436/4];
} cdf_header_t;
#define CDF_SEC_SIZE(h) (1 << (h)->h_sec_size_p2)
#define CDF_SEC_POS(h, secid) (CDF_SEC_SIZE(h) + (secid) * CDF_SEC_SIZE(h))
#define CDF_SHORT_SEC_SIZE(h) (1 << (h)->h_short_sec_size_p2)
#define CDF_SHORT_SEC_POS(h, secid) ((secid) * CDF_SHORT_SEC_SIZE(h))
typedef int32_t cdf_dirid_t;
#define CDF_DIRID_NULL -1
typedef int64_t cdf_timestamp_t;
#define CDF_BASE_YEAR 1601
#define CDF_TIME_PREC 10000000
typedef struct {
uint16_t d_name[32];
uint16_t d_namelen;
uint8_t d_type;
#define CDF_DIR_TYPE_EMPTY 0
#define CDF_DIR_TYPE_USER_STORAGE 1
#define CDF_DIR_TYPE_USER_STREAM 2
#define CDF_DIR_TYPE_LOCKBYTES 3
#define CDF_DIR_TYPE_PROPERTY 4
#define CDF_DIR_TYPE_ROOT_STORAGE 5
uint8_t d_color;
#define CDF_DIR_COLOR_READ 0
#define CDF_DIR_COLOR_BLACK 1
cdf_dirid_t d_left_child;
cdf_dirid_t d_right_child;
cdf_dirid_t d_storage;
uint64_t d_storage_uuid[2];
uint32_t d_flags;
cdf_timestamp_t d_created;
cdf_timestamp_t d_modified;
cdf_secid_t d_stream_first_sector;
uint32_t d_size;
uint32_t d_unused0;
} cdf_directory_t;
#define CDF_DIRECTORY_SIZE 128
typedef struct {
cdf_secid_t *sat_tab;
size_t sat_len;
} cdf_sat_t;
typedef struct {
cdf_directory_t *dir_tab;
size_t dir_len;
} cdf_dir_t;
typedef struct {
void *sst_tab;
size_t sst_len;
size_t sst_dirlen;
} cdf_stream_t;
typedef struct {
uint32_t cl_dword;
uint16_t cl_word[2];
uint8_t cl_two[2];
uint8_t cl_six[6];
} cdf_classid_t;
typedef struct {
uint16_t si_byte_order;
uint16_t si_zero;
uint16_t si_os_version;
uint16_t si_os;
cdf_classid_t si_class;
uint32_t si_count;
} cdf_summary_info_header_t;
#define CDF_SECTION_DECLARATION_OFFSET 0x1c
typedef struct {
cdf_classid_t sd_class;
uint32_t sd_offset;
} cdf_section_declaration_t;
typedef struct {
uint32_t sh_len;
uint32_t sh_properties;
} cdf_section_header_t;
typedef struct {
uint32_t pi_id;
uint32_t pi_type;
union {
uint16_t _pi_u16;
int16_t _pi_s16;
uint32_t _pi_u32;
int32_t _pi_s32;
uint64_t _pi_u64;
int64_t _pi_s64;
cdf_timestamp_t _pi_tp;
struct {
uint32_t s_len;
const char *s_buf;
} _pi_str;
} pi_val;
#define pi_u64 pi_val._pi_u64
#define pi_s64 pi_val._pi_s64
#define pi_u32 pi_val._pi_u32
#define pi_s32 pi_val._pi_s32
#define pi_u16 pi_val._pi_u16
#define pi_s16 pi_val._pi_s16
#define pi_tp pi_val._pi_tp
#define pi_str pi_val._pi_str
} cdf_property_info_t;
#define CDF_ROUND(val, by) (((val) + (by) - 1) & ~((by) - 1))
/* Variant type definitions */
#define CDF_EMPTY 0x00000000
#define CDF_NULL 0x00000001
#define CDF_SIGNED16 0x00000002
#define CDF_SIGNED32 0x00000003
#define CDF_FLOAT 0x00000004
#define CDF_DOUBLE 0x00000005
#define CDF_CY 0x00000006
#define CDF_DATE 0x00000007
#define CDF_BSTR 0x00000008
#define CDF_DISPATCH 0x00000009
#define CDF_ERROR 0x0000000a
#define CDF_BOOL 0x0000000b
#define CDF_VARIANT 0x0000000c
#define CDF_UNKNOWN 0x0000000d
#define CDF_DECIMAL 0x0000000e
#define CDF_SIGNED8 0x00000010
#define CDF_UNSIGNED8 0x00000011
#define CDF_UNSIGNED16 0x00000012
#define CDF_UNSIGNED32 0x00000013
#define CDF_SIGNED64 0x00000014
#define CDF_UNSIGNED64 0x00000015
#define CDF_INT 0x00000016
#define CDF_UINT 0x00000017
#define CDF_VOID 0x00000018
#define CDF_HRESULT 0x00000019
#define CDF_PTR 0x0000001a
#define CDF_SAFEARRAY 0x0000001b
#define CDF_CARRAY 0x0000001c
#define CDF_USERDEFINED 0x0000001d
#define CDF_LENGTH32_STRING 0x0000001e
#define CDF_LENGTH32_WSTRING 0x0000001f
#define CDF_FILETIME 0x00000040
#define CDF_BLOB 0x00000041
#define CDF_STREAM 0x00000042
#define CDF_STORAGE 0x00000043
#define CDF_STREAMED_OBJECT 0x00000044
#define CDF_STORED_OBJECT 0x00000045
#define CDF_BLOB_OBJECT 0x00000046
#define CDF_CLIPBOARD 0x00000047
#define CDF_CLSID 0x00000048
#define CDF_VECTOR 0x00001000
#define CDF_ARRAY 0x00002000
#define CDF_BYREF 0x00004000
#define CDF_RESERVED 0x00008000
#define CDF_ILLEGAL 0x0000ffff
#define CDF_ILLEGALMASKED 0x00000fff
#define CDF_TYPEMASK 0x00000fff
#define CDF_PROPERTY_CODE_PAGE 0x00000001
#define CDF_PROPERTY_TITLE 0x00000002
#define CDF_PROPERTY_SUBJECT 0x00000003
#define CDF_PROPERTY_AUTHOR 0x00000004
#define CDF_PROPERTY_KEYWORDS 0x00000005
#define CDF_PROPERTY_COMMENTS 0x00000006
#define CDF_PROPERTY_TEMPLATE 0x00000007
#define CDF_PROPERTY_LAST_SAVED_BY 0x00000008
#define CDF_PROPERTY_REVISION_NUMBER 0x00000009
#define CDF_PROPERTY_TOTAL_EDITING_TIME 0x0000000a
#define CDF_PROPERTY_LAST_PRINTED 0X0000000b
#define CDF_PROPERTY_CREATE_TIME 0x0000000c
#define CDF_PROPERTY_LAST_SAVED_TIME 0x0000000d
#define CDF_PROPERTY_NUMBER_OF_PAGES 0x0000000e
#define CDF_PROPERTY_NUMBER_OF_WORDS 0x0000000f
#define CDF_PROPERTY_NUMBER_OF_CHARACTERS 0x00000010
#define CDF_PROPERTY_THUMBNAIL 0x00000011
#define CDF_PROPERTY_NAME_OF_APPLICATION 0x00000012
#define CDF_PROPERTY_SECURITY 0x00000013
#define CDF_PROPERTY_LOCALE_ID 0x80000000
struct timeval;
int cdf_timestamp_to_timespec(struct timeval *, cdf_timestamp_t);
int cdf_timespec_to_timestamp(cdf_timestamp_t *, const struct timeval *);
int cdf_read_header(int, cdf_header_t *);
void cdf_swap_header(cdf_header_t *);
void cdf_unpack_header(cdf_header_t *, char *);
void cdf_swap_dir(cdf_directory_t *);
void cdf_unpack_dir(cdf_directory_t *, char *);
void cdf_swap_class(cdf_classid_t *);
ssize_t cdf_read_sector(int, void *, size_t, size_t, const cdf_header_t *,
cdf_secid_t);
ssize_t cdf_read_short_sector(const cdf_stream_t *, void *, size_t, size_t,
const cdf_header_t *, cdf_secid_t);
int cdf_read_sat(int, cdf_header_t *, cdf_sat_t *);
size_t cdf_count_chain(const cdf_header_t *, const cdf_sat_t *,
cdf_secid_t);
int cdf_read_long_sector_chain(int, const cdf_header_t *,
const cdf_sat_t *, cdf_secid_t, size_t, cdf_stream_t *);
int cdf_read_short_sector_chain(const cdf_header_t *, const cdf_sat_t *,
const cdf_stream_t *, cdf_secid_t, size_t, cdf_stream_t *);
int cdf_read_sector_chain(int, const cdf_header_t *,
const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *, cdf_secid_t,
size_t, cdf_stream_t *);
int cdf_read_dir(int, const cdf_header_t *, const cdf_sat_t *, cdf_dir_t *);
int cdf_read_ssat(int, const cdf_header_t *, const cdf_sat_t *, cdf_sat_t *);
int cdf_read_short_stream(int, const cdf_header_t *, const cdf_sat_t *,
const cdf_dir_t *, cdf_stream_t *);
int cdf_read_property_info(const cdf_stream_t *, uint32_t,
cdf_property_info_t **, size_t *, size_t *);
int cdf_read_summary_info(int, const cdf_header_t *, const cdf_sat_t *,
const cdf_sat_t *, const cdf_stream_t *, const cdf_dir_t *,
cdf_stream_t *);
int cdf_unpack_summary_info(const cdf_stream_t *, cdf_summary_info_header_t *,
cdf_property_info_t **, size_t *);
int cdf_print_classid(char *, size_t, const cdf_classid_t *);
int cdf_print_property_name(char *, size_t, uint32_t);
int cdf_print_elapsed_time(char *, size_t, cdf_timestamp_t);
uint16_t cdf_tole2(uint16_t);
uint32_t cdf_tole4(uint32_t);
uint64_t cdf_tole8(uint64_t);
#ifdef CDF_DEBUG
void cdf_dump_header(const cdf_header_t *);
void cdf_dump_sat(const char *, const cdf_header_t *, const cdf_sat_t *);
void cdf_dump(void *, size_t);
void cdf_dump_stream(const cdf_header_t *, const cdf_stream_t *);
void cdf_dump_dir(int, const cdf_header_t *, const cdf_sat_t *,
const cdf_sat_t *, const cdf_stream_t *, const cdf_dir_t *);
void cdf_dump_property_info(const cdf_property_info_t *, size_t);
void cdf_dump_summary_info(const cdf_header_t *, const cdf_stream_t *);
#endif
#endif /* _H_CDF_ */

View File

@ -0,0 +1,183 @@
/*-
* Copyright (c) 2008 Christos Zoulas
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "file.h"
#ifndef lint
FILE_RCSID("@(#)$File: cdf_time.c,v 1.5 2009/02/03 20:27:51 christos Exp $")
#endif
#include <time.h>
#ifdef TEST
#include <err.h>
#endif
#include <string.h>
#include "cdf.h"
#define isleap(y) ((((y) % 4) == 0) && \
((((y) % 100) != 0) || (((y) % 400) == 0)))
static const int mdays[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
/*
* Return the number of days between jan 01 1601 and jan 01 of year.
*/
static int
cdf_getdays(int year)
{
int days = 0;
int y;
for (y = CDF_BASE_YEAR; y < year; y++)
days += isleap(y) + 365;
return days;
}
/*
* Return the day within the month
*/
static int
cdf_getday(int year, int days)
{
size_t m;
for (m = 0; m < sizeof(mdays) / sizeof(mdays[0]); m++) {
int sub = mdays[m] + (m == 1 && isleap(year));
if (days < sub)
return days;
days -= sub;
}
return days;
}
/*
* Return the 0...11 month number.
*/
static int
cdf_getmonth(int year, int days)
{
size_t m;
for (m = 0; m < sizeof(mdays) / sizeof(mdays[0]); m++) {
days -= mdays[m];
if (m == 1 && isleap(year))
days--;
if (days <= 0)
return (int)m;
}
return (int)m;
}
int
cdf_timestamp_to_timespec(struct timeval *ts, cdf_timestamp_t t)
{
struct tm tm;
#ifdef HAVE_STRUCT_TM_TM_ZONE
static char UTC[] = "UTC";
#endif
int rdays;
/* Unit is 100's of nanoseconds */
ts->tv_usec = (t % CDF_TIME_PREC) * 1000000;
t /= CDF_TIME_PREC;
tm.tm_sec = t % 60;
t /= 60;
tm.tm_min = t % 60;
t /= 60;
tm.tm_hour = t % 24;
t /= 24;
// XXX: Approx
tm.tm_year = CDF_BASE_YEAR + (t / 365);
rdays = cdf_getdays(tm.tm_year);
t -= rdays;
tm.tm_mday = cdf_getday(tm.tm_year, t);
tm.tm_mon = cdf_getmonth(tm.tm_year, t);
tm.tm_wday = 0;
tm.tm_yday = 0;
tm.tm_isdst = 0;
#ifdef HAVE_STRUCT_TM_TM_GMTOFF
tm.tm_gmtoff = 0;
#endif
#ifdef HAVE_STRUCT_TM_TM_ZONE
tm.tm_zone = UTC;
#endif
tm.tm_year -= 1900;
ts->tv_sec = mktime(&tm);
if (ts->tv_sec == -1) {
errno = EINVAL;
return -1;
}
return 0;
}
int
cdf_timespec_to_timestamp(cdf_timestamp_t *t, const struct timeval *ts)
{
(void)&t;
(void)&ts;
#ifdef notyet
struct tm tm;
if (gmtime_r(&ts->ts_sec, &tm) == NULL) {
errno = EINVAL;
return -1;
}
*t = (ts->ts_usec / 1000000) * CDF_TIME_PREC;
*t = tm.tm_sec;
*t += tm.tm_min * 60;
*t += tm.tm_hour * 60 * 60;
*t += tm.tm_mday * 60 * 60 * 24;
#endif
return 0;
}
#ifdef TEST
int
main(int argc, char *argv[])
{
struct timeval ts;
static const cdf_timestamp_t tst = 0x01A5E403C2D59C00ULL;
static const char *ref = "Sat Apr 23 01:30:00 1977";
char *p, *q;
cdf_timestamp_to_timespec(&ts, tst);
p = ctime(&ts.tv_sec);
if ((q = strchr(p, '\n')) != NULL)
*q = '\0';
if (strcmp(ref, p) != 0)
errx(1, "Error date %s != %s\n", ref, p);
return 0;
}
#endif

View File

@ -35,8 +35,12 @@
#include "config.h"
#include "file.h"
#ifndef lint
FILE_RCSID("@(#)$File: compress.c,v 1.56 2008/02/07 00:58:52 christos Exp $")
#endif
#include "magic.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@ -60,9 +64,6 @@
#undef FIONREAD
#ifndef lint
FILE_RCSID("@(#)$File: compress.c,v 1.56 2008/02/07 00:58:52 christos Exp $")
#endif
private const struct {
const char magic[8];
@ -82,6 +83,7 @@ private const struct {
{ "PK\3\4", 4, { "gzip", "-cdq", NULL }, 1 }, /* pkzipped, */
/* ...only first file examined */
{ "BZh", 3, { "bzip2", "-cd", NULL }, 1 }, /* bzip2-ed */
{ "LZIP", 4, { "lzip", "-cdq", NULL }, 1 },
};
#define NODATA ((size_t)~0)
@ -242,7 +244,7 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf,
char buf[4096];
int r, tfd;
(void)strcpy(buf, "/tmp/file.XXXXXX");
(void)strlcpy(buf, "/tmp/file.XXXXXX", sizeof buf);
#ifndef HAVE_MKSTEMP
{
char *ptr = mktemp(buf);

View File

@ -0,0 +1,484 @@
/*
* Copyright (c) Ian F. Darwin 1986-1995.
* Software written by Ian F. Darwin and others;
* maintained 1995-present by Christos Zoulas and others.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice immediately at the beginning of the file, without modification,
* this list of conditions, and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Encoding -- determine the character encoding of a text file.
*
* Joerg Wunsch <joerg@freebsd.org> wrote the original support for 8-bit
* international characters.
*/
#include "file.h"
#ifndef lint
FILE_RCSID("@(#)$File: encoding.c,v 1.3 2009/02/03 20:27:51 christos Exp $")
#endif /* lint */
#include "magic.h"
#include <string.h>
#include <memory.h>
#include <stdlib.h>
private int looks_ascii(const unsigned char *, size_t, unichar *, size_t *);
private int looks_utf8_with_BOM(const unsigned char *, size_t, unichar *,
size_t *);
private int looks_ucs16(const unsigned char *, size_t, unichar *, size_t *);
private int looks_latin1(const unsigned char *, size_t, unichar *, size_t *);
private int looks_extended(const unsigned char *, size_t, unichar *, size_t *);
private void from_ebcdic(const unsigned char *, size_t, unsigned char *);
/*
* Try to determine whether text is in some character code we can
* identify. Each of these tests, if it succeeds, will leave
* the text converted into one-unichar-per-character Unicode in
* ubuf, and the number of characters converted in ulen.
*/
protected int
file_encoding(struct magic_set *ms, const unsigned char *buf, size_t nbytes, unichar **ubuf, size_t *ulen, const char **code, const char **code_mime, const char **type)
{
size_t mlen;
int rv = 1, ucs_type;
unsigned char *nbuf = NULL;
mlen = (nbytes + 1) * sizeof(nbuf[0]);
if ((nbuf = CAST(unsigned char *, calloc((size_t)1, mlen))) == NULL) {
file_oomem(ms, mlen);
goto done;
}
mlen = (nbytes + 1) * sizeof((*ubuf)[0]);
if ((*ubuf = CAST(unichar *, calloc((size_t)1, mlen))) == NULL) {
file_oomem(ms, mlen);
goto done;
}
*type = "text";
if (looks_ascii(buf, nbytes, *ubuf, ulen)) {
*code = "ASCII";
*code_mime = "us-ascii";
} else if (looks_utf8_with_BOM(buf, nbytes, *ubuf, ulen) > 0) {
*code = "UTF-8 Unicode (with BOM)";
*code_mime = "utf-8";
} else if (file_looks_utf8(buf, nbytes, *ubuf, ulen) > 1) {
*code = "UTF-8 Unicode";
*code_mime = "utf-8";
} else if ((ucs_type = looks_ucs16(buf, nbytes, *ubuf, ulen)) != 0) {
if (ucs_type == 1) {
*code = "Little-endian UTF-16 Unicode";
*code_mime = "utf-16le";
} else {
*code = "Big-endian UTF-16 Unicode";
*code_mime = "utf-16be";
}
} else if (looks_latin1(buf, nbytes, *ubuf, ulen)) {
*code = "ISO-8859";
*code_mime = "iso-8859-1";
} else if (looks_extended(buf, nbytes, *ubuf, ulen)) {
*code = "Non-ISO extended-ASCII";
*code_mime = "unknown-8bit";
} else {
from_ebcdic(buf, nbytes, nbuf);
if (looks_ascii(nbuf, nbytes, *ubuf, ulen)) {
*code = "EBCDIC";
*code_mime = "ebcdic";
} else if (looks_latin1(nbuf, nbytes, *ubuf, ulen)) {
*code = "International EBCDIC";
*code_mime = "ebcdic";
} else { /* Doesn't look like text at all */
rv = 0;
*type = "binary";
}
}
done:
if (nbuf)
free(nbuf);
return rv;
}
/*
* This table reflects a particular philosophy about what constitutes
* "text," and there is room for disagreement about it.
*
* Version 3.31 of the file command considered a file to be ASCII if
* each of its characters was approved by either the isascii() or
* isalpha() function. On most systems, this would mean that any
* file consisting only of characters in the range 0x00 ... 0x7F
* would be called ASCII text, but many systems might reasonably
* consider some characters outside this range to be alphabetic,
* so the file command would call such characters ASCII. It might
* have been more accurate to call this "considered textual on the
* local system" than "ASCII."
*
* It considered a file to be "International language text" if each
* of its characters was either an ASCII printing character (according
* to the real ASCII standard, not the above test), a character in
* the range 0x80 ... 0xFF, or one of the following control characters:
* backspace, tab, line feed, vertical tab, form feed, carriage return,
* escape. No attempt was made to determine the language in which files
* of this type were written.
*
*
* The table below considers a file to be ASCII if all of its characters
* are either ASCII printing characters (again, according to the X3.4
* standard, not isascii()) or any of the following controls: bell,
* backspace, tab, line feed, form feed, carriage return, esc, nextline.
*
* I include bell because some programs (particularly shell scripts)
* use it literally, even though it is rare in normal text. I exclude
* vertical tab because it never seems to be used in real text. I also
* include, with hesitation, the X3.64/ECMA-43 control nextline (0x85),
* because that's what the dd EBCDIC->ASCII table maps the EBCDIC newline
* character to. It might be more appropriate to include it in the 8859
* set instead of the ASCII set, but it's got to be included in *something*
* we recognize or EBCDIC files aren't going to be considered textual.
* Some old Unix source files use SO/SI (^N/^O) to shift between Greek
* and Latin characters, so these should possibly be allowed. But they
* make a real mess on VT100-style displays if they're not paired properly,
* so we are probably better off not calling them text.
*
* A file is considered to be ISO-8859 text if its characters are all
* either ASCII, according to the above definition, or printing characters
* from the ISO-8859 8-bit extension, characters 0xA0 ... 0xFF.
*
* Finally, a file is considered to be international text from some other
* character code if its characters are all either ISO-8859 (according to
* the above definition) or characters in the range 0x80 ... 0x9F, which
* ISO-8859 considers to be control characters but the IBM PC and Macintosh
* consider to be printing characters.
*/
#define F 0 /* character never appears in text */
#define T 1 /* character appears in plain ASCII text */
#define I 2 /* character appears in ISO-8859 text */
#define X 3 /* character appears in non-ISO extended ASCII (Mac, IBM PC) */
private char text_chars[256] = {
/* BEL BS HT LF FF CR */
F, F, F, F, F, F, F, T, T, T, T, F, T, T, F, F, /* 0x0X */
/* ESC */
F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F, /* 0x1X */
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x2X */
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x3X */
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x4X */
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x5X */
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x6X */
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, /* 0x7X */
/* NEL */
X, X, X, X, X, T, X, X, X, X, X, X, X, X, X, X, /* 0x8X */
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 0x9X */
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xaX */
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xbX */
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xcX */
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xdX */
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xeX */
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I /* 0xfX */
};
private int
looks_ascii(const unsigned char *buf, size_t nbytes, unichar *ubuf,
size_t *ulen)
{
size_t i;
*ulen = 0;
for (i = 0; i < nbytes; i++) {
int t = text_chars[buf[i]];
if (t != T)
return 0;
ubuf[(*ulen)++] = buf[i];
}
return 1;
}
private int
looks_latin1(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen)
{
size_t i;
*ulen = 0;
for (i = 0; i < nbytes; i++) {
int t = text_chars[buf[i]];
if (t != T && t != I)
return 0;
ubuf[(*ulen)++] = buf[i];
}
return 1;
}
private int
looks_extended(const unsigned char *buf, size_t nbytes, unichar *ubuf,
size_t *ulen)
{
size_t i;
*ulen = 0;
for (i = 0; i < nbytes; i++) {
int t = text_chars[buf[i]];
if (t != T && t != I && t != X)
return 0;
ubuf[(*ulen)++] = buf[i];
}
return 1;
}
/*
* Decide whether some text looks like UTF-8. Returns:
*
* -1: invalid UTF-8
* 0: uses odd control characters, so doesn't look like text
* 1: 7-bit text
* 2: definitely UTF-8 text (valid high-bit set bytes)
*
* If ubuf is non-NULL on entry, text is decoded into ubuf, *ulen;
* ubuf must be big enough!
*/
protected int
file_looks_utf8(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen)
{
size_t i;
int n;
unichar c;
int gotone = 0, ctrl = 0;
if (ubuf)
*ulen = 0;
for (i = 0; i < nbytes; i++) {
if ((buf[i] & 0x80) == 0) { /* 0xxxxxxx is plain ASCII */
/*
* Even if the whole file is valid UTF-8 sequences,
* still reject it if it uses weird control characters.
*/
if (text_chars[buf[i]] != T)
ctrl = 1;
if (ubuf)
ubuf[(*ulen)++] = buf[i];
} else if ((buf[i] & 0x40) == 0) { /* 10xxxxxx never 1st byte */
return -1;
} else { /* 11xxxxxx begins UTF-8 */
int following;
if ((buf[i] & 0x20) == 0) { /* 110xxxxx */
c = buf[i] & 0x1f;
following = 1;
} else if ((buf[i] & 0x10) == 0) { /* 1110xxxx */
c = buf[i] & 0x0f;
following = 2;
} else if ((buf[i] & 0x08) == 0) { /* 11110xxx */
c = buf[i] & 0x07;
following = 3;
} else if ((buf[i] & 0x04) == 0) { /* 111110xx */
c = buf[i] & 0x03;
following = 4;
} else if ((buf[i] & 0x02) == 0) { /* 1111110x */
c = buf[i] & 0x01;
following = 5;
} else
return -1;
for (n = 0; n < following; n++) {
i++;
if (i >= nbytes)
goto done;
if ((buf[i] & 0x80) == 0 || (buf[i] & 0x40))
return -1;
c = (c << 6) + (buf[i] & 0x3f);
}
if (ubuf)
ubuf[(*ulen)++] = c;
gotone = 1;
}
}
done:
return ctrl ? 0 : (gotone ? 2 : 1);
}
/*
* Decide whether some text looks like UTF-8 with BOM. If there is no
* BOM, return -1; otherwise return the result of looks_utf8 on the
* rest of the text.
*/
private int
looks_utf8_with_BOM(const unsigned char *buf, size_t nbytes, unichar *ubuf,
size_t *ulen)
{
if (nbytes > 3 && buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf)
return file_looks_utf8(buf + 3, nbytes - 3, ubuf, ulen);
else
return -1;
}
private int
looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf,
size_t *ulen)
{
int bigend;
size_t i;
if (nbytes < 2)
return 0;
if (buf[0] == 0xff && buf[1] == 0xfe)
bigend = 0;
else if (buf[0] == 0xfe && buf[1] == 0xff)
bigend = 1;
else
return 0;
*ulen = 0;
for (i = 2; i + 1 < nbytes; i += 2) {
/* XXX fix to properly handle chars > 65536 */
if (bigend)
ubuf[(*ulen)++] = buf[i + 1] + 256 * buf[i];
else
ubuf[(*ulen)++] = buf[i] + 256 * buf[i + 1];
if (ubuf[*ulen - 1] == 0xfffe)
return 0;
if (ubuf[*ulen - 1] < 128 &&
text_chars[(size_t)ubuf[*ulen - 1]] != T)
return 0;
}
return 1 + bigend;
}
#undef F
#undef T
#undef I
#undef X
/*
* This table maps each EBCDIC character to an (8-bit extended) ASCII
* character, as specified in the rationale for the dd(1) command in
* draft 11.2 (September, 1991) of the POSIX P1003.2 standard.
*
* Unfortunately it does not seem to correspond exactly to any of the
* five variants of EBCDIC documented in IBM's _Enterprise Systems
* Architecture/390: Principles of Operation_, SA22-7201-06, Seventh
* Edition, July, 1999, pp. I-1 - I-4.
*
* Fortunately, though, all versions of EBCDIC, including this one, agree
* on most of the printing characters that also appear in (7-bit) ASCII.
* Of these, only '|', '!', '~', '^', '[', and ']' are in question at all.
*
* Fortunately too, there is general agreement that codes 0x00 through
* 0x3F represent control characters, 0x41 a nonbreaking space, and the
* remainder printing characters.
*
* This is sufficient to allow us to identify EBCDIC text and to distinguish
* between old-style and internationalized examples of text.
*/
private unsigned char ebcdic_to_ascii[] = {
0, 1, 2, 3, 156, 9, 134, 127, 151, 141, 142, 11, 12, 13, 14, 15,
16, 17, 18, 19, 157, 133, 8, 135, 24, 25, 146, 143, 28, 29, 30, 31,
128, 129, 130, 131, 132, 10, 23, 27, 136, 137, 138, 139, 140, 5, 6, 7,
144, 145, 22, 147, 148, 149, 150, 4, 152, 153, 154, 155, 20, 21, 158, 26,
' ', 160, 161, 162, 163, 164, 165, 166, 167, 168, 213, '.', '<', '(', '+', '|',
'&', 169, 170, 171, 172, 173, 174, 175, 176, 177, '!', '$', '*', ')', ';', '~',
'-', '/', 178, 179, 180, 181, 182, 183, 184, 185, 203, ',', '%', '_', '>', '?',
186, 187, 188, 189, 190, 191, 192, 193, 194, '`', ':', '#', '@', '\'','=', '"',
195, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 196, 197, 198, 199, 200, 201,
202, 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', '^', 204, 205, 206, 207, 208,
209, 229, 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 210, 211, 212, '[', 214, 215,
216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, ']', 230, 231,
'{', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 232, 233, 234, 235, 236, 237,
'}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 238, 239, 240, 241, 242, 243,
'\\',159, 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 244, 245, 246, 247, 248, 249,
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 250, 251, 252, 253, 254, 255
};
#ifdef notdef
/*
* The following EBCDIC-to-ASCII table may relate more closely to reality,
* or at least to modern reality. It comes from
*
* http://ftp.s390.ibm.com/products/oe/bpxqp9.html
*
* and maps the characters of EBCDIC code page 1047 (the code used for
* Unix-derived software on IBM's 390 systems) to the corresponding
* characters from ISO 8859-1.
*
* If this table is used instead of the above one, some of the special
* cases for the NEL character can be taken out of the code.
*/
private unsigned char ebcdic_1047_to_8859[] = {
0x00,0x01,0x02,0x03,0x9C,0x09,0x86,0x7F,0x97,0x8D,0x8E,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x9D,0x0A,0x08,0x87,0x18,0x19,0x92,0x8F,0x1C,0x1D,0x1E,0x1F,
0x80,0x81,0x82,0x83,0x84,0x85,0x17,0x1B,0x88,0x89,0x8A,0x8B,0x8C,0x05,0x06,0x07,
0x90,0x91,0x16,0x93,0x94,0x95,0x96,0x04,0x98,0x99,0x9A,0x9B,0x14,0x15,0x9E,0x1A,
0x20,0xA0,0xE2,0xE4,0xE0,0xE1,0xE3,0xE5,0xE7,0xF1,0xA2,0x2E,0x3C,0x28,0x2B,0x7C,
0x26,0xE9,0xEA,0xEB,0xE8,0xED,0xEE,0xEF,0xEC,0xDF,0x21,0x24,0x2A,0x29,0x3B,0x5E,
0x2D,0x2F,0xC2,0xC4,0xC0,0xC1,0xC3,0xC5,0xC7,0xD1,0xA6,0x2C,0x25,0x5F,0x3E,0x3F,
0xF8,0xC9,0xCA,0xCB,0xC8,0xCD,0xCE,0xCF,0xCC,0x60,0x3A,0x23,0x40,0x27,0x3D,0x22,
0xD8,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0xAB,0xBB,0xF0,0xFD,0xFE,0xB1,
0xB0,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0xAA,0xBA,0xE6,0xB8,0xC6,0xA4,
0xB5,0x7E,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0xA1,0xBF,0xD0,0x5B,0xDE,0xAE,
0xAC,0xA3,0xA5,0xB7,0xA9,0xA7,0xB6,0xBC,0xBD,0xBE,0xDD,0xA8,0xAF,0x5D,0xB4,0xD7,
0x7B,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0xAD,0xF4,0xF6,0xF2,0xF3,0xF5,
0x7D,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0xB9,0xFB,0xFC,0xF9,0xFA,0xFF,
0x5C,0xF7,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0xB2,0xD4,0xD6,0xD2,0xD3,0xD5,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xB3,0xDB,0xDC,0xD9,0xDA,0x9F
};
#endif
/*
* Copy buf[0 ... nbytes-1] into out[], translating EBCDIC to ASCII.
*/
private void
from_ebcdic(const unsigned char *buf, size_t nbytes, unsigned char *out)
{
size_t i;
for (i = 0; i < nbytes; i++) {
out[i] = ebcdic_to_ascii[buf[i]];
}
}

View File

@ -53,6 +53,11 @@
#include "ext/pcre/php_pcre.h"
#include <sys/types.h>
#ifdef PHP_WIN32
#include "win32/param.h"
#else
#include <sys/param.h>
#endif
/* Do this here and now, because struct stat gets re-defined on solaris */
#include <sys/stat.h>
#include <stdarg.h>
@ -102,8 +107,8 @@
#define MAXstring 32 /* max leng of "string" types */
#define MAGICNO 0xF11E041C
#define VERSIONNO 6
#define FILE_MAGICSIZE (32 * 6)
#define VERSIONNO 7
#define FILE_MAGICSIZE 200
#define FILE_LOAD 0
#define FILE_CHECK 1
@ -182,7 +187,10 @@ struct magic {
#define FILE_DOUBLE 36
#define FILE_BEDOUBLE 37
#define FILE_LEDOUBLE 38
#define FILE_NAMES_SIZE 39/* size of array to contain all names */
#define FILE_BEID3 39
#define FILE_LEID3 40
#define FILE_INDIRECT 41
#define FILE_NAMES_SIZE 42/* size of array to contain all names */
#define IS_LIBMAGIC_STRING(t) \
((t) == FILE_STRING || \
@ -257,10 +265,12 @@ struct magic {
#define str_flags _u._s._flags
/* Words 9-16 */
union VALUETYPE value; /* either number of string */
/* Words 17..31 */
/* Words 17-24 */
char desc[MAXDESC]; /* description */
/* Words 32..47 */
/* Words 25-32 */
char mimetype[MAXDESC]; /* MIME type */
/* Words 33-34 */
char apple[8];
};
#define BIT(A) (1 << (A))
@ -288,6 +298,12 @@ struct mlist {
struct mlist *next, *prev;
};
#ifdef __cplusplus
#define CAST(T, b) static_cast<T>(b)
#else
#define CAST(T, b) (b)
#endif
struct level_info {
int32_t off;
int got_match;
@ -295,7 +311,7 @@ struct level_info {
int last_match;
int last_cond; /* used for error checking by parse() */
#endif
} *li;
};
struct magic_set {
struct mlist *mlist;
@ -309,8 +325,9 @@ struct magic_set {
} o;
uint32_t offset;
int error;
int flags;
int haderr;
int flags; /* Control magic tests. */
int event_flags; /* Note things that happened. */
#define EVENT_HAD_ERR 0x01
const char *file;
size_t line; /* current magic line number */
@ -340,13 +357,21 @@ protected int file_printf(struct magic_set *, const char *, ...);
protected int file_reset(struct magic_set *);
protected int file_tryelf(struct magic_set *, int, const unsigned char *,
size_t);
protected int file_trycdf(struct magic_set *, int, const unsigned char *,
size_t);
#ifdef PHP_FILEINFO_UNCOMPRESS
protected int file_zmagic(struct magic_set *, int, const char *,
const unsigned char *, size_t);
#endif
protected int file_ascmagic(struct magic_set *, const unsigned char *, size_t);
protected int file_ascmagic_with_encoding(struct magic_set *,
const unsigned char *, size_t, unichar *, size_t, const char *,
const char *);
protected int file_encoding(struct magic_set *, const unsigned char *, size_t,
unichar **, size_t *, const char **, const char **, const char **);
protected int file_is_tar(struct magic_set *, const unsigned char *, size_t);
protected int file_softmagic(struct magic_set *, const unsigned char *, size_t, int);
protected int file_softmagic(struct magic_set *, const unsigned char *, size_t,
int);
protected struct mlist *file_apprentice(struct magic_set *, const char *, int);
protected uint64_t file_signextend(struct magic_set *, struct magic *,
uint64_t);
@ -378,6 +403,14 @@ extern char *sys_errlist[];
#define strtoul(a, b, c) strtol(a, b, c)
#endif
#ifndef HAVE_STRLCPY
size_t strlcpy(char *dst, const char *src, size_t siz);
#endif
#ifndef HAVE_STRLCAT
size_t strlcat(char *dst, const char *src, size_t siz);
#endif
#if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H) && !defined(QUICK)
#define QUICK
#endif
@ -388,12 +421,14 @@ extern char *sys_errlist[];
#ifndef __cplusplus
#ifdef __GNUC__
static const char *rcsid(const char *) __attribute__((__used__));
#endif
#define FILE_RCSID(id) \
static const char rcsid[] __attribute__((__used__)) = id;
#else
#define FILE_RCSID(id) \
static const char *rcsid(const char *p) { \
return rcsid(p = id); \
}
#endif
#else
#define FILE_RCSID(id)
#endif

View File

@ -30,13 +30,17 @@
*/
#include "file.h"
#ifndef lint
FILE_RCSID("@(#)$File: fsmagic.c,v 1.59 2009/02/03 20:27:51 christos Exp $")
#endif /* lint */
#include "magic.h"
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdlib.h>
#include <sys/stat.h>
/* Since major is a function on SVR4, we cannot use `ifndef major'. */
#ifdef MAJOR_IN_MKDEV
# include <sys/mkdev.h>
@ -56,10 +60,6 @@
#endif
#undef HAVE_MAJOR
#ifndef lint
FILE_RCSID("@(#)$File: fsmagic.c,v 1.50 2008/02/12 17:22:54 rrt Exp $")
#endif /* lint */
#ifdef PHP_WIN32
# undef S_IFIFO
@ -74,14 +74,32 @@ FILE_RCSID("@(#)$File: fsmagic.c,v 1.50 2008/02/12 17:22:54 rrt Exp $")
#define S_ISREG(mode) ((mode) & _S_IFREG)
#endif
private int
handle_mime(struct magic_set *ms, int mime, const char *str)
{
if ((mime & MAGIC_MIME_TYPE)) {
if (file_printf(ms, "application/%s", str) == -1)
return -1;
if ((mime & MAGIC_MIME_ENCODING) && file_printf(ms,
"; charset=") == -1)
return -1;
}
if ((mime & MAGIC_MIME_ENCODING) && file_printf(ms, "binary") == -1)
return -1;
return 0;
}
protected int
file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *stream)
{
int mime = ms->flags & MAGIC_MIME;
TSRMLS_FETCH();
if (ms->flags & MAGIC_APPLE)
return 0;
if (!fn && !stream) {
return -1;
return 0;
}
if (stream) {
@ -89,6 +107,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *
if (php_stream_stat(stream, &ssb) < 0) {
if (ms->flags & MAGIC_ERROR) {
file_error(ms, errno, "cannot stat `%s'", fn);
return -1;
}
return 1;
}
@ -97,27 +116,13 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *
if (php_sys_stat(fn, sb) != 0) {
if (ms->flags & MAGIC_ERROR) {
file_error(ms, errno, "cannot stat `%s'", fn);
return -1;
}
return 1;
}
}
if (mime) {
if (!S_ISREG(sb->st_mode)) {
if ((mime & MAGIC_MIME_TYPE) &&
file_printf(ms, "application/x-not-regular-file") == -1) {
return -1;
}
return 1;
}
if (S_ISDIR(sb->st_mode)) {
if (file_printf(ms, "directory") == -1) {
return -1;
}
return 1;
}
} else {
if (!mime) {
#ifdef S_ISUID
if (sb->st_mode & S_ISUID)
if (file_printf(ms, "setuid ") == -1)
@ -147,41 +152,50 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *
if ((ms->flags & MAGIC_DEVICES) != 0) {
break;
}
if (mime) {
if (handle_mime(ms, mime, "x-character-device") == -1)
return -1;
} else {
# ifdef HAVE_STAT_ST_RDEV
# ifdef dv_unit
if (file_printf(ms, "character special (%d/%d/%d)",
major(sb->st_rdev), dv_unit(sb->st_rdev),
dv_subunit(sb->st_rdev)) == -1) {
return -1;
}
if (file_printf(ms, "character special (%d/%d/%d)",
major(sb->st_rdev), dv_unit(sb->st_rdev),
dv_subunit(sb->st_rdev)) == -1)
return -1;
# else
if (file_printf(ms, "character special (%ld/%ld)",
(long) major(sb->st_rdev), (long) minor(sb->st_rdev)) == -1) {
return -1;
}
if (file_printf(ms, "character special (%ld/%ld)",
(long)major(sb->st_rdev), (long)minor(sb->st_rdev))
== -1)
return -1;
# endif
# else
if (file_printf(ms, "character special") == -1) {
return -1;
}
if (file_printf(ms, "character special") == -1)
return -1;
# endif
}
return 1;
# endif
#endif
#ifdef S_IFIFO
case S_IFIFO:
if((ms->flags & MAGIC_DEVICES) != 0)
break;
if (file_printf(ms, "fifo (named pipe)") == -1)
return -1;
return 1;
case S_IFIFO:
if((ms->flags & MAGIC_DEVICES) != 0)
break;
if (mime) {
if (handle_mime(ms, mime, "x-fifo") == -1)
return -1;
} else if (file_printf(ms, "fifo (named pipe)") == -1)
return -1;
return 1;
#endif
#ifdef S_IFDOOR
case S_IFDOOR:
if (file_printf(ms, "door") == -1)
return -1;
return 1;
case S_IFDOOR:
if (mime) {
if (handle_mime(ms, mime, "x-door") == -1)
return -1;
} else if (file_printf(ms, "door") == -1)
return -1;
return 1;
#endif
#ifdef S_IFLNK
@ -197,7 +211,10 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *
#ifdef S_IFSOCK
#ifndef __COHERENT__
case S_IFSOCK:
if (file_printf(ms, "socket") == -1)
if (mime) {
if (handle_mime(ms, mime, "x-socket") == -1)
return -1;
} else if (file_printf(ms, "socket") == -1)
return -1;
return 1;
#endif
@ -225,9 +242,10 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *
* when we read the file.)
*/
if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
file_printf(ms, mime ? "application/x-empty" :
"empty") == -1)
if (mime) {
if (handle_mime(ms, mime, "x-empty") == -1)
return -1;
} else if (file_printf(ms, "empty") == -1)
return -1;
return 1;
}

View File

@ -25,6 +25,11 @@
* SUCH DAMAGE.
*/
#include "file.h"
#ifndef lint
FILE_RCSID("@(#)$File: funcs.c,v 1.39 2008/03/01 22:21:49 rrt Exp $")
#endif /* lint */
#include "magic.h"
#include <stdarg.h>
#include <stdlib.h>
@ -41,10 +46,6 @@
# define SIZE_MAX ((size_t) -1)
#endif
#ifndef lint
FILE_RCSID("@(#)$File: funcs.c,v 1.39 2008/03/01 22:21:49 rrt Exp $")
#endif /* lint */
/*
* Like printf, only we append to a buffer.
*/
@ -83,7 +84,7 @@ file_error_core(struct magic_set *ms, int error, const char *f, va_list va,
char *buf = NULL;
/* Only the first error is ok */
if (ms->haderr) {
if (ms->event_flags & EVENT_HAD_ERR) {
return;
}
@ -106,7 +107,7 @@ file_error_core(struct magic_set *ms, int error, const char *f, va_list va,
efree(buf);
}
ms->haderr++;
ms->event_flags |= EVENT_HAD_ERR;
ms->error = error;
}
@ -133,6 +134,12 @@ file_magerror(struct magic_set *ms, const char *f, ...)
va_end(va);
}
protected void
file_oomem(struct magic_set *ms, size_t len)
{
file_error(ms, errno, "cannot allocate %zu bytes", len);
}
protected void
file_badseek(struct magic_set *ms)
{
@ -149,9 +156,16 @@ protected int
file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const void *buf,
size_t nb)
{
int m;
int m = 0, rv = 0, looks_text = 0;
int mime = ms->flags & MAGIC_MIME;
const unsigned char *ubuf = buf;
unichar *u8buf = NULL;
size_t ulen;
const char *code = NULL;
const char *code_mime = "binary";
const char *type = NULL;
if (nb == 0) {
if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
@ -167,6 +181,11 @@ file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const
return 1;
}
if ((ms->flags & MAGIC_NO_CHECK_ENCODING) == 0) {
looks_text = file_encoding(ms, ubuf, nb, &u8buf, &ulen,
&code, &code_mime, &type);
}
#if defined(__EMX__)
if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) {
switch (file_os2_apptype(ms, inname, buf, nb)) {
@ -181,40 +200,102 @@ file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const
#endif
#if PHP_FILEINFO_UNCOMPRESS
/* try compression stuff */
if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) != 0 ||
(m = file_zmagic(ms, stream, inname, ubuf, nb)) == 0)
if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) == 0)
if ((m = file_zmagic(ms, stream, inname, ubuf, nb)) != 0) {
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "zmagic %d\n", m);
goto done;
}
#endif
{
/* Check if we have a tar file */
if ((ms->flags & MAGIC_NO_CHECK_TAR) != 0 || (m = file_is_tar(ms, ubuf, nb)) == 0) {
/* try tests in /etc/magic (or surrogate magic file) */
if ((ms->flags & MAGIC_NO_CHECK_SOFT) != 0 || (m = file_softmagic(ms, ubuf, nb, BINTEST)) == 0) {
/* try known keywords, check whether it is ASCII */
if ((ms->flags & MAGIC_NO_CHECK_ASCII) != 0 || (m = file_ascmagic(ms, ubuf, nb)) == 0) {
/* abandon hope, all ye who remain here */
if ((!mime || (mime & MAGIC_MIME_TYPE)) && file_printf(ms, mime ? "application/octet-stream" : "data") == -1) {
return -1;
}
m = 1;
}
/* Check if we have a tar file */
if ((ms->flags & MAGIC_NO_CHECK_TAR) == 0)
if ((m = file_is_tar(ms, ubuf, nb)) != 0) {
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "tar %d\n", m);
goto done;
}
/* Check if we have a CDF file */
if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) {
int fd;
TSRMLS_FETCH();
if (stream && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&fd, 0)) {
if ((m = file_trycdf(ms, fd, ubuf, nb)) != 0) {
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "cdf %d\n", m);
goto done;
}
}
}
/* try soft magic tests */
if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0)
if ((m = file_softmagic(ms, ubuf, nb, BINTEST)) != 0) {
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "softmagic %d\n", m);
#ifdef BUILTIN_ELF
if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 && nb > 5 && fd != -1) {
/*
* We matched something in the file, so this *might*
* be an ELF file, and the file is at least 5 bytes
* long, so if it's an ELF file it has at least one
* byte past the ELF magic number - try extracting
* information from the ELF headers that cannot easily
* be extracted with rules in the magic file.
*/
(void)file_tryelf(ms, stream, ubuf, nb);
}
if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 &&
nb > 5 && fd != -1) {
/*
* We matched something in the file, so this
* *might* be an ELF file, and the file is at
* least 5 bytes long, so if it's an ELF file
* it has at least one byte past the ELF magic
* number - try extracting information from the
* ELF headers that cannot easily * be
* extracted with rules in the magic file.
*/
if ((m = file_tryelf(ms, fd, ubuf, nb)) != 0)
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr,
"elf %d\n", m);
}
#endif
goto done;
}
/* try text properties (and possibly text tokens) */
if ((ms->flags & MAGIC_NO_CHECK_TEXT) == 0) {
if ((m = file_ascmagic(ms, ubuf, nb)) != 0) {
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "ascmagic %d\n", m);
goto done;
}
/* try to discover text encoding */
if ((ms->flags & MAGIC_NO_CHECK_ENCODING) == 0) {
if (looks_text == 0)
if ((m = file_ascmagic_with_encoding( ms, ubuf,
nb, u8buf, ulen, code, type)) != 0) {
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr,
"ascmagic/enc %d\n", m);
goto done;
}
}
}
/* give up */
m = 1;
if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
file_printf(ms, mime ? "application/octet-stream" : "data") == -1) {
rv = -1;
}
done:
if ((ms->flags & MAGIC_MIME_ENCODING) != 0) {
if (ms->flags & MAGIC_MIME_TYPE)
if (file_printf(ms, "; charset=") == -1)
rv = -1;
if (file_printf(ms, "%s", code_mime) == -1)
rv = -1;
}
if (u8buf)
free(u8buf);
if (rv)
return rv;
return m;
}
@ -229,7 +310,7 @@ file_reset(struct magic_set *ms)
efree(ms->o.buf);
}
ms->o.buf = NULL;
ms->haderr = 0;
ms->event_flags &= ~EVENT_HAD_ERR;
ms->error = -1;
return 0;
}
@ -248,12 +329,15 @@ file_getbuffer(struct magic_set *ms)
char *pbuf, *op, *np;
size_t psize, len;
if (ms->haderr)
if (ms->event_flags & EVENT_HAD_ERR)
return NULL;
if (ms->flags & MAGIC_RAW)
return ms->o.buf;
if (ms->o.buf == NULL)
return NULL;
/* * 4 is for octal representation, + 1 is for NUL */
len = strlen(ms->o.buf);
if (len > (SIZE_MAX - 1) / 4) {

View File

@ -38,16 +38,16 @@
*/
#include "file.h"
#include "magic.h"
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include "tar.h"
#ifndef lint
FILE_RCSID("@(#)$File: is_tar.c,v 1.31 2008/02/04 20:51:17 christos Exp $")
#endif
#include "magic.h"
#include <string.h>
#include <ctype.h>
#include "tar.h"
#define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
private int is_tar(const unsigned char *, size_t);
@ -66,16 +66,17 @@ file_is_tar(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
* Do the tar test first, because if the first file in the tar
* archive starts with a dot, we can confuse it with an nroff file.
*/
int tar = is_tar(buf, nbytes);
int tar;
int mime = ms->flags & MAGIC_MIME;
if ((ms->flags & MAGIC_APPLE) != 0)
return 0;
tar = is_tar(buf, nbytes);
if (tar < 1 || tar > 3)
return 0;
if (mime == MAGIC_MIME_ENCODING)
return 0;
if (file_printf(ms, mime ? "application/x-tar" :
if (file_printf(ms, "%s", mime ? "application/x-tar" :
tartype[tar - 1]) == -1)
return -1;
return 1;

View File

@ -26,9 +26,13 @@
*/
#include "file.h"
#ifndef lint
FILE_RCSID("@(#)$File: magic.c,v 1.50 2008/02/19 00:58:59 rrt Exp $")
#endif /* lint */
#include "magic.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef PHP_WIN32
#include "win32/unistd.h"
@ -36,14 +40,12 @@
#include <unistd.h>
#endif
#include <string.h>
#include <sys/types.h>
#ifdef PHP_WIN32
# include "config.w32.h"
#else
# include "php_config.h"
#endif
#include <sys/stat.h>
#include <limits.h> /* for PIPE_BUF */
#if defined(HAVE_UTIMES)
@ -68,10 +70,6 @@
#endif
#include "patchlevel.h"
#ifndef lint
FILE_RCSID("@(#)$File: magic.c,v 1.50 2008/02/19 00:58:59 rrt Exp $")
#endif /* lint */
#ifndef PIPE_BUF
/* Get the PIPE_BUF from pathconf */
#ifdef _PC_PIPE_BUF
@ -118,7 +116,7 @@ magic_open(int flags)
ms->c.li = emalloc((ms->c.len = 10) * sizeof(*ms->c.li));
ms->haderr = 0;
ms->event_flags = 0;
ms->error = -1;
ms->mlist = NULL;
ms->file = "unknown";
@ -364,13 +362,13 @@ magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
public const char *
magic_error(struct magic_set *ms)
{
return ms->haderr ? ms->o.buf : NULL;
return (ms->event_flags & EVENT_HAD_ERR) ? ms->o.buf : NULL;
}
public int
magic_errno(struct magic_set *ms)
{
return ms->haderr ? ms->error : 0;
return (ms->event_flags & EVENT_HAD_ERR) ? ms->error : 0;
}
public int

View File

@ -34,21 +34,27 @@
#define MAGIC_SYMLINK 0x000002 /* Follow symlinks */
#define MAGIC_COMPRESS 0x000004 /* Check inside compressed files */
#define MAGIC_DEVICES 0x000008 /* Look at the contents of devices */
#define MAGIC_MIME_TYPE 0x000010 /* Return only the MIME type */
#define MAGIC_MIME_TYPE 0x000010 /* Return the MIME type */
#define MAGIC_CONTINUE 0x000020 /* Return all matches */
#define MAGIC_CHECK 0x000040 /* Print warnings to stderr */
#define MAGIC_PRESERVE_ATIME 0x000080 /* Restore access time on exit */
#define MAGIC_RAW 0x000100 /* Don't translate unprint chars */
#define MAGIC_RAW 0x000100 /* Don't translate unprintable chars */
#define MAGIC_ERROR 0x000200 /* Handle ENOENT etc as real errors */
#define MAGIC_MIME_ENCODING 0x000400 /* Return only the MIME encoding */
#define MAGIC_MIME_ENCODING 0x000400 /* Return the MIME encoding */
#define MAGIC_MIME (MAGIC_MIME_TYPE|MAGIC_MIME_ENCODING)
#define MAGIC_APPLE 0x000800 /* Return the Apple creator and type */
#define MAGIC_NO_CHECK_COMPRESS 0x001000 /* Don't check for compressed files */
#define MAGIC_NO_CHECK_TAR 0x002000 /* Don't check for tar files */
#define MAGIC_NO_CHECK_SOFT 0x004000 /* Don't check magic entries */
#define MAGIC_NO_CHECK_APPTYPE 0x008000 /* Don't check application type */
#define MAGIC_NO_CHECK_ELF 0x010000 /* Don't check for elf details */
#define MAGIC_NO_CHECK_ASCII 0x020000 /* Don't check for ascii files */
#define MAGIC_NO_CHECK_TOKENS 0x100000 /* Don't check ascii/tokens */
#define MAGIC_NO_CHECK_TEXT 0x020000 /* Don't check for text files */
#define MAGIC_NO_CHECK_CDF 0x040000 /* Don't check for cdf files */
#define MAGIC_NO_CHECK_TOKENS 0x100000 /* Don't check tokens */
#define MAGIC_NO_CHECK_ENCODING 0x200000 /* Don't check text encodings */
/* Defined for backwards compatibility (renamed) */
#define MAGIC_NO_CHECK_ASCII MAGIC_NO_CHECK_TEXT
/* Defined for backwards compatibility; do nothing */
#define MAGIC_NO_CHECK_FORTRAN 0x000000 /* Don't check ascii/fortran */

View File

@ -1,11 +1,14 @@
#define FILE_VERSION_MAJOR 4
#define patchlevel 25
#define FILE_VERSION_MAJOR 5
#define patchlevel 0
/*
* Patchlevel file for Ian Darwin's MAGIC command.
* $File: patchlevel.h,v 1.68 2008/03/22 21:39:43 christos Exp $
*
* $Log$
* Revision 1.1.2.1 2008/11/02 16:13:49 scottmac
* MFH: Sync libmagic with 4.26 and add support for the new v6 magic file format
*
* Revision 1.1 2008/07/11 14:13:50 derick
* - Move lib to libmagic
*

View File

@ -32,8 +32,11 @@
#include "php.h"
#include "file.h"
#include <stdio.h>
#include <errno.h>
#ifndef lint
FILE_RCSID("@(#)$File: print.c,v 1.63 2008/02/17 19:28:54 rrt Exp $")
#endif /* lint */
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
@ -42,10 +45,6 @@
#endif
#include <time.h>
#ifndef lint
FILE_RCSID("@(#)$File: print.c,v 1.63 2008/02/17 19:28:54 rrt Exp $")
#endif /* lint */
#define SZOF(a) (sizeof(a) / sizeof(a[0]))
/*VARARGS*/

View File

@ -0,0 +1,262 @@
/*-
* Copyright (c) 2008 Christos Zoulas
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "file.h"
#ifndef lint
FILE_RCSID("@(#)$File: readcdf.c,v 1.11 2009/02/03 20:27:51 christos Exp $")
#endif
#include <stdlib.h>
#ifdef PHP_WIN32
#include "win32/unistd.h"
#else
#include <unistd.h>
#endif
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "cdf.h"
#include "magic.h"
#define NOTMIME(ms) (((ms)->flags & MAGIC_MIME) == 0)
private int
cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info,
size_t count)
{
size_t i;
cdf_timestamp_t tp;
struct timeval ts;
char buf[64];
const char *str = "vnd.ms-office";
const char *s;
int len;
for (i = 0; i < count; i++) {
cdf_print_property_name(buf, sizeof(buf), info[i].pi_id);
switch (info[i].pi_type) {
case CDF_SIGNED16:
if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf,
info[i].pi_s16) == -1)
return -1;
break;
case CDF_SIGNED32:
if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf,
info[i].pi_s32) == -1)
return -1;
break;
case CDF_UNSIGNED32:
if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf,
info[i].pi_u32) == -1)
return -1;
break;
case CDF_LENGTH32_STRING:
len = info[i].pi_str.s_len;
if (len > 1) {
s = info[i].pi_str.s_buf;
if (NOTMIME(ms)) {
if (file_printf(ms, ", %s: %.*s", buf,
len, s) == -1)
return -1;
} else if (info[i].pi_id ==
CDF_PROPERTY_NAME_OF_APPLICATION) {
if (strstr(s, "Word"))
str = "msword";
else if (strstr(s, "Excel"))
str = "vnd.ms-excel";
else if (strstr(s, "Powerpoint"))
str = "vnd.ms-powerpoint";
}
}
break;
case CDF_FILETIME:
tp = info[i].pi_tp;
if (tp != 0) {
if (tp < 1000000000000000LL) {
char tbuf[64];
cdf_print_elapsed_time(tbuf,
sizeof(tbuf), tp);
if (NOTMIME(ms) && file_printf(ms,
", %s: %s", buf, tbuf) == -1)
return -1;
} else {
char *c, *ec;
cdf_timestamp_to_timespec(&ts, tp);
c = ctime(&ts.tv_sec);
if ((ec = strchr(c, '\n')) != NULL)
*ec = '\0';
if (NOTMIME(ms) && file_printf(ms,
", %s: %s", buf, c) == -1)
return -1;
}
}
break;
case CDF_CLIPBOARD:
break;
default:
file_error(ms, 0, "Internal parsing error");
return -1;
}
}
if (!NOTMIME(ms)) {
if (file_printf(ms, "application/%s", str) == -1)
return -1;
}
return 1;
}
private int
cdf_file_summary_info(struct magic_set *ms, const cdf_stream_t *sst)
{
cdf_summary_info_header_t si;
cdf_property_info_t *info;
size_t count;
int m;
if (cdf_unpack_summary_info(sst, &si, &info, &count) == -1) {
if (si.si_byte_order != 0xfffe)
return 0;
else
return -1;
}
if (si.si_byte_order != 0xfffe)
return 0;
if (NOTMIME(ms)) {
if (file_printf(ms, "CDF V2 Document") == -1)
return -1;
if (file_printf(ms, ", %s Endian",
si.si_byte_order == 0xfffe ? "Little" : "Big") == -1)
return -1;
switch (si.si_os) {
case 2:
if (file_printf(ms, ", Os: Windows, Version %d.%d",
si.si_os_version & 0xff, si.si_os_version >> 8)
== -1)
return -1;
break;
case 1:
if (file_printf(ms, ", Os: MacOS, Version %d.%d",
si.si_os_version >> 8, si.si_os_version & 0xff)
== -1)
return -1;
break;
default:
if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os,
si.si_os_version & 0xff, si.si_os_version >> 8)
== -1)
return -1;
break;
}
}
m = cdf_file_property_info(ms, info, count);
free(info);
return m;
}
protected int
file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
size_t nbytes)
{
cdf_header_t h;
cdf_sat_t sat, ssat;
cdf_stream_t sst, scn;
cdf_dir_t dir;
int i;
(void)&nbytes;
(void)&buf;
if (ms->flags & MAGIC_APPLE)
return 0;
if (cdf_read_header(fd, &h) == -1)
return 0;
#ifdef CDF_DEBUG
cdf_dump_header(&h);
#endif
if (cdf_read_sat(fd, &h, &sat) == -1) {
file_error(ms, errno, "Can't read SAT");
return -1;
}
#ifdef CDF_DEBUG
cdf_dump_sat("SAT", &h, &sat);
#endif
if ((i = cdf_read_ssat(fd, &h, &sat, &ssat)) == -1) {
file_error(ms, errno, "Can't read SAT");
goto out1;
}
#ifdef CDF_DEBUG
cdf_dump_sat("SSAT", &h, &ssat);
#endif
if ((i = cdf_read_dir(fd, &h, &sat, &dir)) == -1) {
file_error(ms, errno, "Can't read directory");
goto out2;
}
if ((i = cdf_read_short_stream(fd, &h, &sat, &dir, &sst)) == -1) {
file_error(ms, errno, "Cannot read short stream");
goto out3;
}
#ifdef CDF_DEBUG
cdf_dump_dir(fd, &h, &sat, &ssat, &sst, &dir);
#endif
if ((i = cdf_read_summary_info(fd, &h, &sat, &ssat, &sst, &dir, &scn))
== -1) {
/* Some files don't have summary info! */
#ifdef notyet
file_error(ms, errno, "Can't read summary_info");
#else
i = 0;
#endif
goto out4;
}
#ifdef CDF_DEBUG
cdf_dump_summary_info(&h, &scn);
#endif
if ((i = cdf_file_summary_info(ms, &scn)) == -1)
file_error(ms, errno, "Can't expand summary_info");
free(scn.sst_tab);
out4:
free(sst.sst_tab);
out3:
free(dir.dir_tab);
out2:
free(ssat.sat_tab);
out1:
free(sat.sat_tab);
return i;
}

View File

@ -26,6 +26,10 @@
*/
#include "file.h"
#ifndef lint
FILE_RCSID("@(#)$File: readelf.c,v 1.73 2008/03/27 22:00:28 christos Exp $")
#endif
#ifdef BUILTIN_ELF
#include <string.h>
#include <ctype.h>
@ -37,10 +41,6 @@
#include "readelf.h"
#include "magic.h"
#ifndef lint
FILE_RCSID("@(#)$File: readelf.c,v 1.73 2008/03/27 22:00:28 christos Exp $")
#endif
#ifdef ELFCORE
private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t,
off_t, int *);
@ -870,7 +870,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
noff = 0;
for (;;) {
if (noff >= (size_t)xsh_size)
if (noff >= (off_t)xsh_size)
break;
noff = donote(ms, nbuf, (size_t)noff,
(size_t)xsh_size, clazz, swap, 4,
@ -902,8 +902,9 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
for (;;) {
Elf32_Cap cap32;
Elf64_Cap cap64;
char cbuf[MAX(sizeof cap32, sizeof cap64)];
if ((coff += xcap_sizeof) >= (size_t)xsh_size)
char cbuf[/*CONSTCOND*/
MAX(sizeof cap32, sizeof cap64)];
if ((coff += xcap_sizeof) >= (off_t)xsh_size)
break;
if (read(fd, cbuf, (size_t)xcap_sizeof) !=
(ssize_t)xcap_sizeof) {
@ -924,7 +925,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
if (file_printf(ms,
", with unknown capability "
"0x%llx = 0x%llx",
xcap_tag, xcap_val) == -1)
(unsigned long long)xcap_tag,
(unsigned long long)xcap_val) == -1)
return -1;
break;
}
@ -971,11 +973,12 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
if (cap_hw1)
if (file_printf(ms,
" unknown hardware capability 0x%llx",
cap_hw1) == -1)
(unsigned long long)cap_hw1) == -1)
return -1;
} else {
if (file_printf(ms,
" hardware capability 0x%llx", cap_hw1) == -1)
" hardware capability 0x%llx",
(unsigned long long)cap_hw1) == -1)
return -1;
}
}
@ -991,7 +994,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
if (cap_sf1)
if (file_printf(ms,
", with unknown software capability 0x%llx",
cap_sf1) == -1)
(unsigned long long)cap_sf1) == -1)
return -1;
}
return 0;
@ -1132,7 +1135,7 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
Elf64_Ehdr elf64hdr;
uint16_t type;
if (ms->flags & MAGIC_MIME)
if (ms->flags & (MAGIC_MIME|MAGIC_APPLE))
return 0;
/*

View File

@ -30,6 +30,11 @@
*/
#include "file.h"
#ifndef lint
FILE_RCSID("@(#)$File: softmagic.c,v 1.117 2008/03/01 22:21:49 rrt Exp $")
#endif /* lint */
#include "magic.h"
#include <string.h>
#include <ctype.h>
@ -41,9 +46,6 @@
#endif
#ifndef lint
FILE_RCSID("@(#)$File: softmagic.c,v 1.117 2008/03/01 22:21:49 rrt Exp $")
#endif /* lint */
private int match(struct magic_set *, struct magic *, uint32_t,
const unsigned char *, size_t, int);
@ -51,22 +53,18 @@ private int mget(struct magic_set *, const unsigned char *,
struct magic *, size_t, unsigned int);
private int magiccheck(struct magic_set *, struct magic *);
private int32_t mprint(struct magic_set *, struct magic *);
private int32_t moffset(struct magic_set *, struct magic *);
private void mdebug(uint32_t, const char *, size_t);
private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
const unsigned char *, uint32_t, size_t, size_t);
private int mconvert(struct magic_set *, struct magic *);
private int print_sep(struct magic_set *, int);
private int handle_annotation(struct magic_set *, struct magic *);
private void cvt_8(union VALUETYPE *, const struct magic *);
private void cvt_16(union VALUETYPE *, const struct magic *);
private void cvt_32(union VALUETYPE *, const struct magic *);
private void cvt_64(union VALUETYPE *, const struct magic *);
/*
* Macro to give description string according to whether we want plain
* text or MIME type
*/
#define MAGIC_DESC ((ms->flags & MAGIC_MIME) ? m->mimetype : m->desc)
/*
* softmagic - lookup one file in parsed, in-memory copy of database
* Passed the name and FILE * of one file to be typed.
@ -118,15 +116,16 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
uint32_t magindex = 0;
unsigned int cont_level = 0;
int need_separator = 0;
int returnval = 0; /* if a match is found it is set to 1*/
int returnval = 0, e; /* if a match is found it is set to 1*/
int firstline = 1; /* a flag to print X\n X\n- X */
int printed_something = 0;
int print = (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0;
if (file_check_mem(ms, cont_level) == -1)
return -1;
for (magindex = 0; magindex < nmagic; magindex++) {
int flush;
int flush = 0;
struct magic *m = &magic[magindex];
if ((m->flag & BINTEST) != mode) {
@ -141,11 +140,16 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
ms->line = m->lineno;
/* if main entry matches, print it... */
flush = !mget(ms, s, m, nbytes, cont_level);
if (flush) {
if (m->reln == '!')
flush = 0;
} else {
switch (mget(ms, s, m, nbytes, cont_level)) {
case -1:
return -1;
case 0:
flush = m->reln != '!';
break;
default:
if (m->type == FILE_INDIRECT)
returnval = 1;
switch (magiccheck(ms, m)) {
case -1:
return -1;
@ -153,8 +157,10 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
flush++;
break;
default:
flush = 0;
break;
}
break;
}
if (flush) {
/*
@ -171,15 +177,20 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
* If we are going to print something, we'll need to print
* a blank before we print something else.
*/
if (*MAGIC_DESC) {
if (*m->desc) {
need_separator = 1;
printed_something = 1;
if ((e = handle_annotation(ms, m)) != 0)
return e;
if (print_sep(ms, firstline) == -1)
return -1;
}
if ((ms->c.li[cont_level].off = mprint(ms, m)) == -1)
return -1;
if (print && mprint(ms, m) == -1)
return -1;
ms->c.li[cont_level].off = moffset(ms, m);
/* and any continuations that match */
if (file_check_mem(ms, ++cont_level) == -1)
@ -211,10 +222,21 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
continue;
}
#endif
flush = !mget(ms, s, m, nbytes, cont_level);
if (flush && m->reln != '!')
switch (mget(ms, s, m, nbytes, cont_level)) {
case -1:
return -1;
case 0:
if (m->reln != '!')
continue;
flush = 1;
break;
default:
if (m->type == FILE_INDIRECT)
returnval = 1;
flush = 0;
break;
}
switch (flush ? 1 : magiccheck(ms, m)) {
case -1:
return -1;
@ -237,8 +259,10 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
* If we are going to print something,
* make sure that we have a separator first.
*/
if (*MAGIC_DESC) {
if (*m->desc) {
printed_something = 1;
if ((e = handle_annotation(ms, m)) != 0)
return e;
if (print_sep(ms, firstline) == -1)
return -1;
}
@ -251,14 +275,18 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
/* space if previous printed */
if (need_separator
&& ((m->flag & NOSPACE) == 0)
&& *MAGIC_DESC) {
if (file_printf(ms, " ") == -1)
&& *m->desc) {
if (print &&
file_printf(ms, " ") == -1)
return -1;
need_separator = 0;
}
if ((ms->c.li[cont_level].off = mprint(ms, m)) == -1)
if (print && mprint(ms, m) == -1)
return -1;
if (*MAGIC_DESC)
ms->c.li[cont_level].off = moffset(ms, m);
if (*m->desc)
need_separator = 1;
/*
@ -273,10 +301,11 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
}
if (printed_something) {
firstline = 0;
if (print)
returnval = 1;
}
if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) {
return 1; /* don't keep searching */
return returnval; /* don't keep searching */
}
}
return returnval; /* This is hit if -k is set or there is no match */
@ -290,14 +319,14 @@ check_fmt(struct magic_set *ms, struct magic *m)
pcre_extra *re_extra;
TSRMLS_FETCH();
if (strchr(MAGIC_DESC, '%') == NULL) {
if (strchr(m->desc, '%') == NULL) {
return 0;
}
if ((pce = pcre_get_compiled_regex("~%[-0-9.]*s~", &re_extra, &re_options TSRMLS_CC)) == NULL) {
return -1;
} else {
return !pcre_exec(pce, re_extra, MAGIC_DESC, strlen(MAGIC_DESC), 0, re_options, NULL, 0);
return !pcre_exec(pce, re_extra, m->desc, strlen(m->desc), 0, re_options, NULL, 0);
}
}
@ -308,7 +337,7 @@ mprint(struct magic_set *ms, struct magic *m)
float vf;
double vd;
int64_t t = 0;
char *buf;
char buf[128];
union VALUETYPE *p = &ms->ms_value;
switch (m->type) {
@ -318,13 +347,13 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
if (spprintf(&buf, 0, "%c", (unsigned char)v) < 0)
return -1;
if (file_printf(ms, MAGIC_DESC, buf) == -1)
(void)snprintf(buf, sizeof(buf), "%c",
(unsigned char)v);
if (file_printf(ms, m->desc, buf) == -1)
return -1;
break;
default:
if (file_printf(ms, MAGIC_DESC, (unsigned char) v) == -1)
if (file_printf(ms, m->desc, (unsigned char) v) == -1)
return -1;
break;
}
@ -339,13 +368,13 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
if (spprintf(&buf, 0, "%hu", (unsigned short)v) < 0)
return -1;
if (file_printf(ms, MAGIC_DESC, buf) == -1)
(void)snprintf(buf, sizeof(buf), "%hu",
(unsigned short)v);
if (file_printf(ms, m->desc, buf) == -1)
return -1;
break;
default:
if (file_printf(ms, MAGIC_DESC, (unsigned short) v) == -1)
if (file_printf(ms, m->desc, (unsigned short) v) == -1)
return -1;
break;
}
@ -361,13 +390,12 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
if (spprintf(&buf, 0, "%u", (uint32_t)v) < 0)
return -1;
if (file_printf(ms, MAGIC_DESC, buf) == -1)
(void)snprintf(buf, sizeof(buf), "%u", (uint32_t)v);
if (file_printf(ms, m->desc, buf) == -1)
return -1;
break;
default:
if (file_printf(ms, MAGIC_DESC, (uint32_t) v) == -1)
if (file_printf(ms, m->desc, (uint32_t) v) == -1)
return -1;
break;
}
@ -378,7 +406,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BEQUAD:
case FILE_LEQUAD:
v = file_signextend(ms, m, p->q);
if (file_printf(ms, MAGIC_DESC, (uint64_t) v) == -1)
if (file_printf(ms, m->desc, (uint64_t) v) == -1)
return -1;
t = ms->offset + sizeof(int64_t);
break;
@ -388,14 +416,14 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BESTRING16:
case FILE_LESTRING16:
if (m->reln == '=' || m->reln == '!') {
if (file_printf(ms, MAGIC_DESC, m->value.s) == -1)
if (file_printf(ms, m->desc, m->value.s) == -1)
return -1;
t = ms->offset + m->vallen;
}
else {
if (*m->value.s == '\0')
p->s[strcspn(p->s, "\n")] = '\0';
if (file_printf(ms, MAGIC_DESC, p->s) == -1)
if (file_printf(ms, m->desc, p->s) == -1)
return -1;
t = ms->offset + strlen(p->s);
if (m->type == FILE_PSTRING)
@ -407,7 +435,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BEDATE:
case FILE_LEDATE:
case FILE_MEDATE:
if (file_printf(ms, MAGIC_DESC, file_fmttime(p->l, 1)) == -1)
if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
return -1;
t = ms->offset + sizeof(time_t);
break;
@ -416,7 +444,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BELDATE:
case FILE_LELDATE:
case FILE_MELDATE:
if (file_printf(ms, MAGIC_DESC, file_fmttime(p->l, 0)) == -1)
if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
return -1;
t = ms->offset + sizeof(time_t);
break;
@ -424,8 +452,8 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_QDATE:
case FILE_BEQDATE:
case FILE_LEQDATE:
if (file_printf(ms, MAGIC_DESC, file_fmttime((uint32_t)p->q, 1))
== -1)
if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q,
1)) == -1)
return -1;
t = ms->offset + sizeof(uint64_t);
break;
@ -433,8 +461,8 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_QLDATE:
case FILE_BEQLDATE:
case FILE_LEQLDATE:
if (file_printf(ms, MAGIC_DESC, file_fmttime((uint32_t)p->q, 0))
== -1)
if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q,
0)) == -1)
return -1;
t = ms->offset + sizeof(uint64_t);
break;
@ -447,13 +475,12 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
if (spprintf(&buf, 0, "%g", vf) < 0)
return -1;
if (file_printf(ms, MAGIC_DESC, buf) == -1)
(void)snprintf(buf, sizeof(buf), "%g", vf);
if (file_printf(ms, m->desc, buf) == -1)
return -1;
break;
default:
if (file_printf(ms, MAGIC_DESC, vf) == -1)
if (file_printf(ms, m->desc, vf) == -1)
return -1;
break;
}
@ -468,13 +495,12 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
if (spprintf(&buf, 0, "%g", vd) < 0)
return -1;
if (file_printf(ms, MAGIC_DESC, buf) == -1)
(void)snprintf(buf, sizeof(buf), "%g", vd);
if (file_printf(ms, m->desc, buf) == -1)
return -1;
break;
default:
if (file_printf(ms, MAGIC_DESC, vd) == -1)
if (file_printf(ms, m->desc, vd) == -1)
return -1;
break;
}
@ -487,7 +513,7 @@ mprint(struct magic_set *ms, struct magic *m)
cp = estrndup((const char *)ms->search.s, ms->search.rm_len);
rval = file_printf(ms, MAGIC_DESC, cp);
rval = file_printf(ms, m->desc, cp);
efree(cp);
if (rval == -1)
@ -501,7 +527,7 @@ mprint(struct magic_set *ms, struct magic *m)
}
case FILE_SEARCH:
if (file_printf(ms, MAGIC_DESC, m->value.s) == -1)
if (file_printf(ms, m->desc, m->value.s) == -1)
return -1;
if ((m->str_flags & REGEX_OFFSET_START))
t = ms->search.offset;
@ -510,18 +536,118 @@ mprint(struct magic_set *ms, struct magic *m)
break;
case FILE_DEFAULT:
if (file_printf(ms, MAGIC_DESC, m->value.s) == -1)
if (file_printf(ms, m->desc, m->value.s) == -1)
return -1;
t = ms->offset;
break;
case FILE_INDIRECT:
t = ms->offset;
break;
default:
file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
return -1;
}
return(t);
return (int32_t)t;
}
private int32_t
moffset(struct magic_set *ms, struct magic *m)
{
switch (m->type) {
case FILE_BYTE:
return ms->offset + sizeof(char);
case FILE_SHORT:
case FILE_BESHORT:
case FILE_LESHORT:
return ms->offset + sizeof(short);
case FILE_LONG:
case FILE_BELONG:
case FILE_LELONG:
case FILE_MELONG:
return ms->offset + sizeof(int32_t);
case FILE_QUAD:
case FILE_BEQUAD:
case FILE_LEQUAD:
return ms->offset + sizeof(int64_t);
case FILE_STRING:
case FILE_PSTRING:
case FILE_BESTRING16:
case FILE_LESTRING16:
if (m->reln == '=' || m->reln == '!')
return ms->offset + m->vallen;
else {
union VALUETYPE *p = &ms->ms_value;
uint32_t t;
if (*m->value.s == '\0')
p->s[strcspn(p->s, "\n")] = '\0';
t = ms->offset + strlen(p->s);
if (m->type == FILE_PSTRING)
t++;
return t;
}
case FILE_DATE:
case FILE_BEDATE:
case FILE_LEDATE:
case FILE_MEDATE:
return ms->offset + sizeof(time_t);
case FILE_LDATE:
case FILE_BELDATE:
case FILE_LELDATE:
case FILE_MELDATE:
return ms->offset + sizeof(time_t);
case FILE_QDATE:
case FILE_BEQDATE:
case FILE_LEQDATE:
return ms->offset + sizeof(uint64_t);
case FILE_QLDATE:
case FILE_BEQLDATE:
case FILE_LEQLDATE:
return ms->offset + sizeof(uint64_t);
case FILE_FLOAT:
case FILE_BEFLOAT:
case FILE_LEFLOAT:
return ms->offset + sizeof(float);
case FILE_DOUBLE:
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
return ms->offset + sizeof(double);
break;
case FILE_REGEX:
if ((m->str_flags & REGEX_OFFSET_START) != 0)
return ms->search.offset;
else
return ms->search.offset + ms->search.rm_len;
case FILE_SEARCH:
if ((m->str_flags & REGEX_OFFSET_START) != 0)
return ms->search.offset;
else
return ms->search.offset + m->vallen;
case FILE_DEFAULT:
return ms->offset;
case FILE_INDIRECT:
return ms->offset;
default:
return 0;
}
}
#define DO_CVT(fld, cast) \
if (m->num_mask) \
@ -822,7 +948,7 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
/* check for pointer overflow */
if (src < s) {
file_magerror(ms, "invalid offset %zu in mcopy()",
file_magerror(ms, "invalid offset %u in mcopy()",
offset);
return -1;
}
@ -906,9 +1032,11 @@ mget(struct magic_set *ms, const unsigned char *s,
off = q->l;
break;
case FILE_BELONG:
case FILE_BEID3:
off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
(q->hl[2]<<8)|(q->hl[3]));
break;
case FILE_LEID3:
case FILE_LELONG:
off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
(q->hl[1]<<8)|(q->hl[0]));
@ -1096,6 +1224,7 @@ mget(struct magic_set *ms, const unsigned char *s,
offset = ~offset;
break;
case FILE_BELONG:
case FILE_BEID3:
if (nbytes < (offset + 4))
return 0;
if (off) {
@ -1166,6 +1295,7 @@ mget(struct magic_set *ms, const unsigned char *s,
offset = ~offset;
break;
case FILE_LELONG:
case FILE_LEID3:
if (nbytes < (offset + 4))
return 0;
if (off) {
@ -1342,8 +1472,21 @@ mget(struct magic_set *ms, const unsigned char *s,
break;
}
if (m->flag & INDIROFFADD)
switch (m->in_type) {
case FILE_LEID3:
case FILE_BEID3:
offset = ((((offset >> 0) & 0x7f) << 0) |
(((offset >> 8) & 0x7f) << 7) |
(((offset >> 16) & 0x7f) << 14) |
(((offset >> 24) & 0x7f) << 21)) + 10;
break;
default:
break;
}
if (m->flag & INDIROFFADD) {
offset += ms->c.li[cont_level-1].off;
}
if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
return -1;
ms->offset = offset;
@ -1406,6 +1549,15 @@ mget(struct magic_set *ms, const unsigned char *s,
return 0;
break;
case FILE_INDIRECT:
if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 &&
file_printf(ms, m->desc) == -1)
return -1;
if (nbytes < offset)
return 0;
return file_softmagic(ms, s + offset, nbytes - offset,
BINTEST);
case FILE_DEFAULT: /* nothing to check */
default:
break;
@ -1625,7 +1777,8 @@ magiccheck(struct magic_set *ms, struct magic *m)
default:
matched = 0;
file_magerror(ms, "cannot happen with float: invalid relation `%c'", m->reln);
file_magerror(ms, "cannot happen with float: invalid relation `%c'",
m->reln);
return -1;
}
return matched;
@ -1852,8 +2005,8 @@ magiccheck(struct magic_set *ms, struct magic *m)
efree(pattern);
break;
}
case FILE_INDIRECT:
return 1;
default:
file_magerror(ms, "invalid type %d in magiccheck()", m->type);
return -1;
@ -1943,9 +2096,27 @@ magiccheck(struct magic_set *ms, struct magic *m)
return matched;
}
private int
handle_annotation(struct magic_set *ms, struct magic *m)
{
if (ms->flags & MAGIC_APPLE) {
if (file_printf(ms, "%.8s", m->apple) == -1)
return -1;
return 1;
}
if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
if (file_printf(ms, "%s", m->mimetype) == -1)
return -1;
return 1;
}
return 0;
}
private int
print_sep(struct magic_set *ms, int firstline)
{
if (ms->flags & MAGIC_MIME)
return 0;
if (firstline)
return 0;
/*

View File

@ -46,7 +46,7 @@ string(15) "MIFF image data"
string(25) "RIFF (little-endian) data"
string(28) "text/plain; charset=us-ascii"
string(26) "text/plain; charset=ebcdic"
string(24) "application/octet-stream"
string(40) "application/octet-stream; charset=binary"
string(28) "text/plain; charset=us-ascii"
string(28) "text/plain; charset=us-ascii"
string(25) "text/plain; charset=utf-8"

View File

@ -45,7 +45,7 @@ string(15) "MIFF image data"
string(25) "RIFF (little-endian) data"
string(28) "text/plain; charset=us-ascii"
string(26) "text/plain; charset=ebcdic"
string(24) "application/octet-stream"
string(40) "application/octet-stream; charset=binary"
string(28) "text/plain; charset=us-ascii"
string(28) "text/plain; charset=us-ascii"
string(25) "text/plain; charset=utf-8"

View File

@ -3,7 +3,7 @@ finfo_file(): Testing mime types
--FILE--
<?php
$fp = finfo_open(FILEINFO_MIME);
$fp = finfo_open(FILEINFO_MIME_TYPE);
$results = array();
foreach (glob(__DIR__ . "/resources/*") as $filename) {

View File

@ -22,7 +22,7 @@ var_dump( finfo_file( $finfo, $magicFile ) );
===DONE===
--EXPECTF--
*** Testing finfo_file() : basic functionality ***
string(10) "text/x-php"
string(28) "text/x-php; charset=us-ascii"
string(15) "PHP script text"
string(27) "text/plain; charset=unknown"
string(32) "text/plain; charset=unknown-8bit"
===DONE===