📄 mod_mime_magic.c
字号:
/* * try tests in /etc/magic (or surrogate magic file) */ if (softmagic(r, buf, nb) == 1) return OK; /* * try known keywords, check for ascii-ness too. */ if (ascmagic(r, buf, nb) == 1) return OK; /* * abandon hope, all ye who remain here */ return DECLINED;}#define EATAB {while (apr_isspace(*l)) ++l;}/* * apprentice - load configuration from the magic file r * API request record */static int apprentice(server_rec *s, apr_pool_t *p){ apr_file_t *f = NULL; apr_status_t result; char line[BUFSIZ + 1]; int errs = 0; int lineno;#if MIME_MAGIC_DEBUG int rule = 0; struct magic *m, *prevm;#endif magic_server_config_rec *conf = (magic_server_config_rec *) ap_get_module_config(s->module_config, &mime_magic_module); const char *fname = ap_server_root_relative(p, conf->magicfile); if (!fname) { ap_log_error(APLOG_MARK, APLOG_ERR, APR_EBADPATH, s, MODNAME ": Invalid magic file path %s", conf->magicfile); return -1; } if ((result = apr_file_open(&f, fname, APR_READ | APR_BUFFERED, APR_OS_DEFAULT, p)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, result, 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; apr_file_gets(line, BUFSIZ, f) == APR_SUCCESS; lineno++) { int ws_offset; char *last = line + strlen(line) - 1; /* guaranteed that len >= 1 since an * "empty" line contains a '\n' */ /* delete newline and any other trailing whitespace */ while (last >= line && apr_isspace(*last)) { *last = '\0'; --last; } /* skip leading whitespace */ ws_offset = 0; while (line[ws_offset] && apr_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) ++errs; } (void) apr_file_close(f);#if MIME_MAGIC_DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, MODNAME ": apprentice conf=%x file=%s m=%s m->next=%s last=%s", conf, conf->magicfile ? conf->magicfile : "NULL", conf->magic ? "set" : "NULL", (conf->magic && conf->magic->next) ? "set" : "NULL", conf->last ? "set" : "NULL"); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, MODNAME ": apprentice read %d lines, %d rules, %d errors", lineno, rule, errs);#endif#if MIME_MAGIC_DEBUG prevm = 0; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, MODNAME ": apprentice 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 ": apprentice: 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 (errs ? -1 : 0);}/* * extend the sign bit if the comparison is to be signed */static unsigned long signextend(server_rec *s, struct magic *m, unsigned long v){ if (!(m->flag & UNSIGNED)) switch (m->type) { /* * Do not remove the casts below. They are vital. When later * compared with the data, the sign extension must have happened. */ case BYTE: v = (char) v; break; case SHORT: case BESHORT: case LESHORT: v = (short) v; break; case DATE: case BEDATE: case LEDATE: case LONG: case BELONG: case LELONG: v = (long) v; break; case STRING: break; default: ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, MODNAME ": can't happen: m->type=%d", m->type); return -1; } return v;}/* * parse one line from magic file, put into magic[index++] if valid */static int parse(server_rec *serv, apr_pool_t *p, char *l, int lineno){ struct magic *m; char *t, *s; magic_server_config_rec *conf = (magic_server_config_rec *) ap_get_module_config(serv->module_config, &mime_magic_module); /* allocate magic structure entry */ m = (struct magic *) apr_pcalloc(p, sizeof(struct magic)); /* append to linked list */ m->next = NULL; if (!conf->magic || !conf->last) { conf->magic = conf->last = m; } else { conf->last->next = m; conf->last = m; } /* set values in magic structure */ m->flag = 0; m->cont_level = 0; m->lineno = lineno; while (*l == '>') { ++l; /* step over */ m->cont_level++; } if (m->cont_level != 0 && *l == '(') { ++l; /* step over */ m->flag |= INDIR; } /* get offset, then skip over it */ m->offset = (int) strtol(l, &t, 0); if (l == t) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, serv, MODNAME ": offset %s invalid", l); } l = t; if (m->flag & INDIR) { m->in.type = LONG; m->in.offset = 0; /* * read [.lbs][+-]nnnnn) */ if (*l == '.') { switch (*++l) { case 'l': m->in.type = LONG; break; case 's': m->in.type = SHORT; break; case 'b': m->in.type = BYTE; break; default: ap_log_error(APLOG_MARK, APLOG_ERR, 0, serv, MODNAME ": indirect offset type %c invalid", *l); break; } l++; } s = l; if (*l == '+' || *l == '-') l++; if (apr_isdigit((unsigned char) *l)) { m->in.offset = strtol(l, &t, 0); if (*s == '-') m->in.offset = -m->in.offset; } else t = l; if (*t++ != ')') { ap_log_error(APLOG_MARK, APLOG_ERR, 0, serv, MODNAME ": missing ')' in indirect offset"); } l = t; } while (apr_isdigit((unsigned char) *l)) ++l; EATAB;#define NBYTE 4#define NSHORT 5#define NLONG 4#define NSTRING 6#define NDATE 4#define NBESHORT 7#define NBELONG 6#define NBEDATE 6#define NLESHORT 7#define NLELONG 6#define NLEDATE 6 if (*l == 'u') { ++l; m->flag |= UNSIGNED; } /* get type, skip it */ if (strncmp(l, "byte", NBYTE) == 0) { m->type = BYTE; l += NBYTE; } else if (strncmp(l, "short", NSHORT) == 0) { m->type = SHORT; l += NSHORT; } else if (strncmp(l, "long", NLONG) == 0) { m->type = LONG; l += NLONG; } else if (strncmp(l, "string", NSTRING) == 0) { m->type = STRING; l += NSTRING; } else if (strncmp(l, "date", NDATE) == 0) { m->type = DATE; l += NDATE; } else if (strncmp(l, "beshort", NBESHORT) == 0) { m->type = BESHORT; l += NBESHORT; } else if (strncmp(l, "belong", NBELONG) == 0) { m->type = BELONG; l += NBELONG; } else if (strncmp(l, "bedate", NBEDATE) == 0) { m->type = BEDATE; l += NBEDATE; } else if (strncmp(l, "leshort", NLESHORT) == 0) { m->type = LESHORT; l += NLESHORT; } else if (strncmp(l, "lelong", NLELONG) == 0) { m->type = LELONG; l += NLELONG; } else if (strncmp(l, "ledate", NLEDATE) == 0) { m->type = LEDATE; l += NLEDATE; } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, serv, MODNAME ": type %s invalid", l); return -1; } /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */ if (*l == '&') { ++l; m->mask = signextend(serv, m, strtol(l, &l, 0)); } else m->mask = ~0L; EATAB; switch (*l) { case '>': case '<': /* Old-style anding: "0 byte &0x80 dynamically linked" */ case '&': case '^': case '=': m->reln = *l; ++l; break; case '!': if (m->type != STRING) { m->reln = *l; ++l; break; } /* FALL THROUGH */ default: if (*l == 'x' && apr_isspace(l[1])) { m->reln = *l; ++l; goto GetDesc; /* Bill The Cat */ } m->reln = '='; break; } EATAB; if (getvalue(serv, m, &l)) return -1; /* * now get last part - the description */ GetDesc: EATAB; if (l[0] == '\b') { ++l; m->nospflag = 1; } else if ((l[0] == '\\') && (l[1] == 'b')) { ++l; ++l; m->nospflag = 1; } else m->nospflag = 0; strncpy(m->desc, l, sizeof(m->desc) - 1); m->desc[sizeof(m->desc) - 1] = '\0';#if MIME_MAGIC_DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, serv, MODNAME ": parse line=%d m=%x next=%x cont=%d desc=%s", lineno, m, m->next, m->cont_level, m->desc);#endif /* MIME_MAGIC_DEBUG */ return 0;}/* * Read a numeric value from a pointer, into the value union of a magic * pointer, according to the magic type. Update the string pointer to point * just after the number read. Return 0 for success, non-zero for failure. */static int getvalue(server_rec *s, struct magic *m, char **p){ int slen; if (m->type == STRING) { *p = getstr(s, *p, m->value.s, sizeof(m->value.s), &slen); m->vallen = slen; } else if (m->reln != 'x') m->value.l = signextend(s, m, strtol(*p, p, 0)); return 0;}/* * Convert a string containing C character escapes. Stop at an unescaped * space or tab. Copy the converted version to "p", returning its length in * *slen. Return updated scan pointer as function result. */static char *getstr(server_rec *serv, register char *s, register char *p, int plen, int *slen){ char *origs = s, *origp = p; char *pmax = p + plen - 1; register int c; register int val; while ((c = *s++) != '\0') { if (apr_isspace(c)) break; if (p >= pmax) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, serv, MODNAME ": string too long: %s", origs); break; } if (c == '\\') { switch (c = *s++) { case '\0': goto out; default: *p++ = (char) c; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -