Annotation of embedaddon/php/ext/fileinfo/libmagic/funcs.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) Christos Zoulas 2003.
! 3: * All Rights Reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice immediately at the beginning of the file, without modification,
! 10: * this list of conditions, and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 16: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 17: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
! 19: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 25: * SUCH DAMAGE.
! 26: */
! 27: #include "file.h"
! 28:
! 29: #ifndef lint
! 30: FILE_RCSID("@(#)$File: funcs.c,v 1.53 2009/04/07 11:07:00 christos Exp $")
! 31: #endif /* lint */
! 32:
! 33: #include "magic.h"
! 34: #include <stdarg.h>
! 35: #include <stdlib.h>
! 36: #include <string.h>
! 37: #include <ctype.h>
! 38: #if defined(HAVE_WCHAR_H)
! 39: #include <wchar.h>
! 40: #endif
! 41: #if defined(HAVE_WCTYPE_H)
! 42: #include <wctype.h>
! 43: #endif
! 44:
! 45: #ifndef SIZE_MAX
! 46: # define SIZE_MAX ((size_t) -1)
! 47: #endif
! 48:
! 49: /*
! 50: * Like printf, only we append to a buffer.
! 51: */
! 52: protected int
! 53: file_printf(struct magic_set *ms, const char *fmt, ...)
! 54: {
! 55: va_list ap;
! 56: int len;
! 57: char *buf = NULL, *newstr;
! 58:
! 59: va_start(ap, fmt);
! 60: len = vspprintf(&buf, 0, fmt, ap);
! 61: va_end(ap);
! 62:
! 63: if (ms->o.buf != NULL) {
! 64: len = spprintf(&newstr, 0, "%s%s", ms->o.buf, (buf ? buf : ""));
! 65: if (buf) {
! 66: efree(buf);
! 67: }
! 68: efree(ms->o.buf);
! 69: ms->o.buf = newstr;
! 70: } else {
! 71: ms->o.buf = buf;
! 72: }
! 73: return 0;
! 74: }
! 75:
! 76: /*
! 77: * error - print best error message possible
! 78: */
! 79: /*VARARGS*/
! 80: private void
! 81: file_error_core(struct magic_set *ms, int error, const char *f, va_list va,
! 82: uint32_t lineno)
! 83: {
! 84: char *buf = NULL;
! 85:
! 86: /* Only the first error is ok */
! 87: if (ms->event_flags & EVENT_HAD_ERR) {
! 88: return;
! 89: }
! 90:
! 91: if (lineno != 0) {
! 92: efree(ms->o.buf);
! 93: ms->o.buf = NULL;
! 94: file_printf(ms, "line %u: ", lineno);
! 95: }
! 96:
! 97: vspprintf(&buf, 0, f, va);
! 98: va_end(va);
! 99:
! 100: if (error > 0) {
! 101: file_printf(ms, "%s (%s)", (*buf ? buf : ""), strerror(error));
! 102: } else if (*buf) {
! 103: file_printf(ms, "%s", buf);
! 104: }
! 105:
! 106: if (buf) {
! 107: efree(buf);
! 108: }
! 109:
! 110: ms->event_flags |= EVENT_HAD_ERR;
! 111: ms->error = error;
! 112: }
! 113:
! 114: /*VARARGS*/
! 115: protected void
! 116: file_error(struct magic_set *ms, int error, const char *f, ...)
! 117: {
! 118: va_list va;
! 119: va_start(va, f);
! 120: file_error_core(ms, error, f, va, 0);
! 121: va_end(va);
! 122: }
! 123:
! 124: /*
! 125: * Print an error with magic line number.
! 126: */
! 127: /*VARARGS*/
! 128: protected void
! 129: file_magerror(struct magic_set *ms, const char *f, ...)
! 130: {
! 131: va_list va;
! 132: va_start(va, f);
! 133: file_error_core(ms, 0, f, va, ms->line);
! 134: va_end(va);
! 135: }
! 136:
! 137: protected void
! 138: file_oomem(struct magic_set *ms, size_t len)
! 139: {
! 140: file_error(ms, errno, "cannot allocate %zu bytes", len);
! 141: }
! 142:
! 143: protected void
! 144: file_badseek(struct magic_set *ms)
! 145: {
! 146: file_error(ms, errno, "error seeking");
! 147: }
! 148:
! 149: protected void
! 150: file_badread(struct magic_set *ms)
! 151: {
! 152: file_error(ms, errno, "error reading");
! 153: }
! 154:
! 155: protected int
! 156: file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const void *buf,
! 157: size_t nb)
! 158: {
! 159: int m = 0, rv = 0, looks_text = 0;
! 160: int mime = ms->flags & MAGIC_MIME;
! 161: const unsigned char *ubuf = buf;
! 162: unichar *u8buf = NULL;
! 163: size_t ulen;
! 164: const char *code = NULL;
! 165: const char *code_mime = "binary";
! 166: const char *type = NULL;
! 167:
! 168:
! 169:
! 170: if (nb == 0) {
! 171: if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
! 172: file_printf(ms, mime ? "application/x-empty" :
! 173: "empty") == -1)
! 174: return -1;
! 175: return 1;
! 176: } else if (nb == 1) {
! 177: if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
! 178: file_printf(ms, mime ? "application/octet-stream" :
! 179: "very short file (no magic)") == -1)
! 180: return -1;
! 181: return 1;
! 182: }
! 183:
! 184: if ((ms->flags & MAGIC_NO_CHECK_ENCODING) == 0) {
! 185: looks_text = file_encoding(ms, ubuf, nb, &u8buf, &ulen,
! 186: &code, &code_mime, &type);
! 187: }
! 188:
! 189: #if defined(__EMX__)
! 190: if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) {
! 191: switch (file_os2_apptype(ms, inname, buf, nb)) {
! 192: case -1:
! 193: return -1;
! 194: case 0:
! 195: break;
! 196: default:
! 197: return 1;
! 198: }
! 199: }
! 200: #endif
! 201:
! 202: #if PHP_FILEINFO_UNCOMPRESS
! 203: if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) == 0)
! 204: if ((m = file_zmagic(ms, stream, inname, ubuf, nb)) != 0) {
! 205: if ((ms->flags & MAGIC_DEBUG) != 0)
! 206: (void)fprintf(stderr, "zmagic %d\n", m);
! 207: goto done;
! 208: }
! 209: #endif
! 210:
! 211: /* Check if we have a tar file */
! 212: if ((ms->flags & MAGIC_NO_CHECK_TAR) == 0)
! 213: if ((m = file_is_tar(ms, ubuf, nb)) != 0) {
! 214: if ((ms->flags & MAGIC_DEBUG) != 0)
! 215: (void)fprintf(stderr, "tar %d\n", m);
! 216: goto done;
! 217: }
! 218:
! 219: /* Check if we have a CDF file */
! 220: if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) {
! 221: int fd;
! 222: TSRMLS_FETCH();
! 223: if (stream && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&fd, 0)) {
! 224: if ((m = file_trycdf(ms, fd, ubuf, nb)) != 0) {
! 225: if ((ms->flags & MAGIC_DEBUG) != 0)
! 226: (void)fprintf(stderr, "cdf %d\n", m);
! 227: goto done;
! 228: }
! 229: }
! 230: }
! 231:
! 232: /* try soft magic tests */
! 233: if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0)
! 234: if ((m = file_softmagic(ms, ubuf, nb, BINTEST)) != 0) {
! 235: if ((ms->flags & MAGIC_DEBUG) != 0)
! 236: (void)fprintf(stderr, "softmagic %d\n", m);
! 237: #ifdef BUILTIN_ELF
! 238: if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 &&
! 239: nb > 5 && fd != -1) {
! 240: /*
! 241: * We matched something in the file, so this
! 242: * *might* be an ELF file, and the file is at
! 243: * least 5 bytes long, so if it's an ELF file
! 244: * it has at least one byte past the ELF magic
! 245: * number - try extracting information from the
! 246: * ELF headers that cannot easily * be
! 247: * extracted with rules in the magic file.
! 248: */
! 249: if ((m = file_tryelf(ms, fd, ubuf, nb)) != 0)
! 250: if ((ms->flags & MAGIC_DEBUG) != 0)
! 251: (void)fprintf(stderr,
! 252: "elf %d\n", m);
! 253: }
! 254: #endif
! 255: goto done;
! 256: }
! 257:
! 258: /* try text properties (and possibly text tokens) */
! 259: if ((ms->flags & MAGIC_NO_CHECK_TEXT) == 0) {
! 260:
! 261: if ((m = file_ascmagic(ms, ubuf, nb)) != 0) {
! 262: if ((ms->flags & MAGIC_DEBUG) != 0)
! 263: (void)fprintf(stderr, "ascmagic %d\n", m);
! 264: goto done;
! 265: }
! 266:
! 267: /* try to discover text encoding */
! 268: if ((ms->flags & MAGIC_NO_CHECK_ENCODING) == 0) {
! 269: if (looks_text == 0)
! 270: if ((m = file_ascmagic_with_encoding( ms, ubuf,
! 271: nb, u8buf, ulen, code, type)) != 0) {
! 272: if ((ms->flags & MAGIC_DEBUG) != 0)
! 273: (void)fprintf(stderr,
! 274: "ascmagic/enc %d\n", m);
! 275: goto done;
! 276: }
! 277: }
! 278: }
! 279:
! 280: /* give up */
! 281: m = 1;
! 282: if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
! 283: file_printf(ms, mime ? "application/octet-stream" : "data") == -1) {
! 284: rv = -1;
! 285: }
! 286: done:
! 287: if ((ms->flags & MAGIC_MIME_ENCODING) != 0) {
! 288: if (ms->flags & MAGIC_MIME_TYPE)
! 289: if (file_printf(ms, "; charset=") == -1)
! 290: rv = -1;
! 291: if (file_printf(ms, "%s", code_mime) == -1)
! 292: rv = -1;
! 293: }
! 294: if (u8buf)
! 295: free(u8buf);
! 296: if (rv)
! 297: return rv;
! 298:
! 299: return m;
! 300: }
! 301:
! 302: protected int
! 303: file_reset(struct magic_set *ms)
! 304: {
! 305: if (ms->mlist == NULL) {
! 306: file_error(ms, 0, "no magic files loaded");
! 307: return -1;
! 308: }
! 309: if (ms->o.buf) {
! 310: efree(ms->o.buf);
! 311: ms->o.buf = NULL;
! 312: }
! 313: if (ms->o.pbuf) {
! 314: efree(ms->o.pbuf);
! 315: ms->o.pbuf = NULL;
! 316: }
! 317: ms->event_flags &= ~EVENT_HAD_ERR;
! 318: ms->error = -1;
! 319: return 0;
! 320: }
! 321:
! 322: #define OCTALIFY(n, o) \
! 323: /*LINTED*/ \
! 324: (void)(*(n)++ = '\\', \
! 325: *(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \
! 326: *(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \
! 327: *(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \
! 328: (o)++)
! 329:
! 330: protected const char *
! 331: file_getbuffer(struct magic_set *ms)
! 332: {
! 333: char *pbuf, *op, *np;
! 334: size_t psize, len;
! 335:
! 336: if (ms->event_flags & EVENT_HAD_ERR)
! 337: return NULL;
! 338:
! 339: if (ms->flags & MAGIC_RAW)
! 340: return ms->o.buf;
! 341:
! 342: if (ms->o.buf == NULL)
! 343: return NULL;
! 344:
! 345: /* * 4 is for octal representation, + 1 is for NUL */
! 346: len = strlen(ms->o.buf);
! 347: if (len > (SIZE_MAX - 1) / 4) {
! 348: return NULL;
! 349: }
! 350: psize = len * 4 + 1;
! 351: pbuf = erealloc(ms->o.pbuf, psize);
! 352: ms->o.pbuf = pbuf;
! 353:
! 354: #if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
! 355: {
! 356: mbstate_t state;
! 357: wchar_t nextchar;
! 358: int mb_conv = 1;
! 359: size_t bytesconsumed;
! 360: char *eop;
! 361: (void)memset(&state, 0, sizeof(mbstate_t));
! 362:
! 363: np = ms->o.pbuf;
! 364: op = ms->o.buf;
! 365: eop = op + len;
! 366:
! 367: while (op < eop) {
! 368: bytesconsumed = mbrtowc(&nextchar, op,
! 369: (size_t)(eop - op), &state);
! 370: if (bytesconsumed == (size_t)(-1) ||
! 371: bytesconsumed == (size_t)(-2)) {
! 372: mb_conv = 0;
! 373: break;
! 374: }
! 375:
! 376: if (iswprint(nextchar)) {
! 377: (void)memcpy(np, op, bytesconsumed);
! 378: op += bytesconsumed;
! 379: np += bytesconsumed;
! 380: } else {
! 381: while (bytesconsumed-- > 0)
! 382: OCTALIFY(np, op);
! 383: }
! 384: }
! 385: *np = '\0';
! 386:
! 387: /* Parsing succeeded as a multi-byte sequence */
! 388: if (mb_conv != 0)
! 389: return ms->o.pbuf;
! 390: }
! 391: #endif
! 392:
! 393: for (np = ms->o.pbuf, op = ms->o.buf; *op; op++) {
! 394: if (isprint((unsigned char)*op)) {
! 395: *np++ = *op;
! 396: } else {
! 397: OCTALIFY(np, op);
! 398: }
! 399: }
! 400: *np = '\0';
! 401: return ms->o.pbuf;
! 402: }
! 403:
! 404: protected int
! 405: file_check_mem(struct magic_set *ms, unsigned int level)
! 406: {
! 407: size_t len;
! 408:
! 409: if (level >= ms->c.len) {
! 410: len = (ms->c.len += 20) * sizeof(*ms->c.li);
! 411: ms->c.li = (ms->c.li == NULL) ? emalloc(len) : erealloc(ms->c.li, len);
! 412: }
! 413: ms->c.li[level].got_match = 0;
! 414: #ifdef ENABLE_CONDITIONALS
! 415: ms->c.li[level].last_match = 0;
! 416: ms->c.li[level].last_cond = COND_NONE;
! 417: #endif /* ENABLE_CONDITIONALS */
! 418: return 0;
! 419: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>