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 $success = GetOptions('h' => \$opt_help, 86 'd=s' => \$opt_dir, 'e=s'=>\$opt_exclude, 'f=s'=>\$opt_pfxfile, 'l=s'=>\$opt_log, 87 'p=s'=>\$opt_pass,'v'=>\$opt_verbose, 't=s'=>\$opt_timestamp_url); 88 if ( !$success || $opt_help ) { 89 usage(); 90 exit(1); 91 } 92 if ( !$opt_exclude || !$opt_pfxfile || !$opt_pass || !$opt_timestamp_url) { 93 print "ERROR: Parameter missing!\n!"; 94 usage(); 95 exit(1); 96 } 97 return @ARGV; 98} ##parse_options 99 100############################################################################ 101sub get_exclude_files #09.07.2007 10:12 102############################################################################ 103{ 104 if ( -e $opt_exclude ) { 105 # get data from cache file 106 open( IN, "<$opt_exclude") || die "Can't open exclude file $opt_exclude\n"; 107 while ( my $line = <IN> ) { 108 chomp($line); 109 $exclude_files{$line} = 1; # fill hash 110 print "$line - $exclude_files{$line}\n" if ($debug); 111 } 112 } else 113 { 114 print_error("Can't open $opt_exclude file!\n"); 115 } 116} ##get_exclude_files 117 118############################################################################ 119sub get_files #10.07.2007 10:19 120############################################################################ 121 { 122 use File::Basename; 123 my $target = shift; 124 my $file_pattern; 125 my $file; 126 my @files = (); 127 print "\n"; 128 foreach $file_pattern ( @$target ) 129 { 130 print "Files: $file_pattern\n"; 131 foreach $file ( glob( $file_pattern ) ) 132 { 133 my $lib = File::Basename::basename $file; 134 if ( ! $exclude_files{$lib} ) { 135 push @files,$file; 136 } 137 else 138 { 139 print "exclude=$lib\n" if ($opt_verbose); 140 } 141 } 142 } 143 print "\n"; 144 return @files; 145} ##get_files 146 147############################################################################ 148sub sign_files #09.07.2007 10:36 149############################################################################ 150{ 151 my $files_to_sign = shift; 152 my $commandline_base = ""; # contains whole stuff without the file name 153 my $file = ""; 154 my $result = ""; 155 156 print_error("Can't open PFX file: $opt_pfxfile\n") if ( ! -e $opt_pfxfile ); 157 print_error("Password is empty\n") if ( !$opt_pass ); 158 if ( $opt_pass =~ /\.exe$/ ) { 159 # get password by tool 160 open(PIPE, "$opt_pass 2>&1 |") || die "Can't open PIPE!\n"; 161 my $pass = <PIPE>; 162 close PIPE; 163 print_error("Can't get password!\n") if ( !$pass ); # exit here 164 $opt_pass = $pass; 165 } 166 $signtool .= " -v" if ($opt_verbose); 167 $commandline_base = $signtool . " " . "-f $opt_pfxfile -p $opt_pass -t $opt_timestamp_url"; 168 169 # Here switch between: 170 # one command line for muliple files (all doesn't work, too much) / for each file one command line 171 if ( $max_files > 1 ) { 172 exec_multi_sign($files_to_sign, $commandline_base); 173 } else 174 { 175 exec_single_sign($files_to_sign, $commandline_base); 176 } 177} ##sign_files 178 179############################################################################ 180sub exec_single_sign #11.07.2007 09:05 181############################################################################ 182{ 183 my $files_to_sign = shift; 184 my $commandline_base = shift; # contains whole stuff without the file name 185 my $file = ""; 186 my $commandline = ""; 187 188 foreach $file (@$files_to_sign) 189 { 190 $commandline = $commandline_base . " $file"; 191 print "$commandline\n" if ($debug); 192 execute($commandline); 193 } #foreach 194} ##exec_single_sign 195 196############################################################################ 197sub exec_multi_sign #11.07.2007 08:56 198############################################################################ 199 { 200 # sign multiple file with one command line 201 my $files_to_sign = shift; 202 my $commandline_base = shift; # contains whole stuff without the file name 203 my $commandline = $commandline_base; # contains stuff which will be executed 204 my $file = ""; 205 my $counter = 0; 206 207 foreach $file (@$files_to_sign) 208 { 209 $commandline .= " $file"; 210 ++$counter; 211 if ( $counter >= $max_files ) { 212 execute($commandline); 213 $counter = 0; # reset counter 214 $commandline = $commandline_base; # reset command line 215 } 216 } 217 execute($commandline) if ($counter > 0); 218} ##exec_multi_sign 219 220############################################################################ 221sub execute #11.07.2007 10:02 222############################################################################ 223{ 224 my $commandline = shift; 225 my $result = ""; 226 227 print "$commandline\n" if ($debug); 228 open(PIPE, "$commandline 2>&1 |") || die "Error: Cant open pipe!\n"; 229 while ( $result = <PIPE> ) { 230 print LOG "$result" if ($opt_log); # logging 231 if ( $result =~ /SignTool Error\:/ ) { 232 close PIPE; 233 print_error( "$result\n" ); 234 } # if error 235 } # while 236 close PIPE; 237} ##execute 238 239############################################################################ 240sub print_error #09.07.2007 11:21 241############################################################################ 242 { 243 my $text = shift; 244 print "ERROR: $text\n"; 245 print LOG "ERROR: $text\n" if ($opt_log); # logging 246 close LOG if ($opt_log); # logging 247 exit(1); 248} ##print_error 249 250############################################################################ 251sub usage #09.07.2007 08:39 252############################################################################ 253 { 254 print "Usage:\t $myname <-e filename> <-f filename> <-p password> <-t timestamp> [-l filename] [-v] <file[list]> \n"; 255 print "Options:\n"; 256 print "\t -e filename\t\t\tFile which contains a list of files which don't have to be signed.\n"; 257 print "Mandatory.\n"; 258 print "\t -f pfx_filename\t\t\"Personal Information Exchange\" file. "; 259 print "Mandatory.\n"; 260 print "\t -p password\t\t\tPassword for \"Personal Information Exchange\" file. Mandatory.\n"; 261 print "\t -t timestamp\t\t\tTimestamp URL e.g. \"http://timestamp.verisign.com/scripts/timstamp.dll\"\n"; 262 print "\t\t\t\t\tMandatory.\n"; 263 print "\t -l log_filename\t\tFile for logging.\n"; 264 print "\t -v\t\t\t\tVerbose.\n"; 265} ##usage 266 267 268 269 270