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

📄 mod_mime_magic.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 5 页
字号:
    struct magic_rsl_s *next;   /* pointer to next fragment */} magic_rsl;/* * Apache module configuration structures *//* per-server info */typedef struct {    const char *magicfile;    /* where magic be found */    struct magic *magic;      /* head of magic config list */    struct magic *last;} magic_server_config_rec;/* per-request info */typedef struct {    magic_rsl *head;          /* result string list */    magic_rsl *tail;    unsigned suf_recursion;   /* recursion depth in suffix check */} magic_req_rec;/* * configuration functions - called by Apache API routines */module AP_MODULE_DECLARE_DATA mime_magic_module;static void *create_magic_server_config(apr_pool_t *p, server_rec *d){    /* allocate the config - use pcalloc because it needs to be zeroed */    return apr_pcalloc(p, sizeof(magic_server_config_rec));}static void *merge_magic_server_config(apr_pool_t *p, void *basev, void *addv){    magic_server_config_rec *base = (magic_server_config_rec *) basev;    magic_server_config_rec *add = (magic_server_config_rec *) addv;    magic_server_config_rec *new = (magic_server_config_rec *)                            apr_palloc(p, sizeof(magic_server_config_rec));    new->magicfile = add->magicfile ? add->magicfile : base->magicfile;    new->magic = NULL;    new->last = NULL;    return new;}static const char *set_magicfile(cmd_parms *cmd, void *dummy, const char *arg){    magic_server_config_rec *conf = (magic_server_config_rec *)    ap_get_module_config(cmd->server->module_config,                      &mime_magic_module);    if (!conf) {        return MODNAME ": server structure not allocated";    }    conf->magicfile = arg;    return NULL;}/* * configuration file commands - exported to Apache API */static const command_rec mime_magic_cmds[] ={    AP_INIT_TAKE1("MimeMagicFile", set_magicfile, NULL, RSRC_CONF,     "Path to MIME Magic file (in file(1) format)"),    {NULL}};/* * RSL (result string list) processing routines * * These collect strings that would have been printed in fragments by file(1) * into a list of magic_rsl structures with the strings. When complete, * they're concatenated together to become the MIME content and encoding * types. * * return value conventions for these functions: functions which return int: * failure = -1, other = result functions which return pointers: failure = 0, * other = result *//* allocate a per-request structure and put it in the request record */static magic_req_rec *magic_set_config(request_rec *r){    magic_req_rec *req_dat = (magic_req_rec *) apr_palloc(r->pool,                                                      sizeof(magic_req_rec));    req_dat->head = req_dat->tail = (magic_rsl *) NULL;    ap_set_module_config(r->request_config, &mime_magic_module, req_dat);    return req_dat;}/* add a string to the result string list for this request *//* it is the responsibility of the caller to allocate "str" */static int magic_rsl_add(request_rec *r, char *str){    magic_req_rec *req_dat = (magic_req_rec *)                    ap_get_module_config(r->request_config, &mime_magic_module);    magic_rsl *rsl;    /* make sure we have a list to put it in */    if (!req_dat) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EINVAL, r,                    MODNAME ": request config should not be NULL");        if (!(req_dat = magic_set_config(r))) {            /* failure */            return -1;        }    }    /* allocate the list entry */    rsl = (magic_rsl *) apr_palloc(r->pool, sizeof(magic_rsl));    /* fill it */    rsl->str = str;    rsl->next = (magic_rsl *) NULL;    /* append to the list */    if (req_dat->head && req_dat->tail) {        req_dat->tail->next = rsl;        req_dat->tail = rsl;    }    else {        req_dat->head = req_dat->tail = rsl;    }    /* success */    return 0;}/* RSL hook for puts-type functions */static int magic_rsl_puts(request_rec *r, char *str){    return magic_rsl_add(r, str);}/* RSL hook for printf-type functions */static int magic_rsl_printf(request_rec *r, char *str,...){    va_list ap;    char buf[MAXMIMESTRING];    /* assemble the string into the buffer */    va_start(ap, str);    apr_vsnprintf(buf, sizeof(buf), str, ap);    va_end(ap);    /* add the buffer to the list */    return magic_rsl_add(r, apr_pstrdup(r->pool, buf));}/* RSL hook for putchar-type functions */static int magic_rsl_putchar(request_rec *r, char c){    char str[2];    /* high overhead for 1 char - just hope they don't do this much */    str[0] = c;    str[1] = '\0';    return magic_rsl_add(r, str);}/* allocate and copy a contiguous string from a result string list */static char *rsl_strdup(request_rec *r, int start_frag, int start_pos, int len){    char *result;       /* return value */    int cur_frag,       /* current fragment number/counter */        cur_pos,        /* current position within fragment */        res_pos;        /* position in result string */    magic_rsl *frag;    /* list-traversal pointer */    magic_req_rec *req_dat = (magic_req_rec *)                    ap_get_module_config(r->request_config, &mime_magic_module);    /* allocate the result string */    result = (char *) apr_palloc(r->pool, len + 1);    /* loop through and collect the string */    res_pos = 0;    for (frag = req_dat->head, cur_frag = 0;         frag->next;         frag = frag->next, cur_frag++) {        /* loop to the first fragment */        if (cur_frag < start_frag)            continue;        /* loop through and collect chars */        for (cur_pos = (cur_frag == start_frag) ? start_pos : 0;             frag->str[cur_pos];             cur_pos++) {            if (cur_frag >= start_frag                && cur_pos >= start_pos                && res_pos <= len) {                result[res_pos++] = frag->str[cur_pos];                if (res_pos > len) {                    break;                }            }        }    }    /* clean up and return */    result[res_pos] = 0;#if MIME_MAGIC_DEBUG    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,             MODNAME ": rsl_strdup() %d chars: %s", res_pos - 1, result);#endif    return result;}/* states for the state-machine algorithm in magic_rsl_to_request() */typedef enum {    rsl_leading_space, rsl_type, rsl_subtype, rsl_separator, rsl_encoding} rsl_states;/* process the RSL and set the MIME info in the request record */static int magic_rsl_to_request(request_rec *r){    int cur_frag,         /* current fragment number/counter */        cur_pos,          /* current position within fragment */        type_frag,        /* content type starting point: fragment */        type_pos,         /* content type starting point: position */        type_len,         /* content type length */        encoding_frag,    /* content encoding starting point: fragment */        encoding_pos,     /* content encoding starting point: position */        encoding_len;     /* content encoding length */    magic_rsl *frag;      /* list-traversal pointer */    rsl_states state;    magic_req_rec *req_dat = (magic_req_rec *)                    ap_get_module_config(r->request_config, &mime_magic_module);    /* check if we have a result */    if (!req_dat || !req_dat->head) {        /* empty - no match, we defer to other Apache modules */        return DECLINED;    }    /* start searching for the type and encoding */    state = rsl_leading_space;    type_frag = type_pos = type_len = 0;    encoding_frag = encoding_pos = encoding_len = 0;    for (frag = req_dat->head, cur_frag = 0;         frag && frag->next;         frag = frag->next, cur_frag++) {        /* loop through the characters in the fragment */        for (cur_pos = 0; frag->str[cur_pos]; cur_pos++) {            if (apr_isspace(frag->str[cur_pos])) {                /* process whitespace actions for each state */                if (state == rsl_leading_space) {                    /* eat whitespace in this state */                    continue;                }                else if (state == rsl_type) {                    /* whitespace: type has no slash! */                    return DECLINED;                }                else if (state == rsl_subtype) {                    /* whitespace: end of MIME type */                    state++;                    continue;                }                else if (state == rsl_separator) {                    /* eat whitespace in this state */                    continue;                }                else if (state == rsl_encoding) {                    /* whitespace: end of MIME encoding */                    /* we're done */                    frag = req_dat->tail;                    break;                }                else {                    /* should not be possible */                    /* abandon malfunctioning module */                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                                MODNAME ": bad state %d (ws)", state);                    return DECLINED;                }                /* NOTREACHED */            }            else if (state == rsl_type &&                     frag->str[cur_pos] == '/') {                /* copy the char and go to rsl_subtype state */                type_len++;                state++;            }            else {                /* process non-space actions for each state */                if (state == rsl_leading_space) {                    /* non-space: begin MIME type */                    state++;                    type_frag = cur_frag;                    type_pos = cur_pos;                    type_len = 1;                    continue;                }                else if (state == rsl_type ||                         state == rsl_subtype) {                    /* non-space: adds to type */                    type_len++;                    continue;                }                else if (state == rsl_separator) {                    /* non-space: begin MIME encoding */                    state++;                    encoding_frag = cur_frag;                    encoding_pos = cur_pos;                    encoding_len = 1;                    continue;                }                else if (state == rsl_encoding) {                    /* non-space: adds to encoding */                    encoding_len++;                    continue;                }                else {                    /* should not be possible */                    /* abandon malfunctioning module */                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                                MODNAME ": bad state %d (ns)", state);                    return DECLINED;                }                /* NOTREACHED */            }            /* NOTREACHED */        }    }    /* if we ended prior to state rsl_subtype, we had incomplete info */    if (state != rsl_subtype && state != rsl_separator &&        state != rsl_encoding) {        /* defer to other modules */        return DECLINED;    }    /* save the info in the request record */    if (state == rsl_subtype || state == rsl_encoding ||        state == rsl_encoding) {        char *tmp;        tmp = rsl_strdup(r, type_frag, type_pos, type_len);        /* XXX: this could be done at config time I'm sure... but I'm         * confused by all this magic_rsl stuff. -djg */        ap_content_type_tolower(tmp);        ap_set_content_type(r, tmp);    }    if (state == rsl_encoding) {        char *tmp;        tmp = rsl_strdup(r, encoding_frag,                                         encoding_pos, encoding_len);        /* XXX: this could be done at config time I'm sure... but I'm         * confused by all this magic_rsl stuff. -djg */        ap_str_tolower(tmp);        r->content_encoding = tmp;    }    /* detect memory allocation or other errors */    if (!r->content_type ||        (state == rsl_encoding && !r->content_encoding)) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      MODNAME ": unexpected state %d; could be caused by bad "                      "data in magic file",                      state);        return HTTP_INTERNAL_SERVER_ERROR;    }    /* success! */    return OK;}/* * magic_process - process input file r        Apache API request record * (formerly called "process" in file command, prefix added for clarity) Opens * the file and reads a fixed-size buffer to begin processing the contents. */static int magic_process(request_rec *r){    apr_file_t *fd = NULL;    unsigned char buf[HOWMANY + 1];  /* one extra for terminating '\0' */    apr_size_t nbytes = 0;           /* number of bytes read from a datafile */    int result;    /*     * first try judging the file based on its filesystem status     */    switch ((result = fsmagic(r, r->filename))) {    case DONE:        magic_rsl_putchar(r, '\n');        return OK;    case OK:        break;    default:        /* fatal error, bail out */        return result;    }    if (apr_file_open(&fd, r->filename, APR_READ, APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {        /* We can't open it, but we were able to stat it. */        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                    MODNAME ": can't read `%s'", r->filename);        /* let some other handler decide what the problem is */        return DECLINED;    }    /*     * try looking at the first HOWMANY bytes     */    nbytes = sizeof(buf) - 1;    if ((result = apr_file_read(fd, (char *) buf, &nbytes)) != APR_SUCCESS) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, result, r,                    MODNAME ": read failed: %s", r->filename);        return HTTP_INTERNAL_SERVER_ERROR;    }    if (nbytes == 0) {        return DECLINED;    }    else {        buf[nbytes++] = '\0';  /* null-terminate it */        result = tryit(r, buf, nbytes, 1);        if (result != OK) {            return result;        }    }    (void) apr_file_close(fd);    (void) magic_rsl_putchar(r, '\n');    return OK;}static int tryit(request_rec *r, unsigned char *buf, apr_size_t nb,                 int checkzmagic){    /*     * Try compression stuff     */        if (checkzmagic == 1) {                        if (zmagic(r, buf, nb) == 1)                        return OK;        }

⌨️ 快捷键说明

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