📄 mime_magic.c
字号:
static long from_oct(int digs, char *where){ register long value; while (isspace(*where)) { /* Skip spaces */ where++; if (--digs <= 0) return -1; /* All blank field */ } value = 0; while (digs > 0 && isodigit(*where)) { /* Scan til nonoctal */ value = (value << 3) | (*where++ - '0'); --digs; } if (digs > 0 && *where && !isspace(*where)) return -1; /* Ended on non-space/nul */ return value;}static int mget(union VALUETYPE *p, unsigned char *s, struct magic *m, int nbytes){ long offset = m->offset; if (offset + sizeof(union VALUETYPE) > nbytes) return 0; memcpy(p, s + offset, sizeof(union VALUETYPE)); if (!mconvert(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(p, m)) return 0; } return 1;}static int mcheck(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')) { php_error(E_WARNING, 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 */ php_error(E_WARNING, MODNAME ": invalid type %d in mcheck().", m->type); return 0; } v = signextend(m, v) & m->mask; switch (m->reln) { case 'x': matched = 1; break; case '!': matched = v != l; break; case '=': matched = v == l; break; case '>': if (m->flag & UNSIGNED) { matched = v > l; } else { matched = (long) v > (long) l; } break; case '<': if (m->flag & UNSIGNED) { matched = v < l; } else { matched = (long) v < (long) l; } break; case '&': matched = (v & l) == l; break; case '^': matched = (v & l) != l; break; default: /* bogosity, pretend it didn't match */ matched = 0; php_error(E_WARNING, MODNAME ": mcheck: can't happen: invalid relation %d.", m->reln); break; } return matched;}#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)/* * 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 int zmagic(unsigned char *buf, int nbytes){ if (buf[0] != 0x1f) return 0; switch(buf[1]) { case 0x9d: /* .Z "x-compress" */ break; /* not yet supportet */ case 0x8b: /* .gz "x-gzip" */#if 0 if ((newsize = magic_uncompress(i, &newbuf, nbytes)) > 0) { tryit(newbuf, newsize, 0); /* set encoding type in the request record */ /* TODO r->content_encoding = compr[i].encoding; */ }#endif break; /* not yet supported */ case 0x1e: /* simply packed ? */ break; /* not yet supported */ } return 0;}#endif static void mprint(union VALUETYPE *p, struct magic *m){ char *pp, *rt; unsigned long v; 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(m->desc, m->value.s); } else { (void) magic_rsl_printf(m->desc, p->s); } return; case DATE: case BEDATE: case LEDATE: /* XXX: not multithread safe */ pp = ctime((time_t *) & p->l); if ((rt = strchr(pp, '\n')) != NULL) *rt = '\0'; (void) magic_rsl_printf(m->desc, pp); return; default: php_error(E_WARNING, MODNAME ": invalid m->type (%d) in mprint().", m->type); return; } v = signextend(m, v) & m->mask; (void) magic_rsl_printf(m->desc, (unsigned long) v);}/* * Convert the byte order of the data we are looking at */static int mconvert(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: php_error(E_WARNING, MODNAME ": invalid type %d in mconvert().", m->type); return 0; }}/* 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_get(char **content_type, char **content_encoding){ 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; TSRMLS_FETCH(); req_dat = MIME_MAGIC_G(req_dat); /* check if we have a result */ if (!req_dat || !req_dat->head) { /* empty - no match, we defer to other Apache modules */ return MIME_MAGIC_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 (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 MIME_MAGIC_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 */ php_error(E_WARNING, MODNAME ": bad state %d (ws)", state); return MIME_MAGIC_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 */ php_error(E_WARNING, MODNAME ": bad state %d (ns)", state); return MIME_MAGIC_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 MIME_MAGIC_DECLINED; } /* save the info in the request record */ if (state == rsl_subtype || state == rsl_encoding || state == rsl_encoding) { char *tmp; tmp = rsl_strdup(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 */ /* TODO ap_content_type_tolower(tmp); */ *content_type = tmp; } if (state == rsl_encoding) { char *tmp; tmp = rsl_strdup(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 */ /* TODO ap_str_tolower(tmp); */ *content_encoding = tmp; } /* detect memory allocation errors */ if (!content_type || !(*content_type) || (state == rsl_encoding && !*content_encoding)) { return MIME_MAGIC_ERROR; } /* success! */ return MIME_MAGIC_OK;}/* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -