sar_bool sar_checkNodeContainChar_c(sarNode_p checkNode, char checkChar, sar_nodeClass nodeClass) { if (nodeClass == SAR_CHAR) { if (checkNode->pathChar == checkChar) { return SAR_TRUE; } } else if (nodeClass == SAR_DIGIT) { if (isDIGIT(checkChar)) { return SAR_TRUE; } } else if (nodeClass == SAR_ALPHA_NUM) { if (isALNUM(checkChar)) { return SAR_TRUE; } } else if (nodeClass == SAR_ALPHA) { if (isALPHA(checkChar)) { return SAR_TRUE; } } else if (nodeClass == SAR_SPACE) { if (isSPACE(checkChar)) { return SAR_TRUE; } } else if (nodeClass == SAR_DOT) { return SAR_TRUE; } return SAR_FALSE; }
/* maps to mod_mime_magic::apprentice */ static int fmm_parse_magic_file(PerlFMM *state, char *file) { int ws_offset; int lineno; int errs; /* char line[BUFSIZ + 1];*/ PerlIO *fhandle; SV *err; SV *sv = sv_2mortal(newSV(BUFSIZ)); SV *PL_rs_orig = newSVsv(PL_rs); char *line; fhandle = PerlIO_open(file, "r"); if (! fhandle) { err = newSVpvf( "Failed to open %s: %s", file, strerror(errno)); FMM_SET_ERROR(state, err); PerlIO_close(fhandle); return -1; } /* * Parse it line by line * $/ (slurp mode) is needed here */ PL_rs = sv_2mortal(newSVpvn("\n", 1)); for(lineno = 1; sv_gets(sv, fhandle, 0) != NULL; lineno++) { line = SvPV_nolen(sv); /* delete newline */ if (line[0]) { line[strlen(line) - 1] = '\0'; } /* skip leading whitespace */ ws_offset = 0; while (line[ws_offset] && isSPACE(line[ws_offset])) { ws_offset++; } /* skip blank lines */ if (line[ws_offset] == 0) { continue; } if (line[ws_offset] == '#') { continue; } if (fmm_parse_magic_line(state, line, lineno) != 0) { ++errs; } } PerlIO_close(fhandle); PL_rs = PL_rs_orig; return 1; }
/* * Quick and dirty octal conversion. * * Result is -1 if the field is invalid (all blank, or nonoctal). */ 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; }
NETDB_DEFINE_CONTEXT NETINET_DEFINE_CONTEXT #endif #ifdef I_SYSUIO # include <sys/uio.h> #endif #ifndef AF_NBS # undef PF_NBS #endif #ifndef AF_X25 # undef PF_X25 #endif #ifndef INADDR_NONE # define INADDR_NONE 0xffffffff #endif /* INADDR_NONE */ #ifndef INADDR_BROADCAST # define INADDR_BROADCAST 0xffffffff #endif /* INADDR_BROADCAST */ #ifndef INADDR_LOOPBACK # define INADDR_LOOPBACK 0x7F000001 #endif /* INADDR_LOOPBACK */ #ifndef HAS_INET_ATON /* * Check whether "cp" is a valid ascii representation * of an Internet address and convert to a binary address. * Returns 1 if the address is valid, 0 if not. * This replaces inet_addr, the return value from which * cannot distinguish between failure and a local broadcast address. */ static int my_inet_aton(register const char *cp, struct in_addr *addr) { dTHX; register U32 val; register int base; register char c; int nparts; const char *s; unsigned int parts[4]; register unsigned int *pp = parts; if (!cp || !*cp) return 0; for (;;) { /* * Collect number up to ``.''. * Values are specified as for C: * 0x=hex, 0=octal, other=decimal. */ val = 0; base = 10; if (*cp == '0') { if (*++cp == 'x' || *cp == 'X') base = 16, cp++; else base = 8; } while ((c = *cp) != '\0') { if (isDIGIT(c)) { val = (val * base) + (c - '0'); cp++; continue; } if (base == 16 && (s=strchr(PL_hexdigit,c))) { val = (val << 4) + ((s - PL_hexdigit) & 15); cp++; continue; } break; } if (*cp == '.') { /* * Internet format: * a.b.c.d * a.b.c (with c treated as 16-bits) * a.b (with b treated as 24 bits) */ if (pp >= parts + 3 || val > 0xff) return 0; *pp++ = val, cp++; } else break; } /* * Check for trailing characters. */ if (*cp && !isSPACE(*cp)) return 0; /* * Concoct the address according to * the number of parts specified. */ nparts = pp - parts + 1; /* force to an int for switch() */ switch (nparts) { case 1: /* a -- 32 bits */ break; case 2: /* a.b -- 8.24 bits */ if (val > 0xffffff) return 0; val |= parts[0] << 24; break; case 3: /* a.b.c -- 8.8.16 bits */ if (val > 0xffff) return 0; val |= (parts[0] << 24) | (parts[1] << 16); break; case 4: /* a.b.c.d -- 8.8.8.8 bits */ if (val > 0xff) return 0; val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); break; } addr->s_addr = htonl(val); return 1; }
STATIC char * S_skipspace(pTHX_ register char *s, int incline) { if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) { while (s < PL_bufend && SPACE_OR_TAB(*s)) s++; return s; } for (;;) { STRLEN prevlen; SSize_t oldprevlen, oldoldprevlen; SSize_t oldloplen = 0, oldunilen = 0; while (s < PL_bufend && isSPACE(*s)) { if (*s++ == '\n' && ((incline == 2) || (PL_in_eval && !PL_rsfp && !incline))) incline(s); } /* comment */ if (s < PL_bufend && *s == '#') { while (s < PL_bufend && *s != '\n') s++; if (s < PL_bufend) { s++; if (PL_in_eval && !PL_rsfp && !incline) { incline(s); continue; } } } /* also skip leading whitespace on the beginning of a line before deciding * whether or not to recharge the linestr. --rafl */ while (s < PL_bufend && isSPACE(*s)) { if (*s++ == '\n' && PL_in_eval && !PL_rsfp && !incline) incline(s); } /* only continue to recharge the buffer if we're at the end * of the buffer, we're not reading from a source filter, and * we're in normal lexing mode */ if (s < PL_bufend || !PL_rsfp || PL_lex_inwhat || PL_lex_state == LEX_FORMLINE) return s; /* try to recharge the buffer */ if ((s = filter_gets(PL_linestr, PL_rsfp, (prevlen = SvCUR(PL_linestr)))) == Nullch) { /* end of file. Add on the -p or -n magic */ if (PL_minus_p) { sv_setpv(PL_linestr, ";}continue{print or die qq(-p destination: $!\\n);}"); PL_minus_n = PL_minus_p = 0; } else if (PL_minus_n) { sv_setpvn(PL_linestr, ";}", 2); PL_minus_n = 0; } else sv_setpvn(PL_linestr,";", 1); /* reset variables for next time we lex */ PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = s = PL_linestart = SvPVX(PL_linestr); PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr); PL_last_lop = PL_last_uni = Nullch; /* In perl versions previous to p4-rawid: //depot/perl@32954 -P * preprocessors were supported here. We don't support -P at all, even * on perls that support it, and use the following chunk from blead * perl. (rafl) */ /* Close the filehandle. Could be from * STDIN, or a regular file. If we were reading code from * STDIN (because the commandline held no -e or filename) * then we don't close it, we reset it so the code can * read from STDIN too. */ if ((PerlIO*)PL_rsfp == PerlIO_stdin()) PerlIO_clearerr(PL_rsfp); else (void)PerlIO_close(PL_rsfp); PL_rsfp = Nullfp; return s; } /* not at end of file, so we only read another line */ /* make corresponding updates to old pointers, for yyerror() */ oldprevlen = PL_oldbufptr - PL_bufend; oldoldprevlen = PL_oldoldbufptr - PL_bufend; if (PL_last_uni) oldunilen = PL_last_uni - PL_bufend; if (PL_last_lop) oldloplen = PL_last_lop - PL_bufend; PL_linestart = PL_bufptr = s + prevlen; PL_bufend = s + SvCUR(PL_linestr); s = PL_bufptr; PL_oldbufptr = s + oldprevlen; PL_oldoldbufptr = s + oldoldprevlen; if (PL_last_uni) PL_last_uni = s + oldunilen; if (PL_last_lop) PL_last_lop = s + oldloplen; if (!incline) incline(s); /* debugger active and we're not compiling the debugger code, * so store the line into the debugger's array of lines */ if (PERLDB_LINE && PL_curstash != PL_debstash) { AV *fileav = CopFILEAV(PL_curcop); if (fileav) { SV * const sv = NEWSV(85,0); sv_upgrade(sv, SVt_PVMG); sv_setpvn(sv,PL_bufptr,PL_bufend-PL_bufptr); (void)SvIOK_on(sv); SvIV_set(sv, 0); av_store(fileav,(I32)CopLINE(PL_curcop),sv); } } } }
sar_bool sar_lookPathPos_c(sarNode_p currNode, const char * checkStr, long startPos, long currPos, long len, sar_bool negative) { sar_bool matched = SAR_FALSE; int callPos = 0; while(currNode->callFunc[callPos] != (SV*)NULL) { matched = SAR_TRUE; sar_runCallFunc_c(currNode->callFunc[callPos], startPos, currPos); ++callPos; } if (currPos >= len) { return matched; } char checkChar = checkStr[currPos]; sarNode_p plusNode = currNode->plusNode; if (plusNode != (sarNode_p)NULL) { if (negative) { int pathCharNum = 0; for (pathCharNum=0; pathCharNum < plusNode->charNumber; ++pathCharNum) { if (checkChar != plusNode->sarPathChars[pathCharNum]) { sarNode_p nextPlusNode = plusNode->sarNodes[pathCharNum]; sar_bool plusNodesMatched = sar_matchPlusNode_c(nextPlusNode, checkStr, startPos, currPos, len, SAR_CHAR, negative); matched = matched || plusNodesMatched; } } if (plusNode->digitNode != (sarNode_p)NULL) { if (! isDIGIT(checkChar)) { sarNode_p nextPlusNode = plusNode->digitNode; sar_bool plusNodesMatched = sar_matchPlusNode_c(nextPlusNode, checkStr, startPos, currPos, len, SAR_DIGIT, negative); matched = matched || plusNodesMatched; } } } else { int existListPlusNodePos = sar_searchChar_c(plusNode->sarPathChars, plusNode->charNumber, checkChar); if (existListPlusNodePos >= 0) { sarNode_p nextPlusNode = plusNode->sarNodes[existListPlusNodePos]; sar_bool plusNodesMatched = sar_matchPlusNode_c(nextPlusNode, checkStr, startPos, currPos, len, SAR_CHAR, negative); matched = matched || plusNodesMatched; } if (plusNode->dotNode != (sarNode_p)NULL) { sarNode_p nextPlusNode = plusNode->dotNode; sar_bool plusNodesMatched = sar_matchPlusNode_c(nextPlusNode, checkStr, startPos, currPos, len, SAR_DOT, negative); matched = matched || plusNodesMatched; } if (plusNode->digitNode != (sarNode_p)NULL) { if (isDIGIT(checkChar)) { sarNode_p nextPlusNode = plusNode->digitNode; sar_bool plusNodesMatched = sar_matchPlusNode_c(nextPlusNode, checkStr, startPos, currPos, len, SAR_DIGIT, negative); matched = matched || plusNodesMatched; } } if (plusNode->alphaNumNode != (sarNode_p)NULL) { if (isALNUM(checkChar)) { sarNode_p nextPlusNode = plusNode->alphaNumNode; sar_bool plusNodesMatched = sar_matchPlusNode_c(nextPlusNode, checkStr, startPos, currPos, len, SAR_ALPHA_NUM, negative); matched = matched || plusNodesMatched; } } if (plusNode->alphaNode != (sarNode_p)NULL) { if (isALPHA(checkChar)) { sarNode_p nextPlusNode = plusNode->alphaNode; sar_bool plusNodesMatched = sar_matchPlusNode_c(nextPlusNode, checkStr, startPos, currPos, len, SAR_ALPHA, negative); matched = matched || plusNodesMatched; } } if (plusNode->spaceNode != (sarNode_p)NULL) { if (isSPACE(checkChar)) { sarNode_p nextPlusNode = plusNode->spaceNode; sar_bool plusNodesMatched = sar_matchPlusNode_c(nextPlusNode, checkStr, startPos, currPos, len, SAR_SPACE, negative); matched = matched || plusNodesMatched; } } } } if (negative) { int pathCharNum = 0; for (pathCharNum=0; pathCharNum < currNode->charNumber; ++pathCharNum) { if (checkChar != currNode->sarPathChars[pathCharNum]) { sar_bool nodesMatched = sar_lookPathPos_c(currNode->sarNodes[pathCharNum], checkStr, startPos, currPos + 1, len, SAR_FALSE); matched = matched || nodesMatched; } } if (currNode->spaceNode != (sarNode_p)NULL) { if (! isSPACE(checkChar)) { sar_bool nodesMatched = sar_lookPathPos_c(currNode->spaceNode, checkStr, startPos, currPos + 1, len, SAR_FALSE); matched = matched || nodesMatched; } } if (currNode->digitNode != (sarNode_p)NULL) { if (! isDIGIT(checkChar)) { sar_bool nodesMatched = sar_lookPathPos_c(currNode->digitNode, checkStr, startPos, currPos + 1, len, SAR_FALSE); matched = matched || nodesMatched; } } if (currNode->alphaNumNode != (sarNode_p)NULL) { if (! isALNUM(checkChar)) { sar_bool nodesMatched = sar_lookPathPos_c(currNode->alphaNumNode, checkStr, startPos, currPos + 1, len, SAR_FALSE); matched = matched || nodesMatched; } } if (currNode->alphaNode != (sarNode_p)NULL) { if (! isALPHA(checkChar)) { sar_bool nodesMatched = sar_lookPathPos_c(currNode->alphaNode, checkStr, startPos, currPos + 1, len, SAR_FALSE); matched = matched || nodesMatched; } } } else { int existListNodePos = sar_searchChar_c(currNode->sarPathChars, currNode->charNumber, checkChar); if (existListNodePos >= 0) { sar_bool nodesMatched = sar_lookPathPos_c(currNode->sarNodes[existListNodePos], checkStr, startPos, currPos + 1, len, SAR_FALSE); matched = matched || nodesMatched; } if (currNode->negativeNode != (sarNode_p)NULL) { sar_bool nodesMatched = sar_lookPathPos_c(currNode->negativeNode, checkStr, startPos, currPos, len, SAR_TRUE); matched = matched || nodesMatched; } if (currNode->dotNode != (sarNode_p)NULL) { sar_bool nodesMatched = sar_lookPathPos_c(currNode->dotNode, checkStr, startPos, currPos + 1, len, SAR_FALSE); matched = matched || nodesMatched; } if (currNode->spaceNode != (sarNode_p)NULL) { if (isSPACE(checkChar)) { sar_bool nodesMatched = sar_lookPathPos_c(currNode->spaceNode, checkStr, startPos, currPos + 1, len, SAR_FALSE); matched = matched || nodesMatched; } } if (currNode->digitNode != (sarNode_p)NULL) { if (isDIGIT(checkChar)) { sar_bool nodesMatched = sar_lookPathPos_c(currNode->digitNode, checkStr, startPos, currPos + 1, len, SAR_FALSE); matched = matched || nodesMatched; } } if (currNode->alphaNumNode != (sarNode_p)NULL) { if (isALNUM(checkChar)) { sar_bool nodesMatched = sar_lookPathPos_c(currNode->alphaNumNode, checkStr, startPos, currPos + 1, len, SAR_FALSE); matched = matched || nodesMatched; } } if (currNode->alphaNode != (sarNode_p)NULL) { if (isALPHA(checkChar)) { sar_bool nodesMatched = sar_lookPathPos_c(currNode->alphaNode, checkStr, startPos, currPos + 1, len, SAR_FALSE); matched = matched || nodesMatched; } } } return matched; }
/* maps to mod_mime_magic::parse */ static int fmm_parse_magic_line(PerlFMM *state, char *l, int lineno) { char *t; char *s; fmmagic *m; SV *err; Newz(1234, m, 1, fmmagic); m->next = NULL; m->flag = 0; m->cont_level = 0; m->lineno = lineno; if (! state->magic || !state->last) { state->magic = state->last = m; } else { state->last->next = m; state->last = m; } 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) { err = newSVpvf("Invalid offset in mime magic file, line %d: %s", lineno, l); goto error; } 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: err = newSVpvf( "Invalid indirect offset type in mime magic file, line %d: %c", lineno, *l); goto error; } l++; } s = l; if (*l == '+' || *l == '-') { l++; } if (isdigit((unsigned char) *l)) { m->in.offset = strtol(l, &t, 0); if (*s == '-') { m->in.offset = -(m->in.offset); } } else { t = l; } if (*t++ != ')') { err = newSVpvf( "Missing ')' in indirect offset in mime magic file, line %d", lineno); goto error; } l = t; } while (isdigit((unsigned char) *l)) { ++l; } EATAB(l); #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 { err = newSVpvf("Invalid type in mime magic file, line %d: %s", lineno, l); goto error; } /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */ if (*l == '&') { ++l; m->mask = fmm_signextend(state, m, strtol(l, &l, 0)); } else { m->mask = ~0L; } EATAB(l); 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' && isSPACE(l[1])) { m->reln = *l; ++l; goto GetDesc; /* Bill The Cat */ } m->reln = '='; break; } EATAB(l); if (fmm_getvalue(state, m, &l)) return -1; /* * now get last part - the description */ GetDesc: EATAB(l); 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'; return 0; error: FMM_SET_ERROR(state, err); croak(SvPV_nolen(err)); }
/* * 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 * fmm_getstr(PerlFMM *state, 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; SV *err; while ((c = *s++) != '\0') { if (isSPACE(c)) break; if (p >= pmax) { err = newSVpvf( "fmm_getstr: string too long: %s", origs); FMM_SET_ERROR(state, err); 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 = fmm_hextoint(*s++); /* Get next char */ if (c >= 0) { val = c; c = fmm_hextoint(*s++); if (c >= 0) { val = (val << 4) + c; c = fmm_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; }
static int fmm_ascmagic(unsigned char *buf, size_t nbytes, char **mime_type) { 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; unsigned char *tp; /* 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 == '.') { tp = buf + 1; while (isSPACE(*tp)) ++tp; /* skip leading whitespace */ if ((isALNUM(*tp) || *tp == '\\') && (isALNUM(*(tp + 1)) || *tp == '"')) { strcpy(*mime_type, "application/x-troff"); return 0; } } if ((*buf == 'c' || *buf == 'C') && isSPACE(*(buf + 1))) { /* Fortran */ strcpy(*mime_type, "text/plain"); return 0; } /* 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 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 = strtok_r((char *) s, " \t\n\r\f", &strtok_state)) != NULL) { s = NULL; /* make strtok() keep on tokin' */ for (p = names; p < names + NNAMES; p++) { if (strEQ(p->name, token)) { strcpy(*mime_type, types[p->type]); if (has_escapes) strcat(*mime_type, " (with escape sequences)"); return 0; } } } int is_tarball = is_tar(buf, nbytes); if ( is_tarball == 1 || is_tarball == 2 ) { /* 1: V7 tar archive */ /* 2: POSIX tar archive */ strcpy(*mime_type, "application/x-tar"); return 0; } /* all else fails, but it is ascii... */ strcpy(*mime_type, "text/plain"); return 0; }