📄 mimedecode.c
字号:
if (Debug >= 3) fprintf (stderr, "Transfer-encoding IS UNKNOWN\n"); mhp->transfer_encoding = UNDEF; } } nlbp = NULL; } else { if ((nlbp = decode_header_line (QUERY_CHARSET_NAME, &headers_buffer))) { if ((nlbp[0] == 'x' || nlbp[0] == 'X') &&nlbp[1] == '-') nlbp += 2; strncpy (mhp->headers_charset, nlbp, MIN (strcspn (nlbp, "*"), 79)); mhp->headers_charset[ MIN (strcspn (nlbp, "*"), 79)] = '\0'; if (Debug) fprintf (stderr, " -- Headers's charset: %s\n", mhp->headers_charset); } nlbp = headers_buffer.header_start; } if (Debug >= 7) fprintf (stderr, "Adding to buffer: %s\n", nlbp);/* Generally, we will output _all_ lines as they are read (and * decoded). The exception is the Content-transfer-encoding (cte) * and Content-Type header lines: * We will only output cte when the Content-type has been read or * when the header/body boundary have been reached. */ if (nlbp) headers_buffer.header_start = headers_buffer.next; else headers_buffer.next = headers_buffer.header_start; /* Have we reached the header/body boundary? */ if ((c = getc (stdin)) == '\n') { /* yes we have! */ if (Debug >= 2) fprintf (stderr, "body reached\n"); if (cte_read && !cte_written) { if (!ct_read) { /* Content-type field is missing!! * Assume text/plain! */ if (Debug >= 3) fprintf (stderr, "Content-type field is missing!!\n"); Add_to_buffer (&headers_buffer, "X-2UTF-Content-type: missing\n"); headers_buffer.header_start = headers_buffer.next; ct_read = TRUE; mhp->content_type = TEXT; } write_cte (&headers_buffer, mhp->transfer_encoding, mhp->content_type); cte_written = TRUE; } /* should we output the '\n' here? */ Add_to_buffer (&headers_buffer, "\n"); break; } /* * We have _not_ reached the header/body boundary */ if (ct_read && cte_read & !cte_written) { write_cte (&headers_buffer, mhp->transfer_encoding, mhp->content_type); cte_written = TRUE; } goto again; } } if (!ct_read) mhp->content_type = TEXT; /* second pass */ if (Debug) fprintf (stderr, " -- parse_header - pass 2 -- \n"); if (Debug >= 4) fprintf (stderr, "headers charset: %s\ncontent charset: %s\n", mhp->headers_charset, mhp->content_charset);/* 1) test if charset is known before changing Content-Type header * 2) set charset for non-MIME-encrypted headers - * - assuming the same as Content's one */ if (mhp->content_charset[0] != '\0' && Strcasecmp (mhp->content_charset, "us-ascii") != 0) { if (Validate_charset (mhp->content_charset, IS)) { if (charset_p->type != UTF8) ct_is_changing = TRUE; } else ct_charset_unknown = TRUE; } else if (mhp->headers_charset[0] != '\0') { Validate_charset (mhp->headers_charset, IS); } else Validate_charset ("us-ascii", 0);/* if (ct_read && mhp->content_type == TEXT && ct_header_charset_name_end) if (charset_p->type == KNOWN || charset_p->type == BUF_PIPE || charset_p->type == NON_BUF_PIPE) ct_is_changing = TRUE; else if (charset_p->type == UNKNOWN && mhp->content_charset[0] != '\0' && Strcasecmp (mhp->content_charset, "us-ascii") != 0) ct_charset_unknown = TRUE; */ headers_buffer.end = headers_buffer.next; /* no more Add_to_buffer() */ headers_buffer.header_start = headers_buffer.next = headers_buffer.start; for (; headers_buffer.next <= headers_buffer.end; c = *headers_buffer.next++) { /*again2: *//* *headers_buffer.next++ = c; */ if (c == '\n' && !(*headers_buffer.next == ' ' || *headers_buffer.next == '\t')) /* end of (folded?) header line reached */ { unsigned char saved_char; struct buffer_type new_ct; saved_char = *headers_buffer.next; *headers_buffer.next = '\0'; /* zero terminate the line buf */ if (Debug >= 4) fprintf (stderr, "header: %s\n", headers_buffer.header_start); if (!ct_written && Strcase_has_prefix (headers_buffer.header_start, "Content-Type:") == 0) { ct_written = TRUE; if (ct_is_changing) { EMPTY_BUFFERS(charset_p); fputs ("X-2UTF-Old-", charset_p->pipe); decode_header_line (DECODE, &headers_buffer); /* changing charset name to UTF-8 */ if (ct_header_charset_name_begin > ct_header_charset_name_end) Error (internal_err); new_ct.start = new_ct.header_start = xmalloc ( strlen (headers_buffer.header_start) + strlen ("UTF-8")); strcpy (Stpcpy (Stpncpy (new_ct.start, \ headers_buffer.header_start, \ ct_header_charset_name_begin), \ "UTF-8"), headers_buffer.header_start + ct_header_charset_name_end); new_ct.next = new_ct.header_start + strlen (new_ct.header_start); decode_header_line (DECODE, &new_ct); free (new_ct.start); } else { decode_header_line (DECODE, &headers_buffer); if (ct_charset_unknown) { EMPTY_BUFFERS(charset_p); fprintf (charset_p->pipe, "X-2UTF-Warning: Unknown charset in Content-Type header: \"%s\"\n", mhp->content_charset); } } if (mhp->boundary[0] == '\0') { EMPTY_BUFFERS(charset_p); fputs ("X-2UTF-Warning: missing boundary parameter\n", charset_p->pipe); } } else decode_header_line (DECODE, &headers_buffer); /* Have we reached the header/body boundary? */ if (saved_char == '\n') { /* yes we have! */ if (Debug >= 2) fprintf (stderr, "body reached\n"); /* should we output the '\n' here? */ PUTC_IN_UTF8 ('\n'); goto Return; } *headers_buffer.next = saved_char; headers_buffer.header_start = headers_buffer.next; } }/* set charset for message body */Return: if (mhp->content_charset[0] != '\0' /* && Strcasecmp (mhp->content_charset, "us-ascii") != 0 */ ) Validate_charset (mhp->content_charset, 0); else if (mhp->headers_charset[0] != '\0') Validate_charset (mhp->headers_charset, 0); else Validate_charset ("us-ascii", 0); return (TRUE);}/* * General format of an encoded header field (`[ ]' denotes optional fields): * * header_field: <text>=?<charset>[*<language>]?<encoding>?<encoded_chars>?=<text> * * `X-' charset prefix denotes non-standard charset for private use. * */#define HUNT 0#define START 1#define CHARS 2#define ENCD 3#define Q_FIELD 4#define DEC1 5#define DEC2 6#define B_FIELD 7#define END 8#define binhex(c) ( (c > '9') ? c-'A'+10 : c-'0')/* max MIME charset parameter is 70 bytes */unsigned char rendered_charset_name[80];/*******************************************************************/char *decode_header_line (action, headers_buffer_p)/*******************************************************************/ enum action_type action; struct buffer_type *headers_buffer_p;{ int state = HUNT; int c, c1 = 0, c2, b1 = 0, b2, index, tmp; /* =0 ??? */ unsigned char *buf = headers_buffer_p->header_start; size_t charset_name_length = 0; unsigned char charset_name[80]; unsigned char *charp = charset_name; const int max_encoding_length = 1; unsigned char encoding[max_encoding_length + 1]; unsigned char *encp = encoding; unsigned char space_between_enc_words[80]=""; rendered_charset_name[0] = '\0'; while (buf < headers_buffer_p->next) { c = *buf++; if (Debug > 7) { print_state (state); fprintf (stderr, ", c=`%c\'\n", (char) c); } if (state == END) { if (action == DECODE) { if (encode && charset_p->type == ICONV) Put_to_iconv_buf(-3, charset_p); /* reencode output to MIME word and empty buffer */ /* string may expand while converting */ Validate_charset (NULL, 0); /* pop previous charset */ } } if (state == HUNT) { if (c == ' ' || c == '\t' || c == '(') { state = START; /* *retp++ = c; */ if (action == DECODE) PUTC_IN_UTF8 (c); continue; } } switch (c) { case '=': { switch (state) { case START: if ((tmp = *buf++) == '?') { state = CHARS; charp = charset_name; } else { if (action == DECODE) { PUTC_IN_UTF8 (c); PUTC_IN_UTF8 (tmp); } state = HUNT; } continue; case CHARS: goto it_is_not_charset_name; case Q_FIELD: state = DEC1; continue; case DEC1: /* *retp++ = '='; */ PUTC_IN_UTF8 ('='); continue; case B_FIELD: /* padding */ continue; case END: if ((index=strspn (buf, LWSP)) && buf[index] == '=' && buf[index+1] == '?') { /* space between adjacent encoded-words should be skipped */ memcpy (space_between_enc_words, buf, MIN (79, index)); space_between_enc_words[MIN (79, index)]='\0'; state = CHARS; charp = charset_name; buf += index + 2; } else { space_between_enc_words[0]='\0'; state = HUNT; } continue; } } break; case '?': { switch (state) { case START: /* *retp++ = c; */ if (action == DECODE) PUTC_IN_UTF8 (c); state = HUNT; continue; case CHARS: /* we do not ignore the charset specification. * discard X- prefix for non-standard charsets. */ *charp = '\0'; charset_name_length = charp - charset_name; strcpy (rendered_charset_name, charset_name); if ((rendered_charset_name[0] == 'x' || rendered_charset_name[0] == 'X') && rendered_charset_name[1] == '-') memmove (rendered_charset_name, rendered_charset_name + 2, 78); /* ignore language suffix after `*' */ if (strchr (rendered_charset_name, '*')) *strchr (rendered_charset_name, '*') = '\0'; if (action == QUERY_CHARSET_NAME) { return (rendered_charset_name); } if (Debug >= 4) { fprintf (stderr, "charset: %s\n", charset_name); fprintf (stderr, "rendered charset: %s\n", rendered_charset_name); } state = ENCD; continue; case ENCD: *encp = '\0'; encp = encoding; if (Debug > 7) fprintf (stderr, "encoding: %s\n", encoding); if (encode && Str_is_UTF8(rendered_charset_name) || !(Validate_charset (rendered_charset_name, 0) && (*encoding == 'q' || *encoding == 'Q' ||*encoding == 'b' || *encoding == 'B'))) { if (Debug > 3) fprintf (stderr, "skipping charset '%s', encoding '%c'\n", rendered_charset_name, encoding[0]); Output_consumed_chars (space_between_enc_words, charset_name, charset_name_length, encoding); PUTC_IN_UTF8 ('?'); Validate_charset (NULL, 0); /* pop previous charset */ charp = charset_name; encp = encoding; state = HUNT; continue; } if (encode) { int i = -1; while (space_between_enc_words[++i]) /* don't skip space if we will have encoded words again */ PUTC_IN_UTF8 (space_between_enc_words[i]); EMPTY_BUFFERS(charset_p); } if ((*encoding == 'q') || (*encoding == 'Q')) { state = Q_FIELD; } else if ((*encoding == 'b') || (*encoding == 'B')) { int c1, c2, c3, c4; state = B_FIELD; while ((buf < headers_buffer_p->next) && (*buf != '\?')) { /* find first valid c1 */ while ((buf < headers_buffer_p->next) && (*buf != '\?') && ((c1 = b64_map[(unsigned int) *buf]) == UN)) buf++; c1 = *buf; if (buf < headers_buffer_p->next) buf++; /* find second valid c2 */ while ((buf < headers_buffer_p->next) && (*buf != '\?') && ((c2 = b64_map[(unsigned int) *buf]) == UN)) buf++; c2 = *buf; if (buf < headers_buffer_p->next) buf++; /* find third valid c3 */ while ((buf < headers_buffer_p->next) && (*buf != '\?') && ((c3 = b64_map[(unsigned int) *buf]) == UN)) buf++; c3 = *buf; if (buf < headers_buffer_p->next) buf++; /* find fourth valid c4 */ while ((buf < headers_buffer_p->next) && (*buf != '\?') && ((c4 = b64_map[(unsigned int) *buf]) == UN)) buf++; c4 = *buf; if (buf < headers_buffer_p->next) buf++; if ((c1 == '=') || (c2 == '=') || (c1 == '\0') || (c2 == '\0') || (c1 == '\?') || (c2 == '\?')) { break; } /* *retp++ = ((unsigned int) b64_map[c1] << 2) | (((unsigned int) b64_map[c2] & 0x30) >> 4); */ PUTC_IN_UTF8 (((unsigned int) b64_map[c1] << 2) |(((unsigned int) b64_map[c2] & 0x30) >> 4)); if ((c3 == '=') || (c3 == '\0') || (c3 == '?')) { break; } /* *retp++ = (((unsigned int) b64_map[c2] & 0xF) << 4) | (((unsigned int) b64_map[c3] & 0x3C) >> 2); */ PUTC_IN_UTF8 ((((unsigned int) b64_map[c2] & 0xF) << 4) |(((unsigned int) b64_map[c3] & 0x3C) >> 2)); if ((c4 == '=') || (c4 == '\0') || (c4 == '\?')) { break; } /* *retp++ = (((unsigned int) b64_map[c3] & 0x3) << 6) | ((unsigned int) b64_map[c4]); */ PUTC_IN_UTF8 ((((unsigned int) b64_map[c3] & 0x3) << 6) |((unsigned int) b64_map[c4])); } if (encode && charset_p->type == ICONV) Put_to_iconv_buf(-3, charset_p); /* reencode output to MIME word and empty buffer */ /* *retp = '\0'; */ } continue; case B_FIELD: case Q_FIELD: state = END; continue; case DEC1: /* output the consumed char */ /* *retp++ = '='; */ PUTC_IN_UTF8 ('='); state = END; continue; case DEC2: /* output the consumed chars */ /* *retp++ = '='; *retp++ = c1; */ PUTC_IN_UTF8 ('='); PUTC_IN_UTF8 (c1); state = END; continue; } } break; default: { if (state == START)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -