📄 mod_mime_magic.c
字号:
}}static int mget(request_rec *r, union VALUETYPE *p, unsigned char *s, struct magic *m, apr_size_t nbytes){ long offset = m->offset; if (offset + sizeof(union VALUETYPE) > nbytes) return 0; memcpy(p, s + offset, sizeof(union VALUETYPE)); if (!mconvert(r, p, m)) return 0; if (m->flag & INDIR) { switch (m->in.type) { case BYTE: offset = p->b + m->in.offset; break; case SHORT: offset = p->h + m->in.offset; break; case LONG: offset = p->l + m->in.offset; break; } if (offset + sizeof(union VALUETYPE) > nbytes) return 0; memcpy(p, s + offset, sizeof(union VALUETYPE)); if (!mconvert(r, p, m)) return 0; } return 1;}static int mcheck(request_rec *r, union VALUETYPE *p, struct magic *m){ register unsigned long l = m->value.l; register unsigned long v; int matched; if ((m->value.s[0] == 'x') && (m->value.s[1] == '\0')) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, MODNAME ": BOINK"); return 1; } switch (m->type) { case BYTE: v = p->b; break; case SHORT: case BESHORT: case LESHORT: v = p->h; break; case LONG: case BELONG: case LELONG: case DATE: case BEDATE: case LEDATE: v = p->l; break; case STRING: l = 0; /* * What we want here is: v = strncmp(m->value.s, p->s, m->vallen); * but ignoring any nulls. bcmp doesn't give -/+/0 and isn't * universally available anyway. */ v = 0; { register unsigned char *a = (unsigned char *) m->value.s; register unsigned char *b = (unsigned char *) p->s; register int len = m->vallen; while (--len >= 0) if ((v = *b++ - *a++) != 0) break; } break; default: /* bogosity, pretend that it just wasn't a match */ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, MODNAME ": invalid type %d in mcheck().", m->type); return 0; } v = signextend(r->server, m, v) & m->mask; switch (m->reln) { case 'x':#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%lu == *any* = 1", v);#endif matched = 1; break; case '!': matched = v != l;#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%lu != %lu = %d", v, l, matched);#endif break; case '=': matched = v == l;#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%lu == %lu = %d", v, l, matched);#endif break; case '>': if (m->flag & UNSIGNED) { matched = v > l;#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%lu > %lu = %d", v, l, matched);#endif } else { matched = (long) v > (long) l;#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%ld > %ld = %d", v, l, matched);#endif } break; case '<': if (m->flag & UNSIGNED) { matched = v < l;#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%lu < %lu = %d", v, l, matched);#endif } else { matched = (long) v < (long) l;#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%ld < %ld = %d", v, l, matched);#endif } break; case '&': matched = (v & l) == l;#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "((%lx & %lx) == %lx) = %d", v, l, l, matched);#endif break; case '^': matched = (v & l) != l;#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "((%lx & %lx) != %lx) = %d", v, l, l, matched);#endif break; default: /* bogosity, pretend it didn't match */ matched = 0; ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, MODNAME ": mcheck: can't happen: invalid relation %d.", m->reln); break; } return matched;}/* an optimization over plain strcmp() */#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)static int ascmagic(request_rec *r, unsigned char *buf, apr_size_t nbytes){ int has_escapes = 0; unsigned char *s; char nbuf[HOWMANY + 1]; /* one extra for terminating '\0' */ char *token; register struct names *p; int small_nbytes; char *strtok_state; /* 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 from uncompress of %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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -