From 4fcb1dccfa8ee416684d560a5c0f45aed8a12807 Mon Sep 17 00:00:00 2001 From: Erich Eckner Date: Wed, 20 Feb 2019 13:46:41 +0100 Subject: topal-patch-1 applied --- alpine/send.c | 55 ++++++++++++++++++++++++++++++++++++++++----- imap/src/c-client/mail.h | 1 + pith/conf.c | 2 ++ pith/conftype.h | 1 + pith/pine.hlp | 18 ++++++++++++++- pith/send.c | 58 +++++++++++++++++++++++++++++++++++++----------- 6 files changed, 116 insertions(+), 19 deletions(-) diff --git a/alpine/send.c b/alpine/send.c index bc70dadf..823080c9 100644 --- a/alpine/send.c +++ b/alpine/send.c @@ -4115,6 +4115,23 @@ pine_send(ENVELOPE *outgoing, struct mail_bodystruct **body, pbf = save_previous_pbuf; g_rolenick = NULL; + /* Topal: Unmangle the body types. */ + if ((*body)->type == TYPEMULTIPART + && (*body)->topal_hack == 1) { + /* This was a single part message which Topal mangled. */ + dprint((9, "Topal: unmangling single part message\n")); + (*body)->type = TYPETEXT; + } + if ((*body)->type == TYPEMULTIPART + && (*body)->topal_hack != 1 + && (*body)->nested.part->body.type == TYPEMULTIPART + && (*body)->nested.part->body.topal_hack == 1) { + /* Topal mangled a multipart message. So the first nested part + is really TYPETEXT. */ + dprint((9, "Topal: unmangling first part of multipart message\n")); + (*body)->nested.part->body.type = TYPETEXT; + } + dprint((4, "=== send returning ===\n")); } @@ -5451,22 +5468,50 @@ filter_message_text(char *fcmd, ENVELOPE *outgoing, struct mail_bodystruct *body rfc822_parse_content_header(nb, (char *) ucase((unsigned char *) buf+8),s); + /* Topal: We're working on the first + text segment of the message. If + the filter returns something that + isn't TYPETEXT, then we need to + pretend (later on) that this is in + fact a TYPETEXT, because Topal has + already encoded it.... + + Original code path first, then an + alternate path. + */ if(nb->type == TYPETEXT && nb->subtype && (!b->subtype || strucmp(b->subtype, nb->subtype))){ - if(b->subtype) - fs_give((void **) &b->subtype); - + if(b->subtype) + fs_give((void **) &b->subtype); + + b->subtype = nb->subtype; + nb->subtype = NULL; + + mail_free_body_parameter(&b->parameter); + b->parameter = nb->parameter; + nb->parameter = NULL; + mail_free_body_parameter(&nb->parameter); + } + else if(F_ON(F_ENABLE_TOPAL_HACK, ps_global)){ + /* Perhaps the type isn't TYPETEXT, + and the hack is requested. So, + let's mess with the types. */ + if(nb->type != TYPETEXT){ + b->type = nb->type; b->subtype = nb->subtype; nb->subtype = NULL; - + + dprint((9, "Topal: mangling body!\n")); mail_free_body_parameter(&b->parameter); b->parameter = nb->parameter; nb->parameter = NULL; mail_free_body_parameter(&nb->parameter); + b->topal_hack = 1; + } } - + /* Topal: end */ mail_free_body(&nb); } diff --git a/imap/src/c-client/mail.h b/imap/src/c-client/mail.h index 79f0b3f3..c89d1638 100644 --- a/imap/src/c-client/mail.h +++ b/imap/src/c-client/mail.h @@ -844,6 +844,7 @@ BODY { unsigned long bytes; /* size of text in octets */ } size; char *md5; /* MD5 checksum */ + unsigned short topal_hack; /* set to 1 if topal has wrecked the sending */ void *sparep; /* spare pointer reserved for main program */ }; diff --git a/pith/conf.c b/pith/conf.c index e4f64c71..21afdf4e 100644 --- a/pith/conf.c +++ b/pith/conf.c @@ -2992,6 +2992,8 @@ feature_list(int index) F_SEND_WO_CONFIRM, h_config_send_wo_confirm, PREF_SEND, 0}, {"strip-whitespace-before-send", "Strip Whitespace Before Sending", F_STRIP_WS_BEFORE_SEND, h_config_strip_ws_before_send, PREF_SEND, 0}, + {"enable-topal-hack", "Enable Topal hack for OpenPGP/MIME messages", + F_ENABLE_TOPAL_HACK, h_config_enable_topal_hack, PREF_HIDDEN, 0}, {"warn-if-blank-fcc", "Warn if Blank Fcc", F_WARN_ABOUT_NO_FCC, h_config_warn_if_fcc_blank, PREF_SEND, 0}, {"warn-if-blank-subject", "Warn if Blank Subject", diff --git a/pith/conftype.h b/pith/conftype.h index 3ed5040f..5f695f51 100644 --- a/pith/conftype.h +++ b/pith/conftype.h @@ -532,6 +532,7 @@ typedef enum { F_MARK_FCC_SEEN, F_MULNEWSRC_HOSTNAMES_AS_TYPED, F_STRIP_WS_BEFORE_SEND, + F_ENABLE_TOPAL_HACK, F_QUELL_FLOWED_TEXT, F_COMPOSE_ALWAYS_DOWNGRADE, F_SORT_DEFAULT_FCC_ALPHA, diff --git a/pith/pine.hlp b/pith/pine.hlp index 26e5e269..b42db18a 100644 --- a/pith/pine.hlp +++ b/pith/pine.hlp @@ -4786,7 +4786,8 @@ There are also additional details on
  • FEATURE:
  • FEATURE:
  • FEATURE: -
  • FEATURE: +
  • FEATURE: +
  • FEATURE:
  • FEATURE:
  • FEATURE:
  • FEATURE: @@ -30809,6 +30810,21 @@ is enabled. However, notice that the default is to include text if you edit the reply indent string or if you explicitly set through this menu that you want headers included in the reply message. +

    +<End of help on this topic> + + +====== h_config_enable_topal_hack ===== + + +FEATURE: <!--#echo var="FEAT_enable-topal-hack"--> + + +

    FEATURE:

    +

    +This feature allows Topal (and other sending-filters) to change the +MIME type of the email. This is potentially dangerous because it +pretends that multipart emails are plain emails.

    <End of help on this topic> diff --git a/pith/send.c b/pith/send.c index 8d4d419a..95980b88 100644 --- a/pith/send.c +++ b/pith/send.c @@ -108,7 +108,7 @@ long post_rfc822_output(char *, ENVELOPE *, BODY *, soutr_t, TCPSTREAM *, int l_flush_net(int); int l_putc(int); int pine_write_header_line(char *, char *, STORE_S *); -int pine_write_params(PARAMETER *, STORE_S *); +int pine_write_params(PARAMETER *, STORE_S *, BODY *); char *tidy_smtp_mess(char *, char *, char *, size_t); int lmc_body_header_line(char *, int); int lmc_body_header_finish(void); @@ -1733,7 +1733,9 @@ call_mailer(METAENV *header, struct mail_bodystruct *body, char **alt_smtp_serve /* set up counts and such to keep track sent percentage */ send_bytes_sent = 0; gf_filter_init(); /* zero piped byte count, 'n */ + dprint((1, "Topal: HERE 1!\n")); send_bytes_to_send = send_body_size(body); /* count body bytes */ + dprint((1, "Topal: HERE 2!\n")); ps_global->c_client_error[0] = error_buf[0] = '\0'; we_cancel = busy_cue(_("Sending mail"), send_bytes_to_send ? sent_percent : NULL, 0); @@ -1750,6 +1752,9 @@ call_mailer(METAENV *header, struct mail_bodystruct *body, char **alt_smtp_serve #endif + dprint((1, "Topal: HERE 3!\n")); + + /* * If the user's asked for it, and we find that the first text * part (attachments all get b64'd) is non-7bit, ask for 8BITMIME. @@ -1757,6 +1762,7 @@ call_mailer(METAENV *header, struct mail_bodystruct *body, char **alt_smtp_serve if(F_ON(F_ENABLE_8BIT, ps_global) && (bp = first_text_8bit(body))) smtp_opts |= SOP_8BITMIME; + dprint((1, "Topal: HERE 3.1!\n")); #ifdef DEBUG #ifndef DEBUGJOURNAL if(debug > 5 || (flags & CM_VERBOSE)) @@ -1820,17 +1826,21 @@ call_mailer(METAENV *header, struct mail_bodystruct *body, char **alt_smtp_serve } } + dprint((1, "Topal: HERE 4!\n")); + /* * Install our rfc822 output routine */ sending_hooks.rfc822_out = mail_parameters(NULL, GET_RFC822OUTPUT, NULL); (void)mail_parameters(NULL, SET_RFC822OUTPUT, (void *)post_rfc822_output); + dprint((1, "Topal: HERE 5!\n")); /* * Allow for verbose posting */ (void) mail_parameters(NULL, SET_SMTPVERBOSE, (void *) pine_smtp_verbose_out); + dprint((1, "Topal: HERE 6!\n")); /* * We do this because we want mm_log to put the error message into @@ -1874,6 +1884,7 @@ call_mailer(METAENV *header, struct mail_bodystruct *body, char **alt_smtp_serve ps_global->noshow_error = 0; + dprint((1, "Topal: HERE 7!\n")); TIME_STAMP("smtp open", 1); if(sending_stream){ unsigned short save_encoding, added_encoding; @@ -2468,9 +2479,12 @@ write_fcc(char *fcc, CONTEXT_S *fcc_cntxt, STORE_S *tmp_storage, BODY * first_text_8bit(struct mail_bodystruct *body) { - if(body->type == TYPEMULTIPART) /* advance to first contained part */ + /* Be careful of Topal changes... */ + if(body->type == TYPEMULTIPART + && body->topal_hack != 1) /* advance to first contained part */ body = &body->nested.part->body; + /* Topal: this bit might not be correct, now. */ return((body->type == TYPETEXT && body->encoding != ENC7BIT) ? body : NULL); } @@ -2843,6 +2857,7 @@ pine_encode_body (struct mail_bodystruct *body) char *freethis; case TYPEMULTIPART: /* multi-part */ + if (body->topal_hack != 1) { /* But only if Topal hasn't touched it! */ if(!(freethis=parameter_val(body->parameter, "BOUNDARY"))){ char tmp[MAILTMPLEN]; /* make cookie not in BASE64 or QUOTEPRINT*/ @@ -2858,6 +2873,7 @@ pine_encode_body (struct mail_bodystruct *body) part = body->nested.part; /* encode body parts */ do pine_encode_body (&part->body); while ((part = part->next) != NULL); /* until done */ + } break; case TYPETEXT : @@ -4253,7 +4269,9 @@ pine_rfc822_output_body(struct mail_bodystruct *body, soutr_t f, void *s) bodyso = (STORE_S *) body->contents.text.data; - if(body->type == TYPEMULTIPART) { /* multipart gets special handling */ + if(body->type == TYPEMULTIPART + && body->topal_hack != 1) { /* multipart gets special handling, + unless Topal messed with it */ part = body->nested.part; /* first body part */ /* find cookie */ for (param = body->parameter; param && !cookie; param = param->next) @@ -4360,10 +4378,14 @@ pine_rfc822_output_body(struct mail_bodystruct *body, soutr_t f, void *s) * BEFORE applying any encoding (rfc1341: appendix G)... * NOTE: almost all filters expect CRLF newlines */ - if(body->type == TYPETEXT - && body->encoding != ENCBASE64 + if(((body->type == TYPETEXT + && body->encoding != ENCBASE64) + /* Or if Topal mucked with it... */ + | (body->type == TYPEMULTIPART && body->topal_hack == 1)) && !so_attr(bodyso, "rawbody", NULL)){ - gf_link_filter(gf_local_nvtnl, NULL); + if(body->topal_hack == 1) + dprint((9, "Topal: Canonical conversion, although Topal has mangled...\n")); + gf_link_filter(gf_local_nvtnl, NULL); } switch (body->encoding) { /* all else needs filtering */ @@ -4476,7 +4498,7 @@ pine_write_body_header(struct mail_bodystruct *body, soutr_t f, void *s) return(pwbh_finish(0, so)); if(body->parameter){ - if(!pine_write_params(body->parameter, so)) + if(!pine_write_params(body->parameter, so, body)) return(pwbh_finish(0, so)); } else if ((body->type != TYPEMESSAGE @@ -4558,7 +4580,7 @@ pine_write_body_header(struct mail_bodystruct *body, soutr_t f, void *s) && so_puts(so, body->disposition.type))) return(pwbh_finish(0, so)); - if(!pine_write_params(body->disposition.parameter, so)) + if(!pine_write_params(body->disposition.parameter, so, body)) return(pwbh_finish(0, so)); if(!so_puts(so, "\015\012")) @@ -4620,7 +4642,7 @@ pine_write_header_line(char *hdr, char *val, STORE_S *so) * pine_write_param - convert, encode and write MIME header-field parameters */ int -pine_write_params(PARAMETER *param, STORE_S *so) +pine_write_params(PARAMETER *param, STORE_S *so, BODY *body) { for(; param; param = param->next){ int rv; @@ -4629,9 +4651,17 @@ pine_write_params(PARAMETER *param, STORE_S *so) cs = posting_characterset(param->value, NULL, HdrText); cv = utf8_to_charset(param->value, cs, 0); - rv = (so_puts(so, "; ") - && rfc2231_output(so, param->attribute, cv, (char *) tspecials, cs)); - + if (body->topal_hack == 1 + && !struncmp(param->attribute, "protocol", 9)) { + /* Did Topal introduce more parameters? */ + dprint((9, "Topal: parameter encoding of protocol, with Topal hack\n")); + rv = (so_puts(so, "; \015\012\011") + && rfc2231_output(so, param->attribute, cv, (char *) tspecials, cs)); + } + else + rv = (so_puts(so, "; ") + && rfc2231_output(so, param->attribute, cv, (char *) tspecials, cs)); + if(cv && cv != param->value) fs_give((void **) &cv); @@ -4738,7 +4768,9 @@ send_body_size(struct mail_bodystruct *body) long l = 0L; PART *part; - if(body->type == TYPEMULTIPART) { /* multipart gets special handling */ + if(body->type == TYPEMULTIPART + && body->topal_hack != 1) { /* multipart gets special handling + but again, be careful of Topal */ part = body->nested.part; /* first body part */ do /* for each part */ l += send_body_size(&part->body); -- cgit v1.2.3-70-g09d2