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

📄 mod_mime_magic.c

📁 apache简化版
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * configuration functions - called by Apache API routines */module mime_magic_module;static void *create_magic_server_config(pool *p, server_rec *d){    /* allocate the config - use pcalloc because it needs to be zeroed */    return ap_pcalloc(p, sizeof(magic_server_config_rec));}static void *merge_magic_server_config(pool *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 *)			    ap_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, char *d, 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[] ={    {"MimeMagicFile", set_magicfile, NULL, RSRC_CONF, TAKE1,     "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 *) ap_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_NOERRNO | APLOG_ERR, 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 *) ap_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);    ap_vsnprintf(buf, sizeof(buf), str, ap);    va_end(ap);    /* add the buffer to the list */    return magic_rsl_add(r, strdup(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 *) ap_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_NOERRNO | APLOG_DEBUG, 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 (ap_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_NOERRNO | APLOG_ERR, 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_NOERRNO | APLOG_ERR, 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);	r->content_type = 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 errors */    if (!r->content_type ||	(state == rsl_encoding && !r->content_encoding)) {	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){    int fd = 0;    unsigned char buf[HOWMANY + 1];	/* one extra for terminating '\0' */    int 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 ((fd = ap_popenf(r->pool, r->filename, O_RDONLY, 0)) < 0) {	/* We can't open it, but we were able to stat it. */	ap_log_rerror(APLOG_MARK, APLOG_ERR, 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     */    if ((nbytes = read(fd, (char *) buf, sizeof(buf) - 1)) == -1) {	ap_log_rerror(APLOG_MARK, APLOG_ERR, r,		    MODNAME ": read failed: %s", r->filename);	return HTTP_INTERNAL_SERVER_ERROR;    }    if (nbytes == 0)	magic_rsl_puts(r, MIME_TEXT_UNKNOWN);    else {	buf[nbytes++] = '\0';	/* null-terminate it */	tryit(r, buf, nbytes);    }    (void) ap_pclosef(r->pool, fd);    (void) magic_rsl_putchar(r, '\n');    return OK;}static void tryit(request_rec *r, unsigned char *buf, int nb){    /*     * Try compression stuff     */    if (zmagic(r, buf, nb) == 1)	return;    /*     * try tests in /etc/magic (or surrogate magic file)     */    if (softmagic(r, buf, nb) == 1)	return;    /*     * try known keywords, check for ascii-ness too.     */    if (ascmagic(r, buf, nb) == 1)	return;    /*     * abandon hope, all ye who remain here     */    magic_rsl_puts(r, MIME_BINARY_UNKNOWN);}#define    EATAB {while (ap_isspace((unsigned char) *l))  ++l;}/* * apprentice - load configuration from the magic file r *  API request record */static int apprentice(server_rec *s, pool *p){    FILE *f;    char line[BUFSIZ + 1];    int errs = 0;    int lineno;#if MIME_MAGIC_DEBUG    int rule = 0;    struct magic *m, *prevm;#endif    char *fname;    magic_server_config_rec *conf = (magic_server_config_rec *)		    ap_get_module_config(s->module_config, &mime_magic_module);    fname = ap_server_root_relative(p, conf->magicfile);    f = ap_pfopen(p, fname, "r");    if (f == NULL) {	ap_log_error(APLOG_MARK, APLOG_ERR, s,		    MODNAME ": can't read magic file %s", fname);	return -1;    }    /* set up the magic list (empty) */    conf->magic = conf->last = NULL;    /* parse it */    for (lineno = 1; fgets(line, BUFSIZ, f) != NULL; lineno++) {	int ws_offset;	/* delete newline */	if (line[0]) {	    line[strlen(line) - 1] = '\0';	}	/* skip leading whitespace */	ws_offset = 0;	while (line[ws_offset] && ap_isspace(line[ws_offset])) {	    ws_offset++;	}	/* skip blank lines */	if (line[ws_offset] == 0) {	    continue;	}	/* comment, do not parse */	if (line[ws_offset] == '#')	    continue;#if MIME_MAGIC_DEBUG	/* if we get here, we're going to use it so count it */	rule++;#endif	/* parse it */	if (parse(s, p, line + ws_offset, lineno) != 0)

⌨️ 快捷键说明

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