Annotation of embedaddon/php/ext/fileinfo/libmagic/funcs.c, revision 1.1.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>