summaryrefslogtreecommitdiff
path: root/office/texlive/epstopdf/epstopdf.pl
diff options
context:
space:
mode:
Diffstat (limited to 'office/texlive/epstopdf/epstopdf.pl')
-rw-r--r--office/texlive/epstopdf/epstopdf.pl202
1 files changed, 114 insertions, 88 deletions
diff --git a/office/texlive/epstopdf/epstopdf.pl b/office/texlive/epstopdf/epstopdf.pl
index a312a9b7f9..9299839c41 100644
--- a/office/texlive/epstopdf/epstopdf.pl
+++ b/office/texlive/epstopdf/epstopdf.pl
@@ -2,7 +2,7 @@ eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' && eval 'exec perl -S $0 $
if 0;
use strict;
-# $Id: epstopdf.pl 16244 2009-11-30 01:36:08Z karl $
+# $Id: epstopdf.pl 18319 2010-05-17 16:34:21Z karl $
# (Copyright lines below.)
#
# Redistribution and use in source and binary forms, with or without
@@ -39,14 +39,30 @@ use strict;
# c) the result is piped to Ghostscript and a PDF version written.
#
# It needs a Level 2 PS interpreter.
-# If the bounding box is not right, of course, there will be problems.
+# If the input bounding box is not right, of course there will be problems.
#
-# One thing not allowed for is the case of
+# One thing not allowed for: the case of
# "%%BoundingBox: (atend)" when input is not seekable (e.g., from a pipe),
-# which is more complicated.
#
# emacs-page
# History
+# 2010/05/09 v2.16 (Karl Berry)
+# * make --nogs dump edited PostScript to stdout by default
+# (report from Reinhard Kotucha).
+# 2010/03/19 v2.15 (Karl Berry)
+# * let --outfile override --filter again.
+# * recognize MSWin64 as well as MSWin32, just in case.
+# 2010/03/08 v2.14 (Manuel P\'egouri\'e-Gonnard)
+# * In restricted mode, forbid --gscmd (all platforms) and call GS with full
+# path relative to self location (Windows).
+# 2010/02/26 v2.13 (Karl Berry)
+# * New release.
+# 2010/02/23 (Manuel P\'egouri\'e-Gonnard)
+# * Use kpsewhich for filename validation in restricted mode, both input and
+# output. Requires kpathsea 5.1.0 (TL2010), rejects the name with earlier
+# versions of kpsewhich.
+# * Call external programs with full path on win32 in order to avoid obvious
+# attacks with rogue versions of these programs in the current directory.
# 2009/11/27 v2.12 (Karl Berry)
# * Make --filter work again
# 2009/11/25 (Manuel P\'egouri\'e-Gonnard)
@@ -133,9 +149,9 @@ use strict;
### program identification
my $program = "epstopdf";
-my $ident = '($Id: epstopdf.pl 16244 2009-11-30 01:36:08Z karl $) 2.12';
+my $ident = '($Id: epstopdf.pl 18319 2010-05-17 16:34:21Z karl $) 2.16';
my $copyright = <<END_COPYRIGHT ;
-Copyright 2009 Karl Berry et al.
+Copyright 2009-2010 Karl Berry et al.
Copyright 2002-2009 Gerben Wierda et al.
Copyright 1998-2001 Sebastian Rahtz et al.
License RBSD: Revised BSD <http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5>
@@ -144,26 +160,28 @@ There is NO WARRANTY, to the extent permitted by law.
END_COPYRIGHT
my $title = "$program $ident\n";
+my $on_windows = $^O =~ /^MSWin/;
+my $on_windows_or_cygwin = $on_windows || $^O eq "cygwin";
+
### ghostscript command name
-my $GS = "gs";
-$GS = "gswin32c" if $^O eq 'MSWin32';
+my $GS = $on_windows ? "gswin32c" : "gs";
### restricted mode
my $restricted = 0;
$restricted = 1 if $0 =~ /repstopdf/;
### options
-$::opt_outfile="";
-$::opt_compress=1;
-$::opt_debug=0;
-$::opt_embed=1;
-$::opt_exact=0;
-$::opt_filter=0;
-$::opt_gs=1;
-$::opt_hires=0;
-$::opt_gscmd="";
-$::opt_res=0;
-$::opt_autorotate="None";
+$::opt_autorotate = "None";
+$::opt_compress = 1;
+$::opt_debug = 0;
+$::opt_embed = 1;
+$::opt_exact = 0;
+$::opt_filter = 0;
+$::opt_gs = 1;
+$::opt_gscmd = "";
+$::opt_hires = 0;
+$::opt_outfile = "";
+$::opt_res = 0;
### usage
my @bool = ("false", "true");
@@ -193,7 +211,7 @@ Options:
For EPS files, PageByPage is equivalent to All
--restricted use restricted mode (default: $bool[$restricted])
-Examples for producing 'test.pdf':
+Examples producing test.pdf:
* $program test.eps
* produce postscript | $program --filter >test.pdf
* produce postscript | $program -f -d -o=test.pdf
@@ -211,40 +229,57 @@ END_OF_USAGE
### process options
use Getopt::Long;
GetOptions (
- "help",
- "version",
- "outfile=s", # \ref{openout_any}
+ "autorotate=s", # \ref{val_autorotate}
"compress!",
"debug!",
"embed!",
"exact!",
"filter!",
"gs!",
- "hires!",
"gscmd=s", # \ref{val_gscmd}
- "res=i", # validated by Getopt ('i' specifier)
- "autorotate=s", # \ref{val_autorotate}
+ "help",
+ "hires!",
+ "outfile=s", # \ref{openout_any}
+ "res=i", # validated by getopt ('i' specifier)
"restricted",
+ "version",
) or die $usage;
### help functions
-sub debug {
- print STDERR "* @_\n" if $::opt_debug;
-}
-sub warning {
- print STDERR "==> Warning: @_\n";
-}
-sub error {
- die "$title!!! Error: @_\n";
-}
-sub errorUsage {
- die "$usage\n!!! Error: @_\n";
-}
+sub debug { print STDERR "* @_\n" if $::opt_debug; }
+sub warning { print STDERR "==> Warning: @_\n"; }
+sub error { die "$title!!! Error: @_\n"; }
+sub errorUsage { die "Error: @_ (try --help for more information)\n"; }
### restricted option
$restricted = 1 if $::opt_restricted;
debug "Restricted mode activated" if $restricted;
+### safer external commands for Windows in restricted mode
+my $kpsewhich = 'kpsewhich';
+if ($restricted && $on_windows) {
+ use File::Basename;
+ my $mydirname = dirname $0;
+ # $mydirname is the location of the Perl script
+ $kpsewhich = "$mydirname/../../../bin/win32/$kpsewhich";
+ $GS = "$mydirname/../../../tlpkg/tlgs/bin/$GS";
+}
+debug "kpsewhich command: $kpsewhich";
+
+### check if a name is "safe" according to kpse's open(in|out)_any
+# return true if name is ok, false otherwise
+sub safe_name
+{
+ my ($mode, $name) = @_;
+ my $option = "";
+ $option = '-safe-in-name' if $mode eq 'in';
+ $option = '-safe-out-name' if $mode eq 'out';
+ error "Unknown check mode in safe_name(): $mode" unless $option;
+ my @args = ($kpsewhich, '-progname', 'repstopdf', $option, $name);
+ my $bad = system {$args[0]} @args;
+ return ! $bad;
+}
+
### help, version options.
if ($::opt_help) {
print $usage;
@@ -257,29 +292,28 @@ if ($::opt_version) {
exit (0);
}
-### get input filename
+### get input filename (\ref{openin_any} for validation)
my $InputFilename = "";
if ($::opt_filter) {
@ARGV == 0 or
- die errorUsage "Input file cannot be used with filter option";
+ errorUsage "Input file cannot be used with filter option";
debug "Filtering: will read standard input";
} else {
- @ARGV > 0 or die errorUsage "Input filename missing";
- @ARGV < 2 or die errorUsage "Unknown option or too many input files";
+ @ARGV > 0 or errorUsage "Input filename missing";
+ @ARGV < 2 or errorUsage "Unknown option or too many input files";
$InputFilename = $ARGV[0];
#-r $InputFilename or error "\"$InputFilename\" not readable";
debug "Input filename:", $InputFilename;
}
+### emacs-page
### option gscmd
if ($::opt_gscmd) {
- debug "Switching from $GS to $::opt_gscmd";
- $GS = $::opt_gscmd;
- # validate GS \label{val_gscmd}
- if ($restricted) {
- $GS =~ /^(gs|mgs|gswin32c|gs386|gsos2)\z/
- or $GS =~ /^gs[\-_]?(\d|\d[\.-_]?\d\d)c?\z/
- or die error "Value of gscmd '$GS' not allowed in restricted mode.";
+ if ($restricted) { # \label{val_gscmd}
+ error "Option forbidden in restricted mode: --gscmd";
+ } else {
+ debug "Switching from $GS to $::opt_gscmd";
+ $GS = $::opt_gscmd;
}
}
@@ -289,24 +323,24 @@ push @GS, qw(-q -dNOPAUSE -dSAFER -sDEVICE=pdfwrite);
### option outfile
my $OutputFilename = $::opt_outfile;
-if ($OutputFilename eq "") {
+if (! $OutputFilename) {
if ($::opt_gs) {
- $OutputFilename = $InputFilename;
- if (!$::opt_filter) {
- my $ds = ($^O eq "MSWin32" || $^O eq "cygwin") ? '\\/' : '/';
+ if ($::opt_filter) {
+ debug "Filtering: will write standard output";
+ $OutputFilename = "-";
+ } else {
+ # Ghostscript, no filter: replace input extension with .pdf.
+ $OutputFilename = $InputFilename;
+ my $ds = $on_windows_or_cygwin ? '\\/' : '/';
$OutputFilename =~ s/\.[^\.$ds]*$//;
$OutputFilename .= ".pdf";
}
} else {
- $OutputFilename = "-"; # no ghostscript, write to standard output
+ debug "No Ghostscript: will write standard output";
+ $OutputFilename = "-";
}
}
-if ($::opt_filter) {
- debug "Filtering: will write standard output";
- $OutputFilename = "-";
-} else {
- debug "Output filename:", $OutputFilename;
-}
+debug "Output filename:", $OutputFilename;
push @GS, "-sOutputFile=$OutputFilename";
### options compress, embed, res, autorotate
@@ -321,7 +355,7 @@ $rotmsg = $::opt_autorotate ? $::opt_autorotate : "[use gs default]";
error "Invalid value for autorotate: '$::opt_autorotate' "
. "(use 'All', 'None' or 'PageByPage')."
if ($::opt_autorotate and
- not $::opt_autorotate =~ /^(None|All|PageByPage)\z/);
+ not $::opt_autorotate =~ /^(None|All|PageByPage)$/);
### option BoundingBox types
my $BBName = "%%BoundingBox:";
@@ -331,31 +365,15 @@ $BBName = "%%HiResBoundingBox:" if $::opt_hires;
$BBName = "%%ExactBoundingBox:" if $::opt_exact;
debug "BoundingBox comment:", $BBName;
+### validate input file name in restricted mode \label{openin_any}
+if ($restricted and not $::opt_filter
+ and not safe_name('in', $InputFilename)) {
+ error "Input filename '$InputFilename' not allowed in restricted mode.";
+}
+
### validate output file name in restricted mode \label{openout_any}
-use File::Spec::Functions qw(splitpath file_name_is_absolute);
-if ($restricted) {
- # use the equivalent of openout_any = p
- # (see opennameok() web2c/lib/texmfmp.c)
- # Well, for now, be even more paranoid: don't allow absolute path at all
- my $ok = 1;
- # disallow opening dot-files on Unix
- unless ($^O eq "MSWin32") {
- my ($drive, $path, $basename) = splitpath($OutputFilename);
- $ok = 0 if $basename =~ /^\./;
- }
- # disallow absolute path
- $ok = 0 if file_name_is_absolute($OutputFilename);
- # disallow colon on Windows. It could be used either after a drive
- # (like "a:dir\file") or for an alternate data stream (like
- # "file:ads").
- if ($^O eq "MSWin32" || $^O eq "cygwin") {
- $ok = 0 if $OutputFilename =~ /:/;
- }
- # disallow going to parent directory
- my $ds = ($^O eq "MSWin32" || $^O eq "cygwin") ? qr([\\/]) : qr(/);
- $ok = 0 if $OutputFilename =~ /^\.\.$ds|$ds\.\.$ds/;
- # we passed all tests
- die error "Output filename '$OutputFilename' not allowed in restricted mode." unless $ok;
+if ($restricted and not safe_name('out', $OutputFilename)) {
+ error "Output filename '$OutputFilename' not allowed in restricted mode.";
}
### option gs
@@ -382,7 +400,7 @@ my $tmp_filename; # temporary file for windows
my $OUT; # filehandle for output (GS pipe or temporary file)
use File::Temp 'tempfile';
if ($::opt_gs) {
- unless ($^O eq 'MSWin32' || $^O eq 'cygwin') { # list piped open works
+ if (! $on_windows_or_cygwin) { # list piped open works
push @GS, qw(- -c quit);
debug "Ghostscript pipe:", join(' ', @GS);
open($OUT, '|-', @GS) or error "Cannot open Ghostscript for piped input";
@@ -393,8 +411,14 @@ if ($::opt_gs) {
$outname = $GS;
}
else {
- open($OUT, '>', $OutputFilename) or error "Cannot write \"$OutputFilename\"";
- $outname = $OutputFilename;
+ debug "No Ghostscript: opening $OutputFilename";
+ if ($OutputFilename eq "-") {
+ $OUT = *STDOUT;
+ } else {
+ open($OUT, '>', $OutputFilename)
+ || error ("Cannot write \"$OutputFilename\": $!");
+ $outname = $OutputFilename;
+ }
}
binmode $OUT;
@@ -584,3 +608,5 @@ if ($? & 127) {
warning "BoundingBox not found" unless $BBCorrected;
debug "Done.";
+
+# vim: ts=8 sw=2 expandtab: