📄 mod_mime_magic.c
字号:
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 (apr_isdigit(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.filetype) { case APR_DIR: magic_rsl_puts(r, DIR_MAGIC_TYPE); return DONE; case APR_CHR: /* * (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; case APR_BLK: /* * (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 */ case APR_PIPE: /* * magic_rsl_puts(r,"fifo (named pipe)"); */ (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN); return DONE; case APR_LNK: /* We used stat(), the only possible reason for this is that the * symlink is broken. */ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, MODNAME ": broken symlink (%s)", fn); return HTTP_INTERNAL_SERVER_ERROR; case APR_SOCK: magic_rsl_puts(r, MIME_BINARY_UNKNOWN); return DONE; case APR_REG: break; default: ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, MODNAME ": invalid file type %d.", r->finfo.filetype); return HTTP_INTERNAL_SERVER_ERROR; } /* * regular file, check next possibility */ if (r->finfo.size == 0) { magic_rsl_puts(r, MIME_TEXT_UNKNOWN); return DONE; } return OK;}/* * softmagic - lookup one file in database (already read from /etc/magic by * apprentice.c). Passed the name and FILE * of one file to be typed. */ /* ARGSUSED1 *//* nbytes passed for regularity, maybe need later */static int softmagic(request_rec *r, unsigned char *buf, apr_size_t nbytes){ if (match(r, buf, nbytes)) return 1; return 0;}/* * Go through the whole list, stopping if you find a match. Process all the * continuations of that match before returning. * * We support multi-level continuations: * * At any time when processing a successful top-level match, there is a current * continuation level; it represents the level of the last successfully * matched continuation. * * Continuations above that level are skipped as, if we see one, it means that * the continuation that controls them - i.e, the lower-level continuation * preceding them - failed to match. * * Continuations below that level are processed as, if we see one, it means * we've finished processing or skipping higher-level continuations under the * control of a successful or unsuccessful lower-level continuation, and are * now seeing the next lower-level continuation and should process it. The * current continuation level reverts to the level of the one we're seeing. * * Continuations at the current level are processed as, if we see one, there's * no lower-level continuation that may have failed. * * If a continuation matches, we bump the current continuation level so that * higher-level continuations are processed. */static int match(request_rec *r, unsigned char *s, apr_size_t nbytes){#if MIME_MAGIC_DEBUG int rule_counter = 0;#endif int cont_level = 0; int need_separator = 0; union VALUETYPE p; magic_server_config_rec *conf = (magic_server_config_rec *) ap_get_module_config(r->server->module_config, &mime_magic_module); struct magic *m;#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, MODNAME ": match 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");#endif#if MIME_MAGIC_DEBUG 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_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, MODNAME ": match: POINTER CLOBBERED! " "m=\"%c%c%c%c\"", (((unsigned long) m) >> 24) & 255, (((unsigned long) m) >> 16) & 255, (((unsigned long) m) >> 8) & 255, ((unsigned long) m) & 255); break; } }#endif for (m = conf->magic; m; m = m->next) {#if MIME_MAGIC_DEBUG rule_counter++; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, MODNAME ": line=%d desc=%s", m->lineno, m->desc);#endif /* check if main entry matches */ if (!mget(r, &p, s, m, nbytes) || !mcheck(r, &p, m)) { struct magic *m_cont; /* * main entry didn't match, flush its continuations */ if (!m->next || (m->next->cont_level == 0)) { continue; } m_cont = m->next; while (m_cont && (m_cont->cont_level != 0)) {#if MIME_MAGIC_DEBUG rule_counter++; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, MODNAME ": line=%d mc=%x mc->next=%x cont=%d desc=%s", m_cont->lineno, m_cont, m_cont->next, m_cont->cont_level, m_cont->desc);#endif /* * this trick allows us to keep *m in sync when the continue * advances the pointer */ m = m_cont; m_cont = m_cont->next; } continue; } /* if we get here, the main entry rule was a match */ /* this will be the last run through the loop */#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, MODNAME ": rule matched, line=%d type=%d %s", m->lineno, m->type, (m->type == STRING) ? m->value.s : "");#endif /* print the match */ mprint(r, &p, m); /* * If we printed something, we'll need to print a blank before we * print something else. */ if (m->desc[0]) need_separator = 1; /* and any continuations that match */ cont_level++; /* * while (m && m->next && m->next->cont_level != 0 && ( m = m->next * )) */ m = m->next; while (m && (m->cont_level != 0)) {#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, MODNAME ": match line=%d cont=%d type=%d %s", m->lineno, m->cont_level, m->type, (m->type == STRING) ? m->value.s : "");#endif if (cont_level >= m->cont_level) { if (cont_level > m->cont_level) { /* * We're at the end of the level "cont_level" * continuations. */ cont_level = m->cont_level; } if (mget(r, &p, s, m, nbytes) && mcheck(r, &p, m)) { /* * This continuation matched. Print its message, with a * blank before it if the previous item printed and this * item isn't empty. */ /* space if previous printed */ if (need_separator && (m->nospflag == 0) && (m->desc[0] != '\0') ) { (void) magic_rsl_putchar(r, ' '); need_separator = 0; } mprint(r, &p, m); if (m->desc[0]) need_separator = 1; /* * If we see any continuations at a higher level, process * them. */ cont_level++; } } /* move to next continuation record */ m = m->next; }#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, MODNAME ": matched after %d rules", rule_counter);#endif return 1; /* all through */ }#if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, MODNAME ": failed after %d rules", rule_counter);#endif return 0; /* no match at all */}static void mprint(request_rec *r, union VALUETYPE *p, struct magic *m){ char *pp; unsigned long v; char time_str[APR_CTIME_LEN]; 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: v = p->l; break; case STRING: if (m->reln == '=') { (void) magic_rsl_printf(r, m->desc, m->value.s); } else { (void) magic_rsl_printf(r, m->desc, p->s); } return; case DATE: case BEDATE: case LEDATE: apr_ctime(time_str, apr_time_from_sec(*(time_t *)&p->l)); pp = time_str; (void) magic_rsl_printf(r, m->desc, pp); return; default: ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, MODNAME ": invalid m->type (%d) in mprint().", m->type); return; } v = signextend(r->server, m, v) & m->mask; (void) magic_rsl_printf(r, m->desc, (unsigned long) v);}/* * Convert the byte order of the data we are looking at */static int mconvert(request_rec *r, union VALUETYPE *p, struct magic *m){ char *rt; switch (m->type) { case BYTE: case SHORT: case LONG: case DATE: return 1; case STRING: /* Null terminate and eat the return */ p->s[sizeof(p->s) - 1] = '\0'; if ((rt = strchr(p->s, '\n')) != NULL) *rt = '\0'; return 1; case BESHORT: p->h = (short) ((p->hs[0] << 8) | (p->hs[1])); return 1; case BELONG: case BEDATE: p->l = (long) ((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3])); return 1; case LESHORT: p->h = (short) ((p->hs[1] << 8) | (p->hs[0])); return 1; case LELONG: case LEDATE: p->l = (long) ((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0])); return 1; default: ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, MODNAME ": invalid type %d in mconvert().", m->type); return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -