From 77cff387d9b0edd292d87cc21d8e43fbb69b78eb Mon Sep 17 00:00:00 2001 From: Tomasz Pala Date: Mon, 2 Apr 2018 10:04:00 +0200 Subject: [PATCH] run-mailcap updated from upstream (Debian mime-support) 3.48 to 3.60 - security fixes plus perl 5.25+ compliance --- mailcap.spec | 10 +- run-mailcap | 229 +++++++++++++++++++++------------------ run-mailcap-mktemp.patch | 16 +++ 3 files changed, 146 insertions(+), 109 deletions(-) create mode 100644 run-mailcap-mktemp.patch diff --git a/mailcap.spec b/mailcap.spec index be4c359..1e822a9 100644 --- a/mailcap.spec +++ b/mailcap.spec @@ -16,16 +16,18 @@ Summary(pt_BR.UTF-8): Define aplicações auxiliares multimídia para vários pr Summary(tr.UTF-8): Çeşitli programlar için çokluortam yardımcı uygulamaları tanımlar Name: mailcap Version: %{ver} -Release: 2 +Release: 3 License: Public Domain Group: Base Source0: https://fedorahosted.org/released/mailcap/%{name}-%{fcver}.tar.xz # Source0-md5: d8d66b3a458f0da327a7c4edfff911a1 Source1: %{name} Source2: %{name}.4 +# https://anonscm.debian.org/git/collab-maint/mime-support.git/log/run-mailcap Source3: run-%{name} Source4: run-%{name}.man Patch0: mime.types.patch +Patch1: run-mailcap-mktemp.patch URL: http://git.fedorahosted.org/git/?p=mailcap.git BuildRequires: rpm >= 4.4.9-56 BuildRequires: tar >= 1:1.22 @@ -109,7 +111,8 @@ paketini kullanamalarına olanak sağlar (zgv kurulmuş olmalı). %prep %setup -q -n %{name}-%{fcver} %patch0 -p1 -cp -a %{SOURCE1} mailcap +cp -a %{SOURCE1} %{SOURCE3} . +%patch1 %if "%{pld_release}" == "ac" %{__sed} -i -e 's,/usr/bin/xterm,/usr/X11R6/bin/xterm,g' mailcap @@ -123,10 +126,11 @@ cp -a %{SOURCE1} mailcap %install rm -rf $RPM_BUILD_ROOT install -d $RPM_BUILD_ROOT{%{_sysconfdir},%{_mandir}/man{1,4},%{_bindir}} + cp -p mailcap mime.types $RPM_BUILD_ROOT%{_sysconfdir} cp -p %{SOURCE2} $RPM_BUILD_ROOT%{_mandir}/man4 cp -p %{SOURCE4} $RPM_BUILD_ROOT%{_mandir}/man1/run-%{name}.1 -install -p %{SOURCE3} $RPM_BUILD_ROOT%{_bindir} +cp -p run-mailcap $RPM_BUILD_ROOT%{_bindir} %clean rm -rf $RPM_BUILD_ROOT diff --git a/run-mailcap b/run-mailcap index 851cd13..8ef4665 100644 --- a/run-mailcap +++ b/run-mailcap @@ -9,10 +9,13 @@ # ############################################################################### +use Encode qw(decode); +use I18N::Langinfo qw(langinfo CODESET); +use File::Spec; -$debug=0; +$debug=($ENV{RUN_MAILCAP_DEBUG} || 0); $norun=0; -$pager=0; +$nopager=0; $etcmimetyp="/etc/mime.types"; $shrmimetyp="/usr/share/etc/mime.types"; $locmimetyp="/usr/local/etc/mime.types"; @@ -24,14 +27,6 @@ $quotedprct=chr(254); $retcode=0; -%patterntypes = -( - '(^|/)crontab[^/]+$' => 'text/x-crontab', #' - '/man\d*/' => 'application/x-troff-man', #' - '\.\d[^\.]*$' => 'application/x-troff-man', #' -); - - sub Usage { my($error) = @_; @@ -41,16 +36,16 @@ sub Usage { print STDERR "Options:\n"; print STDERR " action specify what action to do on these files (default=view)\n"; print STDERR " debug be verbose about what's going on\n"; - print STDERR " pager ignore any \"copiousoutput\" directives and use a \"pager\"\n"; + print STDERR " nopager ignore any \"copiousoutput\" directives and never use a \"pager\"\n"; print STDERR " norun just print but don't execute the command (useful with --debug)\n"; print STDERR "\n"; print STDERR "Mime-Type:\n"; print STDERR " any standard mime type designation in the form / -- if\n"; print STDERR " not specified, it will be determined from the filename extension\n\n"; print STDERR "Encoding:\n"; - print STDERR " how the file (and type) has been encoded (only \"gzip\", \"bzip\", \"bzip2\"\n"; - print STDERR " and \"compress\" are supported) -- if not specified, it will be determined\n"; - print STDERR " from the filename extension\n\n"; + print STDERR " how the file (and type) has been encoded (only \"gzip\", \"bzip2,\"\n"; + print STDERR " \"xz\" and \"compress\" are supported) -- if not specified, it will be\n"; + print STDERR " determined from the filename extension\n\n"; exit ($error ? 1 : 0); } @@ -62,8 +57,8 @@ sub EncodingForFile { my $encoding; if ($file =~ m/\.gz$/) { $encoding = "gzip"; } - if ($file =~ m/\.bz$/) { $encoding = "bzip"; } if ($file =~ m/\.bz2$/) { $encoding = "bzip2"; } + if ($file =~ m/\.xz$/) { $encoding = "xz"; } if ($file =~ m/\.Z$/) { $encoding = "compress"; } print STDERR " - file \"$file\" has encoding \"$encoding\"\n" if $debug && $encoding; @@ -76,10 +71,14 @@ sub EncodingForFile { sub ReadMimetypes { my($file) = @_; - return unless -r $file; - print STDERR " - Reading mime.types file \"$file\"...\n" if $debug; - open(MIMETYPES,"<$file") || die "Error: could not read \"$file\" -- $!\n"; + unless (open(MIMETYPES,'<',$file)) { + # Quietly ignore an unreadable file, perhaps non-existent, perhaps + # permission denied. + print STDERR " could not read \"$file\" -- $!\n" if $debug; + return; + } + while () { chomp; s/\#.*$//; @@ -101,10 +100,14 @@ sub ReadMailcap { my($file) = @_; my $line = ""; - return unless -r $file; - print STDERR " - Reading mailcap file \"$file\"...\n" if $debug; - open(MAILCAP,"<$file") || die "Error: could not read \"$file\" -- $!\n"; + unless (open(MAILCAP,'<',$file)) { + # Quietly ignore an unreadable file, perhaps non-existent, perhaps + # permission denied. + print STDERR " could not read \"$file\" -- $!\n" if $debug; + return; + } + while () { chomp; s/^\s+// if $line; @@ -138,10 +141,9 @@ sub TempFile { # $tmpfile = POSIX::tmpnam($name); # unlink($tmpfile); - $cmd = "mktemp -t "; # -t is depreciated, but --tmpdir would not be handled by older mktemp - $cmd .= "$head" if $head; - $cmd .= ".$tail" if $tail; - $cmd .= "XXXXXX"; + $cmd = "tempfile --mode=600"; + $cmd .= " --prefix $head" if $head; + $cmd .= " --suffix $tail" if $tail; $tmpfile = `$cmd`; chomp($tmpfile); @@ -196,18 +198,18 @@ sub DecodeFile { } else { $res = system "gzip -dc \Q$efile\E >\Q$tmpfile\E"; } - } elsif ($encoding eq "bzip") { - if ($efile eq '-') { - $res = system "bzip -d >\Q$tmpfile\E"; - } else { - $res = system "bzip -dc <\Q$efile\E >\Q$tmpfile\E"; - } } elsif ($encoding eq "bzip2") { if ($efile eq '-') { $res = system "bzip2 -d >\Q$tmpfile\E"; } else { $res = system "bzip2 -dc <\Q$efile\E >\Q$tmpfile\E"; } + } elsif ($encoding eq "xz") { + if ($efile eq '-') { + $res = system "xz -d >\Q$tmpfile\E"; + } else { + $res = system "xz -dc <\Q$efile\E >\Q$tmpfile\E"; + } } elsif ($encoding eq "compress") { if ($efile eq '-') { $res = system "uncompress >\Q$tmpfile\E"; @@ -244,6 +246,12 @@ sub EncodeFile { } else { $res = system "gzip -c \Q$dfile\E >\Q$efile\E"; } + } elsif ($encoding eq "xz") { + if ($efile eq '-') { + $res = system "xz < \Q$dfile\E"; + } else { + $res = system "xz < \Q$dfile\E >\Q$efile\E"; + } } elsif ($encoding eq "compress") { if ($efile eq '-') { $res = system "compress <\Q$dfile\E"; @@ -267,52 +275,36 @@ sub EncodeFile { sub ExtensionMimetype { - my($ext) = @_; + my($file) = @_; + my($ext) = ($file =~ m!\.([^/\.]+)$!); my($typ); - - unless ($donemimetypes) { - ReadMimetypes($usrmimetyp); - ReadMimetypes($locmimetyp); - ReadMimetypes($shrmimetyp); - ReadMimetypes($etcmimetyp); - $donemimetypes = 1; + if ($ext) { + unless ($donemimetypes) { + ReadMimetypes($usrmimetyp); + ReadMimetypes($locmimetyp); + ReadMimetypes($shrmimetyp); + ReadMimetypes($etcmimetyp); + $donemimetypes = 1; + } + $typ = $mimetypes{lc($ext)}; + print STDERR " - extension \"$ext\" maps to mime-type \"$typ\"\n" if $debug; } - - $typ = $mimetypes{lc($ext)}; - - print STDERR " - extension \"$ext\" maps to mime-type \"$typ\"\n" if $debug; return $typ; } -sub PatternMimetype { +sub MagicMimetype { my($file) = @_; - my($key,$val); + my($typ); - while (($key,$val) = each %patterntypes) { - if ($file =~ m!$key!i) { - print STDERR " - file \"$file\" maps to mime-type \"$val\"\n" if $debug; - return $val; - } + if (`which file`) { + open(READER, "-|", "file", "-b", "--mime-type", "-e", "tokens", "-L", "-z", $file); + $typ = ; + chomp $typ; + print STDERR " - file command returned mime-type \"$typ\"\n" if $debug; } - - print STDERR " - file \"$file\" does not conform to any known pattern\n" if $debug; - return; -} - - - -sub FileMimetype { - my($file) = @_; - my($ext) = ($file =~ m!\.([^/\.]+)$!); - - my $type; - - $type = ExtensionMimetype($ext) if $ext; - $type = PatternMimetype($file) unless $type; - - return $type; + return $typ; } @@ -345,10 +337,11 @@ foreach (@ARGV) { if ($code) { my $efile = $file; $efile =~ s/\.[^\.]+$//; - $type = FileMimetype($efile); + $type = ExtensionMimetype($efile); } else { - $type = FileMimetype($file); + $type = ExtensionMimetype($file); } + $type = MagicMimetype($file) unless $type; if ($type) { push @files,"${type}:${code}:${file}"; } else { @@ -358,16 +351,19 @@ foreach (@ARGV) { } } +# Pass --debug to sub-calls to this program. +$ENV{RUN_MAILCAP_DEBUG} = 1 if $debug; + unless ($action) { - if ($0 =~ m!(^|/)view$!) { $action="view"; } - elsif ($0 =~ m!(^|/)see$!) { $action="view"; } - elsif ($0 =~ m!(^|/)cat$!) { $action="cat"; } - elsif ($0 =~ m!(^|/)edit$!) { $action="edit"; } - elsif ($0 =~ m!(^|/)change$!) { $action="edit"; } - elsif ($0 =~ m!(^|/)compose$!) { $action="compose";} - elsif ($0 =~ m!(^|/)print$!) { $action="print"; } - elsif ($0 =~ m!(^|/)create$!) { $action="compose";} - else { $action="view"; } + if ($0 =~ m!(^|/)(mime-)?view$!) { $action="view"; } + elsif ($0 =~ m!(^|/)(mime-)?see$!) { $action="view"; } + elsif ($0 =~ m!(^|/)(mime-)?cat$!) { $action="cat"; } + elsif ($0 =~ m!(^|/)(mime-)?edit$!) { $action="edit"; } + elsif ($0 =~ m!(^|/)(mime-)?change$!) { $action="edit"; } + elsif ($0 =~ m!(^|/)(mime-)?compose$!) { $action="compose";} + elsif ($0 =~ m!(^|/)(mime-)?print$!) { $action="print"; } + elsif ($0 =~ m!(^|/)(mime-)?create$!) { $action="compose";} + else { $action="view"; } } @@ -429,6 +425,7 @@ foreach (@files) { my $done=0; my $fail=0; + my $needsterminal; foreach $match (@matches) { my $comm; print STDERR " - checking mailcap entry \"$match\"\n" if $debug; @@ -447,15 +444,21 @@ foreach (@files) { } my($tmpfile,$tmplink); - if ($action ne 'print' && $match =~ m/;\s*needsterminal\s*($|;)/ && ! -t STDOUT) { - if ($ENV{DISPLAY}) { - $comm = "$xtermprgrm -T '$file ($type)' -e $0 --action=$action '${type}:%s'"; + if ($action ne 'print' && $match =~ m/;\s*needsterminal\s*($|;)/) { + $needsterminal = 1; + if (-t STDOUT) { + print STDERR " - needsterminal is satisfied by stdout\n" if $debug; } else { - print STDERR " - no terminal available for rule (needsterminal)\n" if $debug; - $fail++; - next; + if ($ENV{DISPLAY}) { + $comm = "$xtermprgrm -T '$file ($type)' -e $0 --action=$action '${type}:%s'"; + } else { + print STDERR " - no terminal available for rule (needsterminal)\n" if $debug; + $fail++; + next; + } } - } elsif ($action eq 'view' && $pager && $match =~ m/;\s*copiousoutput\s*($|;)/ && $type ne 'text/plain') { + + } elsif ($action eq 'view' && !$nopager && $match =~ m/;\s*copiousoutput\s*($|;)/ && $type ne 'text/plain') { $comm .= " | $0 --action=$action text/plain:-"; } @@ -472,27 +475,22 @@ foreach (@files) { } if ($file ne "-") { - if ($comm =~ m/[^%]%s/) { - if ($file =~ m![^ a-z0-9,.:/@%^+=_-]!i) { - $match =~ m/nametemplate=(.*?)\s*($|;)/; - my $prefix = $1; - my $linked = 0; - while (!$linked) { - $tmplink = TempFile($prefix); - unlink($tmplink); - if ($file =~ m!^/!) { - $linked = symlink($file,$tmplink); - } else { - my $pwd = `/bin/pwd`; - chomp($pwd); - $linked = symlink("$pwd/$file",$tmplink); - } - } - print STDERR " - filename contains shell meta-characters; aliased to '$tmplink'\n" if $debug; - $comm =~ s/([^%])%s/$1$tmplink/g; - } else { - $comm =~ s/([^%])%s/$1"$file"/g; + # Resolve file name to an absolute path + $file = File::Spec->rel2abs($file); + if (decode(langinfo(CODESET()), $file) =~ m![^[:alnum:],.:/@%^+=_-]!i) { + $match =~ m/nametemplate=(.*?)\s*($|;)/; + my $prefix = $1; + my $linked = 0; + while (!$linked) { + $tmplink = TempFile($prefix); + unlink($tmplink); + $linked = symlink($file,$tmplink); } + $file = $tmplink; + print STDERR " - filename contains shell meta-characters; aliased to '$tmplink'\n" if $debug; + } + if ($comm =~ m/[^%]%s/) { + $comm =~ s/([^%])%s/$1$file/g; } else { if ($comm =~ m/\|/) { $comm =~ s/\|/<\Q$file\E \|/; @@ -507,6 +505,25 @@ foreach (@files) { if ($comm =~ m/[^%]%s/) { $tmpfile = SaveStdin($match); $comm =~ s/([^%])%s/$1$tmpfile/g; + + # If needsterminal then redirect stdin to the tty which is + # on stdout, rather than leaving it as the input data stream + # which has now been read through to EOF. + # + # Some programs such as "more" and "less" already use + # /dev/tty rather than stdin. But "vim" on non-tty stdin + # gives a warning message and then leaves the tty in raw + # mode on exit. Or "nvi" refuses to run at all unless both + # stdin and stdout are the tty. + # + # RFC 1524 is silent on exactly what a program with + # "needsterminal" should expect, but it seems sensible to + # arrange that both stdin and stdout are the terminal for + # "needsterminal" with "%s". + # + if ($needsterminal) { + $comm .= ' <&1'; + } } else { # no name means same as "-"... read from stdin } @@ -514,7 +531,7 @@ foreach (@files) { $comm =~ s!([^%])%t!$1$type!g; $comm =~ s!([^%])%F!$1!g; - $comm =~ s!%{(.*?)}!$_="'$ENV{$1}'";s/\`//g;s/\'\'//g;$_!ge; + $comm =~ s!%\{(.*?)}!$_="'$ENV{$1}'";s/\`//g;s/\'\'//g;$_!ge; $comm =~ s!\\(.)!$1!g; $comm =~ s!\'\'!\'!g; $comm =~ s!$quotedsemi!;!go; diff --git a/run-mailcap-mktemp.patch b/run-mailcap-mktemp.patch new file mode 100644 index 0000000..4205313 --- /dev/null +++ b/run-mailcap-mktemp.patch @@ -0,0 +1,16 @@ +--- run-mailcap 2018-04-02 09:44:40.000000000 +0200 ++++ run-mailcap 2018-04-02 09:51:19.000000000 +0200 +@@ -141,9 +141,10 @@ + # $tmpfile = POSIX::tmpnam($name); + # unlink($tmpfile); + +- $cmd = "tempfile --mode=600"; +- $cmd .= " --prefix $head" if $head; +- $cmd .= " --suffix $tail" if $tail; ++ $cmd = "mktemp -t "; # -t is depreciated, but --tmpdir would not be handled by older mktemp ++ $cmd .= "$head" if $head; ++ $cmd .= ".$tail" if $tail; ++ $cmd .= "XXXXXX"; + + $tmpfile = `$cmd`; + chomp($tmpfile); -- 2.44.0