Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Apache/modules/metadata/   (Apache Software Stiftung Version 2.4.65©)  Datei vom 24.5.2024 mit Größe 72 kB image not shown  

SSL mod_mime_magic.c   Sprache: C

 
/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


/*
 * mod_mime_magic: MIME type lookup via file magic numbers
 * Copyright (c) 1996-1997 Cisco Systems, Inc.
 *
 * This software was submitted by Cisco Systems to the Apache Software Foundation in July
 * 1997.  Future revisions and derivatives of this source code must
 * acknowledge Cisco Systems as the original contributor of this module.
 * All other licensing and usage conditions are those of the Apache Software Foundation.
 *
 * Some of this code is derived from the free version of the file command
 * originally posted to comp.sources.unix.  Copyright info for that program
 * is included below as required.
 * ---------------------------------------------------------------------------
 * - Copyright (c) Ian F. Darwin, 1987. Written by Ian F. Darwin.
 *
 * This software is not subject to any license of the American Telephone and
 * Telegraph Company or of the Regents of the University of California.
 *
 * Permission is granted to anyone to use this software for any purpose on any
 * computer system, and to alter it and redistribute it freely, subject to
 * the following restrictions:
 *
 * 1. The author is not responsible for the consequences of use of this
 * software, no matter how awful, even if they arise from flaws in it.
 *
 * 2. The origin of this software must not be misrepresented, either by
 * explicit claim or by omission.  Since few users ever read sources, credits
 * must appear in the documentation.
 *
 * 3. Altered versions must be plainly marked as such, and must not be
 * misrepresented as being the original software.  Since few users ever read
 * sources, credits must appear in the documentation.
 *
 * 4. This notice may not be removed or altered.
 * -------------------------------------------------------------------------
 *
 * For compliance with Mr Darwin's terms: this has been very significantly
 * modified from the free "file" command.
 * - all-in-one file for compilation convenience when moving from one
 *   version of Apache to the next.
 * - Memory allocation is done through the Apache API's apr_pool_t structure.
 * - All functions have had necessary Apache API request or server
 *   structures passed to them where necessary to call other Apache API
 *   routines.  (i.e. usually for logging, files, or memory allocation in
 *   itself or a called function.)
 * - struct magic has been converted from an array to a single-ended linked
 *   list because it only grows one record at a time, it's only accessed
 *   sequentially, and the Apache API has no equivalent of realloc().
 * - Functions have been changed to get their parameters from the server
 *   configuration instead of globals.  (It should be reentrant now but has
 *   not been tested in a threaded environment.)
 * - Places where it used to print results to stdout now saves them in a
 *   list where they're used to set the MIME type in the Apache request
 *   record.
 * - Command-line flags have been removed since they will never be used here.
 *
 * Ian Kluft <ikluft@cisco.com>
 * Engineering Information Framework
 * Central Engineering
 * Cisco Systems, Inc.
 * San Jose, CA, USA
 *
 * Initial installation          July/August 1996
 * Misc bug fixes                May 1997
 * Submission to Apache Software Foundation    July 1997
 *
 */


#include "apr.h"
#include "apr_strings.h"
#include "apr_lib.h"
#define APR_WANT_STRFUNC
#include "apr_want.h"

#if APR_HAVE_UNISTD_H
#include <unistd.h>
#endif

#include "ap_config.h"
#include "httpd.h"
#include "http_config.h"
#include "http_request.h"
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
#include "util_script.h"

/* ### this isn't set by configure? does anybody set this? */
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif

/*
 * data structures and related constants
 */


#define MODNAME        "mod_mime_magic"
#define MIME_MAGIC_DEBUG        0

#define MIME_BINARY_UNKNOWN    "application/octet-stream"
#define MIME_TEXT_UNKNOWN    "text/plain"

#define MAXMIMESTRING        256

/* HOWMANY must be at least 4096 to make gzip -dcq work */
#define HOWMANY  4096
/* SMALL_HOWMANY limits how much work we do to figure out text files */
#define SMALL_HOWMANY 1024
#define MAXDESC    50   /* max leng of text description */
#define MAXstring 64    /* max leng of "string" types */

struct magic {
    struct magic *next;     /* link to next entry */
    int lineno;             /* line number from magic file */

    short flag;
#define INDIR  1            /* if '>(...)' appears,  */
#define UNSIGNED 2          /* comparison is unsigned */
    short cont_level;       /* level of ">" */
    struct {
        char type;          /* byte short long */
        long offset;        /* offset from indirection */
    } in;
    long offset;            /* offset to magic number */
    unsigned char reln;     /* relation (0=eq, '>'=gt, etc) */
    char type;              /* int, short, long or string. */
    char vallen;            /* length of string value, if any */
#define BYTE      1
#define SHORT     2
#define LONG      4
#define STRING    5
#define DATE      6
#define BESHORT   7
#define BELONG    8
#define BEDATE    9
#define LESHORT  10
#define LELONG   11
#define LEDATE   12
    union VALUETYPE {
        unsigned char b;
        unsigned short h;
        unsigned long l;
        char s[MAXstring];
        unsigned char hs[2];   /* 2 bytes of a fixed-endian "short" */
        unsigned char hl[4];   /* 2 bytes of a fixed-endian "long" */
    } value;                   /* either number or string */
    unsigned long mask;        /* mask before comparison with value */
    char nospflag;             /* suppress space character */

    /* NOTE: this string is suspected of overrunning - find it! */
    char desc[MAXDESC];        /* description */
};

/*
 * data structures for tar file recognition
 * --------------------------------------------------------------------------
 * Header file for public domain tar (tape archive) program.
 *
 * @(#)tar.h 1.20 86/10/29    Public Domain. Created 25 August 1985 by John
 * Gilmore, ihnp4!hoptoad!gnu.
 *
 * Header block on tape.
 *
 * I'm going to use traditional DP naming conventions here. A "block" is a big
 * chunk of stuff that we do I/O on. A "record" is a piece of info that we
 * care about. Typically many "record"s fit into a "block".
 */

#define RECORDSIZE    512
#define NAMSIZ    100
#define TUNMLEN    32
#define TGNMLEN    32

union record {
    char charptr[RECORDSIZE];
    struct header {
        char name[NAMSIZ];
        char mode[8];
        char uid[8];
        char gid[8];
        char size[12];
        char mtime[12];
        char chksum[8];
        char linkflag;
        char linkname[NAMSIZ];
        char magic[8];
        char uname[TUNMLEN];
        char gname[TGNMLEN];
        char devmajor[8];
        char devminor[8];
    } header;
};

/* The magic field is filled with this if uname and gname are valid. */
#define    TMAGIC        "ustar "   /* 7 chars and a null */

/*
 * file-function prototypes
 */

static int ascmagic(request_rec *, unsigned char *, apr_size_t);
static int is_tar(unsigned char *, apr_size_t);
static int softmagic(request_rec *, unsigned char *, apr_size_t);
static int tryit(request_rec *, unsigned char *, apr_size_t, int);
static int zmagic(request_rec *, unsigned char *, apr_size_t);

static int getvalue(server_rec *, struct magic *, char **);
static int hextoint(int);
static char *getstr(server_rec *, char *, char *, intint *);
static int parse(server_rec *, apr_pool_t *p, char *, int);

static int match(request_rec *, unsigned char *, apr_size_t);
static int mget(request_rec *, union VALUETYPE *, unsigned char *,
                struct magic *, apr_size_t);
static int mcheck(request_rec *, union VALUETYPE *, struct magic *);
static void mprint(request_rec *, union VALUETYPE *, struct magic *);

static int uncompress(request_rec *, int,
                      unsigned char **, apr_size_t);
static long from_oct(intchar *);
static int fsmagic(request_rec *r, const char *fn);

/*
 * includes for ASCII substring recognition formerly "names.h" in file
 * command
 *
 * Original notes: names and types used by ascmagic in file(1). These tokens are
 * here because they can appear anywhere in the first HOWMANY bytes, while
 * tokens in /etc/magic must appear at fixed offsets into the file. Don't
 * make HOWMANY too high unless you have a very fast CPU.
 */


/* these types are used to index the apr_table_t 'types': keep em in sync! */
/* HTML inserted in first because this is a web server module now */
#define L_HTML    0   /* HTML */
#define L_C       1   /* first and foremost on UNIX */
#define L_FORT    2   /* the oldest one */
#define L_MAKE    3   /* Makefiles */
#define L_PLI     4   /* PL/1 */
#define L_MACH    5   /* some kinda assembler */
#define L_ENG     6   /* English */
#define L_PAS     7   /* Pascal */
#define L_MAIL    8   /* Electronic mail */
#define L_NEWS    9   /* Usenet Netnews */

static const char *const types[] =
{
    "text/html",             /* HTML */
    "text/plain",            /* "c program text", */
    "text/plain",            /* "fortran program text", */
    "text/plain",            /* "make commands text", */
    "text/plain",            /* "pl/1 program text", */
    "text/plain",            /* "assembler program text", */
    "text/plain",            /* "English text", */
    "text/plain",            /* "pascal program text", */
    "message/rfc822",        /* "mail text", */
    "message/news",          /* "news text", */
    "application/binary",    /* "can't happen error on names.h/types", */
    0
};

static const struct names {
    const char *name;
    short type;
} names[] = {

    /* These must be sorted by eye for optimal hit rate */
    /* Add to this list only after substantial meditation */
    {
        "", L_HTML
    },
    {
        "", L_HTML
    },
    {
        "", L_HTML
    },
    {
        "", L_HTML
    },
    {
        ""</span>, L_HTML<br>     },<br>     {<br>         <span style='color:blue'>"<TITLE>"</span>, L_HTML<br>     },<br>     {<br>         <span style='color:blue'>"<h1>"</span>, L_HTML<br>     },<br>     {<br>         <span style='color:blue'>"<H1>"</span>, L_HTML<br>     },<br>     {<br>         <span style='color:blue'>"<!--"</span>, L_HTML<br>     },<br>     {<br>         <span style='color:blue'>"<!DOCTYPE HTML"</span>, L_HTML<br>     },<br>     {<br>         <span style='color:blue'>"/*", L_C</span><br>     },               <span style='color:green'>/* must precede "The", "the", etc. */</span><br>     {<br>         <span style='color:blue'>"#include"</span>, L_C<br>     },<br>     {<br>         <span style='color:blue'>"char"</span>, L_C<br>     },<br>     {<br>         <span style='color:blue'>"The"</span>, L_ENG<br>     },<br>     {<br>         <span style='color:blue'>"the"</span>, L_ENG<br>     },<br>     {<br>         <span style='color:blue'>"double"</span>, L_C<br>     },<br>     {<br>         <span style='color:blue'>"extern"</span>, L_C<br>     },<br>     {<br>         <span style='color:blue'>"float"</span>, L_C<br>     },<br>     {<br>         <span style='color:blue'>"real"</span>, L_C<br>     },<br>     {<br>         <span style='color:blue'>"struct"</span>, L_C<br>     },<br>     {<br>         <span style='color:blue'>"union"</span>, L_C<br>     },<br>     {<br>         <span style='color:blue'>"CFLAGS"</span>, L_MAKE<br>     },<br>     {<br>         <span style='color:blue'>"LDFLAGS"</span>, L_MAKE<br>     },<br>     {<br>         <span style='color:blue'>"all:"</span>, L_MAKE<br>     },<br>     {<br>         <span style='color:blue'>".PRECIOUS"</span>, L_MAKE<br>     },<br>     <span style='color:green'>/*<br> <span style='color:green'>     * Too many files of text have these words in them.  Find another way to</span><br> <span style='color:green'>     * recognize Fortrash.</span><br>      */</span><br> <span style='color:turquoise'>#ifdef</span>    NOTDEF<br>     {<br>         <span style='color:blue'>"subroutine"</span>, L_FORT<br>     },<br>     {<br>         <span style='color:blue'>"function"</span>, L_FORT<br>     },<br>     {<br>         <span style='color:blue'>"block"</span>, L_FORT<br>     },<br>     {<br>         <span style='color:blue'>"common"</span>, L_FORT<br>     },<br>     {<br>         <span style='color:blue'>"dimension"</span>, L_FORT<br>     },<br>     {<br>         <span style='color:blue'>"integer"</span>, L_FORT<br>     },<br>     {<br>         <span style='color:blue'>"data"</span>, L_FORT<br>     },<br> <span style='color:turquoise'>#endif</span> <span style='color:green'>/* NOTDEF */</span><br>     {<br>         <span style='color:blue'>".ascii"</span>, L_MACH<br>     },<br>     {<br>         <span style='color:blue'>".asciiz"</span>, L_MACH<br>     },<br>     {<br>         <span style='color:blue'>".byte"</span>, L_MACH<br>     },<br>     {<br>         <span style='color:blue'>".even"</span>, L_MACH<br>     },<br>     {<br>         <span style='color:blue'>".globl"</span>, L_MACH<br>     },<br>     {<br>         <span style='color:blue'>"clr"</span>, L_MACH<br>     },<br>     {<br>         <span style='color:blue'>"(input,"</span>, L_PAS<br>     },<br>     {<br>         <span style='color:blue'>"dcl"</span>, L_PLI<br>     },<br>     {<br>         <span style='color:blue'>"Received:"</span>, L_MAIL<br>     },<br>     {<br>         <span style='color:blue'>">From"</span>, L_MAIL<br>     },<br>     {<br>         <span style='color:blue'>"Return-Path:"</span>, L_MAIL<br>     },<br>     {<br>         <span style='color:blue'>"Cc:"</span>, L_MAIL<br>     },<br>     {<br>         <span style='color:blue'>"Newsgroups:"</span>, L_NEWS<br>     },<br>     {<br>         <span style='color:blue'>"Path:"</span>, L_NEWS<br>     },<br>     {<br>         <span style='color:blue'>"Organization:"</span>, L_NEWS<br>     },<br>     {<br>         NULL, 0<br>     }<br> };<br> <br> <span style='color:turquoise'>#define</span> NNAMES ((<span style='color:red'>sizeof</span>(names)/<span style='color:red'>sizeof</span>(<span style='color:red'>struct</span> names)) - 1)<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * Result String List (RSL)</span><br> <span style='color:green'> *</span><br> <span style='color:green'> * The file(1) command prints its output.  Instead, we store the various</span><br> <span style='color:green'> * "printed" strings in a list (allocating memory as we go) and concatenate</span><br> <span style='color:green'> * them at the end when we finally know how much space they'll need.</span><br>  */</span><br> <br> <span style='color:red'>typedef</span> <span style='color:red'>struct</span> magic_rsl_s {<br>     <span style='color:red'>const</span> <span style='color:red'>char</span> *str;                  <span style='color:green'>/* string, possibly a fragment */</span><br>     <span style='color:red'>struct</span> magic_rsl_s *next;   <span style='color:green'>/* pointer to next fragment */</span><br> } magic_rsl;<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * Apache module configuration structures</span><br>  */</span><br> <br> <span style='color:green'>/* per-server info */</span><br> <span style='color:red'>typedef</span> <span style='color:red'>struct</span> {<br>     <span style='color:red'>const</span> <span style='color:red'>char</span> *magicfile;    <span style='color:green'>/* where magic be found */</span><br>     <span style='color:red'>struct</span> magic *magic;      <span style='color:green'>/* head of magic config list */</span><br>     <span style='color:red'>struct</span> magic *last;<br> } magic_server_config_rec;<br> <br> <span style='color:green'>/* per-request info */</span><br> <span style='color:red'>typedef</span> <span style='color:red'>struct</span> {<br>     magic_rsl *head;          <span style='color:green'>/* result string list */</span><br>     magic_rsl *tail;<br> } magic_req_rec;<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * configuration functions - called by Apache API routines</span><br>  */</span><br> <br> module AP_MODULE_DECLARE_DATA mime_magic_module;<br> <br> <span style='color:red'>static</span> <span style='color:red'>void</span> *create_magic_server_config(apr_pool_t *p, server_rec *d)<br> {<br>     <span style='color:green'>/* allocate the config - use pcalloc because it needs to be zeroed */</span><br>     <span style='color:red'>return</span> apr_pcalloc(p, <span style='color:red'>sizeof</span>(magic_server_config_rec));<br> }<br> <br> <span style='color:red'>static</span> <span style='color:red'>void</span> *merge_magic_server_config(apr_pool_t *p, <span style='color:red'>void</span> *basev, <span style='color:red'>void</span> *addv)<br> {<br>     magic_server_config_rec *base = (magic_server_config_rec *) basev;<br>     magic_server_config_rec *add = (magic_server_config_rec *) addv;<br>     magic_server_config_rec *<span style='color:red'>new</span> = (magic_server_config_rec *)<br>                             apr_palloc(p, <span style='color:red'>sizeof</span>(magic_server_config_rec));<br> <br>     new->magicfile = add->magicfile ? add->magicfile : base->magicfile;<br>     new->magic = NULL;<br>     new->last = NULL;<br>     <span style='color:red'>return</span> <span style='color:red'>new</span>;<br> }<br> <br> <span style='color:red'>static</span> <span style='color:red'>const</span> <span style='color:red'>char</span> *set_magicfile(cmd_parms *cmd, <span style='color:red'>void</span> *dummy, <span style='color:red'>const</span> <span style='color:red'>char</span> *arg)<br> {<br>     magic_server_config_rec *conf = (magic_server_config_rec *)<br>     ap_get_module_config(cmd->server->module_config,<br>                       &mime_magic_module);<br> <br>     <span style='color:red'>if</span> (!conf) {<br>         <span style='color:red'>return</span> MODNAME <span style='color:blue'>": server structure not allocated"</span>;<br>     }<br>     conf->magicfile = arg;<br>     <span style='color:red'>return</span> NULL;<br> }<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * configuration file commands - exported to Apache API</span><br>  */</span><br> <br> <span style='color:red'>static</span> <span style='color:red'>const</span> command_rec mime_magic_cmds[] =<br> {<br>     AP_INIT_TAKE1(<span style='color:blue'>"MimeMagicFile"</span>, set_magicfile, NULL, RSRC_CONF,<br>      <span style='color:blue'>"Path to MIME Magic file (in file(1) format)"</span>),<br>     {NULL}<br> };<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * RSL (result string list) processing routines</span><br> <span style='color:green'> *</span><br> <span style='color:green'> * These collect strings that would have been printed in fragments by file(1)</span><br> <span style='color:green'> * into a list of magic_rsl structures with the strings. When complete,</span><br> <span style='color:green'> * they're concatenated together to become the MIME content and encoding</span><br> <span style='color:green'> * types.</span><br> <span style='color:green'> *</span><br> <span style='color:green'> * return value conventions for these functions: functions which return int:</span><br> <span style='color:green'> * failure = -1, other = result functions which return pointers: failure = 0,</span><br> <span style='color:green'> * other = result</span><br>  */</span><br> <br> <span style='color:green'>/* allocate a per-request structure and put it in the request record */</span><br> <span style='color:red'>static</span> magic_req_rec *magic_set_config(request_rec *r)<br> {<br>     magic_req_rec *req_dat = (magic_req_rec *) apr_palloc(r->pool,<br>                                                       <span style='color:red'>sizeof</span>(magic_req_rec));<br> <br>     req_dat->head = req_dat->tail = (magic_rsl *) NULL;<br>     ap_set_module_config(r->request_config, &mime_magic_module, req_dat);<br>     <span style='color:red'>return</span> req_dat;<br> }<br> <br> <span style='color:green'>/* add a string to the result string list for this request */</span><br> <span style='color:green'>/* it is the responsibility of the caller to allocate "str" */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> magic_rsl_add(request_rec *r, <span style='color:red'>const</span> <span style='color:red'>char</span> *str)<br> {<br>     magic_req_rec *req_dat = (magic_req_rec *)<br>                     ap_get_module_config(r->request_config, &mime_magic_module);<br>     magic_rsl *rsl;<br> <br>     <span style='color:green'>/* make sure we have a list to put it in */</span><br>     <span style='color:red'>if</span> (!req_dat) {<br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EINVAL, r, APLOGNO(01507)<br>                     MODNAME <span style='color:blue'>": request config should not be NULL"</span>);<br>         <span style='color:red'>if</span> (!(req_dat = magic_set_config(r))) {<br>             <span style='color:green'>/* failure */</span><br>             <span style='color:red'>return</span> -1;<br>         }<br>     }<br> <br>     <span style='color:green'>/* allocate the list entry */</span><br>     rsl = (magic_rsl *) apr_palloc(r->pool, <span style='color:red'>sizeof</span>(magic_rsl));<br> <br>     <span style='color:green'>/* fill it */</span><br>     rsl->str = str;<br>     rsl->next = (magic_rsl *) NULL;<br> <br>     <span style='color:green'>/* append to the list */</span><br>     <span style='color:red'>if</span> (req_dat->head && req_dat->tail) {<br>         req_dat->tail->next = rsl;<br>         req_dat->tail = rsl;<br>     }<br>     <span style='color:red'>else</span> {<br>         req_dat->head = req_dat->tail = rsl;<br>     }<br> <br>     <span style='color:green'>/* success */</span><br>     <span style='color:red'>return</span> 0;<br> }<br> <br> <span style='color:green'>/* RSL hook for puts-type functions */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> magic_rsl_puts(request_rec *r, <span style='color:red'>const</span> <span style='color:red'>char</span> *str)<br> {<br>     <span style='color:red'>return</span> magic_rsl_add(r, str);<br> }<br> <br> <span style='color:green'>/* RSL hook for printf-type functions */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> magic_rsl_printf(request_rec *r, <span style='color:red'>char</span> *str,...)<br> {<br>     va_list ap;<br> <br>     <span style='color:red'>char</span> buf[MAXMIMESTRING];<br> <br>     <span style='color:green'>/* assemble the string into the buffer */</span><br>     va_start(ap, str);<br>     apr_vsnprintf(buf, <span style='color:red'>sizeof</span>(buf), str, ap);<br>     va_end(ap);<br> <br>     <span style='color:green'>/* add the buffer to the list */</span><br>     <span style='color:red'>return</span> magic_rsl_add(r, apr_pstrdup(r->pool, buf));<br> }<br> <br> <span style='color:green'>/* RSL hook for putchar-type functions */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> magic_rsl_putchar(request_rec *r, <span style='color:red'>char</span> c)<br> {<br>     <span style='color:red'>char</span> str[2];<br> <br>     <span style='color:green'>/* high overhead for 1 char - just hope they don't do this much */</span><br>     str[0] = c;<br>     str[1] = <span style='color:blue'>'\0'</span>;<br>     <span style='color:red'>return</span> magic_rsl_add(r, apr_pstrdup(r->pool, str));<br> }<br> <br> <span style='color:green'>/* allocate and copy a contiguous string from a result string list */</span><br> <span style='color:red'>static</span> <span style='color:red'>char</span> *rsl_strdup(request_rec *r, <span style='color:red'>int</span> start_frag, <span style='color:red'>int</span> start_pos, <span style='color:red'>int</span> len)<br> {<br>     <span style='color:red'>char</span> *result;       <span style='color:green'>/* return value */</span><br>     <span style='color:red'>int</span> cur_frag,       <span style='color:green'>/* current fragment number/counter */</span><br>         cur_pos,        <span style='color:green'>/* current position within fragment */</span><br>         res_pos;        <span style='color:green'>/* position in result string */</span><br>     magic_rsl *frag;    <span style='color:green'>/* list-traversal pointer */</span><br>     magic_req_rec *req_dat = (magic_req_rec *)<br>                     ap_get_module_config(r->request_config, &mime_magic_module);<br> <br>     <span style='color:green'>/* allocate the result string */</span><br>     result = (<span style='color:red'>char</span> *) apr_palloc(r->pool, len + 1);<br> <br>     <span style='color:green'>/* loop through and collect the string */</span><br>     res_pos = 0;<br>     <span style='color:red'>for</span> (frag = req_dat->head, cur_frag = 0;<br>          frag->next;<br>          frag = frag->next, cur_frag++) {<br>         <span style='color:green'>/* loop to the first fragment */</span><br>         <span style='color:red'>if</span> (cur_frag < start_frag)<br>             <span style='color:red'>continue</span>;<br> <br>         <span style='color:green'>/* loop through and collect chars */</span><br>         <span style='color:red'>for</span> (cur_pos = (cur_frag == start_frag) ? start_pos : 0;<br>              frag->str[cur_pos];<br>              cur_pos++) {<br>             <span style='color:red'>if</span> (cur_frag >= start_frag<br>                 && cur_pos >= start_pos<br>                 && res_pos <= len) {<br>                 result[res_pos++] = frag->str[cur_pos];<br>                 <span style='color:red'>if</span> (res_pos > len) {<br>                     <span style='color:red'>break</span>;<br>                 }<br>             }<br>         }<br>     }<br> <br>     <span style='color:green'>/* clean up and return */</span><br>     result[res_pos] = 0;<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01508)<br>              MODNAME <span style='color:blue'>": rsl_strdup() %d chars: %s"</span>, res_pos - 1, result);<br> <span style='color:turquoise'>#endif</span><br>     <span style='color:red'>return</span> result;<br> }<br> <br> <span style='color:green'>/* states for the state-machine algorithm in magic_rsl_to_request() */</span><br> <span style='color:red'>typedef</span> <span style='color:red'>enum</span> {<br>     rsl_leading_space, rsl_type, rsl_subtype, rsl_separator, rsl_encoding<br> } rsl_states;<br> <br> <span style='color:green'>/* process the RSL and set the MIME info in the request record */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> magic_rsl_to_request(request_rec *r)<br> {<br>     <span style='color:red'>int</span> cur_frag,         <span style='color:green'>/* current fragment number/counter */</span><br>         cur_pos,          <span style='color:green'>/* current position within fragment */</span><br>         type_frag,        <span style='color:green'>/* content type starting point: fragment */</span><br>         type_pos,         <span style='color:green'>/* content type starting point: position */</span><br>         type_len,         <span style='color:green'>/* content type length */</span><br>         encoding_frag,    <span style='color:green'>/* content encoding starting point: fragment */</span><br>         encoding_pos,     <span style='color:green'>/* content encoding starting point: position */</span><br>         encoding_len;     <span style='color:green'>/* content encoding length */</span><br> <br>     <span style='color:red'>char</span> *tmp;<br>     magic_rsl *frag;      <span style='color:green'>/* list-traversal pointer */</span><br>     rsl_states state;<br> <br>     magic_req_rec *req_dat = (magic_req_rec *)<br>                     ap_get_module_config(r->request_config, &mime_magic_module);<br> <br>     <span style='color:green'>/* check if we have a result */</span><br>     <span style='color:red'>if</span> (!req_dat || !req_dat->head) {<br>         <span style='color:green'>/* empty - no match, we defer to other Apache modules */</span><br>         <span style='color:red'>return</span> DECLINED;<br>     }<br> <br>     <span style='color:green'>/* start searching for the type and encoding */</span><br>     state = rsl_leading_space;<br>     type_frag = type_pos = type_len = 0;<br>     encoding_frag = encoding_pos = encoding_len = 0;<br>     <span style='color:red'>for</span> (frag = req_dat->head, cur_frag = 0;<br>          frag && frag->next;<br>          frag = frag->next, cur_frag++) {<br>         <span style='color:green'>/* loop through the characters in the fragment */</span><br>         <span style='color:red'>for</span> (cur_pos = 0; frag->str[cur_pos]; cur_pos++) {<br>             <span style='color:red'>if</span> (apr_isspace(frag->str[cur_pos])) {<br>                 <span style='color:green'>/* process whitespace actions for each state */</span><br>                 <span style='color:red'>if</span> (state == rsl_leading_space) {<br>                     <span style='color:green'>/* eat whitespace in this state */</span><br>                     <span style='color:red'>continue</span>;<br>                 }<br>                 <span style='color:red'>else</span> <span style='color:red'>if</span> (state == rsl_type) {<br>                     <span style='color:green'>/* whitespace: type has no slash! */</span><br>                     <span style='color:red'>return</span> DECLINED;<br>                 }<br>                 <span style='color:red'>else</span> <span style='color:red'>if</span> (state == rsl_subtype) {<br>                     <span style='color:green'>/* whitespace: end of MIME type */</span><br>                     state++;<br>                     <span style='color:red'>continue</span>;<br>                 }<br>                 <span style='color:red'>else</span> <span style='color:red'>if</span> (state == rsl_separator) {<br>                     <span style='color:green'>/* eat whitespace in this state */</span><br>                     <span style='color:red'>continue</span>;<br>                 }<br>                 <span style='color:red'>else</span> <span style='color:red'>if</span> (state == rsl_encoding) {<br>                     <span style='color:green'>/* whitespace: end of MIME encoding */</span><br>                     <span style='color:green'>/* we're done */</span><br>                     frag = req_dat->tail;<br>                     <span style='color:red'>break</span>;<br>                 }<br>                 <span style='color:red'>else</span> {<br>                     <span style='color:green'>/* should not be possible */</span><br>                     <span style='color:green'>/* abandon malfunctioning module */</span><br>                     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01509)<br>                                 MODNAME <span style='color:blue'>": bad state %d (ws)"</span>, state);<br>                     <span style='color:red'>return</span> DECLINED;<br>                 }<br>                 <span style='color:green'>/* NOTREACHED */</span><br>             }<br>             <span style='color:red'>else</span> <span style='color:red'>if</span> (state == rsl_type &&<br>                      frag->str[cur_pos] == <span style='color:blue'>'/'</span>) {<br>                 <span style='color:green'>/* copy the char and go to rsl_subtype state */</span><br>                 type_len++;<br>                 state++;<br>             }<br>             <span style='color:red'>else</span> {<br>                 <span style='color:green'>/* process non-space actions for each state */</span><br>                 <span style='color:red'>if</span> (state == rsl_leading_space) {<br>                     <span style='color:green'>/* non-space: begin MIME type */</span><br>                     state++;<br>                     type_frag = cur_frag;<br>                     type_pos = cur_pos;<br>                     type_len = 1;<br>                     <span style='color:red'>continue</span>;<br>                 }<br>                 <span style='color:red'>else</span> <span style='color:red'>if</span> (state == rsl_type ||<br>                          state == rsl_subtype) {<br>                     <span style='color:green'>/* non-space: adds to type */</span><br>                     type_len++;<br>                     <span style='color:red'>continue</span>;<br>                 }<br>                 <span style='color:red'>else</span> <span style='color:red'>if</span> (state == rsl_separator) {<br>                     <span style='color:green'>/* non-space: begin MIME encoding */</span><br>                     state++;<br>                     encoding_frag = cur_frag;<br>                     encoding_pos = cur_pos;<br>                     encoding_len = 1;<br>                     <span style='color:red'>continue</span>;<br>                 }<br>                 <span style='color:red'>else</span> <span style='color:red'>if</span> (state == rsl_encoding) {<br>                     <span style='color:green'>/* non-space: adds to encoding */</span><br>                     encoding_len++;<br>                     <span style='color:red'>continue</span>;<br>                 }<br>                 <span style='color:red'>else</span> {<br>                     <span style='color:green'>/* should not be possible */</span><br>                     <span style='color:green'>/* abandon malfunctioning module */</span><br>                     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01510)<br>                                 MODNAME <span style='color:blue'>": bad state %d (ns)"</span>, state);<br>                     <span style='color:red'>return</span> DECLINED;<br>                 }<br>                 <span style='color:green'>/* NOTREACHED */</span><br>             }<br>             <span style='color:green'>/* NOTREACHED */</span><br>         }<br>     }<br> <br>     <span style='color:green'>/* if we ended prior to state rsl_subtype, we had incomplete info */</span><br>     <span style='color:red'>if</span> (state != rsl_subtype && state != rsl_separator &&<br>         state != rsl_encoding) {<br>         <span style='color:green'>/* defer to other modules */</span><br>         <span style='color:red'>return</span> DECLINED;<br>     }<br> <br>     <span style='color:green'>/* save the info in the request record */</span><br>     tmp = rsl_strdup(r, type_frag, type_pos, type_len);<br>     <span style='color:green'>/* XXX: this could be done at config time I'm sure... but I'm<br>      * confused by all this magic_rsl stuff. -djg */</span><br>     ap_content_type_tolower(tmp);<br>     ap_set_content_type_ex(r, tmp, 1);<br> <br>     <span style='color:red'>if</span> (state == rsl_encoding) {<br>         tmp = rsl_strdup(r, encoding_frag,<br>                                          encoding_pos, encoding_len);<br>         <span style='color:green'>/* XXX: this could be done at config time I'm sure... but I'm<br>          * confused by all this magic_rsl stuff. -djg */</span><br>         ap_str_tolower(tmp);<br>         r->content_encoding = tmp;<br>     }<br> <br>     <span style='color:green'>/* detect memory allocation or other errors */</span><br>     <span style='color:red'>if</span> (!r->content_type ||<br>         (state == rsl_encoding && !r->content_encoding)) {<br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01511)<br>                       MODNAME <span style='color:blue'>": unexpected state %d; could be caused by bad "</span><br>                       <span style='color:blue'>"data in magic file"</span>,<br>                       state);<br>         <span style='color:red'>return</span> HTTP_INTERNAL_SERVER_ERROR;<br>     }<br> <br>     <span style='color:green'>/* success! */</span><br>     <span style='color:red'>return</span> OK;<br> }<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * magic_process - process input file r        Apache API request record</span><br> <span style='color:green'> * (formerly called "process" in file command, prefix added for clarity) Opens</span><br> <span style='color:green'> * the file and reads a fixed-size buffer to begin processing the contents.</span><br>  */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> magic_process(request_rec *r)<br> {<br>     apr_file_t *fd = NULL;<br>     <span style='color:red'>unsigned</span> <span style='color:red'>char</span> buf[HOWMANY + 1];  <span style='color:green'>/* one extra for terminating '\0' */</span><br>     apr_size_t nbytes = 0;           <span style='color:green'>/* number of bytes read from a datafile */</span><br>     <span style='color:red'>int</span> result;<br> <br>     <span style='color:green'>/*<br> <span style='color:green'>     * first try judging the file based on its filesystem status</span><br>      */</span><br>     <span style='color:red'>switch</span> ((result = fsmagic(r, r->filename))) {<br>     <span style='color:red'>case</span> DONE:<br>         magic_rsl_putchar(r, <span style='color:blue'>'\n'</span>);<br>         <span style='color:red'>return</span> OK;<br>     <span style='color:red'>case</span> OK:<br>         <span style='color:red'>break</span>;<br>     <span style='color:red'>default</span>:<br>         <span style='color:green'>/* fatal error, bail out */</span><br>         <span style='color:red'>return</span> result;<br>     }<br> <br>     <span style='color:red'>if</span> (apr_file_open(&fd, r->filename, APR_READ, APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {<br>         <span style='color:green'>/* We can't open it, but we were able to stat it. */</span><br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01512)<br>                     MODNAME <span style='color:blue'>": can't read `%s'"</span>, r->filename);<br>         <span style='color:green'>/* let some other handler decide what the problem is */</span><br>         <span style='color:red'>return</span> DECLINED;<br>     }<br> <br>     <span style='color:green'>/*<br> <span style='color:green'>     * try looking at the first HOWMANY bytes</span><br>      */</span><br>     nbytes = <span style='color:red'>sizeof</span>(buf) - 1;<br>     <span style='color:red'>if</span> ((result = apr_file_read(fd, (<span style='color:red'>char</span> *) buf, &nbytes)) != APR_SUCCESS) {<br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, result, r, APLOGNO(01513)<br>                     MODNAME <span style='color:blue'>": read failed: %s"</span>, r->filename);<br>         <span style='color:red'>return</span> HTTP_INTERNAL_SERVER_ERROR;<br>     }<br> <br>     <span style='color:red'>if</span> (nbytes == 0) {<br>         <span style='color:red'>return</span> DECLINED;<br>     }<br>     <span style='color:red'>else</span> {<br>         buf[nbytes++] = <span style='color:blue'>'\0'</span>;  <span style='color:green'>/* null-terminate it */</span><br>         result = tryit(r, buf, nbytes, 1);<br>         <span style='color:red'>if</span> (result != OK) {<br>             <span style='color:red'>return</span> result;<br>         }<br>     }<br> <br>     (<span style='color:red'>void</span>) apr_file_close(fd);<br>     (<span style='color:red'>void</span>) magic_rsl_putchar(r, <span style='color:blue'>'\n'</span>);<br> <br>     <span style='color:red'>return</span> OK;<br> }<br> <br> <br> <span style='color:red'>static</span> <span style='color:red'>int</span> tryit(request_rec *r, <span style='color:red'>unsigned</span> <span style='color:red'>char</span> *buf, apr_size_t nb,<br>                  <span style='color:red'>int</span> checkzmagic)<br> {<br>     <span style='color:green'>/*<br> <span style='color:green'>     * Try compression stuff</span><br>      */</span><br>     <span style='color:red'>if</span> (checkzmagic == 1) {<br>         <span style='color:red'>if</span> (zmagic(r, buf, nb) == 1)<br>             <span style='color:red'>return</span> OK;<br>     }<br> <br>     <span style='color:green'>/*<br> <span style='color:green'>     * try tests in /etc/magic (or surrogate magic file)</span><br>      */</span><br>     <span style='color:red'>if</span> (softmagic(r, buf, nb) == 1)<br>         <span style='color:red'>return</span> OK;<br> <br>     <span style='color:green'>/*<br> <span style='color:green'>     * try known keywords, check for ascii-ness too.</span><br>      */</span><br>     <span style='color:red'>if</span> (ascmagic(r, buf, nb) == 1)<br>         <span style='color:red'>return</span> OK;<br> <br>     <span style='color:green'>/*<br> <span style='color:green'>     * abandon hope, all ye who remain here</span><br>      */</span><br>     <span style='color:red'>return</span> DECLINED;<br> }<br> <br> <span style='color:turquoise'>#define</span>    EATAB {<span style='color:red'>while</span> (apr_isspace(*l))  ++l;}<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * apprentice - load configuration from the magic file r</span><br> <span style='color:green'> *  API request record</span><br>  */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> apprentice(server_rec *s, apr_pool_t *p)<br> {<br>     apr_file_t *f = NULL;<br>     apr_status_t result;<br>     <span style='color:red'>char</span> line[BUFSIZ + 1];<br>     <span style='color:red'>int</span> errs = 0;<br>     <span style='color:red'>int</span> lineno;<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>     <span style='color:red'>int</span> rule = 0;<br>     <span style='color:red'>struct</span> magic *m, *prevm;<br> <span style='color:turquoise'>#endif</span><br>     magic_server_config_rec *conf = (magic_server_config_rec *)<br>                     ap_get_module_config(s->module_config, &mime_magic_module);<br>     <span style='color:red'>const</span> <span style='color:red'>char</span> *fname = ap_server_root_relative(p, conf->magicfile);<br> <br>     <span style='color:red'>if</span> (!fname) {<br>         ap_log_error(APLOG_MARK, APLOG_ERR, APR_EBADPATH, s, APLOGNO(01514)<br>                      MODNAME <span style='color:blue'>": Invalid magic file path %s"</span>, conf->magicfile);<br>         <span style='color:red'>return</span> -1;<br>     }<br>     <span style='color:red'>if</span> ((result = apr_file_open(&f, fname, APR_READ | APR_BUFFERED,<br>                                 APR_OS_DEFAULT, p)) != APR_SUCCESS) {<br>         ap_log_error(APLOG_MARK, APLOG_ERR, result, s, APLOGNO(01515)<br>                      MODNAME <span style='color:blue'>": can't read magic file %s"</span>, fname);<br>         <span style='color:red'>return</span> -1;<br>     }<br> <br>     <span style='color:green'>/* set up the magic list (empty) */</span><br>     conf->magic = conf->last = NULL;<br> <br>     <span style='color:green'>/* parse it */</span><br>     <span style='color:red'>for</span> (lineno = 1; apr_file_gets(line, BUFSIZ, f) == APR_SUCCESS; lineno++) {<br>         <span style='color:red'>int</span> ws_offset;<br>         <span style='color:red'>char</span> *last = line + strlen(line) - 1; <span style='color:green'>/* guaranteed that len >= 1 since an<br> <span style='color:green'>                                               * "empty" line contains a '\n'</span><br>                                                */</span><br> <br>         <span style='color:green'>/* delete newline and any other trailing whitespace */</span><br>         <span style='color:red'>while</span> (last >= line<br>                && apr_isspace(*last)) {<br>             *last = <span style='color:blue'>'\0'</span>;<br>             --last;<br>         }<br> <br>         <span style='color:green'>/* skip leading whitespace */</span><br>         ws_offset = 0;<br>         <span style='color:red'>while</span> (line[ws_offset] && apr_isspace(line[ws_offset])) {<br>             ws_offset++;<br>         }<br> <br>         <span style='color:green'>/* skip blank lines */</span><br>         <span style='color:red'>if</span> (line[ws_offset] == 0) {<br>             <span style='color:red'>continue</span>;<br>         }<br> <br>         <span style='color:green'>/* comment, do not parse */</span><br>         <span style='color:red'>if</span> (line[ws_offset] == <span style='color:blue'>'#'</span>)<br>             <span style='color:red'>continue</span>;<br> <br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>         <span style='color:green'>/* if we get here, we're going to use it so count it */</span><br>         rule++;<br> <span style='color:turquoise'>#endif</span><br> <br>         <span style='color:green'>/* parse it */</span><br>         <span style='color:red'>if</span> (parse(s, p, line + ws_offset, lineno) != 0)<br>             ++errs;<br>     }<br> <br>     (<span style='color:red'>void</span>) apr_file_close(f);<br> <br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01516)<br>                 MODNAME <span style='color:blue'>": apprentice conf=%pp file=%s m=%s m->next=%s last=%s"</span>,<br>                 conf,<br>                 conf->magicfile ? conf->magicfile : <span style='color:blue'>"NULL"</span>,<br>                 conf->magic ? <span style='color:blue'>"set"</span> : <span style='color:blue'>"NULL"</span>,<br>                 (conf->magic && conf->magic->next) ? <span style='color:blue'>"set"</span> : <span style='color:blue'>"NULL"</span>,<br>                 conf->last ? <span style='color:blue'>"set"</span> : <span style='color:blue'>"NULL"</span>);<br>     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01517)<br>                 MODNAME <span style='color:blue'>": apprentice read %d lines, %d rules, %d errors"</span>,<br>                 lineno, rule, errs);<br> <span style='color:turquoise'>#endif</span><br> <br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>     prevm = 0;<br>     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01518)<br>                 MODNAME <span style='color:blue'>": apprentice test"</span>);<br>     <span style='color:red'>for</span> (m = conf->magic; m; m = m->next) {<br>         <span style='color:red'>if</span> (apr_isprint((((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) >> 24) & 255) &&<br>             apr_isprint((((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) >> 16) & 255) &&<br>             apr_isprint((((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) >> 8) & 255) &&<br>             apr_isprint(((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) & 255)) {<br>             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01519)<br>                         MODNAME <span style='color:blue'>": apprentice: POINTER CLOBBERED! "</span><br>                         <span style='color:blue'>"m=\"</span>%c%c%c%c\<span style='color:blue'>" line=%d"</span>,<br>                         (((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) >> 24) & 255,<br>                         (((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) >> 16) & 255,<br>                         (((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) >> 8) & 255,<br>                         ((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) & 255,<br>                         prevm ? prevm->lineno : -1);<br>             <span style='color:red'>break</span>;<br>         }<br>         prevm = m;<br>     }<br> <span style='color:turquoise'>#endif</span><br> <br>     <span style='color:red'>return</span> (errs ? -1 : 0);<br> }<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * extend the sign bit if the comparison is to be signed</span><br>  */</span><br> <span style='color:red'>static</span> <span style='color:red'>unsigned</span> <span style='color:red'>long</span> signextend(server_rec *s, <span style='color:red'>struct</span> magic *m, <span style='color:red'>unsigned</span> <span style='color:red'>long</span> v)<br> {<br>     <span style='color:red'>if</span> (!(m->flag & <span style='color:red'>UNSIGNED</span>))<br>         <span style='color:red'>switch</span> (m->type) {<br>             <span style='color:green'>/*<br> <span style='color:green'>             * Do not remove the casts below.  They are vital. When later</span><br> <span style='color:green'>             * compared with the data, the sign extension must have happened.</span><br>              */</span><br>         <span style='color:red'>case</span> BYTE:<br>             v = (<span style='color:red'>char</span>) v;<br>             <span style='color:red'>break</span>;<br>         <span style='color:red'>case</span> <span style='color:red'>SHORT</span>:<br>         <span style='color:red'>case</span> BESHORT:<br>         <span style='color:red'>case</span> LESHORT:<br>             v = (<span style='color:red'>short</span>) v;<br>             <span style='color:red'>break</span>;<br>         <span style='color:red'>case</span> DATE:<br>         <span style='color:red'>case</span> BEDATE:<br>         <span style='color:red'>case</span> LEDATE:<br>         <span style='color:red'>case</span> <span style='color:red'>LONG</span>:<br>         <span style='color:red'>case</span> BELONG:<br>         <span style='color:red'>case</span> LELONG:<br>             v = (<span style='color:red'>long</span>) v;<br>             <span style='color:red'>break</span>;<br>         <span style='color:red'>case</span> STRING:<br>             <span style='color:red'>break</span>;<br>         <span style='color:red'>default</span>:<br>             ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01520)<br>                         MODNAME <span style='color:blue'>": can't happen: m->type=%d"</span>, m->type);<br>             <span style='color:red'>return</span> -1;<br>         }<br>     <span style='color:red'>return</span> v;<br> }<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * parse one line from magic file, put into magic[index++] if valid</span><br>  */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> parse(server_rec *serv, apr_pool_t *p, <span style='color:red'>char</span> *l, <span style='color:red'>int</span> lineno)<br> {<br>     <span style='color:red'>struct</span> magic *m;<br>     <span style='color:red'>char</span> *t, *s;<br>     magic_server_config_rec *conf = (magic_server_config_rec *)<br>                     ap_get_module_config(serv->module_config, &mime_magic_module);<br> <br>     <span style='color:green'>/* allocate magic structure entry */</span><br>     m = (<span style='color:red'>struct</span> magic *) apr_pcalloc(p, <span style='color:red'>sizeof</span>(<span style='color:red'>struct</span> magic));<br> <br>     <span style='color:green'>/* append to linked list */</span><br>     m->next = NULL;<br>     <span style='color:red'>if</span> (!conf->magic || !conf->last) {<br>         conf->magic = conf->last = m;<br>     }<br>     <span style='color:red'>else</span> {<br>         conf->last->next = m;<br>         conf->last = m;<br>     }<br> <br>     <span style='color:green'>/* set values in magic structure */</span><br>     m->flag = 0;<br>     m->cont_level = 0;<br>     m->lineno = lineno;<br> <br>     <span style='color:red'>while</span> (*l == <span style='color:blue'>'>'</span>) {<br>         ++l;  <span style='color:green'>/* step over */</span><br>         m->cont_level++;<br>     }<br> <br>     <span style='color:red'>if</span> (m->cont_level != 0 && *l == <span style='color:blue'>'('</span>) {<br>         ++l;  <span style='color:green'>/* step over */</span><br>         m->flag |= INDIR;<br>     }<br> <br>     <span style='color:green'>/* get offset, then skip over it */</span><br>     m->offset = (<span style='color:red'>int</span>) strtol(l, &t, 0);<br>     <span style='color:red'>if</span> (l == t) {<br>         ap_log_error(APLOG_MARK, APLOG_ERR, 0, serv, APLOGNO(01521)<br>                     MODNAME <span style='color:blue'>": offset %s invalid"</span>, l);<br>     }<br>     l = t;<br> <br>     <span style='color:red'>if</span> (m->flag & INDIR) {<br>         m->in.type = <span style='color:red'>LONG</span>;<br>         m->in.offset = 0;<br>         <span style='color:green'>/*<br> <span style='color:green'>         * read [.lbs][+-]nnnnn)</span><br>          */</span><br>         <span style='color:red'>if</span> (*l == <span style='color:blue'>'.'</span>) {<br>             <span style='color:red'>switch</span> (*++l) {<br>             <span style='color:red'>case</span> <span style='color:blue'>'l'</span>:<br>                 m->in.type = <span style='color:red'>LONG</span>;<br>                 <span style='color:red'>break</span>;<br>             <span style='color:red'>case</span> <span style='color:blue'>'s'</span>:<br>                 m->in.type = <span style='color:red'>SHORT</span>;<br>                 <span style='color:red'>break</span>;<br>             <span style='color:red'>case</span> <span style='color:blue'>'b'</span>:<br>                 m->in.type = BYTE;<br>                 <span style='color:red'>break</span>;<br>             <span style='color:red'>default</span>:<br>                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, serv, APLOGNO(01522)<br>                         MODNAME <span style='color:blue'>": indirect offset type %c invalid"</span>, *l);<br>                 <span style='color:red'>break</span>;<br>             }<br>             l++;<br>         }<br>         s = l;<br>         <span style='color:red'>if</span> (*l == <span style='color:blue'>'+'</span> || *l == <span style='color:blue'>'-'</span>)<br>             l++;<br>         <span style='color:red'>if</span> (apr_isdigit((<span style='color:red'>unsigned</span> <span style='color:red'>char</span>) *l)) {<br>             m->in.offset = strtol(l, &t, 0);<br>             <span style='color:red'>if</span> (*s == <span style='color:blue'>'-'</span>)<br>                 m->in.offset = -m->in.offset;<br>         }<br>         <span style='color:red'>else</span><br>             t = l;<br>         <span style='color:red'>if</span> (*t++ != <span style='color:blue'>')'</span>) {<br>             ap_log_error(APLOG_MARK, APLOG_ERR, 0, serv, APLOGNO(01523)<br>                         MODNAME <span style='color:blue'>": missing ')' in indirect offset"</span>);<br>         }<br>         l = t;<br>     }<br> <br> <br>     <span style='color:red'>while</span> (apr_isdigit((<span style='color:red'>unsigned</span> <span style='color:red'>char</span>) *l))<br>         ++l;<br>     EATAB;<br> <br> <span style='color:turquoise'>#define</span> NBYTE           4<br> <span style='color:turquoise'>#define</span> NSHORT          5<br> <span style='color:turquoise'>#define</span> NLONG           4<br> <span style='color:turquoise'>#define</span> NSTRING         6<br> <span style='color:turquoise'>#define</span> NDATE           4<br> <span style='color:turquoise'>#define</span> NBESHORT        7<br> <span style='color:turquoise'>#define</span> NBELONG         6<br> <span style='color:turquoise'>#define</span> NBEDATE         6<br> <span style='color:turquoise'>#define</span> NLESHORT        7<br> <span style='color:turquoise'>#define</span> NLELONG         6<br> <span style='color:turquoise'>#define</span> NLEDATE         6<br> <br>     <span style='color:red'>if</span> (*l == <span style='color:blue'>'u'</span>) {<br>         ++l;<br>         m->flag |= <span style='color:red'>UNSIGNED</span>;<br>     }<br> <br>     <span style='color:green'>/* get type, skip it */</span><br>     <span style='color:red'>if</span> (strncmp(l, <span style='color:blue'>"byte"</span>, NBYTE) == 0) {<br>         m->type = BYTE;<br>         l += NBYTE;<br>     }<br>     <span style='color:red'>else</span> <span style='color:red'>if</span> (strncmp(l, <span style='color:blue'>"short"</span>, NSHORT) == 0) {<br>         m->type = <span style='color:red'>SHORT</span>;<br>         l += NSHORT;<br>     }<br>     <span style='color:red'>else</span> <span style='color:red'>if</span> (strncmp(l, <span style='color:blue'>"long"</span>, NLONG) == 0) {<br>         m->type = <span style='color:red'>LONG</span>;<br>         l += NLONG;<br>     }<br>     <span style='color:red'>else</span> <span style='color:red'>if</span> (strncmp(l, <span style='color:blue'>"string"</span>, NSTRING) == 0) {<br>         m->type = STRING;<br>         l += NSTRING;<br>     }<br>     <span style='color:red'>else</span> <span style='color:red'>if</span> (strncmp(l, <span style='color:blue'>"date"</span>, NDATE) == 0) {<br>         m->type = DATE;<br>         l += NDATE;<br>     }<br>     <span style='color:red'>else</span> <span style='color:red'>if</span> (strncmp(l, <span style='color:blue'>"beshort"</span>, NBESHORT) == 0) {<br>         m->type = BESHORT;<br>         l += NBESHORT;<br>     }<br>     <span style='color:red'>else</span> <span style='color:red'>if</span> (strncmp(l, <span style='color:blue'>"belong"</span>, NBELONG) == 0) {<br>         m->type = BELONG;<br>         l += NBELONG;<br>     }<br>     <span style='color:red'>else</span> <span style='color:red'>if</span> (strncmp(l, <span style='color:blue'>"bedate"</span>, NBEDATE) == 0) {<br>         m->type = BEDATE;<br>         l += NBEDATE;<br>     }<br>     <span style='color:red'>else</span> <span style='color:red'>if</span> (strncmp(l, <span style='color:blue'>"leshort"</span>, NLESHORT) == 0) {<br>         m->type = LESHORT;<br>         l += NLESHORT;<br>     }<br>     <span style='color:red'>else</span> <span style='color:red'>if</span> (strncmp(l, <span style='color:blue'>"lelong"</span>, NLELONG) == 0) {<br>         m->type = LELONG;<br>         l += NLELONG;<br>     }<br>     <span style='color:red'>else</span> <span style='color:red'>if</span> (strncmp(l, <span style='color:blue'>"ledate"</span>, NLEDATE) == 0) {<br>         m->type = LEDATE;<br>         l += NLEDATE;<br>     }<br>     <span style='color:red'>else</span> {<br>         ap_log_error(APLOG_MARK, APLOG_ERR, 0, serv, APLOGNO(01524)<br>                     MODNAME <span style='color:blue'>": type %s invalid"</span>, l);<br>         <span style='color:red'>return</span> -1;<br>     }<br>     <span style='color:green'>/* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */</span><br>     <span style='color:red'>if</span> (*l == <span style='color:blue'>'&'</span>) {<br>         ++l;<br>         m->mask = signextend(serv, m, strtol(l, &l, 0));<br>     }<br>     <span style='color:red'>else</span><br>         m->mask = ~0L;<br>     EATAB;<br> <br>     <span style='color:red'>switch</span> (*l) {<br>     <span style='color:red'>case</span> <span style='color:blue'>'>'</span>:<br>     <span style='color:red'>case</span> <span style='color:blue'>'<'</span>:<br>         <span style='color:green'>/* Old-style anding: "0 byte &0x80 dynamically linked" */</span><br>     <span style='color:red'>case</span> <span style='color:blue'>'&'</span>:<br>     <span style='color:red'>case</span> <span style='color:blue'>'^'</span>:<br>     <span style='color:red'>case</span> <span style='color:blue'>'='</span>:<br>         m->reln = *l;<br>         ++l;<br>         <span style='color:red'>break</span>;<br>     <span style='color:red'>case</span> <span style='color:blue'>'!'</span>:<br>         <span style='color:red'>if</span> (m->type != STRING) {<br>             m->reln = *l;<br>             ++l;<br>             <span style='color:red'>break</span>;<br>         }<br>         <span style='color:green'>/* FALL THROUGH */</span><br>     <span style='color:red'>default</span>:<br>         <span style='color:red'>if</span> (*l == <span style='color:blue'>'x'</span> && apr_isspace(l[1])) {<br>             m->reln = *l;<br>             ++l;<br>             <span style='color:red'>goto</span> GetDesc;  <span style='color:green'>/* Bill The Cat */</span><br>         }<br>         m->reln = <span style='color:blue'>'='</span>;<br>         <span style='color:red'>break</span>;<br>     }<br>     EATAB;<br> <br>     <span style='color:red'>if</span> (getvalue(serv, m, &l))<br>         <span style='color:red'>return</span> -1;<br>     <span style='color:green'>/*<br> <span style='color:green'>     * now get last part - the description</span><br>      */</span><br>   GetDesc:<br>     EATAB;<br>     <span style='color:red'>if</span> (l[0] == <span style='color:blue'>'\b'</span>) {<br>         ++l;<br>         m->nospflag = 1;<br>     }<br>     <span style='color:red'>else</span> <span style='color:red'>if</span> ((l[0] == <span style='color:blue'>'\\'</span>) && (l[1] == <span style='color:blue'>'b'</span>)) {<br>         ++l;<br>         ++l;<br>         m->nospflag = 1;<br>     }<br>     <span style='color:red'>else</span><br>         m->nospflag = 0;<br>     apr_cpystrn(m->desc, l, <span style='color:red'>sizeof</span>(m->desc));<br> <br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, serv, APLOGNO(01525)<br>                 MODNAME <span style='color:blue'>": parse line=%d m=%pp next=%pp cont=%d desc=%s"</span>,<br>                 lineno, m, m->next, m->cont_level, m->desc);<br> <span style='color:turquoise'>#endif</span> <span style='color:green'>/* MIME_MAGIC_DEBUG */</span><br> <br>     <span style='color:red'>return</span> 0;<br> }<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * Read a numeric value from a pointer, into the value union of a magic</span><br> <span style='color:green'> * pointer, according to the magic type.  Update the string pointer to point</span><br> <span style='color:green'> * just after the number read.  Return 0 for success, non-zero for failure.</span><br>  */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> getvalue(server_rec *s, <span style='color:red'>struct</span> magic *m, <span style='color:red'>char</span> **p)<br> {<br>     <span style='color:red'>int</span> slen;<br> <br>     <span style='color:red'>if</span> (m->type == STRING) {<br>         *p = getstr(s, *p, m->value.s, <span style='color:red'>sizeof</span>(m->value.s), &slen);<br>         m->vallen = slen;<br>     }<br>     <span style='color:red'>else</span> <span style='color:red'>if</span> (m->reln != <span style='color:blue'>'x'</span>)<br>         m->value.l = signextend(s, m, strtol(*p, p, 0));<br>     <span style='color:red'>return</span> 0;<br> }<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * Convert a string containing C character escapes.  Stop at an unescaped</span><br> <span style='color:green'> * space or tab. Copy the converted version to "p", returning its length in</span><br> <span style='color:green'> * *slen. Return updated scan pointer as function result.</span><br>  */</span><br> <span style='color:red'>static</span> <span style='color:red'>char</span> *getstr(server_rec *serv, <span style='color:red'>register</span> <span style='color:red'>char</span> *s, <span style='color:red'>register</span> <span style='color:red'>char</span> *p,<br>                     <span style='color:red'>int</span> plen, <span style='color:red'>int</span> *slen)<br> {<br>     <span style='color:red'>char</span> *origs = s, *origp = p;<br>     <span style='color:red'>char</span> *pmax = p + plen - 1;<br>     <span style='color:red'>register</span> <span style='color:red'>int</span> c;<br>     <span style='color:red'>register</span> <span style='color:red'>int</span> val;<br> <br>     <span style='color:red'>while</span> ((c = *s++) != <span style='color:blue'>'\0'</span>) {<br>         <span style='color:red'>if</span> (apr_isspace(c))<br>             <span style='color:red'>break</span>;<br>         <span style='color:red'>if</span> (p >= pmax) {<br>             ap_log_error(APLOG_MARK, APLOG_ERR, 0, serv, APLOGNO(01526)<br>                         MODNAME <span style='color:blue'>": string too long: %s"</span>, origs);<br>             <span style='color:red'>break</span>;<br>         }<br>         <span style='color:red'>if</span> (c == <span style='color:blue'>'\\'</span>) {<br>             <span style='color:red'>switch</span> (c = *s++) {<br> <br>             <span style='color:red'>case</span> <span style='color:blue'>'\0'</span>:<br>                 <span style='color:red'>goto</span> out;<br> <br>             <span style='color:red'>default</span>:<br>                 *p++ = (<span style='color:red'>char</span>) c;<br>                 <span style='color:red'>break</span>;<br> <br>             <span style='color:red'>case</span> <span style='color:blue'>'n'</span>:<br>                 *p++ = <span style='color:blue'>'\n'</span>;<br>                 <span style='color:red'>break</span>;<br> <br>             <span style='color:red'>case</span> <span style='color:blue'>'r'</span>:<br>                 *p++ = <span style='color:blue'>'\r'</span>;<br>                 <span style='color:red'>break</span>;<br> <br>             <span style='color:red'>case</span> <span style='color:blue'>'b'</span>:<br>                 *p++ = <span style='color:blue'>'\b'</span>;<br>                 <span style='color:red'>break</span>;<br> <br>             <span style='color:red'>case</span> <span style='color:blue'>'t'</span>:<br>                 *p++ = <span style='color:blue'>'\t'</span>;<br>                 <span style='color:red'>break</span>;<br> <br>             <span style='color:red'>case</span> <span style='color:blue'>'f'</span>:<br>                 *p++ = <span style='color:blue'>'\f'</span>;<br>                 <span style='color:red'>break</span>;<br> <br>             <span style='color:red'>case</span> <span style='color:blue'>'v'</span>:<br>                 *p++ = <span style='color:blue'>'\v'</span>;<br>                 <span style='color:red'>break</span>;<br> <br>                 <span style='color:green'>/* \ and up to 3 octal digits */</span><br>             <span style='color:red'>case</span> <span style='color:blue'>'0'</span>:<br>             <span style='color:red'>case</span> <span style='color:blue'>'1'</span>:<br>             <span style='color:red'>case</span> <span style='color:blue'>'2'</span>:<br>             <span style='color:red'>case</span> <span style='color:blue'>'3'</span>:<br>             <span style='color:red'>case</span> <span style='color:blue'>'4'</span>:<br>             <span style='color:red'>case</span> <span style='color:blue'>'5'</span>:<br>             <span style='color:red'>case</span> <span style='color:blue'>'6'</span>:<br>             <span style='color:red'>case</span> <span style='color:blue'>'7'</span>:<br>                 val = c - <span style='color:blue'>'0'</span>;<br>                 c = *s++;  <span style='color:green'>/* try for 2 */</span><br>                 <span style='color:red'>if</span> (c >= <span style='color:blue'>'0'</span> && c <= <span style='color:blue'>'7'</span>) {<br>                     val = (val << 3) | (c - <span style='color:blue'>'0'</span>);<br>                     c = *s++;  <span style='color:green'>/* try for 3 */</span><br>                     <span style='color:red'>if</span> (c >= <span style='color:blue'>'0'</span> && c <= <span style='color:blue'>'7'</span>)<br>                         val = (val << 3) | (c - <span style='color:blue'>'0'</span>);<br>                     <span style='color:red'>else</span><br>                         --s;<br>                 }<br>                 <span style='color:red'>else</span><br>                     --s;<br>                 *p++ = (<span style='color:red'>char</span>) val;<br>                 <span style='color:red'>break</span>;<br> <br>                 <span style='color:green'>/* \x and up to 3 hex digits */</span><br>             <span style='color:red'>case</span> <span style='color:blue'>'x'</span>:<br>                 val = <span style='color:blue'>'x'</span>;            <span style='color:green'>/* Default if no digits */</span><br>                 c = hextoint(*s++);   <span style='color:green'>/* Get next char */</span><br>                 <span style='color:red'>if</span> (c >= 0) {<br>                     val = c;<br>                     c = hextoint(*s++);<br>                     <span style='color:red'>if</span> (c >= 0) {<br>                         val = (val << 4) + c;<br>                         c = hextoint(*s++);<br>                         <span style='color:red'>if</span> (c >= 0) {<br>                             val = (val << 4) + c;<br>                         }<br>                         <span style='color:red'>else</span><br>                             --s;<br>                     }<br>                     <span style='color:red'>else</span><br>                         --s;<br>                 }<br>                 <span style='color:red'>else</span><br>                     --s;<br>                 *p++ = (<span style='color:red'>char</span>) val;<br>                 <span style='color:red'>break</span>;<br>             }<br>         }<br>         <span style='color:red'>else</span><br>             *p++ = (<span style='color:red'>char</span>) c;<br>     }<br>   out:<br>     *p = <span style='color:blue'>'\0'</span>;<br>     *slen = p - origp;<br>     <span style='color:red'>return</span> s;<br> }<br> <br> <br> <span style='color:green'>/* Single hex char to int; -1 if not a hex char. */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> hextoint(<span style='color:red'>int</span> c)<br> {<br>     <span style='color:red'>if</span> (apr_isdigit(c))<br>         <span style='color:red'>return</span> c - <span style='color:blue'>'0'</span>;<br>     <span style='color:red'>if</span> ((c >= <span style='color:blue'>'a'</span>) && (c <= <span style='color:blue'>'f'</span>))<br>         <span style='color:red'>return</span> c + 10 - <span style='color:blue'>'a'</span>;<br>     <span style='color:red'>if</span> ((c >= <span style='color:blue'>'A'</span>) && (c <= <span style='color:blue'>'F'</span>))<br>         <span style='color:red'>return</span> c + 10 - <span style='color:blue'>'A'</span>;<br>     <span style='color:red'>return</span> -1;<br> }<br> <br> <br> <span style='color:green'>/*<br> <span style='color:green'> * return DONE to indicate it's been handled</span><br> <span style='color:green'> * return OK to indicate it's a regular file still needing handling</span><br> <span style='color:green'> * other returns indicate a failure of some sort</span><br>  */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> fsmagic(request_rec *r, <span style='color:red'>const</span> <span style='color:red'>char</span> *fn)<br> {<br>     <span style='color:red'>switch</span> (r->finfo.filetype) {<br>     <span style='color:red'>case</span> APR_DIR:<br>         magic_rsl_puts(r, DIR_MAGIC_TYPE);<br>         <span style='color:red'>return</span> DONE;<br>     <span style='color:red'>case</span> APR_CHR:<br>         <span style='color:green'>/*<br> <span style='color:green'>         * (void) magic_rsl_printf(r,"character special (%d/%d)",</span><br> <span style='color:green'>         * major(sb->st_rdev), minor(sb->st_rdev));</span><br>          */</span><br>         (<span style='color:red'>void</span>) magic_rsl_puts(r, MIME_BINARY_UNKNOWN);<br>         <span style='color:red'>return</span> DONE;<br>     <span style='color:red'>case</span> APR_BLK:<br>         <span style='color:green'>/*<br> <span style='color:green'>         * (void) magic_rsl_printf(r,"block special (%d/%d)",</span><br> <span style='color:green'>         * major(sb->st_rdev), minor(sb->st_rdev));</span><br>          */</span><br>         (<span style='color:red'>void</span>) magic_rsl_puts(r, MIME_BINARY_UNKNOWN);<br>         <span style='color:red'>return</span> DONE;<br>         <span style='color:green'>/* TODO add code to handle V7 MUX and Blit MUX files */</span><br>     <span style='color:red'>case</span> APR_PIPE:<br>         <span style='color:green'>/*<br> <span style='color:green'>         * magic_rsl_puts(r,"fifo (named pipe)");</span><br>          */</span><br>         (<span style='color:red'>void</span>) magic_rsl_puts(r, MIME_BINARY_UNKNOWN);<br>         <span style='color:red'>return</span> DONE;<br>     <span style='color:red'>case</span> APR_LNK:<br>         <span style='color:green'>/* We used stat(), the only possible reason for this is that the<br> <span style='color:green'>         * symlink is broken.</span><br>          */</span><br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01527)<br>                     MODNAME <span style='color:blue'>": broken symlink (%s)"</span>, fn);<br>         <span style='color:red'>return</span> HTTP_INTERNAL_SERVER_ERROR;<br>     <span style='color:red'>case</span> APR_SOCK:<br>         magic_rsl_puts(r, MIME_BINARY_UNKNOWN);<br>         <span style='color:red'>return</span> DONE;<br>     <span style='color:red'>case</span> APR_REG:<br>         <span style='color:red'>break</span>;<br>     <span style='color:red'>default</span>:<br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01528)<br>                       MODNAME <span style='color:blue'>": invalid file type %d."</span>, r->finfo.filetype);<br>         <span style='color:red'>return</span> HTTP_INTERNAL_SERVER_ERROR;<br>     }<br> <br>     <span style='color:green'>/*<br> <span style='color:green'>     * regular file, check next possibility</span><br>      */</span><br>     <span style='color:red'>if</span> (r->finfo.size == 0) {<br>         magic_rsl_puts(r, MIME_TEXT_UNKNOWN);<br>         <span style='color:red'>return</span> DONE;<br>     }<br>     <span style='color:red'>return</span> OK;<br> }<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * softmagic - lookup one file in database (already read from /etc/magic by</span><br> <span style='color:green'> * apprentice.c). Passed the name and FILE * of one file to be typed.</span><br>  */</span><br>                 <span style='color:green'>/* ARGSUSED1 *//* nbytes passed for regularity, maybe need later */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> softmagic(request_rec *r, <span style='color:red'>unsigned</span> <span style='color:red'>char</span> *buf, apr_size_t nbytes)<br> {<br>     <span style='color:red'>if</span> (match(r, buf, nbytes))<br>         <span style='color:red'>return</span> 1;<br> <br>     <span style='color:red'>return</span> 0;<br> }<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * Go through the whole list, stopping if you find a match.  Process all the</span><br> <span style='color:green'> * continuations of that match before returning.</span><br> <span style='color:green'> *</span><br> <span style='color:green'> * We support multi-level continuations:</span><br> <span style='color:green'> *</span><br> <span style='color:green'> * At any time when processing a successful top-level match, there is a current</span><br> <span style='color:green'> * continuation level; it represents the level of the last successfully</span><br> <span style='color:green'> * matched continuation.</span><br> <span style='color:green'> *</span><br> <span style='color:green'> * Continuations above that level are skipped as, if we see one, it means that</span><br> <span style='color:green'> * the continuation that controls them - i.e, the lower-level continuation</span><br> <span style='color:green'> * preceding them - failed to match.</span><br> <span style='color:green'> *</span><br> <span style='color:green'> * Continuations below that level are processed as, if we see one, it means</span><br> <span style='color:green'> * we've finished processing or skipping higher-level continuations under the</span><br> <span style='color:green'> * control of a successful or unsuccessful lower-level continuation, and are</span><br> <span style='color:green'> * now seeing the next lower-level continuation and should process it.  The</span><br> <span style='color:green'> * current continuation level reverts to the level of the one we're seeing.</span><br> <span style='color:green'> *</span><br> <span style='color:green'> * Continuations at the current level are processed as, if we see one, there's</span><br> <span style='color:green'> * no lower-level continuation that may have failed.</span><br> <span style='color:green'> *</span><br> <span style='color:green'> * If a continuation matches, we bump the current continuation level so that</span><br> <span style='color:green'> * higher-level continuations are processed.</span><br>  */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> match(request_rec *r, <span style='color:red'>unsigned</span> <span style='color:red'>char</span> *s, apr_size_t nbytes)<br> {<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>     <span style='color:red'>int</span> rule_counter = 0;<br> <span style='color:turquoise'>#endif</span><br>     <span style='color:red'>int</span> cont_level = 0;<br>     <span style='color:red'>int</span> need_separator = 0;<br>     <span style='color:red'>union</span> VALUETYPE p;<br>     magic_server_config_rec *conf = (magic_server_config_rec *)<br>                 ap_get_module_config(r->server->module_config, &mime_magic_module);<br>     <span style='color:red'>struct</span> magic *m;<br> <br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01529)<br>                 MODNAME <span style='color:blue'>": match conf=%pp file=%s m=%s m->next=%s last=%s"</span>,<br>                 conf,<br>                 conf->magicfile ? conf->magicfile : <span style='color:blue'>"NULL"</span>,<br>                 conf->magic ? <span style='color:blue'>"set"</span> : <span style='color:blue'>"NULL"</span>,<br>                 (conf->magic && conf->magic->next) ? <span style='color:blue'>"set"</span> : <span style='color:blue'>"NULL"</span>,<br>                 conf->last ? <span style='color:blue'>"set"</span> : <span style='color:blue'>"NULL"</span>);<br> <span style='color:turquoise'>#endif</span><br> <br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>     <span style='color:red'>for</span> (m = conf->magic; m; m = m->next) {<br>         <span style='color:red'>if</span> (apr_isprint((((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) >> 24) & 255) &&<br>             apr_isprint((((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) >> 16) & 255) &&<br>             apr_isprint((((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) >> 8) & 255) &&<br>             apr_isprint(((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) & 255)) {<br>             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01530)<br>                         MODNAME <span style='color:blue'>": match: POINTER CLOBBERED! "</span><br>                         <span style='color:blue'>"m=\"</span>%c%c%c%c\<span style='color:blue'>""</span>,<br>                         (((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) >> 24) & 255,<br>                         (((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) >> 16) & 255,<br>                         (((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) >> 8) & 255,<br>                         ((<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) m) & 255);<br>             <span style='color:red'>break</span>;<br>         }<br>     }<br> <span style='color:turquoise'>#endif</span><br> <br>     <span style='color:red'>for</span> (m = conf->magic; m; m = m->next) {<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>         rule_counter++;<br>         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01531)<br>                     MODNAME <span style='color:blue'>": line=%d desc=%s"</span>, m->lineno, m->desc);<br> <span style='color:turquoise'>#endif</span><br> <br>         <span style='color:green'>/* check if main entry matches */</span><br>         <span style='color:red'>if</span> (!mget(r, &p, s, m, nbytes) ||<br>             !mcheck(r, &p, m)) {<br>             <span style='color:red'>struct</span> magic *m_cont;<br> <br>             <span style='color:green'>/*<br> <span style='color:green'>             * main entry didn't match, flush its continuations</span><br>              */</span><br>             <span style='color:red'>if</span> (!m->next || (m->next->cont_level == 0)) {<br>                 <span style='color:red'>continue</span>;<br>             }<br> <br>             m_cont = m->next;<br>             <span style='color:red'>while</span> (m_cont && (m_cont->cont_level != 0)) {<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>                 rule_counter++;<br>                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01532)<br>                         MODNAME <span style='color:blue'>": line=%d mc=%pp mc->next=%pp cont=%d desc=%s"</span>,<br>                             m_cont->lineno, m_cont,<br>                             m_cont->next, m_cont->cont_level,<br>                             m_cont->desc);<br> <span style='color:turquoise'>#endif</span><br>                 <span style='color:green'>/*<br> <span style='color:green'>                 * this trick allows us to keep *m in sync when the continue</span><br> <span style='color:green'>                 * advances the pointer</span><br>                  */</span><br>                 m = m_cont;<br>                 m_cont = m_cont->next;<br>             }<br>             <span style='color:red'>continue</span>;<br>         }<br> <br>         <span style='color:green'>/* if we get here, the main entry rule was a match */</span><br>         <span style='color:green'>/* this will be the last run through the loop */</span><br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01533)<br>                     MODNAME <span style='color:blue'>": rule matched, line=%d type=%d %s"</span>,<br>                     m->lineno, m->type,<br>                     (m->type == STRING) ? m->value.s : <span style='color:blue'>""</span>);<br> <span style='color:turquoise'>#endif</span><br> <br>         <span style='color:green'>/* print the match */</span><br>         mprint(r, &p, m);<br> <br>         <span style='color:green'>/*<br> <span style='color:green'>         * If we printed something, we'll need to print a blank before we</span><br> <span style='color:green'>         * print something else.</span><br>          */</span><br>         <span style='color:red'>if</span> (m->desc[0])<br>             need_separator = 1;<br>         <span style='color:green'>/* and any continuations that match */</span><br>         cont_level++;<br>         <span style='color:green'>/*<br> <span style='color:green'>         * while (m && m->next && m->next->cont_level != 0 && ( m = m->next</span><br> <span style='color:green'>         * ))</span><br>          */</span><br>         m = m->next;<br>         <span style='color:red'>while</span> (m && (m->cont_level != 0)) {<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01534)<br>                         MODNAME <span style='color:blue'>": match line=%d cont=%d type=%d %s"</span>,<br>                         m->lineno, m->cont_level, m->type,<br>                         (m->type == STRING) ? m->value.s : <span style='color:blue'>""</span>);<br> <span style='color:turquoise'>#endif</span><br>             <span style='color:red'>if</span> (cont_level >= m->cont_level) {<br>                 <span style='color:red'>if</span> (cont_level > m->cont_level) {<br>                     <span style='color:green'>/*<br> <span style='color:green'>                     * We're at the end of the level "cont_level"</span><br> <span style='color:green'>                     * continuations.</span><br>                      */</span><br>                     cont_level = m->cont_level;<br>                 }<br>                 <span style='color:red'>if</span> (mget(r, &p, s, m, nbytes) &&<br>                     mcheck(r, &p, m)) {<br>                     <span style='color:green'>/*<br> <span style='color:green'>                     * This continuation matched. Print its message, with a</span><br> <span style='color:green'>                     * blank before it if the previous item printed and this</span><br> <span style='color:green'>                     * item isn't empty.</span><br>                      */</span><br>                     <span style='color:green'>/* space if previous printed */</span><br>                     <span style='color:red'>if</span> (need_separator<br>                         && (m->nospflag == 0)<br>                         && (m->desc[0] != <span style='color:blue'>'\0'</span>)<br>                         ) {<br>                         (<span style='color:red'>void</span>) magic_rsl_putchar(r, <span style='color:blue'>' '</span>);<br>                         need_separator = 0;<br>                     }<br>                     mprint(r, &p, m);<br>                     <span style='color:red'>if</span> (m->desc[0])<br>                         need_separator = 1;<br> <br>                     <span style='color:green'>/*<br> <span style='color:green'>                     * If we see any continuations at a higher level, process</span><br> <span style='color:green'>                     * them.</span><br>                      */</span><br>                     cont_level++;<br>                 }<br>             }<br> <br>             <span style='color:green'>/* move to next continuation record */</span><br>             m = m->next;<br>         }<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01535)<br>                     MODNAME <span style='color:blue'>": matched after %d rules"</span>, rule_counter);<br> <span style='color:turquoise'>#endif</span><br>         <span style='color:red'>return</span> 1;  <span style='color:green'>/* all through */</span><br>     }<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01536)<br>                 MODNAME <span style='color:blue'>": failed after %d rules"</span>, rule_counter);<br> <span style='color:turquoise'>#endif</span><br>     <span style='color:red'>return</span> 0;  <span style='color:green'>/* no match at all */</span><br> }<br> <br> <span style='color:red'>static</span> <span style='color:red'>void</span> mprint(request_rec *r, <span style='color:red'>union</span> VALUETYPE *p, <span style='color:red'>struct</span> magic *m)<br> {<br>     <span style='color:red'>char</span> *pp;<br>     <span style='color:red'>unsigned</span> <span style='color:red'>long</span> v;<br>     <span style='color:red'>char</span> time_str[APR_CTIME_LEN];<br> <br>     <span style='color:red'>switch</span> (m->type) {<br>     <span style='color:red'>case</span> BYTE:<br>         v = p->b;<br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>case</span> <span style='color:red'>SHORT</span>:<br>     <span style='color:red'>case</span> BESHORT:<br>     <span style='color:red'>case</span> LESHORT:<br>         v = p->h;<br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>case</span> <span style='color:red'>LONG</span>:<br>     <span style='color:red'>case</span> BELONG:<br>     <span style='color:red'>case</span> LELONG:<br>         v = p->l;<br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>case</span> STRING:<br>         <span style='color:red'>if</span> (m->reln == <span style='color:blue'>'='</span>) {<br>             (<span style='color:red'>void</span>) magic_rsl_printf(r, m->desc, m->value.s);<br>         }<br>         <span style='color:red'>else</span> {<br>             (<span style='color:red'>void</span>) magic_rsl_printf(r, m->desc, p->s);<br>         }<br>         <span style='color:red'>return</span>;<br> <br>     <span style='color:red'>case</span> DATE:<br>     <span style='color:red'>case</span> BEDATE:<br>     <span style='color:red'>case</span> LEDATE:<br>         apr_ctime(time_str, apr_time_from_sec(*(time_t *)&p->l));<br>         pp = time_str;<br>         (<span style='color:red'>void</span>) magic_rsl_printf(r, m->desc, pp);<br>         <span style='color:red'>return</span>;<br>     <span style='color:red'>default</span>:<br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01537)<br>                     MODNAME <span style='color:blue'>": invalid m->type (%d) in mprint()."</span>,<br>                     m->type);<br>         <span style='color:red'>return</span>;<br>     }<br> <br>     v = signextend(r->server, m, v) & m->mask;<br>     (<span style='color:red'>void</span>) magic_rsl_printf(r, m->desc, (<span style='color:red'>unsigned</span> <span style='color:red'>long</span>) v);<br> }<br> <br> <span style='color:green'>/*<br> <span style='color:green'> * Convert the byte order of the data we are looking at</span><br>  */</span><br> <span style='color:red'>static</span> <span style='color:red'>int</span> mconvert(request_rec *r, <span style='color:red'>union</span> VALUETYPE *p, <span style='color:red'>struct</span> magic *m)<br> {<br>     <span style='color:red'>char</span> *rt;<br> <br>     <span style='color:red'>switch</span> (m->type) {<br>     <span style='color:red'>case</span> BYTE:<br>     <span style='color:red'>case</span> <span style='color:red'>SHORT</span>:<br>     <span style='color:red'>case</span> <span style='color:red'>LONG</span>:<br>     <span style='color:red'>case</span> DATE:<br>         <span style='color:red'>return</span> 1;<br>     <span style='color:red'>case</span> STRING:<br>         <span style='color:green'>/* Null terminate and eat the return */</span><br>         p->s[<span style='color:red'>sizeof</span>(p->s) - 1] = <span style='color:blue'>'\0'</span>;<br>         <span style='color:red'>if</span> ((rt = strchr(p->s, <span style='color:blue'>'\n'</span>)) != NULL)<br>             *rt = <span style='color:blue'>'\0'</span>;<br>         <span style='color:red'>return</span> 1;<br>     <span style='color:red'>case</span> BESHORT:<br>         p->h = (<span style='color:red'>short</span>) ((p->hs[0] << 8) | (p->hs[1]));<br>         <span style='color:red'>return</span> 1;<br>     <span style='color:red'>case</span> BELONG:<br>     <span style='color:red'>case</span> BEDATE:<br>         p->l = (<span style='color:red'>long</span>)<br>             ((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3]));<br>         <span style='color:red'>return</span> 1;<br>     <span style='color:red'>case</span> LESHORT:<br>         p->h = (<span style='color:red'>short</span>) ((p->hs[1] << 8) | (p->hs[0]));<br>         <span style='color:red'>return</span> 1;<br>     <span style='color:red'>case</span> LELONG:<br>     <span style='color:red'>case</span> LEDATE:<br>         p->l = (<span style='color:red'>long</span>)<br>             ((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0]));<br>         <span style='color:red'>return</span> 1;<br>     <span style='color:red'>default</span>:<br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01538)<br>                     MODNAME <span style='color:blue'>": invalid type %d in mconvert()."</span>, m->type);<br>         <span style='color:red'>return</span> 0;<br>     }<br> }<br> <br> <br> <span style='color:red'>static</span> <span style='color:red'>int</span> mget(request_rec *r, <span style='color:red'>union</span> VALUETYPE *p, <span style='color:red'>unsigned</span> <span style='color:red'>char</span> *s,<br>                 <span style='color:red'>struct</span> magic *m, apr_size_t nbytes)<br> {<br>     <span style='color:red'>long</span> offset = m->offset;<br> <br>     <span style='color:red'>if</span> (offset + <span style='color:red'>sizeof</span>(<span style='color:red'>union</span> VALUETYPE) > nbytes)<br>                   <span style='color:red'>return</span> 0;<br> <br>     memcpy(p, s + offset, <span style='color:red'>sizeof</span>(<span style='color:red'>union</span> VALUETYPE));<br> <br>     <span style='color:red'>if</span> (!mconvert(r, p, m))<br>         <span style='color:red'>return</span> 0;<br> <br>     <span style='color:red'>if</span> (m->flag & INDIR) {<br> <br>         <span style='color:red'>switch</span> (m->in.type) {<br>         <span style='color:red'>case</span> BYTE:<br>             offset = p->b + m->in.offset;<br>             <span style='color:red'>break</span>;<br>         <span style='color:red'>case</span> <span style='color:red'>SHORT</span>:<br>             offset = p->h + m->in.offset;<br>             <span style='color:red'>break</span>;<br>         <span style='color:red'>case</span> <span style='color:red'>LONG</span>:<br>             offset = p->l + m->in.offset;<br>             <span style='color:red'>break</span>;<br>         }<br> <br>         <span style='color:red'>if</span> (offset + <span style='color:red'>sizeof</span>(<span style='color:red'>union</span> VALUETYPE) > nbytes)<br>                       <span style='color:red'>return</span> 0;<br> <br>         memcpy(p, s + offset, <span style='color:red'>sizeof</span>(<span style='color:red'>union</span> VALUETYPE));<br> <br>         <span style='color:red'>if</span> (!mconvert(r, p, m))<br>             <span style='color:red'>return</span> 0;<br>     }<br>     <span style='color:red'>return</span> 1;<br> }<br> <br> <span style='color:red'>static</span> <span style='color:red'>int</span> mcheck(request_rec *r, <span style='color:red'>union</span> VALUETYPE *p, <span style='color:red'>struct</span> magic *m)<br> {<br>     <span style='color:red'>register</span> <span style='color:red'>unsigned</span> <span style='color:red'>long</span> l = m->value.l;<br>     <span style='color:red'>register</span> <span style='color:red'>unsigned</span> <span style='color:red'>long</span> v;<br>     <span style='color:red'>int</span> matched;<br> <br>     <span style='color:red'>if</span> ((m->value.s[0] == <span style='color:blue'>'x'</span>) && (m->value.s[1] == <span style='color:blue'>'\0'</span>)) {<br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01539)<br>                     MODNAME <span style='color:blue'>": BOINK"</span>);<br>         <span style='color:red'>return</span> 1;<br>     }<br> <br>     <span style='color:red'>switch</span> (m->type) {<br>     <span style='color:red'>case</span> BYTE:<br>         v = p->b;<br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>case</span> <span style='color:red'>SHORT</span>:<br>     <span style='color:red'>case</span> BESHORT:<br>     <span style='color:red'>case</span> LESHORT:<br>         v = p->h;<br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>case</span> <span style='color:red'>LONG</span>:<br>     <span style='color:red'>case</span> BELONG:<br>     <span style='color:red'>case</span> LELONG:<br>     <span style='color:red'>case</span> DATE:<br>     <span style='color:red'>case</span> BEDATE:<br>     <span style='color:red'>case</span> LEDATE:<br>         v = p->l;<br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>case</span> STRING:<br>         l = 0;<br>         <span style='color:green'>/*<br> <span style='color:green'>         * What we want here is: v = strncmp(m->value.s, p->s, m->vallen);</span><br> <span style='color:green'>         * but ignoring any nulls.  bcmp doesn't give -/+/0 and isn't</span><br> <span style='color:green'>         * universally available anyway.</span><br>          */</span><br>         v = 0;<br>         {<br>             <span style='color:red'>register</span> <span style='color:red'>unsigned</span> <span style='color:red'>char</span> *a = (<span style='color:red'>unsigned</span> <span style='color:red'>char</span> *) m->value.s;<br>             <span style='color:red'>register</span> <span style='color:red'>unsigned</span> <span style='color:red'>char</span> *b = (<span style='color:red'>unsigned</span> <span style='color:red'>char</span> *) p->s;<br>             <span style='color:red'>register</span> <span style='color:red'>int</span> len = m->vallen;<br> <br>             <span style='color:red'>while</span> (--len >= 0)<br>                 <span style='color:red'>if</span> ((v = *b++ - *a++) != 0)<br>                     <span style='color:red'>break</span>;<br>         }<br>         <span style='color:red'>break</span>;<br>     <span style='color:red'>default</span>:<br>         <span style='color:green'>/*  bogosity, pretend that it just wasn't a match */</span><br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01540)<br>                     MODNAME <span style='color:blue'>": invalid type %d in mcheck()."</span>, m->type);<br>         <span style='color:red'>return</span> 0;<br>     }<br> <br>     v = signextend(r->server, m, v) & m->mask;<br> <br>     <span style='color:red'>switch</span> (m->reln) {<br>     <span style='color:red'>case</span> <span style='color:blue'>'x'</span>:<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01541)<br>                     <span style='color:blue'>"%lu == *any* = 1"</span>, v);<br> <span style='color:turquoise'>#endif</span><br>         matched = 1;<br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>case</span> <span style='color:blue'>'!'</span>:<br>         matched = v != l;<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01542)<br>                     <span style='color:blue'>"%lu != %lu = %d"</span>, v, l, matched);<br> <span style='color:turquoise'>#endif</span><br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>case</span> <span style='color:blue'>'='</span>:<br>         matched = v == l;<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01543)<br>                     <span style='color:blue'>"%lu == %lu = %d"</span>, v, l, matched);<br> <span style='color:turquoise'>#endif</span><br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>case</span> <span style='color:blue'>'>'</span>:<br>         <span style='color:red'>if</span> (m->flag & <span style='color:red'>UNSIGNED</span>) {<br>             matched = v > l;<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01544)<br>                         <span style='color:blue'>"%lu > %lu = %d"</span>, v, l, matched);<br> <span style='color:turquoise'>#endif</span><br>         }<br>         <span style='color:red'>else</span> {<br>             matched = (<span style='color:red'>long</span>) v > (<span style='color:red'>long</span>) l;<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01545)<br>                         <span style='color:blue'>"%ld > %ld = %d"</span>, v, l, matched);<br> <span style='color:turquoise'>#endif</span><br>         }<br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>case</span> <span style='color:blue'>'<'</span>:<br>         <span style='color:red'>if</span> (m->flag & <span style='color:red'>UNSIGNED</span>) {<br>             matched = v < l;<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01546)<br>                         <span style='color:blue'>"%lu < %lu = %d"</span>, v, l, matched);<br> <span style='color:turquoise'>#endif</span><br>         }<br>         <span style='color:red'>else</span> {<br>             matched = (<span style='color:red'>long</span>) v < (<span style='color:red'>long</span>) l;<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01547)<br>                         <span style='color:blue'>"%ld < %ld = %d"</span>, v, l, matched);<br> <span style='color:turquoise'>#endif</span><br>         }<br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>case</span> <span style='color:blue'>'&'</span>:<br>         matched = (v & l) == l;<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01548)<br>                     <span style='color:blue'>"((%lx & %lx) == %lx) = %d"</span>, v, l, l, matched);<br> <span style='color:turquoise'>#endif</span><br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>case</span> <span style='color:blue'>'^'</span>:<br>         matched = (v & l) != l;<br> <span style='color:turquoise'>#if</span> MIME_MAGIC_DEBUG<br>         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01549)<br>                     <span style='color:blue'>"((%lx & %lx) != %lx) = %d"</span>, v, l, l, matched);<br> <span style='color:turquoise'>#endif</span><br>         <span style='color:red'>break</span>;<br> <br>     <span style='color:red'>default</span>:<br>         <span style='color:green'>/* bogosity, pretend it didn't match */</span><br>         matched = 0;<br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01550)<br>                     MODNAME <span style='color:blue'>": mcheck: can't happen: invalid relation %d."</span>,<br>                     m->reln);<br>         <span style='color:red'>break</span>;<br>     }<br> <br>     <span style='color:red'>return</span> matched;<br> }<br> <br> <span style='color:green'>/* an optimization over plain strcmp() */</span><br> <span style='color:turquoise'>#define</span>    STREQ(a, b)    (*(a) == *(b) && strcmp((a), (b)) == 0)<br> <br> <span style='color:red'>static</span> <span style='color:red'>int</span> ascmagic(request_rec *r, <span style='color:red'>unsigned</span> <span style='color:red'>char</span> *buf, apr_size_t nbytes)<br> {<br>     <span style='color:red'>int</span> has_escapes = 0;<br>     <span style='color:red'>unsigned</span> <span style='color:red'>char</span> *s;<br>     <span style='color:red'>char</span> nbuf[SMALL_HOWMANY + 1];  <span style='color:green'>/* one extra for terminating '\0' */</span><br>     <span style='color:red'>char</span> *token;<br>     <span style='color:red'>const</span> <span style='color:red'>struct</span> names *p;<br>     <span style='color:red'>int</span> small_nbytes;<br>     <span style='color:red'>char</span> *strtok_state;<br> <br>     <span style='color:green'>/* these are easy, do them first */</span><br> <br>     <span style='color:green'>/*<br> <span style='color:green'>     * for troff, look for . + letter + letter or .\"; this must be done to</span><br> <span style='color:green'>     * disambiguate tar archives' ./file and other trash from real troff</span><br> <span style='color:green'>     * input.</span><br>      */</span><br>     <span style='color:red'>if</span> (*buf == <span style='color:blue'>'.'</span>) {<br>         <span style='color:red'>unsigned</span> <span style='color:red'>char</span> *tp = buf + 1;<br> <br>         <span style='color:red'>while</span> (apr_isspace(*tp))<br>             ++tp;  <span style='color:green'>/* skip leading whitespace */</span><br>         <span style='color:red'>if</span> ((apr_isalnum(*tp) || *tp == <span style='color:blue'>'\\'</span>) &&<br>              (apr_isalnum(*(tp + 1)) || *tp == <span style='color:blue'>'"'</span>)) {<br>             magic_rsl_puts(r, <span style='color:blue'>"application/x-troff"</span>);<br>             <span style='color:red'>return</span> 1;<br>         }<br>     }<br>     <span style='color:red'>if</span> ((*buf == <span style='color:blue'>'c'</span> || *buf == <span style='color:blue'>'C'</span>) && apr_isspace(*(buf + 1))) {<br>         <span style='color:green'>/* Fortran */</span><br>         magic_rsl_puts(r, <span style='color:blue'>"text/plain"</span>);<br>         <span style='color:red'>return</span> 1;<br>     }<br> <br>     <span style='color:green'>/* look for tokens from names.h - this is expensive!, so we'll limit<br>      * ourselves to only SMALL_HOWMANY bytes */</span><br>     small_nbytes = (nbytes > SMALL_HOWMANY) ? SMALL_HOWMANY : nbytes;<br>     <span style='color:green'>/* make a copy of the buffer here because apr_strtok() will destroy it */</span><br>     s = (<span style='color:red'>unsigned</span> <span style='color:red'>char</span> *) memcpy(nbuf, buf, small_nbytes);<br>     s[small_nbytes] = <span style='color:blue'>'\0'</span>;<br>     has_escapes = (memchr(s, <span style='color:blue'>'\033'</span>, small_nbytes) != NULL);<br>     <span style='color:red'>while</span> ((token = apr_strtok((<span style='color:red'>char</span> *) s, <span style='color:blue'>" \t\n\r\f"</span>, &strtok_state)) != NULL) {<br>         s = NULL;  <span style='color:green'>/* make apr_strtok() keep on tokin' */</span><br>         <span style='color:red'>for</span> (p = names; p < names + NNAMES; p++) {<br>             <span style='color:red'>if</span> (STREQ(p->name, token)) {<br>                 magic_rsl_puts(r, types[p->type]);<br>                 <span style='color:red'>if</span> (has_escapes)<br>                     magic_rsl_puts(r, <span style='color:blue'>" (with escape sequences)"</span>);<br>                 <span style='color:red'>return</span> 1;<br>             }<br>         }<br>     }<br> <br>     <span style='color:red'>switch</span> (is_tar(buf, nbytes)) {<br>     <span style='color:red'>case</span> 1:<br>         <span style='color:green'>/* V7 tar archive */</span><br>         magic_rsl_puts(r, <span style='color:blue'>"application/x-tar"</span>);<br>         <span style='color:red'>return</span> 1;<br>     <span style='color:red'>case</span> 2:<br>         <span style='color:green'>/* POSIX tar archive */</span><br>         magic_rsl_puts(r, <span style='color:blue'>"application/x-tar"</span>);<br>         <span style='color:red'>return</span> 1;<br>     }<br> <br>     <span style='color:green'>/* all else fails, but it is ascii... */</span><br>     <span style='color:red'>return</span> 0;<br> }<br> <br> <br> <span style='color:green'>/*<br> <span style='color:green'> * compress routines: zmagic() - returns 0 if not recognized, uncompresses</span><br> <span style='color:green'> * and prints information if recognized uncompress(s, method, old, n, newch)</span><br> <span style='color:green'> * - uncompress old into new, using method, return sizeof new</span><br>  */</span><br> <br> <span style='color:red'>static</span> <span style='color:red'>const</span> <span style='color:red'>struct</span> {<br>     <span style='color:red'>const</span> <span style='color:red'>char</span> *magic;<br>     apr_size_t maglen;<br>     <span style='color:red'>const</span> <span style='color:red'>char</span> *argv[3];<br>     <span style='color:red'>int</span> silent;<br>     <span style='color:red'>const</span> <span style='color:red'>char</span> *encoding;  <span style='color:green'>/* MUST be lowercase */</span><br> } compr[] = {<br> <br>     <span style='color:green'>/* we use gzip here rather than uncompress because we have to pass<br> <span style='color:green'>     * it a full filename -- and uncompress only considers filenames</span><br> <span style='color:green'>     * ending with .Z</span><br>      */</span><br>     {<br>         <span style='color:blue'>"\037\235"</span>, 2, {<br>             <span style='color:blue'>"gzip"</span>, <span style='color:blue'>"-dcq"</span>, NULL<br>         }, 0, <span style='color:blue'>"x-compress"</span><br>     },<br>     {<br>         <span style='color:blue'>"\037\213"</span>, 2, {<br>             <span style='color:blue'>"gzip"</span>, <span style='color:blue'>"-dcq"</span>, NULL<br>         }, 1, <span style='color:blue'>"x-gzip"</span><br>     },<br>     <span style='color:green'>/*<br> <span style='color:green'>     * XXX pcat does not work, cause I don't know how to make it read stdin,</span><br> <span style='color:green'>     * so we use gzip</span><br>      */</span><br>     {<br>         <span style='color:blue'>"\037\036"</span>, 2, {<br>             <span style='color:blue'>"gzip"</span>, <span style='color:blue'>"-dcq"</span>, NULL<br>         }, 0, <span style='color:blue'>"x-gzip"</span><br>     },<br> };<br> <br> <span style='color:turquoise'>#define</span> ncompr (<span style='color:red'>sizeof</span>(compr) / <span style='color:red'>sizeof</span>(compr[0]))<br> <br> <span style='color:red'>static</span> <span style='color:red'>int</span> zmagic(request_rec *r, <span style='color:red'>unsigned</span> <span style='color:red'>char</span> *buf, apr_size_t nbytes)<br> {<br>     <span style='color:red'>unsigned</span> <span style='color:red'>char</span> *newbuf;<br>     <span style='color:red'>int</span> newsize;<br>     <span style='color:red'>int</span> i;<br> <br>     <span style='color:red'>for</span> (i = 0; i < ncompr; i++) {<br>         <span style='color:red'>if</span> (nbytes < compr[i].maglen)<br>             <span style='color:red'>continue</span>;<br>         <span style='color:red'>if</span> (memcmp(buf, compr[i].magic, compr[i].maglen) == 0)<br>             <span style='color:red'>break</span>;<br>     }<br> <br>     <span style='color:red'>if</span> (i == ncompr)<br>         <span style='color:red'>return</span> 0;<br> <br>     <span style='color:red'>if</span> ((newsize = uncompress(r, i, &newbuf, HOWMANY)) > 0) {<br>         <span style='color:green'>/* set encoding type in the request record */</span><br>         r->content_encoding = compr[i].encoding;<br> <br>         newbuf[newsize-1] = <span style='color:blue'>'\0'</span>;  <span style='color:green'>/* null-terminate uncompressed data */</span><br>         <span style='color:green'>/* Try to detect the content type of the uncompressed data */</span><br>         <span style='color:red'>if</span> (tryit(r, newbuf, newsize, 0) != OK) {<br>             <span style='color:red'>return</span> 0;<br>         }<br>     }<br>     <span style='color:red'>return</span> 1;<br> }<br> <br> <br> <span style='color:red'>struct</span> uncompress_parms {<br>     request_rec *r;<br>     <span style='color:red'>int</span> method;<br> };<br> <br> <span style='color:red'>static</span> <span style='color:red'>int</span> create_uncompress_child(<span style='color:red'>struct</span> uncompress_parms *parm, apr_pool_t *cntxt,<br>                                    apr_file_t **pipe_in)<br> {<br>     <span style='color:red'>int</span> rc = 1;<br>     <span style='color:red'>const</span> <span style='color:red'>char</span> *new_argv[4];<br>     request_rec *r = parm->r;<br>     apr_pool_t *child_context = cntxt;<br>     apr_procattr_t *procattr;<br>     apr_proc_t *procnew;<br> <br>     <span style='color:green'>/* XXX missing 1.3 logic:<br> <span style='color:green'>     *</span><br> <span style='color:green'>     * what happens when !compr[parm->method].silent?</span><br> <span style='color:green'>     * Should we create the err pipe, read it, and copy to the log?</span><br>      */</span><br> <br>     <span style='color:red'>if</span> ((apr_procattr_create(&procattr, child_context) != APR_SUCCESS) ||<br>         (apr_procattr_io_set(procattr, APR_FULL_BLOCK,<br>                            APR_FULL_BLOCK, APR_NO_PIPE)   != APR_SUCCESS) ||<br>         (apr_procattr_dir_set(procattr,<br>                               ap_make_dirstr_parent(r->pool, r->filename)) != APR_SUCCESS) ||<br>         (apr_procattr_cmdtype_set(procattr, APR_PROGRAM_PATH) != APR_SUCCESS)) {<br>         <span style='color:green'>/* Something bad happened, tell the world. */</span><br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_ENOPROC, r, APLOGNO(01551)<br>                <span style='color:blue'>"couldn't setup child process: %s"</span>, r->filename);<br>     }<br>     <span style='color:red'>else</span> {<br>         new_argv[0] = compr[parm->method].argv[0];<br>         new_argv[1] = compr[parm->method].argv[1];<br>         new_argv[2] = r->filename;<br>         new_argv[3] = NULL;<br> <br>         procnew = apr_pcalloc(child_context, <span style='color:red'>sizeof</span>(*procnew));<br>         rc = apr_proc_create(procnew, compr[parm->method].argv[0],<br>                                new_argv, NULL, procattr, child_context);<br> <br>         <span style='color:red'>if</span> (rc != APR_SUCCESS) {<br>             <span style='color:green'>/* Bad things happened. Everyone should have cleaned up. */</span><br>             ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_ENOPROC, r, APLOGNO(01552)<br>                           MODNAME <span style='color:blue'>": could not execute `%s'."</span>,<br>                           compr[parm->method].argv[0]);<br>         }<br>         <span style='color:red'>else</span> {<br>             apr_pool_note_subprocess(child_context, procnew, APR_KILL_AFTER_TIMEOUT);<br>             *pipe_in = procnew->out;<br>         }<br>     }<br> <br>     <span style='color:red'>return</span> (rc);<br> }<br> <br> <span style='color:red'>static</span> <span style='color:red'>int</span> uncompress(request_rec *r, <span style='color:red'>int</span> method,<br>                       <span style='color:red'>unsigned</span> <span style='color:red'>char</span> **newch, apr_size_t n)<br> {<br>     <span style='color:red'>struct</span> uncompress_parms parm;<br>     apr_file_t *pipe_out = NULL;<br>     apr_pool_t *sub_context;<br>     apr_status_t rv;<br> <br>     parm.r = r;<br>     parm.method = method;<br> <br>     <span style='color:green'>/* We make a sub_pool so that we can collect our child early, otherwise<br> <span style='color:green'>     * there are cases (i.e. generating directory indices with mod_autoindex)</span><br> <span style='color:green'>     * where we would end up with LOTS of zombies.</span><br>      */</span><br>     <span style='color:red'>if</span> (apr_pool_create(&sub_context, r->pool) != APR_SUCCESS)<br>         <span style='color:red'>return</span> -1;<br>     apr_pool_tag(sub_context, <span style='color:blue'>"magic_uncompress"</span>);<br> <br>     <span style='color:red'>if</span> ((rv = create_uncompress_child(&parm, sub_context, &pipe_out)) != APR_SUCCESS) {<br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01553)<br>                     MODNAME <span style='color:blue'>": couldn't spawn uncompress process: %s"</span>, r->uri);<br>         <span style='color:red'>return</span> -1;<br>     }<br> <br>     *newch = (<span style='color:red'>unsigned</span> <span style='color:red'>char</span> *) apr_palloc(r->pool, n);<br>     rv = apr_file_read(pipe_out, *newch, &n);<br>     <span style='color:red'>if</span> (n == 0) {<br>         apr_pool_destroy(sub_context);<br>         ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01554)<br>             MODNAME <span style='color:blue'>": read failed from uncompress of %s"</span>, r->filename);<br>         <span style='color:red'>return</span> -1;<br>     }<br>     apr_pool_destroy(sub_context);<br> --> --------------------<br> <br> --> maximum size reached<br> <br> --> --------------------<br> <p align=center><label for='file'>quality</label><progress id='qual' value=95 max=100>95% </progress></p> </span><br> <h3><b>¤</b> Dauer der Verarbeitung: 0.74 Sekunden  (vorverarbeitet)  <b>¤</b></h3> <p height="2" colspan="2" align="center"><span style="font-size: 3px;">*© Formatika GbR, Deutschland</span></p> </div> </td> <td valign="top" align="center" class="greenscreensmall"> <br><br><br> <br> <table width="20%"> <tr><td align="center"> <a href="mobile.jsp?content=directory"> <br>Wurzel<br> <img border="0" src="/Images/penguin.jpg" height=36 alt="" title="Wurzel"> </a> </td> </tr> <tr><td align="center"> <a href="mobile.jsp?content=search" title="Suchen"> <br>Suchen<br> <img src="/Images/find.png" height="48" alt="" border="0"> </a> </td> </tr> <tr><td align="left"><a href="mobile.jsp?content=directory&detail=products/Sources/formale%20Sprachen/PVS/" title="Projekt "><br>Beweissystem der NASA</a></td></tr> <tr><td align="left"><a href="mobile.jsp?content=directory&detail=products/Sources/formale%20Sprachen/Isabelle/" title="Projekt "><br>Beweissystem Isabelle</a></td></tr> <tr><td align="left"><a href="mobile.jsp?content=directory&detail=products/Sources/formale%20Sprachen/Cobol/Test-Suite/" title="Projekt "><br>NIST Cobol Testsuite</a></td></tr> <tr><td align="left"><a href="mobile.jsp?content=directory&detail=products/Sources/formale%20Sprachen/Fortran/f90gl-1.2.15/" title="Projekt "><br>Cephes Mathematical Library</a></td></tr> <tr><td align="left"><a href="mobile.jsp?content=directory&detail=products/Sources/formale%20Sprachen/VDM/" title="Projekt "><br>Wiener Entwicklungsmethode</a></td></tr> <tr><td align="center"> <br> <h2>Haftungshinweis</h2> <div align="justify" class="featuresmall">Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.</div> <br> <h2>Bemerkung:</h2> <div align="justify" class="featuresmall"> Die farbliche Syntaxdarstellung ist noch experimentell.</div> <br> </td> </tr> </table> <br><br> <div> <br> <script src="https://formatika.de/base/formcheck.js"></script> <script> function checkform(form) { var res = true; res = res && isnotempty(form.file); res = res && isurl(form.file); return res; } </script> </div><br> <br> </td> </tr> </table> </div> <div class="printelement"> <script> warningpreview(); </script> </div> <p align=right class=hidden>2026-03-28</p> </td></tr> </table> </body> </html>