#include #include #include #include "httpd.h" #include "httpsrv.h" typedef struct Suffix Suffix; struct Suffix { Suffix *next; char *suffix; char *generic; char *specific; char *encoding; }; Suffix *suffixes = nil; static Suffix* parsesuffix(char*, Suffix*); static char* skipwhite(char*); static HContents suffixclass(char*); static char* towhite(char*); int updateQid(int fd, Qid *q) { Dir *dir; Qid dq; dir = dirfstat(fd); if(dir == nil) sysfatal("can't dirfstat"); dq = dir->qid; free(dir); if(q->path == dq.path && q->vers == dq.vers && q->type == dq.type) return 0; *q = dq; return 1; } void contentinit(void) { static Biobuf *b = nil; static Qid qid; char *file, *s; Suffix *this; file = "/sys/lib/mimetype"; if(b == nil){ /* first time */ b = Bopen(file, OREAD); if(b == nil) sysfatal("can't read from %s", file); } if(updateQid(Bfildes(b), &qid) == 0) return; Bseek(b, 0, 0); while(suffixes!=nil){ this = suffixes; suffixes = suffixes->next; free(this->suffix); free(this->generic); free(this->specific); free(this->encoding); free(this); } while((s = Brdline(b, '\n')) != nil){ s[Blinelen(b) - 1] = 0; suffixes = parsesuffix(s, suffixes); } } static Suffix* parsesuffix(char *line, Suffix *suffix) { Suffix *s; char *p, *fields[5]; int i, nf; p = strchr(line, '#'); if(p != nil) *p = '\0'; nf = tokenize(line, fields, 5); for(i = 0; i < 4; i++) if(i >= nf || fields[i][0] == '-') fields[i] = nil; if(fields[2] == nil) fields[1] = nil; if(fields[1] == nil && fields[3] == nil) return suffix; if(fields[0] == nil) return suffix; s = ezalloc(sizeof *s); s->next = suffix; s->suffix = estrdup(fields[0]); if(fields[1] != nil){ s->generic = estrdup(fields[1]); s->specific = estrdup(fields[2]); } if(fields[3] != nil) s->encoding = estrdup(fields[3]); return s; } /* * classify by file name extensions */ HContents uriclass(HConnect *hc, char *name) { HContents conts; Suffix *s; HContent *type, *enc; char *buf, *p; type = nil; enc = nil; if((p = strrchr(name, '/')) != nil) name = p + 1; buf = hstrdup(hc, name); while((p = strrchr(buf, '.')) != nil){ for(s = suffixes; s; s = s->next){ if(strcmp(p, s->suffix) == 0){ if(s->generic != nil && type == nil) type = hmkcontent(hc, s->generic, s->specific, nil); if(s->encoding != nil && enc == nil) enc = hmkcontent(hc, s->encoding, nil, nil); } } *p = 0; } conts.type = type; conts.encoding = enc; return conts; } /* * classify by initial contents of file */ HContents dataclass(HConnect *hc, char *buf, int n) { HContents conts; Rune r; int c, m; for(; n > 0; n -= m){ c = *buf; if(c < Runeself){ if(c < 32 && c != '\n' && c != '\r' && c != '\t' && c != '\v'){ conts.type = nil; conts.encoding = nil; return conts; } m = 1; }else{ m = chartorune(&r, buf); if(r == Runeerror){ conts.type = nil; conts.encoding = nil; return conts; } } buf += m; } conts.type = hmkcontent(hc, "text", "plain", nil); conts.encoding = nil; return conts; }