mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
NNTP: Add support for handling RFC2047 encoded words
Code adapted from git's builtin-mailinfo.c file.
This commit is contained in:
parent
78eae9cbf3
commit
0b0222d64f
@ -199,6 +199,128 @@ get_nntp_title(struct connection *conn)
|
||||
return title.source;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
decode_q_segment(struct string *str, unsigned char *in, unsigned char *end)
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = *in++) != 0 && (in <= end)) {
|
||||
if (c == '=') {
|
||||
int d = *in++;
|
||||
|
||||
if (d == '\n' || !d)
|
||||
break; /* drop trailing newline */
|
||||
d = (unhx(d) << 4) | unhx(*in++);
|
||||
add_format_to_string(str, "&#%d;", d);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '_') /* rfc2047 4.2 (2) */
|
||||
c = 0x20;
|
||||
add_char_to_string(str, c);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
decode_b_segment(struct string *str, unsigned char *in, unsigned char *end)
|
||||
{
|
||||
/* Decode in..ep, possibly in-place to ot */
|
||||
int c, pos = 0, acc = 0;
|
||||
|
||||
while ((c = *in++) != 0 && (in <= end)) {
|
||||
if (c == '+')
|
||||
c = 62;
|
||||
else if (c == '/')
|
||||
c = 63;
|
||||
else if ('A' <= c && c <= 'Z')
|
||||
c -= 'A';
|
||||
else if ('a' <= c && c <= 'z')
|
||||
c -= 'a' - 26;
|
||||
else if ('0' <= c && c <= '9')
|
||||
c -= '0' - 52;
|
||||
else if (c == '=') {
|
||||
/* padding is almost like (c == 0), except we do
|
||||
* not output NUL resulting only from it;
|
||||
* for now we just trust the data.
|
||||
*/
|
||||
c = 0;
|
||||
}
|
||||
else
|
||||
continue; /* garbage */
|
||||
|
||||
switch (pos++) {
|
||||
case 0:
|
||||
acc = (c << 2);
|
||||
break;
|
||||
case 1:
|
||||
add_format_to_string(str, "&#%d;", (acc | (c >> 4)));
|
||||
acc = (c & 15) << 4;
|
||||
break;
|
||||
case 2:
|
||||
add_format_to_string(str, "&#%d;", (acc | (c >> 2)));
|
||||
acc = (c & 3) << 6;
|
||||
break;
|
||||
case 3:
|
||||
add_format_to_string(str, "&#%d;", (acc | c));
|
||||
acc = pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_header_to_string(struct string *str, unsigned char *header)
|
||||
{
|
||||
unsigned char *end;
|
||||
int rfc2047 = 0;
|
||||
|
||||
while ((end = strstr(header, "=?")) != NULL) {
|
||||
int encoding;
|
||||
unsigned char charset_q[256];
|
||||
unsigned char *cp, *sp;
|
||||
|
||||
rfc2047 = 1;
|
||||
|
||||
if (header != end) {
|
||||
add_html_to_string(str, header, end - header);
|
||||
header = end;
|
||||
}
|
||||
|
||||
/* E.g.
|
||||
* ep : "=?iso-2022-jp?B?GyR...?= foo"
|
||||
* ep : "=?ISO-8859-1?Q?Foo=FCbar?= baz"
|
||||
*/
|
||||
end += 2;
|
||||
cp = strchr(end, '?');
|
||||
if (!cp)
|
||||
break;
|
||||
|
||||
for (sp = end; sp < cp; sp++)
|
||||
charset_q[sp - end] = tolower(*sp);
|
||||
charset_q[cp - end] = 0;
|
||||
encoding = tolower(cp[1]);
|
||||
|
||||
if (!encoding || cp[2] != '?')
|
||||
break;
|
||||
cp += 3;
|
||||
end = strstr(cp + 3, "?=");
|
||||
if (!end)
|
||||
break;
|
||||
if (encoding == 'b')
|
||||
decode_b_segment(str, cp, end);
|
||||
else if (encoding == 'q')
|
||||
decode_q_segment(str, cp, end);
|
||||
else
|
||||
break;
|
||||
|
||||
header = end + 2;
|
||||
}
|
||||
|
||||
add_html_to_string(str, header, strlen(header));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
add_nntp_html_start(struct string *html, struct connection *conn)
|
||||
{
|
||||
@ -236,7 +358,7 @@ add_nntp_html_start(struct string *html, struct connection *conn)
|
||||
}
|
||||
|
||||
add_format_to_string(html, "<b>%s</b>: ", entry);
|
||||
add_html_to_string(html, value, strlen(value));
|
||||
add_header_to_string(html, value);
|
||||
add_char_to_string(html, '\n');
|
||||
mem_free(value);
|
||||
mem_free(entry);
|
||||
|
Loading…
Reference in New Issue
Block a user