]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'jc/send-email-sensible-encoding'
authorJunio C Hamano <gitster@pobox.com>
Wed, 25 Feb 2015 23:40:19 +0000 (15:40 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 25 Feb 2015 23:40:19 +0000 (15:40 -0800)
"git send-email" used to accept a mistaken "y" (or "yes") as an
answer to "What encoding do you want to use [UTF-8]? " without
questioning.  Now it asks for confirmation when the answer looks
too short to be a valid encoding name.

* jc/send-email-sensible-encoding:
  send-email: ask confirmation if given encoding name is very short

1  2 
git-send-email.perl

diff --combined git-send-email.perl
index 3092ab356c765cd593d2a988d020665c8b626ea1,eb3237115125ebb749a6b2e8b2cf612106a05516..848f17623a88af89676bce6d8be44c869226ab14
@@@ -54,12 -54,10 +54,12 @@@ git send-email [options] <file | direct
      --[no-]bcc              <str>  * Email Bcc:
      --subject               <str>  * Email "Subject:"
      --in-reply-to           <str>  * Email "In-Reply-To:"
 +    --[no-]xmailer                 * Add "X-Mailer:" header (default).
      --[no-]annotate                * Review each patch that will be sent in an editor.
      --compose                      * Open an editor for introduction.
      --compose-encoding      <str>  * Encoding to assume for introduction.
      --8bit-encoding         <str>  * Encoding to assume 8bit mails if undeclared
 +    --transfer-encoding     <str>  * Transfer encoding to use (quoted-printable, 8bit, base64)
  
    Sending:
      --envelope-sender       <str>  * Email envelope sender.
@@@ -82,8 -80,6 +82,8 @@@
      --to-cmd                <str>  * Email To: via `<str> \$patch_path`
      --cc-cmd                <str>  * Email Cc: via `<str> \$patch_path`
      --suppress-cc           <str>  * author, self, sob, cc, cccmd, body, bodycc, all.
 +    --[no-]cc-cover                * Email Cc: addresses in the cover letter.
 +    --[no-]to-cover                * Email To: addresses in the cover letter.
      --[no-]signed-off-by-cc        * Send to Signed-off-by: addresses. Default on.
      --[no-]suppress-from           * Send to self. Default off.
      --[no-]chain-reply-to          * Chain In-Reply-To: fields. Default off.
@@@ -147,15 -143,10 +147,15 @@@ my $have_mail_address = eval { require 
  my $smtp;
  my $auth;
  
 +# Regexes for RFC 2047 productions.
 +my $re_token = qr/[^][()<>@,;:\\"\/?.= \000-\037\177-\377]+/;
 +my $re_encoded_text = qr/[^? \000-\037\177-\377]+/;
 +my $re_encoded_word = qr/=\?($re_token)\?($re_token)\?($re_encoded_text)\?=/;
 +
  # Variables we fill in automatically, or via prompting:
  my (@to,$no_to,@initial_to,@cc,$no_cc,@initial_cc,@bcclist,$no_bcc,@xh,
        $initial_reply_to,$initial_subject,@files,
 -      $author,$sender,$smtp_authpass,$annotate,$compose,$time);
 +      $author,$sender,$smtp_authpass,$annotate,$use_xmailer,$compose,$time);
  
  my $envelope_sender;
  
@@@ -204,7 -195,6 +204,7 @@@ sub do_edit 
  
  # Variables with corresponding config settings
  my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc);
 +my ($cover_cc, $cover_to);
  my ($to_cmd, $cc_cmd);
  my ($smtp_server, $smtp_server_port, @smtp_server_options);
  my ($smtp_authuser, $smtp_encryption, $smtp_ssl_cert_path);
@@@ -213,7 -203,6 +213,7 @@@ my ($validate, $confirm)
  my (@suppress_cc);
  my ($auto_8bit_encoding);
  my ($compose_encoding);
 +my ($target_xfer_encoding);
  
  my ($debug_net_smtp) = 0;             # Net::SMTP, see send_message()
  
@@@ -222,13 -211,10 +222,13 @@@ my %config_bool_settings = 
      "chainreplyto" => [\$chain_reply_to, 0],
      "suppressfrom" => [\$suppress_from, undef],
      "signedoffbycc" => [\$signed_off_by_cc, undef],
 +    "cccover" => [\$cover_cc, undef],
 +    "tocover" => [\$cover_to, undef],
      "signedoffcc" => [\$signed_off_by_cc, undef],      # Deprecated
      "validate" => [\$validate, 1],
      "multiedit" => [\$multiedit, undef],
 -    "annotate" => [\$annotate, undef]
 +    "annotate" => [\$annotate, undef],
 +    "xmailer" => [\$use_xmailer, 1]
  );
  
  my %config_settings = (
      "from" => \$sender,
      "assume8bitencoding" => \$auto_8bit_encoding,
      "composeencoding" => \$compose_encoding,
 +    "transferencoding" => \$target_xfer_encoding,
  );
  
  my %config_path_settings = (
@@@ -317,19 -302,15 +317,19 @@@ my $rc = GetOptions("h" => \$help
                    "suppress-from!" => \$suppress_from,
                    "suppress-cc=s" => \@suppress_cc,
                    "signed-off-cc|signed-off-by-cc!" => \$signed_off_by_cc,
 +                  "cc-cover|cc-cover!" => \$cover_cc,
 +                  "to-cover|to-cover!" => \$cover_to,
                    "confirm=s" => \$confirm,
                    "dry-run" => \$dry_run,
                    "envelope-sender=s" => \$envelope_sender,
                    "thread!" => \$thread,
                    "validate!" => \$validate,
 +                  "transfer-encoding=s" => \$target_xfer_encoding,
                    "format-patch!" => \$format_patch,
                    "8bit-encoding=s" => \$auto_8bit_encoding,
                    "compose-encoding=s" => \$compose_encoding,
                    "force" => \$force,
 +                  "xmailer!" => \$use_xmailer,
         );
  
  usage() if $help;
@@@ -752,6 -733,7 +752,7 @@@ if (!defined $auto_8bit_encoding && sca
                print "    $f\n";
        }
        $auto_8bit_encoding = ask("Which 8bit encoding should I declare [UTF-8]? ",
+                                 valid_re => qr/.{4}/, confirm_only => 1,
                                  default => "UTF-8");
  }
  
@@@ -925,26 -907,15 +926,26 @@@ $time = time - scalar $#files
  
  sub unquote_rfc2047 {
        local ($_) = @_;
 -      my $encoding;
 -      s{=\?([^?]+)\?q\?(.*?)\?=}{
 -              $encoding = $1;
 -              my $e = $2;
 -              $e =~ s/_/ /g;
 -              $e =~ s/=([0-9A-F]{2})/chr(hex($1))/eg;
 -              $e;
 +      my $charset;
 +      my $sep = qr/[ \t]+/;
 +      s{$re_encoded_word(?:$sep$re_encoded_word)*}{
 +              my @words = split $sep, $&;
 +              foreach (@words) {
 +                      m/$re_encoded_word/;
 +                      $charset = $1;
 +                      my $encoding = $2;
 +                      my $text = $3;
 +                      if ($encoding eq 'q' || $encoding eq 'Q') {
 +                              $_ = $text;
 +                              s/_/ /g;
 +                              s/=([0-9A-F]{2})/chr(hex($1))/egi;
 +                      } else {
 +                              # other encodings not supported yet
 +                      }
 +              }
 +              join '', @words;
        }eg;
 -      return wantarray ? ($_, $encoding) : $_;
 +      return wantarray ? ($_, $charset) : $_;
  }
  
  sub quote_rfc2047 {
  
  sub is_rfc2047_quoted {
        my $s = shift;
 -      my $token = qr/[^][()<>@,;:"\/?.= \000-\037\177-\377]+/;
 -      my $encoded_text = qr/[!->@-~]+/;
        length($s) <= 75 &&
 -      $s =~ m/^(?:"[[:ascii:]]*"|=\?$token\?$token\?$encoded_text\?=)$/o;
 +      $s =~ m/^(?:"[[:ascii:]]*"|$re_encoded_word)$/o;
  }
  
  sub subject_needs_rfc2047_quoting {
@@@ -1141,18 -1114,6 +1142,18 @@@ sub ssl_verify_params 
        }
  }
  
 +sub file_name_is_absolute {
 +      my ($path) = @_;
 +
 +      # msys does not grok DOS drive-prefixes
 +      if ($^O eq 'msys') {
 +              return ($path =~ m#^/# || $path =~ m#^[a-zA-Z]\:#)
 +      }
 +
 +      require File::Spec::Functions;
 +      return File::Spec::Functions::file_name_is_absolute($path);
 +}
 +
  # Returns 1 if the message was sent, and 0 otherwise.
  # In actuality, the whole program dies when there
  # is an error sending a message.
@@@ -1184,10 -1145,8 +1185,10 @@@ To: $to${ccline
  Subject: $subject
  Date: $date
  Message-Id: $message_id
 -X-Mailer: git-send-email $gitversion
  ";
 +      if ($use_xmailer) {
 +              $header .= "X-Mailer: git-send-email $gitversion\n";
 +      }
        if ($reply_to) {
  
                $header .= "In-Reply-To: $reply_to\n";
  
        if ($dry_run) {
                # We don't want to send the email.
 -      } elsif ($smtp_server =~ m#^/#) {
 +      } elsif (file_name_is_absolute($smtp_server)) {
                my $pid = open my $sm, '|-';
                defined $pid or die $!;
                if (!$pid) {
                printf (($dry_run ? "Dry-" : "")."Sent %s\n", $subject);
        } else {
                print (($dry_run ? "Dry-" : "")."OK. Log says:\n");
 -              if ($smtp_server !~ m#^/#) {
 +              if (!file_name_is_absolute($smtp_server)) {
                        print "Server: $smtp_server\n";
                        print "MAIL FROM:<$raw_from>\n";
                        foreach my $entry (@recipients) {
@@@ -1347,8 -1306,6 +1348,8 @@@ foreach my $t (@files) 
        my $author_encoding;
        my $has_content_type;
        my $body_encoding;
 +      my $xfer_encoding;
 +      my $has_mime_version;
        @to = ();
        @cc = ();
        @xh = ();
                                }
                                push @xh, $_;
                        }
 +                      elsif (/^MIME-Version/i) {
 +                              $has_mime_version = 1;
 +                              push @xh, $_;
 +                      }
                        elsif (/^Message-Id: (.*)/i) {
                                $message_id = $1;
                        }
 +                      elsif (/^Content-Transfer-Encoding: (.*)/i) {
 +                              $xfer_encoding = $1 if not defined $xfer_encoding;
 +                      }
                        elsif (!/^Date:\s/i && /^[-A-Za-z]+:\s+\S/) {
                                push @xh, $_;
                        }
                if defined $cc_cmd && !$suppress_cc{'cccmd'};
  
        if ($broken_encoding{$t} && !$has_content_type) {
 +              $xfer_encoding = '8bit' if not defined $xfer_encoding;
                $has_content_type = 1;
 -              push @xh, "MIME-Version: 1.0",
 -                      "Content-Type: text/plain; charset=$auto_8bit_encoding",
 -                      "Content-Transfer-Encoding: 8bit";
 +              push @xh, "Content-Type: text/plain; charset=$auto_8bit_encoding";
                $body_encoding = $auto_8bit_encoding;
        }
  
                                }
                        }
                        else {
 +                              $xfer_encoding = '8bit' if not defined $xfer_encoding;
                                $has_content_type = 1;
                                push @xh,
 -                                'MIME-Version: 1.0',
 -                                "Content-Type: text/plain; charset=$author_encoding",
 -                                'Content-Transfer-Encoding: 8bit';
 +                                "Content-Type: text/plain; charset=$author_encoding";
                        }
                }
        }
 +      if (defined $target_xfer_encoding) {
 +              $xfer_encoding = '8bit' if not defined $xfer_encoding;
 +              $message = apply_transfer_encoding(
 +                      $message, $xfer_encoding, $target_xfer_encoding);
 +              $xfer_encoding = $target_xfer_encoding;
 +      }
 +      if (defined $xfer_encoding) {
 +              push @xh, "Content-Transfer-Encoding: $xfer_encoding";
 +      }
 +      if (defined $xfer_encoding or $has_content_type) {
 +              unshift @xh, 'MIME-Version: 1.0' unless $has_mime_version;
 +      }
  
        $needs_confirm = (
                $confirm eq "always" or
        @to = (@initial_to, @to);
        @cc = (@initial_cc, @cc);
  
 +      if ($message_num == 1) {
 +              if (defined $cover_cc and $cover_cc) {
 +                      @initial_cc = @cc;
 +              }
 +              if (defined $cover_to and $cover_to) {
 +                      @initial_to = @to;
 +              }
 +      }
 +
        my $message_was_sent = send_message();
  
        # set up for the next message
@@@ -1585,32 -1516,6 +1586,32 @@@ sub cleanup_compose_files 
  
  $smtp->quit if $smtp;
  
 +sub apply_transfer_encoding {
 +      my $message = shift;
 +      my $from = shift;
 +      my $to = shift;
 +
 +      return $message if ($from eq $to and $from ne '7bit');
 +
 +      require MIME::QuotedPrint;
 +      require MIME::Base64;
 +
 +      $message = MIME::QuotedPrint::decode($message)
 +              if ($from eq 'quoted-printable');
 +      $message = MIME::Base64::decode($message)
 +              if ($from eq 'base64');
 +
 +      die "cannot send message as 7bit"
 +              if ($to eq '7bit' and $message =~ /[^[:ascii:]]/);
 +      return $message
 +              if ($to eq '7bit' or $to eq '8bit');
 +      return MIME::QuotedPrint::encode($message, "\n", 0)
 +              if ($to eq 'quoted-printable');
 +      return MIME::Base64::encode($message, "\n")
 +              if ($to eq 'base64');
 +      die "invalid transfer encoding";
 +}
 +
  sub unique_email_list {
        my %seen;
        my @emails;