ref: 20bca0c2029c53de3d4149d957240b17d44684a8
dir: /sys/src/cmd/upas/fs/header.c/
#include "common.h" #include <ctype.h> #include <libsec.h> #include "dat.h" int hdrlen(char *p, char *e) { char *ep; ep = p; do { ep = memchr(ep, '\n', e - ep); if(ep == nil){ ep = e; break; } if(ep == p) break; if(ep - p == 1 && ep[-1] == '\r') break; ep++; if(ep >= e){ ep = e; break; } } while(*ep == ' ' || *ep == '\t'); return ep - p; } /* rfc2047 non-ascii: =?charset?q?encoded-text?= */ static int tok(char **sp, char *se, char *token, int len) { char charset[100], *s, *e, *x; int l; if(len == 0) return -1; s = *sp; e = token + len - 2; token += 2; x = memchr(token, '?', e - token); if(x == nil || (l = x - token) >= sizeof charset) return -1; memmove(charset, token, l); charset[l] = 0; /* bail if it doesn't fit */ token = x + 1; if(e - token > se - s - 1) return -1; if(cistrncmp(token, "b?", 2) == 0){ token += 2; len = dec64((uchar*)s, se - s - 1, token, e - token); if(len == -1) return -1; s[len] = 0; }else if(cistrncmp(token, "q?", 2) == 0){ token += 2; len = decquoted(s, token, e, 1); if(len > 0 && s[len - 1] == '\n') len--; s[len] = 0; }else return -1; if(xtoutf(charset, &x, s, s + len) <= 0) s += len; else { s = seprint(s, se, "%s", x); free(x); } *sp = s; return 0; } char* tokbegin(char *start, char *end) { int quests; if(*--end != '=') return nil; if(*--end != '?') return nil; quests = 0; for(end--; end >= start; end--){ switch(*end){ case '=': if(quests == 3 && *(end + 1) == '?') return end; break; case '?': ++quests; break; case ' ': case '\t': case '\n': case '\r': /* can't have white space in a token */ return nil; } } return nil; } static char* seappend822f(char *s, char *e, char *a, int n) { int skip, c; skip = 0; for(; n--; a++){ c = *a; if(skip && isspace(c)) continue; if(c == '\n'){ c = ' '; skip = 1; }else{ if(c < 0x20) continue; skip = 0; } s = sputc(s, e, c); } return s; } static char* seappend822(char *s, char *e, char *a, int n) { int c; for(; n--; a++){ c = *a; if(c < 0x20 && c != '\n' && c != '\t') continue; s = sputc(s, e, c); } return s; } /* convert a header line */ char* rfc2047(char *s, char *se, char *uneaten, int len, int fold) { char *sp, *token, *p, *e; char *(*f)(char*, char*, char*, int); f = seappend822; if(fold) f = seappend822f; sp = s; p = uneaten; for(e = p + len; p < e; ){ while(*p++ == '=' && (token = tokbegin(uneaten, p))){ sp = f(sp, se, uneaten, token - uneaten); if(tok(&sp, se, token, p - token) < 0) sp = f(sp, se, token, p - token); uneaten = p; for(; p < e && isspace(*p);) p++; if(p + 2 < e && p[0] == '=' && p[1] == '?') uneaten = p; /* paste */ } } if(p > uneaten) sp = f(sp, se, uneaten, e - uneaten); *sp = 0; return sp; }