diff options
-rw-r--r-- | alpine/send.c | 55 | ||||
-rw-r--r-- | imap/src/c-client/mail.h | 1 | ||||
-rw-r--r-- | pith/conf.c | 2 | ||||
-rw-r--r-- | pith/conftype.h | 1 | ||||
-rw-r--r-- | pith/pine.hlp | 18 | ||||
-rw-r--r-- | 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 <li><a href="h_config_always_spell_check">FEATURE: <!--#echo var="FEAT_spell-check-before-sending"--></a> <li><a href="h_config_winpos_in_config">FEATURE: <!--#echo var="FEAT_store-window-position-in-config"--></a> <li><a href="h_config_strip_sigdashes">FEATURE: <!--#echo var="FEAT_strip-from-sigdashes-on-reply"--></a> -<li><a href="h_config_strip_ws_before_send">FEATURE: <!--#echo var="FEAT_strip-whitespace-before-send"--></a> +<li><a href="h_config_strip_ws_before_send">FEATURE: <!--#echo var="FEAT_strip-whitespace-before-send"--></a> +<li><a href="h_config_enable_topal_hack">FEATURE: <!--#echo var="FEAT_enable-topal-hack"--></a> <li><a href="h_config_quells_asterisks">FEATURE: <!--#echo var="FEAT_suppress-asterisks-in-password-prompt"--></a> <li><a href="h_config_quell_attach_ext_warn">FEATURE: <!--#echo var="FEAT_quell-attachment-extension-warn"--></a> <li><a href="h_config_quell_attach_extra_prompt">FEATURE: <!--#echo var="FEAT_quell-attachment-extra-prompt"--></a> @@ -30813,6 +30814,21 @@ want headers included in the reply message. <End of help on this topic> </BODY> </HTML> +====== h_config_enable_topal_hack ===== +<HTML> +<HEAD> +<TITLE>FEATURE: <!--#echo var="FEAT_enable-topal-hack"--></TITLE> +</HEAD> +<BODY> +<H1>FEATURE: <!--#echo var="FEAT_enable-topal-hack"--></H1> +<P> +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. +<P> +<End of help on this topic> +</BODY> +</HTML> ====== h_config_del_from_dot ===== <HTML> <HEAD> 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); |