⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_mime_magic.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* these are easy, do them first */    /*     * for troff, look for . + letter + letter or .\"; this must be done to     * disambiguate tar archives' ./file and other trash from real troff     * input.     */    if (*buf == '.') {	unsigned char *tp = buf + 1;	while (apr_isspace(*tp))	    ++tp;		/* skip leading whitespace */	if ((apr_isalnum(*tp) || *tp == '\\') &&	     (apr_isalnum(*(tp + 1)) || *tp == '"')) {	    magic_rsl_puts(r, "application/x-troff");	    return 1;	}    }    if ((*buf == 'c' || *buf == 'C') && apr_isspace(*(buf + 1))) {	/* Fortran */	magic_rsl_puts(r, "text/plain");	return 1;    }    /* look for tokens from names.h - this is expensive!, so we'll limit     * ourselves to only SMALL_HOWMANY bytes */    small_nbytes = (nbytes > SMALL_HOWMANY) ? SMALL_HOWMANY : nbytes;    /* make a copy of the buffer here because apr_strtok() will destroy it */    s = (unsigned char *) memcpy(nbuf, buf, small_nbytes);    s[small_nbytes] = '\0';    has_escapes = (memchr(s, '\033', small_nbytes) != NULL);    while ((token = apr_strtok((char *) s, " \t\n\r\f", &strtok_state)) != NULL) {	s = NULL;		/* make apr_strtok() keep on tokin' */	for (p = names; p < names + NNAMES; p++) {	    if (STREQ(p->name, token)) {		magic_rsl_puts(r, types[p->type]);		if (has_escapes)		    magic_rsl_puts(r, " (with escape sequences)");		return 1;	    }	}    }    switch (is_tar(buf, nbytes)) {    case 1:	/* V7 tar archive */	magic_rsl_puts(r, "application/x-tar");	return 1;    case 2:	/* POSIX tar archive */	magic_rsl_puts(r, "application/x-tar");	return 1;    }    /* all else fails, but it is ascii... */    return 0;}/* * compress routines: zmagic() - returns 0 if not recognized, uncompresses * and prints information if recognized uncompress(s, method, old, n, newch) * - uncompress old into new, using method, return sizeof new */static struct {    char *magic;    apr_size_t maglen;    char *argv[3];    int silent;    char *encoding;	/* MUST be lowercase */} compr[] = {    /* we use gzip here rather than uncompress because we have to pass     * it a full filename -- and uncompress only considers filenames     * ending with .Z     */    {	"\037\235", 2, {	    "gzip", "-dcq", NULL	}, 0, "x-compress"    },    {	"\037\213", 2, {	    "gzip", "-dcq", NULL	}, 1, "x-gzip"    },    /*     * XXX pcat does not work, cause I don't know how to make it read stdin,     * so we use gzip     */    {	"\037\036", 2, {	    "gzip", "-dcq", NULL	}, 0, "x-gzip"    },};static int ncompr = sizeof(compr) / sizeof(compr[0]);static int zmagic(request_rec *r, unsigned char *buf, apr_size_t nbytes){    unsigned char *newbuf;    int newsize;    int i;    for (i = 0; i < ncompr; i++) {	if (nbytes < compr[i].maglen)	    continue;	if (memcmp(buf, compr[i].magic, compr[i].maglen) == 0)	    break;    }    if (i == ncompr)	return 0;    if ((newsize = uncompress(r, i, &newbuf, nbytes)) > 0) {	if (tryit(r, newbuf, newsize, 0) != OK) {            return 0;        }	/* set encoding type in the request record */	r->content_encoding = compr[i].encoding;    }    return 1;}struct uncompress_parms {    request_rec *r;    int method;};static int create_uncompress_child(struct uncompress_parms *parm, apr_pool_t *cntxt,                                   apr_file_t **pipe_in){    int rc = 1;    const char *new_argv[4];    const char *const *env;    request_rec *r = parm->r;    apr_pool_t *child_context = cntxt;    apr_procattr_t *procattr;    apr_proc_t *procnew;    /* XXX missing 1.3 logic:      *     * what happens when !compr[parm->method].silent?     * Should we create the err pipe, read it, and copy to the log?     */            env = (const char *const *)ap_create_environment(child_context, r->subprocess_env);    if ((apr_procattr_create(&procattr, child_context) != APR_SUCCESS) ||        (apr_procattr_io_set(procattr, APR_FULL_BLOCK,                            APR_FULL_BLOCK, APR_NO_PIPE)   != APR_SUCCESS) ||        (apr_procattr_dir_set(procattr, r->filename)        != APR_SUCCESS) ||        (apr_procattr_cmdtype_set(procattr, APR_PROGRAM)    != APR_SUCCESS)) {        /* Something bad happened, tell the world. */        ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_ENOPROC, r,               "couldn't setup child process: %s", r->filename);    }    else {        new_argv[0] = compr[parm->method].argv[0];        new_argv[1] = compr[parm->method].argv[1];        new_argv[2] = r->filename;        new_argv[3] = NULL;        procnew = apr_pcalloc(child_context, sizeof(*procnew));        rc = apr_proc_create(procnew, compr[parm->method].argv[0],                               new_argv, env, procattr, child_context);        if (rc != APR_SUCCESS) {            /* Bad things happened. Everyone should have cleaned up. */            ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_ENOPROC, r,                          MODNAME ": could not execute `%s'.",                          compr[parm->method].argv[0]);        }        else {            apr_pool_note_subprocess(child_context, procnew, APR_KILL_AFTER_TIMEOUT);            *pipe_in = procnew->out;        }    }    return (rc);}static int uncompress(request_rec *r, int method, 		      unsigned char **newch, apr_size_t n){    struct uncompress_parms parm;    apr_file_t *pipe_out = NULL;    apr_pool_t *sub_context;    apr_status_t rv;    parm.r = r;    parm.method = method;    /* We make a sub_pool so that we can collect our child early, otherwise     * there are cases (i.e. generating directory indicies with mod_autoindex)     * where we would end up with LOTS of zombies.     */    if (apr_pool_create(&sub_context, r->pool) != APR_SUCCESS)        return -1;    if ((rv = create_uncompress_child(&parm, sub_context, &pipe_out)) != APR_SUCCESS) {	ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,		    MODNAME ": couldn't spawn uncompress process: %s", r->uri);	return -1;    }    *newch = (unsigned char *) apr_palloc(r->pool, n);    rv = apr_file_read(pipe_out, *newch, &n);    if (n == 0) {	apr_pool_destroy(sub_context);	ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,	    MODNAME ": read failed %s", r->filename);	return -1;    }    apr_pool_destroy(sub_context);    return n;}/* * is_tar() -- figure out whether file is a tar archive. * * Stolen (by author of file utility) from the public domain tar program: Public * Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu). * * @(#)list.c 1.18 9/23/86 Public Domain - gnu $Id: mod_mime_magic.c,v 1.7 * 1997/06/24 00:41:02 ikluft Exp ikluft $ * * Comments changed and some code/comments reformatted for file command by Ian * Darwin. */#define isodigit(c) (((unsigned char)(c) >= '0') && ((unsigned char)(c) <= '7'))/* * Return 0 if the checksum is bad (i.e., probably not a tar archive), 1 for * old UNIX tar file, 2 for Unix Std (POSIX) tar file. */static int is_tar(unsigned char *buf, apr_size_t nbytes){    register union record *header = (union record *) buf;    register int i;    register long sum, recsum;    register char *p;    if (nbytes < sizeof(union record))	       return 0;    recsum = from_oct(8, header->header.chksum);    sum = 0;    p = header->charptr;    for (i = sizeof(union record); --i >= 0;) {	/*	 * We can't use unsigned char here because of old compilers, e.g. V7.	 */	sum += 0xFF & *p++;    }    /* Adjust checksum to count the "chksum" field as blanks. */    for (i = sizeof(header->header.chksum); --i >= 0;)	sum -= 0xFF & header->header.chksum[i];    sum += ' ' * sizeof header->header.chksum;    if (sum != recsum)	return 0;		/* Not a tar archive */    if (0 == strcmp(header->header.magic, TMAGIC))	return 2;		/* Unix Standard tar archive */    return 1;			/* Old fashioned tar archive */}/* * Quick and dirty octal conversion. * * Result is -1 if the field is invalid (all blank, or nonoctal). */static long from_oct(int digs, char *where){    register long value;    while (apr_isspace(*where)) {	/* Skip spaces */	where++;	if (--digs <= 0)	    return -1;		/* All blank field */    }    value = 0;    while (digs > 0 && isodigit(*where)) {	/* Scan til nonoctal */	value = (value << 3) | (*where++ - '0');	--digs;    }    if (digs > 0 && *where && !apr_isspace(*where))	return -1;		/* Ended on non-space/nul */    return value;}/* * Check for file-revision suffix * * This is for an obscure document control system used on an intranet. * The web representation of each file's revision has an @1, @2, etc * appended with the revision number.  This needs to be stripped off to * find the file suffix, which can be recognized by sending the name back * through a sub-request.  The base file name (without the @num suffix) * must exist because its type will be used as the result. */static int revision_suffix(request_rec *r){    int suffix_pos, result;    char *sub_filename;    request_rec *sub;#if MIME_MAGIC_DEBUG    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,		MODNAME ": revision_suffix checking %s", r->filename);#endif /* MIME_MAGIC_DEBUG */    /* check for recognized revision suffix */    suffix_pos = strlen(r->filename) - 1;    if (!apr_isdigit(r->filename[suffix_pos])) {	return 0;    }    while (suffix_pos >= 0 && apr_isdigit(r->filename[suffix_pos]))	suffix_pos--;    if (suffix_pos < 0 || r->filename[suffix_pos] != '@') {	return 0;    }    /* perform sub-request for the file name without the suffix */    result = 0;    sub_filename = apr_pstrndup(r->pool, r->filename, suffix_pos);#if MIME_MAGIC_DEBUG    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,		MODNAME ": subrequest lookup for %s", sub_filename);#endif /* MIME_MAGIC_DEBUG */    sub = ap_sub_req_lookup_file(sub_filename, r, NULL);    /* extract content type/encoding/language from sub-request */    if (sub->content_type) {	ap_set_content_type(r, apr_pstrdup(r->pool, sub->content_type));#if MIME_MAGIC_DEBUG	ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,		    MODNAME ": subrequest %s got %s",		    sub_filename, r->content_type);#endif /* MIME_MAGIC_DEBUG */	if (sub->content_encoding)	    r->content_encoding =		apr_pstrdup(r->pool, sub->content_encoding);        if (sub->content_languages) {            int n;	    r->content_languages = apr_array_copy(r->pool,                                                   sub->content_languages);            for (n = 0; n < r->content_languages->nelts; ++n) {                char **lang = ((char **)r->content_languages->elts) + n;                *lang = apr_pstrdup(r->pool, *lang);            }        }	result = 1;    }    /* clean up */    ap_destroy_sub_req(sub);    return result;}/* * initialize the module */static int magic_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_server){    int result;    magic_server_config_rec *conf;    magic_server_config_rec *main_conf;    server_rec *s;#if MIME_MAGIC_DEBUG    struct magic *m, *prevm;#endif /* MIME_MAGIC_DEBUG */    main_conf = ap_get_module_config(main_server->module_config, &mime_magic_module);    for (s = main_server; s; s = s->next) {	conf = ap_get_module_config(s->module_config, &mime_magic_module);	if (conf->magicfile == NULL && s != main_server) {	    /* inherits from the parent */	    *conf = *main_conf;	}	else if (conf->magicfile) {	    result = apprentice(s, p);	    if (result == -1)		return OK;#if MIME_MAGIC_DEBUG	    prevm = 0;	    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,			MODNAME ": magic_init 1 test");	    for (m = conf->magic; m; m = m->next) {		if (apr_isprint((((unsigned long) m) >> 24) & 255) &&		    apr_isprint((((unsigned long) m) >> 16) & 255) &&		    apr_isprint((((unsigned long) m) >> 8) & 255) &&		    apr_isprint(((unsigned long) m) & 255)) {		    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,				MODNAME ": magic_init 1: POINTER CLOBBERED! "				"m=\"%c%c%c%c\" line=%d",				(((unsigned long) m) >> 24) & 255,				(((unsigned long) m) >> 16) & 255,				(((unsigned long) m) >> 8) & 255,				((unsigned long) m) & 255,				prevm ? prevm->lineno : -1);		    break;		}		prevm = m;	    }#endif	}    }    return OK;}/* * Find the Content-Type from any resource this module has available */static int magic_find_ct(request_rec *r){    int result;    magic_server_config_rec *conf;    /* the file has to exist */    if (r->finfo.filetype == 0 || !r->filename) {	return DECLINED;    }    /* was someone else already here? */    if (r->content_type) {	return DECLINED;    }    conf = ap_get_module_config(r->server->module_config, &mime_magic_module);    if (!conf || !conf->magic) {	return DECLINED;    }    /* initialize per-request info */    if (!magic_set_config(r)) {	return HTTP_INTERNAL_SERVER_ERROR;    }    /* try excluding file-revision suffixes */    if (revision_suffix(r) != 1) {	/* process it based on the file contents */	if ((result = magic_process(r)) != OK) {	    return result;	}    }    /* if we have any results, put them in the request structure */    return magic_rsl_to_request(r);}static void register_hooks(apr_pool_t *p){    static const char * const aszPre[]={ "mod_mime.c", NULL };    /* mod_mime_magic should be run after mod_mime, if at all. */    ap_hook_type_checker(magic_find_ct, aszPre, NULL, APR_HOOK_MIDDLE);    ap_hook_post_config(magic_init, NULL, NULL, APR_HOOK_FIRST);}/* * Apache API module interface */module AP_MODULE_DECLARE_DATA mime_magic_module ={    STANDARD20_MODULE_STUFF,    NULL,                      /* dir config creator */    NULL,                      /* dir merger --- default is to override */    create_magic_server_config,        /* server config */    merge_magic_server_config, /* merge server config */    mime_magic_cmds,           /* command apr_table_t */    register_hooks              /* register hooks */};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -