1: 2eval 'exec perl -wS $0 ${1+"$@"}' 3 if 0; 4#************************************************************** 5# 6# Licensed to the Apache Software Foundation (ASF) under one 7# or more contributor license agreements. See the NOTICE file 8# distributed with this work for additional information 9# regarding copyright ownership. The ASF licenses this file 10# to you under the Apache License, Version 2.0 (the 11# "License"); you may not use this file except in compliance 12# with the License. You may obtain a copy of the License at 13# 14# http://www.apache.org/licenses/LICENSE-2.0 15# 16# Unless required by applicable law or agreed to in writing, 17# software distributed under the License is distributed on an 18# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19# KIND, either express or implied. See the License for the 20# specific language governing permissions and limitations 21# under the License. 22# 23#************************************************************** 24 25 26 27use strict; 28use Getopt::Long; 29 30my $debug = 0; 31my $max_files = 20; # sign $max_files with one command line 32 33#### globals ##### 34my $myname = ""; 35my $opt_dir = ""; 36my $opt_exclude = ""; # file with a list of not signable dll and exe files 37my $opt_verbose = 0; 38my $opt_help = 0; 39my $opt_log = ""; # for logging 40my $opt_pass = ""; # password for signing 41my $opt_pfxfile = ""; # Personal Information Exchange file 42my $opt_timestamp_url = ""; # timestamp url 43my %exclude_files = (); # list of not signable dll and exe files 44my $signtool = "signtool.exe sign"; 45my @args = (); 46my @files_to_sign = (); 47 48#### main ##### 49$myname = script_id(); 50if ( $#ARGV < 2 ) { 51 usage(); 52 exit(1); 53} 54@args = parse_options(); 55get_exclude_files(); 56@files_to_sign = get_files(\@args); 57if ( $opt_log ) { # logging 58 open(LOG,">$opt_log") || die "Can't open log file $opt_log\n"; 59} 60sign_files(\@files_to_sign); 61close LOG if ($opt_log); # logging 62exit 0; 63 64 65#### subroutines #### 66 67sub script_id 68{ 69 ( my $script_name = $0 ) =~ s/^.*[\\\/]([\w\.]+)$/$1/; 70 71 my $script_rev; 72 my $id_str = ' $Revision$ '; 73 $id_str =~ /Revision:\s+(\S+)\s+\$/ 74 ? ($script_rev = $1) : ($script_rev = "-"); 75# print "\n$script_name -- version: $script_rev\n"; 76 return $script_name; 77} 78 79############################################################################ 80sub parse_options #09.07.2007 08:13 81############################################################################ 82{ 83 # e exclude list file 84 # v verbose 85 my $filelist_filename = undef; 86 my $success = GetOptions('h' => \$opt_help, 87 'd=s' => \$opt_dir, 'e=s'=>\$opt_exclude, 'f=s'=>\$opt_pfxfile, 'l=s'=>\$opt_log, 88 'p=s'=>\$opt_pass,'v'=>\$opt_verbose, 't=s'=>\$opt_timestamp_url, 'i=s'=>\$filelist_filename); 89 if ( !$success || $opt_help ) { 90 usage(); 91 exit(1); 92 } 93 if ( !$opt_exclude || !$opt_pfxfile || !$opt_pass || !$opt_timestamp_url) { 94 print "ERROR: Parameter missing!\n!"; 95 usage(); 96 exit(1); 97 } 98 99 # Read the names of files to sign from the given file. 100 die "no list of files given" unless defined $filelist_filename; 101 open my $in, $filelist_filename; 102 my @filelist = (); 103 while (<$in>) 104 { 105 chomp($_); 106 push @filelist, $_; 107 } 108 return @filelist; 109} ##parse_options 110 111############################################################################ 112sub get_exclude_files #09.07.2007 10:12 113############################################################################ 114{ 115 if ( -e $opt_exclude ) { 116 # get data from cache file 117 open( IN, "<$opt_exclude") || die "Can't open exclude file $opt_exclude\n"; 118 while ( my $line = <IN> ) { 119 chomp($line); 120 $exclude_files{$line} = 1; # fill hash 121 print "$line - $exclude_files{$line}\n" if ($debug); 122 } 123 } else 124 { 125 print_error("Can't open $opt_exclude file!\n"); 126 } 127} ##get_exclude_files 128 129############################################################################ 130sub get_files #10.07.2007 10:19 131############################################################################ 132 { 133 use File::Basename; 134 my $target = shift; 135 my $file_pattern; 136 my $file; 137 my @files = (); 138 print "\n"; 139 foreach $file_pattern ( @$target ) 140 { 141 print "Files: $file_pattern\n"; 142 foreach $file ( glob( $file_pattern ) ) 143 { 144 my $lib = File::Basename::basename $file; 145 if ( ! $exclude_files{$lib} ) { 146 push @files,$file; 147 } 148 else 149 { 150 print "exclude=$lib\n" if ($opt_verbose); 151 } 152 } 153 } 154 print "\n"; 155 return @files; 156} ##get_files 157 158############################################################################ 159sub sign_files #09.07.2007 10:36 160############################################################################ 161{ 162 my $files_to_sign = shift; 163 my $commandline_base = ""; # contains whole stuff without the file name 164 my $file = ""; 165 my $result = ""; 166 167 print_error("Can't open PFX file: $opt_pfxfile\n") if ( ! -e $opt_pfxfile ); 168 print_error("Password is empty\n") if ( !$opt_pass ); 169 if ( $opt_pass =~ /\.exe$/ ) { 170 # get password by tool 171 open(PIPE, "$opt_pass 2>&1 |") || die "Can't open PIPE!\n"; 172 my $pass = <PIPE>; 173 close PIPE; 174 print_error("Can't get password!\n") if ( !$pass ); # exit here 175 $opt_pass = $pass; 176 } 177 $signtool .= " -v" if ($opt_verbose); 178 $commandline_base = $signtool . " " . "-f $opt_pfxfile -p $opt_pass -t $opt_timestamp_url"; 179 180 # Here switch between: 181 # one command line for muliple files (all doesn't work, too much) / for each file one command line 182 if ( $max_files > 1 ) { 183 exec_multi_sign($files_to_sign, $commandline_base); 184 } else 185 { 186 exec_single_sign($files_to_sign, $commandline_base); 187 } 188} ##sign_files 189 190############################################################################ 191sub exec_single_sign #11.07.2007 09:05 192############################################################################ 193{ 194 my $files_to_sign = shift; 195 my $commandline_base = shift; # contains whole stuff without the file name 196 my $file = ""; 197 my $commandline = ""; 198 199 foreach $file (@$files_to_sign) 200 { 201 $commandline = $commandline_base . " $file"; 202 print "$commandline\n" if ($debug); 203 execute($commandline); 204 } #foreach 205} ##exec_single_sign 206 207############################################################################ 208sub exec_multi_sign #11.07.2007 08:56 209############################################################################ 210 { 211 # sign multiple file with one command line 212 my $files_to_sign = shift; 213 my $commandline_base = shift; # contains whole stuff without the file name 214 my $commandline = $commandline_base; # contains stuff which will be executed 215 my $file = ""; 216 my $counter = 0; 217 218 foreach $file (@$files_to_sign) 219 { 220 $commandline .= " $file"; 221 ++$counter; 222 if ( $counter >= $max_files ) { 223 execute($commandline); 224 $counter = 0; # reset counter 225 $commandline = $commandline_base; # reset command line 226 } 227 } 228 execute($commandline) if ($counter > 0); 229} ##exec_multi_sign 230 231############################################################################ 232sub execute #11.07.2007 10:02 233############################################################################ 234{ 235 my $commandline = shift; 236 my $result = ""; 237 238 print "$commandline\n" if ($debug); 239 open(PIPE, "$commandline 2>&1 |") || die "Error: Can't open pipe!\n"; 240 while ( $result = <PIPE> ) { 241 print LOG "$result" if ($opt_log); # logging 242 if ( $result =~ /SignTool Error\:/ ) { 243 close PIPE; 244 print_error( "$result\n" ); 245 } # if error 246 } # while 247 close PIPE; 248} ##execute 249 250############################################################################ 251sub print_error #09.07.2007 11:21 252############################################################################ 253 { 254 my $text = shift; 255 print "ERROR: $text\n"; 256 print LOG "ERROR: $text\n" if ($opt_log); # logging 257 close LOG if ($opt_log); # logging 258 exit(1); 259} ##print_error 260 261############################################################################ 262sub usage #09.07.2007 08:39 263############################################################################ 264 { 265 print "Usage:\t $myname <-e filename> <-f filename> <-p password> <-t timestamp> <-i filename> [-l filename] [-v]\n"; 266 print "Options:\n"; 267 print "\t -e filename\t\t\tFile which contains a list of files which don't have to be signed.\n"; 268 print "Mandatory.\n"; 269 print "\t -f pfx_filename\t\t\"Personal Information Exchange\" file. "; 270 print "Mandatory.\n"; 271 print "\t -p password\t\t\tPassword for \"Personal Information Exchange\" file. Mandatory.\n"; 272 print "\t -t timestamp\t\t\tTimestamp URL e.g. \"http://timestamp.verisign.com/scripts/timstamp.dll\"\n"; 273 print "\t -i filename\t\t\tName of the file that contains the names of files to sign.\"\n"; 274 print "\t\t\t\t\tMandatory.\n"; 275 print "\t -l log_filename\t\tFile for logging.\n"; 276 print "\t -v\t\t\t\tVerbose.\n"; 277} ##usage 278