📄 vf.c
字号:
if(np && np->boundary){ cp = Brdline(&in, '\n'); Bwrite(&out, cp, Blinelen(&in)); }fprint(2, "a %p\n", np); return np;}static intisattribute(char **pp, char *attr){ char *p; int n; n = strlen(attr); p = *pp; if(cistrncmp(p, attr, n) != 0) return 0; p += n; while(*p == ' ') p++; if(*p++ != '=') return 0; while(*p == ' ') p++; *pp = p; return 1;}/* * parse content type header */static voidctype(Part *p, Hdef *h, char *cp){ String *s; cp += h->len; cp = skipwhite(cp); p->type = s_new(); cp = getstring(cp, p->type, 1); if(badtype(s_to_c(p->type))) p->badtype = 1; while(*cp){ if(isattribute(&cp, "boundary")){ s = s_new(); cp = getstring(cp, s, 0); p->boundary = s_reset(p->boundary); s_append(p->boundary, "--"); s_append(p->boundary, s_to_c(s)); p->blen = s_len(p->boundary); s_free(s); } else if(cistrncmp(cp, "multipart", 9) == 0){ /* * the first unbounded part of a multipart message, * the preamble, is not displayed or saved */ } else if(isattribute(&cp, "name")){ setfilename(p, cp); } else if(isattribute(&cp, "charset")){ if(p->charset == nil) p->charset = s_new(); cp = getstring(cp, s_reset(p->charset), 0); } cp = skiptosemi(cp); }}/* * parse content encoding header */static voidcencoding(Part *m, Hdef *h, char *p){ p += h->len; p = skipwhite(p); if(cistrncmp(p, "base64", 6) == 0) m->encoding = Ebase64; else if(cistrncmp(p, "quoted-printable", 16) == 0) m->encoding = Equoted;}/* * parse content disposition header */static voidcdisposition(Part *p, Hdef *h, char *cp){ cp += h->len; cp = skipwhite(cp); while(*cp){ if(cistrncmp(cp, "inline", 6) == 0){ p->disposition = Dinline; } else if(cistrncmp(cp, "attachment", 10) == 0){ p->disposition = Dfile; } else if(cistrncmp(cp, "filename=", 9) == 0){ cp += 9; setfilename(p, cp); } cp = skiptosemi(cp); }}static voidsetfilename(Part *p, char *name){ if(p->filename == nil) p->filename = s_new(); getstring(name, s_reset(p->filename), 0); p->filename = tokenconvert(p->filename); p->badfile = badfile(s_to_c(p->filename));}static char*skipwhite(char *p){ while(isspace(*p)) p++; return p;}static char*skiptosemi(char *p){ while(*p && *p != ';') p++; while(*p == ';' || isspace(*p)) p++; return p;}/* * parse a possibly "'d string from a header. A * ';' terminates the string. */static char*getstring(char *p, String *s, int dolower){ s = s_reset(s); p = skipwhite(p); if(*p == '"'){ p++; for(;*p && *p != '"'; p++) if(dolower) s_putc(s, tolower(*p)); else s_putc(s, *p); if(*p == '"') p++; s_terminate(s); return p; } for(; *p && !isspace(*p) && *p != ';'; p++) if(dolower) s_putc(s, tolower(*p)); else s_putc(s, *p); s_terminate(s); return p;}static voidinit_hdefs(void){ Hdef *hd; static int already; if(already) return; already = 1; for(hd = hdefs; hd->type != nil; hd++) hd->len = strlen(hd->type);}/* * create a new boundary */static String*mkboundary(void){ char buf[32]; int i; static int already; if(already == 0){ srand((time(0)<<16)|getpid()); already = 1; } strcpy(buf, "upas-"); for(i = 5; i < sizeof(buf)-1; i++) buf[i] = 'a' + nrand(26); buf[i] = 0; return s_copy(buf);}/* * skip blank lines till header */static voidpassnotheader(void){ char *cp; int i, n; while((cp = Brdline(&in, '\n')) != nil){ n = Blinelen(&in); for(i = 0; i < n-1; i++) if(cp[i] != ' ' && cp[i] != '\t' && cp[i] != '\r'){ Bseek(&in, -n, 1); return; } Bwrite(&out, cp, n); }}/* * pass unix header lines */static voidpassunixheader(void){ char *p; int n; while((p = Brdline(&in, '\n')) != nil){ n = Blinelen(&in); if(strncmp(p, "From ", 5) != 0){ Bseek(&in, -n, 1); break; } Bwrite(&out, p, n); }}/* * Read mime types */static voidreadmtypes(void){ Biobuf *b; char *p; char *f[6]; Mtype *m; Mtype **l; b = Bopen("/sys/lib/mimetype", OREAD); if(b == nil) return; l = &mtypes; while((p = Brdline(b, '\n')) != nil){ if(*p == '#') continue; p[Blinelen(b)-1] = 0; if(tokenize(p, f, nelem(f)) < 5) continue; m = mallocz(sizeof *m, 1); if(m == nil) goto err; m->ext = strdup(f[0]); if(m->ext == 0) goto err; m->gtype = strdup(f[1]); if(m->gtype == 0) goto err; m->stype = strdup(f[2]); if(m->stype == 0) goto err; m->class = *f[4]; *l = m; l = &(m->next); } Bterm(b); return;err: if(m == nil) return; free(m->ext); free(m->gtype); free(m->stype); free(m); Bterm(b);}/* * if the class is 'm' or 'y', accept it * if the class is 'p' check a previous extension * otherwise, filename is bad */static intbadfile(char *name){ char *p; Mtype *m; int rv; p = strrchr(name, '.'); if(p == nil) return 0; for(m = mtypes; m != nil; m = m->next) if(cistrcmp(p, m->ext) == 0){ switch(m->class){ case 'm': case 'y': return 0; case 'p': *p = 0; rv = badfile(name); *p = '.'; return rv; case 'r': return 2; } } return 1;}/* * if the class is 'm' or 'y' or 'p', accept it * otherwise, filename is bad */static intbadtype(char *type){ Mtype *m; char *s, *fix; int rv = 1; fix = s = strchr(type, '/'); if(s != nil) *s++ = 0; else s = "-"; for(m = mtypes; m != nil; m = m->next){ if(cistrcmp(type, m->gtype) != 0) continue; if(cistrcmp(s, m->stype) != 0) continue; switch(m->class){ case 'y': case 'p': case 'm': rv = 0; break; } break; } if(fix != nil) *fix = '/'; return rv;}/* rfc2047 non-ascii */typedef struct Charset Charset;struct Charset { char *name; int len; int convert;} charsets[] ={ { "us-ascii", 8, 1, }, { "utf-8", 5, 0, }, { "iso-8859-1", 10, 1, },};/* * convert to UTF if need be */static String*tokenconvert(String *t){ String *s; char decoded[1024]; char utfbuf[2*1024]; int i, len; char *e; char *token; token = s_to_c(t); len = s_len(t); if(token[0] != '=' || token[1] != '?' || token[len-2] != '?' || token[len-1] != '=') goto err; e = token+len-2; token += 2; // bail if we don't understand the character set for(i = 0; i < nelem(charsets); i++) if(cistrncmp(charsets[i].name, token, charsets[i].len) == 0) if(token[charsets[i].len] == '?'){ token += charsets[i].len + 1; break; } if(i >= nelem(charsets)) goto err; // bail if it doesn't fit if(strlen(token) > sizeof(decoded)-1) goto err; // bail if we don't understand the encoding if(cistrncmp(token, "b?", 2) == 0){ token += 2; len = dec64((uchar*)decoded, sizeof(decoded), token, e-token); decoded[len] = 0; } else if(cistrncmp(token, "q?", 2) == 0){ token += 2; len = decquoted(decoded, token, e); if(len > 0 && decoded[len-1] == '\n') len--; decoded[len] = 0; } else goto err; s = nil; switch(charsets[i].convert){ case 0: s = s_copy(decoded); break; case 1: s = s_new(); latin1toutf(utfbuf, decoded, decoded+len); s_append(s, utfbuf); break; } return s;err: return s_clone(t);}/* * decode quoted */enum{ Self= 1, Hex= 2,};uchar tableqp[256];static voidinitquoted(void){ int c; memset(tableqp, 0, 256); for(c = ' '; c <= '<'; c++) tableqp[c] = Self; for(c = '>'; c <= '~'; c++) tableqp[c] = Self; tableqp['\t'] = Self; tableqp['='] = Hex;}static inthex2int(int x){ if(x >= '0' && x <= '9') return x - '0'; if(x >= 'A' && x <= 'F') return (x - 'A') + 10; if(x >= 'a' && x <= 'f') return (x - 'a') + 10; return 0;}static char*decquotedline(char *out, char *in, char *e){ int c, soft; /* dump trailing white space */ while(e >= in && (*e == ' ' || *e == '\t' || *e == '\r' || *e == '\n')) e--; /* trailing '=' means no newline */ if(*e == '='){ soft = 1; e--; } else soft = 0; while(in <= e){ c = (*in++) & 0xff; switch(tableqp[c]){ case Self: *out++ = c; break; case Hex: c = hex2int(*in++)<<4; c |= hex2int(*in++); *out++ = c; break; } } if(!soft) *out++ = '\n'; *out = 0; return out;}static intdecquoted(char *out, char *in, char *e){ char *p, *nl; if(tableqp[' '] == 0) initquoted(); p = out; while((nl = strchr(in, '\n')) != nil && nl < e){ p = decquotedline(p, in, nl); in = nl + 1; } if(in < e) p = decquotedline(p, in, e-1); // make sure we end with a new line if(*(p-1) != '\n'){ *p++ = '\n'; *p = 0; } return p - out;}/* translate latin1 directly since it fits neatly in utf */static intlatin1toutf(char *out, char *in, char *e){ Rune r; char *p; p = out; for(; in < e; in++){ r = (*in) & 0xff; p += runetochar(p, &r); } *p = 0; return p - out;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -