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

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.2 ! misho      30: FILE_RCSID("@(#)$File: funcs.c,v 1.60 2011/12/08 12:38:24 rrt 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: 
                    194: #if defined(__EMX__)
                    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: {
                    310:        if (ms->mlist == NULL) {
                    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: {
                    338:        char *pbuf, *op, *np;
                    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;
                    356:        pbuf = erealloc(ms->o.pbuf, psize);
                    357:        ms->o.pbuf = pbuf;
                    358: 
                    359: #if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
                    360:        {
                    361:                mbstate_t state;
                    362:                wchar_t nextchar;
                    363:                int mb_conv = 1;
                    364:                size_t bytesconsumed;
                    365:                char *eop;
                    366:                (void)memset(&state, 0, sizeof(mbstate_t));
                    367: 
                    368:                np = ms->o.pbuf;
                    369:                op = ms->o.buf;
                    370:                eop = op + len;
                    371: 
                    372:                while (op < eop) {
                    373:                        bytesconsumed = mbrtowc(&nextchar, op,
                    374:                            (size_t)(eop - op), &state);
                    375:                        if (bytesconsumed == (size_t)(-1) ||
                    376:                            bytesconsumed == (size_t)(-2)) {
                    377:                                mb_conv = 0;
                    378:                                break;
                    379:                        }
                    380: 
                    381:                        if (iswprint(nextchar)) {
                    382:                                (void)memcpy(np, op, bytesconsumed);
                    383:                                op += bytesconsumed;
                    384:                                np += bytesconsumed;
                    385:                        } else {
                    386:                                while (bytesconsumed-- > 0)
                    387:                                        OCTALIFY(np, op);
                    388:                        }
                    389:                }
                    390:                *np = '\0';
                    391: 
                    392:                /* Parsing succeeded as a multi-byte sequence */
                    393:                if (mb_conv != 0)
                    394:                        return ms->o.pbuf;
                    395:        }
                    396: #endif
                    397: 
1.1.1.2 ! misho     398:        for (np = ms->o.pbuf, op = ms->o.buf; *op;) {
1.1       misho     399:                if (isprint((unsigned char)*op)) {
1.1.1.2 ! misho     400:                        *np++ = *op++;
1.1       misho     401:                } else {
                    402:                        OCTALIFY(np, op);
                    403:                }
                    404:        }
                    405:        *np = '\0';
                    406:        return ms->o.pbuf;
                    407: }
                    408: 
                    409: protected int
                    410: file_check_mem(struct magic_set *ms, unsigned int level)
                    411: {
                    412:        size_t len;
                    413: 
                    414:        if (level >= ms->c.len) {
                    415:                len = (ms->c.len += 20) * sizeof(*ms->c.li);
                    416:                ms->c.li = (ms->c.li == NULL) ? emalloc(len) : erealloc(ms->c.li, len);
                    417:        }
                    418:        ms->c.li[level].got_match = 0;
                    419: #ifdef ENABLE_CONDITIONALS
                    420:        ms->c.li[level].last_match = 0;
                    421:        ms->c.li[level].last_cond = COND_NONE;
                    422: #endif /* ENABLE_CONDITIONALS */
                    423:        return 0;
                    424: }
1.1.1.2 ! misho     425: 
        !           426: protected size_t
        !           427: file_printedlen(const struct magic_set *ms)
        !           428: {
        !           429:        return ms->o.buf == NULL ? 0 : strlen(ms->o.buf);
        !           430: }
        !           431: 
        !           432: 
        !           433: protected int 
        !           434: file_replace(struct magic_set *ms, const char *pat, const char *rep)
        !           435: {
        !           436:        zval *patt;
        !           437:        int opts = 0;
        !           438:        pcre_cache_entry *pce;
        !           439:        char *res;
        !           440:        zval *repl;
        !           441:        int res_len, rep_cnt;
        !           442:        TSRMLS_FETCH();
        !           443: 
        !           444:        MAKE_STD_ZVAL(patt);
        !           445:        ZVAL_STRINGL(patt, pat, strlen(pat), 0);
        !           446:        opts |= PCRE_MULTILINE;
        !           447:        convert_libmagic_pattern(patt, opts);
        !           448: #if (PHP_MAJOR_VERSION < 6)
        !           449:        if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(patt), Z_STRLEN_P(patt) TSRMLS_CC)) == NULL) {
        !           450: #else
        !           451:        if ((pce = pcre_get_compiled_regex_cache(IS_STRING, Z_STRVAL_P(patt), Z_STRLEN_P(patt) TSRMLS_CC)) == NULL) {
        !           452: #endif
        !           453:                zval_dtor(patt);
        !           454:                FREE_ZVAL(patt);
        !           455:                return -1;
        !           456:        }
        !           457: 
        !           458:        MAKE_STD_ZVAL(repl);
        !           459:        ZVAL_STRINGL(repl, rep, strlen(rep), 0);
        !           460: 
        !           461:        res = php_pcre_replace_impl(pce, ms->o.buf, strlen(ms->o.buf), repl,
        !           462:                        0, &res_len, -1, &rep_cnt TSRMLS_CC);
        !           463: 
        !           464:        FREE_ZVAL(repl);
        !           465:        zval_dtor(patt);
        !           466:        FREE_ZVAL(patt);
        !           467: 
        !           468:        if (NULL == res) {
        !           469:                return -1;
        !           470:        }
        !           471: 
        !           472:        strncpy(ms->o.buf, res, res_len);
        !           473:        ms->o.buf[res_len] = '\0';
        !           474: 
        !           475:        efree(res);
        !           476: 
        !           477:        return rep_cnt;
        !           478: }
        !           479: 

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