static void add_rfc2047(struct strbuf *sb, const char *line, int len, const char *encoding) { int i, last; for (i = 0; i < len; i++) { int ch = line[i]; if (non_ascii(ch)) goto needquote; if ((i + 1 < len) && (ch == '=' && line[i+1] == '?')) goto needquote; } strbuf_add(sb, line, len); return; needquote: strbuf_grow(sb, len * 3 + strlen(encoding) + 100); strbuf_addf(sb, "=?%s?q?", encoding); for (i = last = 0; i < len; i++) { unsigned ch = line[i] & 0xFF; /* * We encode ' ' using '=20' even though rfc2047 * allows using '_' for readability. Unfortunately, * many programs do not understand this and just * leave the underscore in place. */ if (is_rfc2047_special(ch) || ch == ' ') { strbuf_add(sb, line + last, i - last); strbuf_addf(sb, "=%02X", ch); last = i + 1; } } strbuf_add(sb, line + last, len - last); strbuf_addstr(sb, "?="); }
static void add_rfc2047(struct strbuf *sb, const char *line, int len, const char *encoding) { static const int max_length = 78; /* per rfc2822 */ int i; int line_len; /* How many bytes are already used on the current line? */ for (i = sb->len - 1; i >= 0; i--) if (sb->buf[i] == '\n') break; line_len = sb->len - (i+1); for (i = 0; i < len; i++) { int ch = line[i]; if (non_ascii(ch) || ch == '\n') goto needquote; if ((i + 1 < len) && (ch == '=' && line[i+1] == '?')) goto needquote; } strbuf_add_wrapped_bytes(sb, line, len, 0, 1, max_length - line_len); return; needquote: strbuf_grow(sb, len * 3 + strlen(encoding) + 100); strbuf_addf(sb, "=?%s?q?", encoding); line_len += strlen(encoding) + 5; /* 5 for =??q? */ for (i = 0; i < len; i++) { unsigned ch = line[i] & 0xFF; if (line_len >= max_length - 2) { strbuf_addf(sb, "?=\n =?%s?q?", encoding); line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */ } /* * We encode ' ' using '=20' even though rfc2047 * allows using '_' for readability. Unfortunately, * many programs do not understand this and just * leave the underscore in place. */ if (is_rfc2047_special(ch) || ch == ' ' || ch == '\n') { strbuf_addf(sb, "=%02X", ch); line_len += 3; } else { strbuf_addch(sb, ch); line_len++; } } strbuf_addstr(sb, "?="); }
static void add_rfc2047(struct strbuf *sb, const char *line, size_t len, const char *encoding, enum rfc2047_type type) { static const int max_encoded_length = 76; /* per rfc2047 */ int i; int line_len = last_line_length(sb); strbuf_grow(sb, len * 3 + strlen(encoding) + 100); strbuf_addf(sb, "=?%s?q?", encoding); line_len += strlen(encoding) + 5; /* 5 for =??q? */ while (len) { /* * RFC 2047, section 5 (3): * * Each 'encoded-word' MUST represent an integral number of * characters. A multi-octet character may not be split across * adjacent 'encoded- word's. */ const unsigned char *p = (const unsigned char *)line; int chrlen = mbs_chrlen(&line, &len, encoding); int is_special = (chrlen > 1) || is_rfc2047_special(*p, type); /* "=%02X" * chrlen, or the byte itself */ const char *encoded_fmt = is_special ? "=%02X" : "%c"; int encoded_len = is_special ? 3 * chrlen : 1; /* * According to RFC 2047, we could encode the special character * ' ' (space) with '_' (underscore) for readability. But many * programs do not understand this and just leave the * underscore in place. Thus, we do nothing special here, which * causes ' ' to be encoded as '=20', avoiding this problem. */ if (line_len + encoded_len + 2 > max_encoded_length) { /* It won't fit with trailing "?=" --- break the line */ strbuf_addf(sb, "?=\n =?%s?q?", encoding); line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */ } for (i = 0; i < chrlen; i++) strbuf_addf(sb, encoded_fmt, p[i]); line_len += encoded_len; } strbuf_addstr(sb, "?="); }
static void add_rfc2047(struct strbuf *sb, const char *line, int len, const char *encoding, enum rfc2047_type type) { static const int max_encoded_length = 76; /* per rfc2047 */ int i; int line_len = last_line_length(sb); strbuf_grow(sb, len * 3 + strlen(encoding) + 100); strbuf_addf(sb, "=?%s?q?", encoding); line_len += strlen(encoding) + 5; /* 5 for =??q? */ for (i = 0; i < len; i++) { unsigned ch = line[i] & 0xFF; int is_special = is_rfc2047_special(ch, type); /* * According to RFC 2047, we could encode the special character * ' ' (space) with '_' (underscore) for readability. But many * programs do not understand this and just leave the * underscore in place. Thus, we do nothing special here, which * causes ' ' to be encoded as '=20', avoiding this problem. */ if (line_len + 2 + (is_special ? 3 : 1) > max_encoded_length) { strbuf_addf(sb, "?=\n =?%s?q?", encoding); line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */ } if (is_special) { strbuf_addf(sb, "=%02X", ch); line_len += 3; } else { strbuf_addch(sb, ch); line_len++; } } strbuf_addstr(sb, "?="); }