📄 rfc2047.c
字号:
/* Find earliest and latest things we must encode. */ s0 = s1 = t0 = t1 = 0; for (t = u; t < u + ulen; t++) { if ((*t & 0x80) || (*t == '=' && t[1] == '?' && (t == u || HSPACE(*(t-1))))) { if (!t0) t0 = t; t1 = t; } else if (specials && strchr (specials, *t)) { if (!s0) s0 = t; s1 = t; } } /* If we have something to encode, include RFC822 specials */ if (t0 && s0 && s0 < t0) t0 = s0; if (t1 && s1 && s1 > t1) t1 = s1; if (!t0) { /* No encoding is required. */ *e = u; *elen = ulen; return ret; } /* Choose target charset. */ tocode = fromcode; if (icode) { if ((tocode1 = mutt_choose_charset (icode, charsets, u, ulen, 0, 0))) tocode = tocode1; else ret = 2, icode = 0; } /* Hack to avoid labelling 8-bit data as us-ascii. */ if (!icode && mutt_is_us_ascii (tocode)) tocode = "unknown-8bit"; /* Adjust t0 for maximum length of line. */ t = u + (ENCWORD_LEN_MAX + 1) - col - ENCWORD_LEN_MIN; if (t < u) t = u; if (t < t0) t0 = t; /* Adjust t0 until we can encode a character after a space. */ for (; t0 > u; t0--) { if (!HSPACE(*(t0-1))) continue; t = t0 + 1; if (icode) while (t < u + ulen && CONTINUATION_BYTE(*t)) ++t; if (!try_block (t0, t - t0, icode, tocode, &encoder, &wlen) && col + (t0 - u) + wlen <= ENCWORD_LEN_MAX + 1) break; } /* Adjust t1 until we can encode a character before a space. */ for (; t1 < u + ulen; t1++) { if (!HSPACE(*t1)) continue; t = t1 - 1; if (icode) while (CONTINUATION_BYTE(*t)) --t; if (!try_block (t, t1 - t, icode, tocode, &encoder, &wlen) && 1 + wlen + (u + ulen - t1) <= ENCWORD_LEN_MAX + 1) break; } /* We shall encode the region [t0,t1). */ /* Initialise the output buffer with the us-ascii prefix. */ buflen = 2 * ulen; buf = safe_malloc (buflen); bufpos = t0 - u; memcpy (buf, u, t0 - u); col += t0 - u; t = t0; for (;;) { /* Find how much we can encode. */ n = choose_block (t, t1 - t, col, icode, tocode, &encoder, &wlen); if (n == t1 - t) { /* See if we can fit the us-ascii suffix, too. */ if (col + wlen + (u + ulen - t1) <= ENCWORD_LEN_MAX + 1) break; n = t1 - t - 1; if (icode) while (CONTINUATION_BYTE(t[n])) --n; assert (t + n >= t); if (!n) { /* This should only happen in the really stupid case where the only word that needs encoding is one character long, but there is too much us-ascii stuff after it to use a single encoded word. We add the next word to the encoded region and try again. */ assert (t1 < u + ulen); for (t1++; t1 < u + ulen && !HSPACE(*t1); t1++) ; continue; } n = choose_block (t, n, col, icode, tocode, &encoder, &wlen); } /* Add to output buffer. */#define LINEBREAK "\n\t" if (bufpos + wlen + strlen (LINEBREAK) > buflen) { buflen = bufpos + wlen + strlen (LINEBREAK); safe_realloc (&buf, buflen); } r = encode_block (buf + bufpos, t, n, icode, tocode, encoder); assert (r == wlen); bufpos += wlen; memcpy (buf + bufpos, LINEBREAK, strlen (LINEBREAK)); bufpos += strlen (LINEBREAK);#undef LINEBREAK col = 1; t += n; } /* Add last encoded word and us-ascii suffix to buffer. */ buflen = bufpos + wlen + (u + ulen - t1); safe_realloc (&buf, buflen + 1); r = encode_block (buf + bufpos, t, t1 - t, icode, tocode, encoder); assert (r == wlen); bufpos += wlen; memcpy (buf + bufpos, t1, u + ulen - t1); FREE (&tocode1); FREE (&u); buf[buflen] = '\0'; *e = buf; *elen = buflen + 1; return ret;}void _rfc2047_encode_string (char **pd, int encode_specials, int col){ char *e; size_t elen; char *charsets; if (!Charset || !*pd) return; charsets = SendCharset; if (!charsets || !*charsets) charsets = "UTF-8"; rfc2047_encode (*pd, strlen (*pd), col, Charset, charsets, &e, &elen, encode_specials ? RFC822Specials : NULL); FREE (pd); /* __FREE_CHECKED__ */ *pd = e;}void rfc2047_encode_adrlist (ADDRESS *addr, const char *tag){ ADDRESS *ptr = addr; int col = tag ? strlen (tag) + 2 : 32; while (ptr) { if (ptr->personal) _rfc2047_encode_string (&ptr->personal, 1, col);#ifdef EXACT_ADDRESS if (ptr->val) _rfc2047_encode_string (&ptr->val, 1, col);#endif ptr = ptr->next; }}static int rfc2047_decode_word (char *d, const char *s, size_t len){ const char *pp, *pp1; char *pd, *d0; const char *t, *t1; int enc = 0, count = 0; char *charset = NULL; pd = d0 = safe_malloc (strlen (s)); for (pp = s; (pp1 = strchr (pp, '?')); pp = pp1 + 1) { count++; switch (count) { case 2: /* ignore language specification a la RFC 2231 */ t = pp1; if ((t1 = memchr (pp, '*', t - pp))) t = t1; charset = safe_malloc (t - pp + 1); memcpy (charset, pp, t - pp); charset[t-pp] = '\0'; break; case 3: if (toupper ((unsigned char) *pp) == 'Q') enc = ENCQUOTEDPRINTABLE; else if (toupper ((unsigned char) *pp) == 'B') enc = ENCBASE64; else { FREE (&charset); FREE (&d0); return (-1); } break; case 4: if (enc == ENCQUOTEDPRINTABLE) { for (; pp < pp1; pp++) { if (*pp == '_') *pd++ = ' '; else if (*pp == '=' && (!(pp[1] & ~127) && hexval(pp[1]) != -1) && (!(pp[2] & ~127) && hexval(pp[2]) != -1)) { *pd++ = (hexval(pp[1]) << 4) | hexval(pp[2]); pp += 2; } else *pd++ = *pp; } *pd = 0; } else if (enc == ENCBASE64) { int c, b = 0, k = 0; for (; pp < pp1; pp++) { if (*pp == '=') break; if ((*pp & ~127) || (c = base64val(*pp)) == -1) continue; if (k + 6 >= 8) { k -= 2; *pd++ = b | (c >> k); b = c << (8 - k); } else { b |= c << (k + 2); k += 6; } } *pd = 0; } break; } } if (charset) mutt_convert_string (&d0, charset, Charset, M_ICONV_HOOK_FROM); mutt_filter_unprintable (&d0); strfcpy (d, d0, len); FREE (&charset); FREE (&d0); return (0);}/* * Find the start and end of the first encoded word in the string. * We use the grammar in section 2 of RFC 2047, but the "encoding" * must be B or Q. Also, we don't require the encoded word to be * separated by linear-white-space (section 5(1)). */static const char *find_encoded_word (const char *s, const char **x){ const char *p, *q; q = s; while ((p = strstr (q, "=?"))) { for (q = p + 2; 0x20 < *q && *q < 0x7f && !strchr ("()<>@,;:\"/[]?.=", *q); q++) ; if (q[0] != '?' || !strchr ("BbQq", q[1]) || q[2] != '?') continue; for (q = q + 3; 0x20 < *q && *q < 0x7f && *q != '?'; q++) ; if (q[0] != '?' || q[1] != '=') { --q; continue; } *x = q + 2; return p; } return 0;}/* try to decode anything that looks like a valid RFC2047 encoded * header field, ignoring RFC822 parsing rules */void rfc2047_decode (char **pd){ const char *p, *q; size_t n; int found_encoded = 0; char *d0, *d; const char *s = *pd; size_t dlen; if (!s || !*s) return; dlen = 4 * strlen (s); /* should be enough */ d = d0 = safe_malloc (dlen + 1); while (*s && dlen > 0) { if (!(p = find_encoded_word (s, &q))) { /* no encoded words */ strncpy (d, s, dlen); d += dlen; break; } if (p != s) { n = (size_t) (p - s); /* ignore spaces between encoded words */ if (!found_encoded || strspn (s, " \t\r\n") != n) { if (n > dlen) n = dlen; memcpy (d, s, n); d += n; dlen -= n; } } rfc2047_decode_word (d, p, dlen); found_encoded = 1; s = q; n = mutt_strlen (d); dlen -= n; d += n; } *d = 0; FREE (pd); /* __FREE_CHECKED__ */ *pd = d0; mutt_str_adjust (pd);}void rfc2047_decode_adrlist (ADDRESS *a){ while (a) { if (a->personal && strstr (a->personal, "=?") != NULL) rfc2047_decode (&a->personal);#ifdef EXACT_ADDRESS if (a->val && strstr (a->val, "=?") != NULL) rfc2047_decode (&a->val);#endif a = a->next; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -