📄 mod_mime_magic.c
字号:
++errs; } (void) ap_pfclose(p, f);#if MIME_MAGIC_DEBUG ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 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_NOERRNO | APLOG_DEBUG, 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_NOERRNO | APLOG_DEBUG, s, MODNAME ": apprentice test"); for (m = conf->magic; m; m = m->next) { if (ap_isprint((((unsigned long) m) >> 24) & 255) && ap_isprint((((unsigned long) m) >> 16) & 255) && ap_isprint((((unsigned long) m) >> 8) & 255) && ap_isprint(((unsigned long) m) & 255)) { ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 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_NOERRNO | APLOG_ERR, 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, pool *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 *) ap_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_NOERRNO | APLOG_ERR, 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_NOERRNO | APLOG_ERR, serv, MODNAME ": indirect offset type %c invalid", *l); break; } l++; } s = l; if (*l == '+' || *l == '-') l++; if (ap_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_NOERRNO | APLOG_ERR, serv, MODNAME ": missing ')' in indirect offset"); } l = t; } while (ap_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_NOERRNO | APLOG_ERR, 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' && ap_isspace((unsigned char) 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_NOERRNO | APLOG_DEBUG, 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 (ap_isspace((unsigned char) c)) break; if (p >= pmax) { ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, serv, MODNAME ": string too long: %s", origs); break; } if (c == '\\') { switch (c = *s++) { case '\0': goto out; default: *p++ = (char) c; break; case 'n': *p++ = '\n'; break; case 'r': *p++ = '\r'; break; case 'b': *p++ = '\b'; break; case 't': *p++ = '\t'; break; case 'f': *p++ = '\f'; break; case 'v': *p++ = '\v'; break; /* \ and up to 3 octal digits */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': val = c - '0'; c = *s++; /* try for 2 */ if (c >= '0' && c <= '7') { val = (val << 3) | (c - '0'); c = *s++; /* try for 3 */ if (c >= '0' && c <= '7') val = (val << 3) | (c - '0'); else --s; } else --s; *p++ = (char) val; break; /* \x and up to 3 hex digits */ case 'x': val = 'x'; /* Default if no digits */ c = hextoint(*s++); /* Get next char */ if (c >= 0) { val = c; c = hextoint(*s++); if (c >= 0) { val = (val << 4) + c; c = hextoint(*s++); if (c >= 0) { val = (val << 4) + c; } else --s; } else --s; } else --s; *p++ = (char) val; break; } } else *p++ = (char) c; } out: *p = '\0'; *slen = p - origp; return s;}/* Single hex char to int; -1 if not a hex char. */static int hextoint(int c){ if (ap_isdigit((unsigned char) c)) return c - '0'; if ((c >= 'a') && (c <= 'f')) return c + 10 - 'a'; if ((c >= 'A') && (c <= 'F')) return c + 10 - 'A'; return -1;}/* * return DONE to indicate it's been handled * return OK to indicate it's a regular file still needing handling * other returns indicate a failure of some sort */static int fsmagic(request_rec *r, const char *fn){ switch (r->finfo.st_mode & S_IFMT) { case S_IFDIR: magic_rsl_puts(r, DIR_MAGIC_TYPE); return DONE; case S_IFCHR: /* * (void) magic_rsl_printf(r,"character special (%d/%d)", * major(sb->st_rdev), minor(sb->st_rdev)); */ (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN); return DONE;#ifdef S_IFBLK case S_IFBLK: /* * (void) magic_rsl_printf(r,"block special (%d/%d)", * major(sb->st_rdev), minor(sb->st_rdev)); */ (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN); return DONE; /* TODO add code to handle V7 MUX and Blit MUX files */#endif#ifdef S_IFIFO case S_IFIFO: /* * magic_rsl_puts(r,"fifo (named pipe)"); */ (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN); return DONE;#endif#ifdef S_IFLNK case S_IFLNK: /* We used stat(), the only possible reason for this is that the * symlink is broken. */ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -