Annotation of embedaddon/php/ext/fileinfo/libmagic/funcs.c, revision 1.1.1.3

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
1.1.1.3 ! misho      30: FILE_RCSID("@(#)$File: funcs.c,v 1.61 2012/10/30 23:11:51 christos Exp $")
1.1       misho      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: 
1.1.1.2   misho      49: #ifndef PREG_OFFSET_CAPTURE
                     50: # define PREG_OFFSET_CAPTURE                 (1<<8)
                     51: #endif
                     52: 
                     53: extern public void convert_libmagic_pattern(zval *pattern, int options);
                     54: 
1.1       misho      55: /*
                     56:  * Like printf, only we append to a buffer.
                     57:  */
                     58: protected int
                     59: file_printf(struct magic_set *ms, const char *fmt, ...)
                     60: {
                     61:        va_list ap;
                     62:        int len;
                     63:        char *buf = NULL, *newstr;
                     64: 
                     65:        va_start(ap, fmt);
                     66:        len = vspprintf(&buf, 0, fmt, ap);
                     67:        va_end(ap);
                     68: 
                     69:        if (ms->o.buf != NULL) {
                     70:                len = spprintf(&newstr, 0, "%s%s", ms->o.buf, (buf ? buf : ""));
                     71:                if (buf) {
                     72:                        efree(buf);
                     73:                }
                     74:                efree(ms->o.buf);
                     75:                ms->o.buf = newstr;
                     76:        } else {
                     77:                ms->o.buf = buf;
                     78:        }
                     79:        return 0;
                     80: }
                     81: 
                     82: /*
                     83:  * error - print best error message possible
                     84:  */
                     85: /*VARARGS*/
                     86: private void
                     87: file_error_core(struct magic_set *ms, int error, const char *f, va_list va,
1.1.1.2   misho      88:     size_t lineno)
1.1       misho      89: {
                     90:        char *buf = NULL;
                     91:        
                     92:        /* Only the first error is ok */
1.1.1.2   misho      93:        if (ms->event_flags & EVENT_HAD_ERR)
1.1       misho      94:                return;
                     95:        if (lineno != 0) {
                     96:                efree(ms->o.buf);
                     97:                ms->o.buf = NULL;
1.1.1.2   misho      98:                file_printf(ms, "line %" SIZE_T_FORMAT "u: ", lineno);
1.1       misho      99:        }
                    100: 
                    101:        vspprintf(&buf, 0, f, va);
                    102:        va_end(va);
                    103:        
                    104:        if (error > 0) {
                    105:                file_printf(ms, "%s (%s)", (*buf ? buf : ""), strerror(error));
                    106:        } else if (*buf) {
                    107:                file_printf(ms, "%s", buf);
                    108:        }
                    109:        
                    110:        if (buf) {
                    111:                efree(buf);
                    112:        }
                    113: 
                    114:        ms->event_flags |= EVENT_HAD_ERR;
                    115:        ms->error = error;
                    116: }
                    117: 
                    118: /*VARARGS*/
                    119: protected void
                    120: file_error(struct magic_set *ms, int error, const char *f, ...)
                    121: {
                    122:        va_list va;
                    123:        va_start(va, f);
                    124:        file_error_core(ms, error, f, va, 0);
                    125:        va_end(va);
                    126: }
                    127: 
                    128: /*
                    129:  * Print an error with magic line number.
                    130:  */
                    131: /*VARARGS*/
                    132: protected void
                    133: file_magerror(struct magic_set *ms, const char *f, ...)
                    134: {
                    135:        va_list va;
                    136:        va_start(va, f);
                    137:        file_error_core(ms, 0, f, va, ms->line);
                    138:        va_end(va);
                    139: }
                    140: 
                    141: protected void
                    142: file_oomem(struct magic_set *ms, size_t len)
                    143: {
1.1.1.2   misho     144:        file_error(ms, errno, "cannot allocate %" SIZE_T_FORMAT "u bytes",
                    145:            len);
1.1       misho     146: }
                    147: 
                    148: protected void
                    149: file_badseek(struct magic_set *ms)
                    150: {
                    151:        file_error(ms, errno, "error seeking");
                    152: }
                    153: 
                    154: protected void
                    155: file_badread(struct magic_set *ms)
                    156: {
                    157:        file_error(ms, errno, "error reading");
                    158: }
                    159: 
                    160: protected int
                    161: file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const void *buf,
                    162:     size_t nb)
                    163: {
                    164:        int m = 0, rv = 0, looks_text = 0;
                    165:        int mime = ms->flags & MAGIC_MIME;
1.1.1.2   misho     166:        const unsigned char *ubuf = CAST(const unsigned char *, buf);
1.1       misho     167:        unichar *u8buf = NULL;
                    168:        size_t ulen;
                    169:        const char *code = NULL;
                    170:        const char *code_mime = "binary";
                    171:        const char *type = NULL;
                    172: 
                    173: 
                    174: 
                    175:        if (nb == 0) {
                    176:                if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
                    177:                    file_printf(ms, mime ? "application/x-empty" :
                    178:                    "empty") == -1)
                    179:                        return -1;
                    180:                return 1;
                    181:        } else if (nb == 1) {
                    182:                if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
                    183:                    file_printf(ms, mime ? "application/octet-stream" :
                    184:                    "very short file (no magic)") == -1)
                    185:                        return -1;
                    186:                return 1;
                    187:        }
                    188: 
                    189:        if ((ms->flags & MAGIC_NO_CHECK_ENCODING) == 0) {
                    190:                looks_text = file_encoding(ms, ubuf, nb, &u8buf, &ulen,
                    191:                    &code, &code_mime, &type);
                    192:        }
                    193: 
1.1.1.3 ! misho     194: #ifdef __EMX__
1.1       misho     195:        if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) {
                    196:                switch (file_os2_apptype(ms, inname, buf, nb)) {
                    197:                case -1:
                    198:                        return -1;
                    199:                case 0:
                    200:                        break;
                    201:                default:
                    202:                        return 1;
                    203:                }
                    204:        }
                    205: #endif
                    206: 
                    207: #if PHP_FILEINFO_UNCOMPRESS
                    208:        if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) == 0)
                    209:                if ((m = file_zmagic(ms, stream, inname, ubuf, nb)) != 0) {
                    210:                        if ((ms->flags & MAGIC_DEBUG) != 0)
                    211:                                (void)fprintf(stderr, "zmagic %d\n", m);
                    212:                        goto done;
1.1.1.2   misho     213:                }
1.1       misho     214: #endif
                    215:        /* Check if we have a tar file */
                    216:        if ((ms->flags & MAGIC_NO_CHECK_TAR) == 0)
                    217:                if ((m = file_is_tar(ms, ubuf, nb)) != 0) {
                    218:                        if ((ms->flags & MAGIC_DEBUG) != 0)
                    219:                                (void)fprintf(stderr, "tar %d\n", m);
                    220:                        goto done;
                    221:                }
                    222: 
                    223:        /* Check if we have a CDF file */
                    224:        if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) {
                    225:                int fd;
                    226:                TSRMLS_FETCH();
                    227:                if (stream && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&fd, 0)) {
                    228:                        if ((m = file_trycdf(ms, fd, ubuf, nb)) != 0) {
                    229:                                if ((ms->flags & MAGIC_DEBUG) != 0)
                    230:                                        (void)fprintf(stderr, "cdf %d\n", m);
                    231:                                goto done;
                    232:                        }
                    233:                }
                    234:        }
                    235: 
                    236:        /* try soft magic tests */
                    237:        if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0)
1.1.1.2   misho     238:                if ((m = file_softmagic(ms, ubuf, nb, BINTEST,
                    239:                    looks_text)) != 0) {
1.1       misho     240:                        if ((ms->flags & MAGIC_DEBUG) != 0)
                    241:                                (void)fprintf(stderr, "softmagic %d\n", m);
                    242: #ifdef BUILTIN_ELF
                    243:                        if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 &&
                    244:                            nb > 5 && fd != -1) {
                    245:                                /*
                    246:                                 * We matched something in the file, so this
                    247:                                 * *might* be an ELF file, and the file is at
                    248:                                 * least 5 bytes long, so if it's an ELF file
                    249:                                 * it has at least one byte past the ELF magic
                    250:                                 * number - try extracting information from the
                    251:                                 * ELF headers that cannot easily * be
                    252:                                 * extracted with rules in the magic file.
                    253:                                 */
                    254:                                if ((m = file_tryelf(ms, fd, ubuf, nb)) != 0)
                    255:                                        if ((ms->flags & MAGIC_DEBUG) != 0)
                    256:                                                (void)fprintf(stderr,
                    257:                                                    "elf %d\n", m);
                    258:                        }
                    259: #endif
                    260:                        goto done;
                    261:                }
                    262: 
1.1.1.2   misho     263:        /* try text properties */
1.1       misho     264:        if ((ms->flags & MAGIC_NO_CHECK_TEXT) == 0) {
                    265: 
1.1.1.2   misho     266:                if ((m = file_ascmagic(ms, ubuf, nb, looks_text)) != 0) {
1.1       misho     267:                        if ((ms->flags & MAGIC_DEBUG) != 0)
                    268:                                (void)fprintf(stderr, "ascmagic %d\n", m);
                    269:                        goto done;
                    270:                }
                    271: 
                    272:                /* try to discover text encoding */
                    273:                if ((ms->flags & MAGIC_NO_CHECK_ENCODING) == 0) {
                    274:                        if (looks_text == 0)
                    275:                                if ((m = file_ascmagic_with_encoding( ms, ubuf,
1.1.1.2   misho     276:                                    nb, u8buf, ulen, code, type, looks_text))
                    277:                                    != 0) {
1.1       misho     278:                                        if ((ms->flags & MAGIC_DEBUG) != 0)
                    279:                                                (void)fprintf(stderr,
                    280:                                                    "ascmagic/enc %d\n", m);
                    281:                                        goto done;
                    282:                                }
                    283:                }
                    284:        }
                    285: 
                    286:        /* give up */
                    287:        m = 1;
                    288:        if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
                    289:            file_printf(ms, mime ? "application/octet-stream" : "data") == -1) {
                    290:            rv = -1;
                    291:        }
                    292:  done:
                    293:        if ((ms->flags & MAGIC_MIME_ENCODING) != 0) {
                    294:                if (ms->flags & MAGIC_MIME_TYPE)
                    295:                        if (file_printf(ms, "; charset=") == -1)
                    296:                                rv = -1;
                    297:                if (file_printf(ms, "%s", code_mime) == -1)
                    298:                        rv = -1;
                    299:        }
1.1.1.2   misho     300:        free(u8buf);
1.1       misho     301:        if (rv)
                    302:                return rv;
                    303: 
                    304:        return m;
                    305: }
                    306: 
                    307: protected int
                    308: file_reset(struct magic_set *ms)
                    309: {
1.1.1.3 ! misho     310:        if (ms->mlist[0] == NULL) {
1.1       misho     311:                file_error(ms, 0, "no magic files loaded");
                    312:                return -1;
                    313:        }
                    314:        if (ms->o.buf) {
                    315:                efree(ms->o.buf);
                    316:                ms->o.buf = NULL;
                    317:        }
                    318:        if (ms->o.pbuf) {
                    319:                efree(ms->o.pbuf);
                    320:                ms->o.pbuf = NULL;
                    321:        }
                    322:        ms->event_flags &= ~EVENT_HAD_ERR;
                    323:        ms->error = -1;
                    324:        return 0;
                    325: }
                    326: 
                    327: #define OCTALIFY(n, o) \
                    328:        /*LINTED*/ \
                    329:        (void)(*(n)++ = '\\', \
                    330:        *(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \
                    331:        *(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \
                    332:        *(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \
                    333:        (o)++)
                    334: 
                    335: protected const char *
                    336: file_getbuffer(struct magic_set *ms)
                    337: {
1.1.1.3 ! misho     338:        char *op, *np;
1.1       misho     339:        size_t psize, len;
                    340: 
                    341:        if (ms->event_flags & EVENT_HAD_ERR)
                    342:                return NULL;
                    343: 
                    344:        if (ms->flags & MAGIC_RAW)
                    345:                return ms->o.buf;
                    346: 
                    347:        if (ms->o.buf == NULL)
                    348:                return NULL;
                    349: 
                    350:        /* * 4 is for octal representation, + 1 is for NUL */
                    351:        len = strlen(ms->o.buf);
                    352:        if (len > (SIZE_MAX - 1) / 4) {
                    353:                return NULL;
                    354:        }
                    355:        psize = len * 4 + 1;
1.1.1.3 ! misho     356:        if ((ms->o.pbuf = CAST(char *, erealloc(ms->o.pbuf, psize))) == NULL) {
        !           357:                file_oomem(ms, psize);
        !           358:                return NULL;
        !           359:        }
1.1       misho     360: 
                    361: #if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
                    362:        {
                    363:                mbstate_t state;
                    364:                wchar_t nextchar;
                    365:                int mb_conv = 1;
                    366:                size_t bytesconsumed;
                    367:                char *eop;
                    368:                (void)memset(&state, 0, sizeof(mbstate_t));
                    369: 
                    370:                np = ms->o.pbuf;
                    371:                op = ms->o.buf;
                    372:                eop = op + len;
                    373: 
                    374:                while (op < eop) {
                    375:                        bytesconsumed = mbrtowc(&nextchar, op,
                    376:                            (size_t)(eop - op), &state);
                    377:                        if (bytesconsumed == (size_t)(-1) ||
                    378:                            bytesconsumed == (size_t)(-2)) {
                    379:                                mb_conv = 0;
                    380:                                break;
                    381:                        }
                    382: 
                    383:                        if (iswprint(nextchar)) {
                    384:                                (void)memcpy(np, op, bytesconsumed);
                    385:                                op += bytesconsumed;
                    386:                                np += bytesconsumed;
                    387:                        } else {
                    388:                                while (bytesconsumed-- > 0)
                    389:                                        OCTALIFY(np, op);
                    390:                        }
                    391:                }
                    392:                *np = '\0';
                    393: 
                    394:                /* Parsing succeeded as a multi-byte sequence */
                    395:                if (mb_conv != 0)
                    396:                        return ms->o.pbuf;
                    397:        }
                    398: #endif
                    399: 
1.1.1.2   misho     400:        for (np = ms->o.pbuf, op = ms->o.buf; *op;) {
1.1       misho     401:                if (isprint((unsigned char)*op)) {
1.1.1.2   misho     402:                        *np++ = *op++;
1.1       misho     403:                } else {
                    404:                        OCTALIFY(np, op);
                    405:                }
                    406:        }
                    407:        *np = '\0';
                    408:        return ms->o.pbuf;
                    409: }
                    410: 
                    411: protected int
                    412: file_check_mem(struct magic_set *ms, unsigned int level)
                    413: {
                    414:        size_t len;
                    415: 
                    416:        if (level >= ms->c.len) {
                    417:                len = (ms->c.len += 20) * sizeof(*ms->c.li);
1.1.1.3 ! misho     418:                ms->c.li = CAST(struct level_info *, (ms->c.li == NULL) ?
        !           419:                    emalloc(len) :
        !           420:                    erealloc(ms->c.li, len));
        !           421:                if (ms->c.li == NULL) {
        !           422:                        file_oomem(ms, len);
        !           423:                        return -1;
        !           424:                }
1.1       misho     425:        }
                    426:        ms->c.li[level].got_match = 0;
                    427: #ifdef ENABLE_CONDITIONALS
                    428:        ms->c.li[level].last_match = 0;
                    429:        ms->c.li[level].last_cond = COND_NONE;
                    430: #endif /* ENABLE_CONDITIONALS */
                    431:        return 0;
                    432: }
1.1.1.2   misho     433: 
                    434: protected size_t
                    435: file_printedlen(const struct magic_set *ms)
                    436: {
                    437:        return ms->o.buf == NULL ? 0 : strlen(ms->o.buf);
                    438: }
                    439: 
                    440: 
                    441: protected int 
                    442: file_replace(struct magic_set *ms, const char *pat, const char *rep)
                    443: {
                    444:        zval *patt;
                    445:        int opts = 0;
                    446:        pcre_cache_entry *pce;
                    447:        char *res;
                    448:        zval *repl;
1.1.1.3 ! misho     449:        int res_len, rep_cnt = 0;
1.1.1.2   misho     450:        TSRMLS_FETCH();
                    451: 
                    452:        MAKE_STD_ZVAL(patt);
                    453:        ZVAL_STRINGL(patt, pat, strlen(pat), 0);
                    454:        opts |= PCRE_MULTILINE;
                    455:        convert_libmagic_pattern(patt, opts);
                    456:        if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(patt), Z_STRLEN_P(patt) TSRMLS_CC)) == NULL) {
                    457:                zval_dtor(patt);
                    458:                FREE_ZVAL(patt);
                    459:                return -1;
                    460:        }
                    461: 
                    462:        MAKE_STD_ZVAL(repl);
                    463:        ZVAL_STRINGL(repl, rep, strlen(rep), 0);
                    464: 
                    465:        res = php_pcre_replace_impl(pce, ms->o.buf, strlen(ms->o.buf), repl,
                    466:                        0, &res_len, -1, &rep_cnt TSRMLS_CC);
                    467: 
                    468:        FREE_ZVAL(repl);
                    469:        zval_dtor(patt);
                    470:        FREE_ZVAL(patt);
                    471: 
                    472:        if (NULL == res) {
                    473:                return -1;
                    474:        }
                    475: 
                    476:        strncpy(ms->o.buf, res, res_len);
                    477:        ms->o.buf[res_len] = '\0';
                    478: 
                    479:        efree(res);
                    480: 
                    481:        return rep_cnt;
                    482: }
                    483: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>