1 #!/usr/bin/perl |
1 #!/usr/bin/perl |
2 ############################################################################# |
2 ############################################################################# |
3 ## |
3 ## |
4 ## Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
4 ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
5 ## All rights reserved. |
5 ## All rights reserved. |
6 ## Contact: Nokia Corporation (qt-info@nokia.com) |
6 ## Contact: Nokia Corporation (qt-info@nokia.com) |
7 ## |
7 ## |
8 ## This file is part of the S60 port of the Qt Toolkit. |
8 ## This file is part of the S60 port of the Qt Toolkit. |
9 ## |
9 ## |
52 use Getopt::Long; |
52 use Getopt::Long; |
53 # Use file name parsing module |
53 # Use file name parsing module |
54 use File::Basename; |
54 use File::Basename; |
55 # Use File::Spec services mainly rel2abs |
55 # Use File::Spec services mainly rel2abs |
56 use File::Spec; |
56 use File::Spec; |
|
57 # Use File::Path - to make stub sis target directory |
|
58 use File::Path; |
57 # use CWD abs_bath, which is exported only on request |
59 # use CWD abs_bath, which is exported only on request |
58 use Cwd 'abs_path'; |
60 use Cwd 'abs_path'; |
59 |
61 |
60 |
62 |
61 sub Usage() { |
63 sub Usage() { |
62 print <<ENDUSAGESTRING; |
64 print <<ENDUSAGESTRING; |
63 |
65 |
64 ============================================================================================== |
66 ============================================================================================== |
65 Convenience script for creating signed packages you can install on your phone. |
67 Convenience script for creating signed packages you can install on your phone. |
66 |
68 |
67 Usage: createpackage.pl [options] templatepkg target-platform [certificate key [passphrase]] |
69 Usage: createpackage.pl [options] templatepkg [target]-[platform] [certificate key [passphrase]] |
68 |
70 |
69 Where supported optiobns are as follows: |
71 Where supported optiobns are as follows: |
70 [-i|install] = Install the package right away using PC suite |
72 [-i|install] = Install the package right away using PC suite |
71 [-p|preprocess] = Only preprocess the template .pkg file. |
73 [-p|preprocess] = Only preprocess the template .pkg file. |
72 [-c|certfile=<file>] = The file containing certificate information for signing. |
74 [-c|certfile=<file>] = The file containing certificate information for signing. |
73 The file can have several certificates, each specified in |
75 The file can have several certificates, each specified in |
74 separate line. The certificate, key and passphrase in line |
76 separate line. The certificate, key and passphrase in line |
75 must be ';' separated. Lines starting with '#' are treated |
77 must be ';' separated. Lines starting with '#' are treated |
76 as a comments. Also empty lines are ignored. The paths in |
78 as a comments. Also empty lines are ignored. The paths in |
77 <file> can be absolute or relative to <file>. |
79 <file> can be absolute or relative to <file>. |
|
80 [-u|unsigned] = Preserves the unsigned package |
78 Where parameters are as follows: |
81 Where parameters are as follows: |
79 templatepkg = Name of .pkg file template |
82 templatepkg = Name of .pkg file template |
80 target = Either debug or release |
83 target = Either debug or release |
81 platform = One of the supported platform |
84 platform = One of the supported platform |
82 winscw | gcce | armv5 | armv6 | armv7 |
85 winscw | gcce | armv5 | armv6 | armv7 |
84 key = The certificate's private key file |
87 key = The certificate's private key file |
85 passphrase = The certificate's private key file's passphrase |
88 passphrase = The certificate's private key file's passphrase |
86 |
89 |
87 Example: |
90 Example: |
88 createpackage.pl fluidlauncher_template.pkg release-armv5 |
91 createpackage.pl fluidlauncher_template.pkg release-armv5 |
89 |
92 |
90 Example with certfile: |
93 Example with certfile: |
91 createpackage.pl -c=mycerts.txt fluidlauncher_template.pkg release-armv5 |
94 createpackage.pl -c=mycerts.txt fluidlauncher_template.pkg release-armv5 |
92 |
95 |
93 Content of 'mycerts.txt' must be something like this: |
96 Content of 'mycerts.txt' must be something like this: |
94 # This is comment line, also the empty lines are ignored |
97 # This is comment line, also the empty lines are ignored |
95 rd.cer;rd-key.pem |
98 rd.cer;rd-key.pem |
96 .\\cert\\mycert.cer;.\\cert\\mykey.key;yourpassword |
99 .\\cert\\mycert.cer;.\\cert\\mykey.key;yourpassword |
97 X:\\QtS60\\selfsigned.cer;X:\\QtS60\\selfsigned.key |
100 X:\\QtS60\\s60installs\\selfsigned.cer;X:\\QtS60\\s60installs\\selfsigned.key |
98 |
101 |
99 If no certificate and key files are provided, either a RnD certificate or |
102 If no certificate and key files are provided, either a RnD certificate or |
100 a self-signed certificate from Qt installation root directory is used. |
103 a self-signed certificate from QtDir\\src\\s60installs directory is used. |
101 ============================================================================================== |
104 ============================================================================================== |
102 |
105 |
103 ENDUSAGESTRING |
106 ENDUSAGESTRING |
104 |
107 |
105 exit(); |
108 exit(); |
107 |
110 |
108 # Read given options |
111 # Read given options |
109 my $install = ""; |
112 my $install = ""; |
110 my $preprocessonly = ""; |
113 my $preprocessonly = ""; |
111 my $certfile = ""; |
114 my $certfile = ""; |
112 |
115 my $preserveUnsigned = ""; |
113 unless (GetOptions('i|install' => \$install, 'p|preprocess' => \$preprocessonly, 'c|certfile=s' => \$certfile)){ |
116 my $stub = ""; |
|
117 |
|
118 unless (GetOptions('i|install' => \$install, |
|
119 'p|preprocess' => \$preprocessonly, |
|
120 'c|certfile=s' => \$certfile, |
|
121 'u|unsigned' => \$preserveUnsigned, |
|
122 's|stub' => \$stub,)){ |
114 Usage(); |
123 Usage(); |
115 } |
124 } |
116 |
125 |
117 my $certfilepath = abs_path(dirname($certfile)); |
126 my $certfilepath = abs_path(dirname($certfile)); |
118 |
127 |
132 my $key = $ARGV[3]; |
141 my $key = $ARGV[3]; |
133 my $passphrase = $ARGV[4]; |
142 my $passphrase = $ARGV[4]; |
134 |
143 |
135 # Generate output pkg basename (i.e. file name without extension) |
144 # Generate output pkg basename (i.e. file name without extension) |
136 my $pkgoutputbasename = $templatepkg; |
145 my $pkgoutputbasename = $templatepkg; |
137 $pkgoutputbasename =~ s/_template\.pkg/_$targetplatform/g; |
146 my $preservePkgOutput = ""; |
|
147 $pkgoutputbasename =~ s/_template/_$targetplatform/g; |
|
148 if ($pkgoutputbasename eq $templatepkg) { |
|
149 $preservePkgOutput = "1"; |
|
150 } |
|
151 $pkgoutputbasename =~ s/\.pkg//g; |
138 $pkgoutputbasename = lc($pkgoutputbasename); |
152 $pkgoutputbasename = lc($pkgoutputbasename); |
139 |
153 |
140 # Store output file names to variables |
154 # Store output file names to variables |
141 my $pkgoutput = lc($pkgoutputbasename.".pkg"); |
155 my $pkgoutput = lc($pkgoutputbasename.".pkg"); |
142 my $unsigned_sis_name = $pkgoutputbasename."_unsigned.sis"; |
156 my $sisoutputbasename = lc($pkgoutputbasename); |
143 my $signed_sis_name = $pkgoutputbasename.".sis"; |
157 $sisoutputbasename =~ s/_$targetplatform//g; |
|
158 my $unsigned_sis_name = $sisoutputbasename."_unsigned.sis"; |
|
159 my $signed_sis_name = $sisoutputbasename.".sis"; |
|
160 my $stub_sis_name = $sisoutputbasename."_stub.sis"; |
144 |
161 |
145 # Store some utility variables |
162 # Store some utility variables |
146 my $scriptpath = dirname(__FILE__); |
163 my $scriptpath = dirname(__FILE__); |
147 my $certtext = $certificate; |
164 my $certtext = $certificate; |
148 my $certpath = $scriptpath; |
165 my $certpath = $scriptpath; |
149 $certpath =~ s-^(.*[^\\])$-$1\\-o; # ensure path ends with a backslash |
166 $certpath =~ s-^(.*[^\\])$-$1\\-o; # ensure path ends with a backslash |
150 $certpath =~ s-/-\\-go; # for those working with UNIX shells |
167 $certpath =~ s-/-\\-go; # for those working with UNIX shells |
151 $certpath =~ s-bin\\$-src\\s60installs\\-; # certificates are one step up in hierarcy |
168 $certpath =~ s-bin\\$-src\\s60installs\\-; # certificates are one step up in hierarcy |
152 |
169 |
153 # Check some pre-conditions and print error messages if needed |
170 # Check some pre-conditions and print error messages if needed. |
154 unless (length($templatepkg) && length($platform) && length($target)) { |
171 unless (length($templatepkg)) { |
155 print "\nError: Template PKG filename, platform or target is not defined!\n"; |
172 print "\nError: Template PKG filename is not defined!\n"; |
156 Usage(); |
173 Usage(); |
|
174 } |
|
175 |
|
176 # If the pkg file is not actually a template, there is no need for plaform or target. |
|
177 if ($templatepkg =~ m/_template\.pkg/i) { |
|
178 unless (length($platform) && length($target)) { |
|
179 print "\nError: Platform or target is not defined!\n"; |
|
180 Usage(); |
|
181 } |
157 } |
182 } |
158 |
183 |
159 # Check template exist |
184 # Check template exist |
160 stat($templatepkg); |
185 stat($templatepkg); |
161 unless( -e _ ) { |
186 unless( -e _ ) { |
190 while(<CERTFILE>){ |
215 while(<CERTFILE>){ |
191 s/#.*//; # ignore comments by erasing them |
216 s/#.*//; # ignore comments by erasing them |
192 next if /^(\s)*$/; # skip blank lines |
217 next if /^(\s)*$/; # skip blank lines |
193 chomp; # remove trailing newline characters |
218 chomp; # remove trailing newline characters |
194 my @certinfo = split(';', $_); # split row to certinfo |
219 my @certinfo = split(';', $_); # split row to certinfo |
195 |
220 |
196 # Trim spaces |
221 # Trim spaces |
197 for(@certinfo) { |
222 for(@certinfo) { |
198 s/^\s+//; |
223 s/^\s+//; |
199 s/\s+$//; |
224 s/\s+$//; |
200 } |
225 } |
201 |
226 |
202 # Do some validation |
227 # Do some validation |
203 unless(scalar(@certinfo) >= 2 && scalar(@certinfo) <= 3 && length($certinfo[0]) && length($certinfo[1]) ) { |
228 unless(scalar(@certinfo) >= 2 && scalar(@certinfo) <= 3 && length($certinfo[0]) && length($certinfo[1]) ) { |
204 print "\nError: $certfile line '$_' does not contain valid information!\n"; |
229 print "\nError: $certfile line '$_' does not contain valid information!\n"; |
205 Usage(); |
230 Usage(); |
206 } |
231 } |
207 |
232 |
208 push @certificates, [@certinfo]; # push data to two dimensional array |
233 push @certificates, [@certinfo]; # push data to two dimensional array |
209 } |
234 } |
210 } |
235 } |
211 |
236 |
212 # Remove any existing .sis packages |
237 # Remove any existing .sis packages |
213 unlink $unsigned_sis_name; |
238 unlink $unsigned_sis_name; |
214 unlink $signed_sis_name; |
239 unlink $signed_sis_name; |
215 unlink $pkgoutput; |
240 if (!$preservePkgOutput) { |
|
241 unlink $pkgoutput; |
|
242 } |
216 |
243 |
217 # Preprocess PKG |
244 # Preprocess PKG |
218 local $/; |
245 local $/; |
219 # read template file |
246 # read template file |
220 open( TEMPLATE, $templatepkg) or die "Error '$templatepkg': $!\n"; |
247 open( TEMPLATE, $templatepkg) or die "Error '$templatepkg': $!\n"; |
232 |
259 |
233 if ($preprocessonly) { |
260 if ($preprocessonly) { |
234 exit; |
261 exit; |
235 } |
262 } |
236 |
263 |
237 # Create SIS. |
264 if($stub) { |
238 system ("makesis $pkgoutput $unsigned_sis_name"); |
265 if(!($ENV{EPOCROOT})) { die("EPOCROOT must be set to create stub sis files"); } |
239 |
266 my $systeminstall = "$ENV{EPOCROOT}epoc32/data/z/system/install"; |
240 # Sign SIS with certificate info given as an argument. |
267 mkpath($systeminstall); |
241 system ("signsis $unsigned_sis_name $signed_sis_name $certificate $key $passphrase"); |
268 my $stub_sis_name = $systeminstall."/".$stub_sis_name; |
242 |
269 # Create stub SIS. |
243 # Check if creating signed SIS Succeeded |
270 system ("makesis -s $pkgoutput $stub_sis_name"); |
244 stat($signed_sis_name); |
|
245 if( -e _ ) { |
|
246 print ("\nSuccessfully created $signed_sis_name using certificate: $certtext!\n"); |
|
247 |
|
248 # Sign with additional certificates & keys |
|
249 for my $row ( @certificates ) { |
|
250 # Get certificate absolute file names, relative paths are relative to certfilepath |
|
251 my $abscert = File::Spec->rel2abs( $row->[0], $certfilepath); |
|
252 my $abskey = File::Spec->rel2abs( $row->[1], $certfilepath); |
|
253 |
|
254 system ("signsis $signed_sis_name $signed_sis_name $abscert $abskey $row->[2]"); |
|
255 print ("\tAdditionally signed the SIS with certificate: $row->[0]!\n"); |
|
256 } |
|
257 |
|
258 # remove temporary pkg and unsigned sis |
|
259 unlink $pkgoutput; |
|
260 unlink $unsigned_sis_name; |
|
261 |
|
262 # Install the sis if requested |
|
263 if ($install) { |
|
264 print ("\nInstalling $signed_sis_name...\n"); |
|
265 system ("$signed_sis_name"); |
|
266 } |
|
267 } else { |
271 } else { |
268 # Lets leave the generated PKG for problem solving purposes |
272 # Create SIS. |
269 print ("\nSIS creation failed!\n"); |
273 system ("makesis $pkgoutput $unsigned_sis_name"); |
270 } |
274 print("\n"); |
271 |
275 |
|
276 # Sign SIS with certificate info given as an argument. |
|
277 system ("signsis $unsigned_sis_name $signed_sis_name $certificate $key $passphrase"); |
|
278 |
|
279 # Check if creating signed SIS Succeeded |
|
280 stat($signed_sis_name); |
|
281 if( -e _ ) { |
|
282 my $targetInsert = ""; |
|
283 if ($targetplatform ne "-") { |
|
284 $targetInsert = "for $targetplatform "; |
|
285 } |
|
286 print ("Successfully created $signed_sis_name ${targetInsert}using certificate: $certtext!\n"); |
|
287 |
|
288 # Sign with additional certificates & keys |
|
289 for my $row ( @certificates ) { |
|
290 # Get certificate absolute file names, relative paths are relative to certfilepath |
|
291 my $abscert = File::Spec->rel2abs( $row->[0], $certfilepath); |
|
292 my $abskey = File::Spec->rel2abs( $row->[1], $certfilepath); |
|
293 |
|
294 system ("signsis $signed_sis_name $signed_sis_name $abscert $abskey $row->[2]"); |
|
295 print ("\tAdditionally signed the SIS with certificate: $row->[0]!\n"); |
|
296 } |
|
297 |
|
298 # remove temporary pkg and unsigned sis |
|
299 if (!$preservePkgOutput) { |
|
300 unlink $pkgoutput; |
|
301 } |
|
302 if (!$preserveUnsigned) { |
|
303 unlink $unsigned_sis_name; |
|
304 } |
|
305 |
|
306 # Install the sis if requested |
|
307 if ($install) { |
|
308 print ("\nInstalling $signed_sis_name...\n"); |
|
309 system ("$signed_sis_name"); |
|
310 } |
|
311 } else { |
|
312 # Lets leave the generated PKG for problem solving purposes |
|
313 print ("\nSIS creation failed!\n"); |
|
314 } |
|
315 } |
272 |
316 |
273 #end of file |
317 #end of file |