diff --git a/alpine/send.c b/alpine/send.c index 6eb3313..ba55d1c 100644 --- a/alpine/send.c +++ b/alpine/send.c @@ -4111,6 +4111,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")); } @@ -5447,22 +5464,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.c b/imap/src/c-client/mail.c index 49444eb..4b2c67e 100644 --- a/imap/src/c-client/mail.c +++ b/imap/src/c-client/mail.c @@ -2815,6 +2815,8 @@ BODY *mail_body_section (BODY *b, unsigned char *section) BODY *mail_body (MAILSTREAM *stream,unsigned long msgno,unsigned char *section) { BODY *b = NIL; + /* Topal hack 2 */ + mail_fetchstructure (stream,msgno,&b); /* make sure have a body */ if (section && *section && mail_fetchstructure (stream,msgno,&b) && b) return mail_body_section(b, section); diff --git a/imap/src/c-client/mail.h b/imap/src/c-client/mail.h index b5cd65d..dbf607f 100644 --- a/imap/src/c-client/mail.h +++ b/imap/src/c-client/mail.h @@ -831,6 +831,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 3742e9a..bf31096 100644 --- a/pith/conf.c +++ b/pith/conf.c @@ -2910,6 +2910,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 bfb337c..21b630d 100644 --- a/pith/conftype.h +++ b/pith/conftype.h @@ -522,6 +522,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/mailcap.c b/pith/mailcap.c index 06f521f..04d1b7d 100644 --- a/pith/mailcap.c +++ b/pith/mailcap.c @@ -583,8 +583,17 @@ mc_get_command(int type, char *subtype, BODY *body, * typically two scans through the check_extension * mechanism, the mailcap entry now takes precedence. */ - if((fname = get_filename_parameter(NULL, 0, body, &e2b.from.ext)) != NULL - && e2b.from.ext && e2b.from.ext[0]){ + /* Topal hack 2 */ + fname = get_filename_parameter(NULL, 0, body, &e2b.from.ext); + if (fname == NULL) { + if (body->type == TYPEMULTIPART && + ((body->subtype && !strucmp(body->subtype, "signed")) + ||(body->subtype && !strucmp(body->subtype, "encrypted")))) + fname = cpystr("openpgp.msg"); + } + + if(fname != NULL + && e2b.from.ext && e2b.from.ext[0]){ if(strlen(e2b.from.ext) < sizeof(tmp_ext) - 2){ strncpy(ext = tmp_ext, e2b.from.ext - 1, sizeof(tmp_ext)); /* remember it */ tmp_ext[sizeof(tmp_ext)-1] = '\0'; diff --git a/pith/pine.hlp b/pith/pine.hlp index 8a1fff7..e334631 100644 --- a/pith/pine.hlp +++ b/pith/pine.hlp @@ -4368,7 +4368,8 @@ There are also additional details on
  • FEATURE:
  • FEATURE:
  • FEATURE: -
  • FEATURE: +
  • FEATURE: +
  • FEATURE:
  • FEATURE:
  • FEATURE:
  • FEATURE: @@ -30014,6 +30015,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 32722a3..7c20b80 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); @@ -1782,7 +1782,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); @@ -1799,6 +1801,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. @@ -1806,6 +1811,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)) @@ -1869,17 +1875,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 @@ -1923,6 +1933,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; @@ -2517,9 +2528,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); } @@ -2892,6 +2906,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*/ @@ -2907,6 +2922,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 : @@ -4302,7 +4318,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) @@ -4402,10 +4420,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 */ @@ -4518,7 +4540,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 @@ -4600,7 +4622,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")) @@ -4662,7 +4684,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; @@ -4671,9 +4693,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); @@ -4780,7 +4810,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);