bin/patch_capabilities.pl
changeset 30 5dc02b23752f
parent 18 2f34d5167611
child 33 3e2da88830cd
--- a/bin/patch_capabilities.pl	Wed Jun 23 19:07:03 2010 +0300
+++ b/bin/patch_capabilities.pl	Tue Jul 06 15:10:48 2010 +0300
@@ -46,18 +46,32 @@
 #
 #######################################################################
 
+use File::Copy;
+
 sub Usage() {
     print("This script can be used to set capabilities of all binaries\n");
     print("specified for deployment in a .pkg file.\n");
     print("If no capabilities are given, the binaries will be given the\n");
-    print("capabilities supported by self-signed certificates.\n");
-    print("\n *** NOTE: If *_template.pkg file is given, 'target-platform' is REQUIRED. ***\n");
-    print("\nUsage: patch_capabilities.pl pkg_filename <target-platform> [capability list]\n");
+    print("capabilities supported by self-signed certificates.\n\n");
+    print(" *** NOTE: If *_template.pkg file is given and one is using symbian-abld or\n");
+    print(" symbian-sbsv2 platform, 'target-platform' is REQUIRED. ***\n");
+    print("\nUsage: patch_capabilities.pl pkg_filename [target-platform [capability list]]\n");
     print("\nE.g. patch_capabilities.pl myapp_template.pkg release-armv5 \"All -TCB\"\n");
     exit();
 }
 
-my @capabilitiesToSet = ("LocalServices", "NetworkServices", "ReadUserData", "UserEnvironment", "WriteUserData");
+sub trim($) {
+    my $string = shift;
+    $string =~ s/^\s+//;
+    $string =~ s/\s+$//;
+    return $string;
+}
+
+my $nullDevice = "/dev/null";
+$nullDevice = "NUL" if ($^O =~ /MSWin/);
+
+my @capabilitiesToAllow = ("LocalServices", "NetworkServices", "ReadUserData", "UserEnvironment", "WriteUserData");
+my @capabilitiesSpecified = ();
 
 # If arguments were given to the script,
 if (@ARGV)
@@ -73,11 +87,16 @@
     if (($pkgFileName =~ m|_template\.pkg$|i) && -r($pkgFileName))
     {
         my $targetplatform;
-        unless ($targetplatform = shift(@ARGV))
+        my $templateFile;
+        my $templateContents;
+        open($templateFile, "< $pkgFileName") or die ("Could not open $pkgFileName");
+        $templateContents = <$templateFile>;
+        close($templateFile);
+        unless (($targetplatform = shift(@ARGV)) || $templateContents !~ /\$\(PLATFORM\)/)
         {
             Usage();
         }
-
+        $targetplatform = "-" if (!$targetplatform);
         my @tmpvalues = split('-', $targetplatform);
         $target = $tmpvalues[0];
         $platform = $tmpvalues[1];
@@ -90,13 +109,16 @@
     # If the specified ".pkg" file exists (and can be read),
     if (($pkgFileName =~ m|\.pkg$|i) && -r($pkgFileName))
     {
+        print ("\n");
+        print ("Patching package file and relevant binaries...\n");
+
         # If there are more arguments given, parse them as capabilities.
         if (@ARGV)
         {
-            @capabilitiesToSet = ();
+            @capabilitiesSpecified = ();
             while (@ARGV)
             {
-                push (@capabilitiesToSet, pop(@ARGV));
+                push (@capabilitiesSpecified, pop(@ARGV));
             }
         }
 
@@ -163,18 +185,13 @@
                 $manufacturerElseBlock = 0;
             }
 
-            print NEW_PKG $newLine;
-
-            chomp ($line);
-
             # If the line specifies a file, parse the source and destination locations.
             if ($line =~ m|\"([^\"]+)\"\s*\-\s*\"([^\"]+)\"|)
             {
                 my $sourcePath = $1;
-                my $destinationPath = $2;
 
                 # If the given file is a binary, check the target and binary type (+ the actual filename) from its path.
-                if ($sourcePath =~ m:/epoc32/release/([^/]+)/(udeb|urel|\$\(TARGET\))/(\w+(\.dll|\.exe)):i)
+                if ($sourcePath =~ m:\w+(\.dll|\.exe)$:i)
                 {
                     # Do preprocessing for template pkg,
                     # In case of template pkg target and platform variables are set
@@ -184,9 +201,22 @@
                         $sourcePath =~ s/\$\(TARGET\)/$target/gm;
                     }
 
-                    push (@binaries, $sourcePath);
+                    # Change the source file name (but only if not already patched)
+                    my $patchedSourcePath = $sourcePath;
+                    if ($patchedSourcePath !~ m/_patched_caps/)
+                    {
+                        $newLine =~ s/(^.*)(\.dll|\.exe)(.*)(\.dll|\.exe)/$1_patched_caps$2$3$4/i;
+                        $patchedSourcePath =~ s/(^.*)(\.dll|\.exe)/$1_patched_caps$2/i;
+
+                        copy($sourcePath, $patchedSourcePath) or die "$sourcePath cannot be copied for patching.";
+                    }
+                    push (@binaries, $patchedSourcePath);
                 }
             }
+
+            print NEW_PKG $newLine;
+
+            chomp ($line);
         }
 
         close (PKG);
@@ -197,29 +227,50 @@
 
         print ("\n");
 
-        my $baseCommandToExecute = "elftran -vid 0x0 -capability \"";
-        if (@capabilitiesToSet)
-        {
-            $baseCommandToExecute .= join(" ", @capabilitiesToSet);
-        }
-        $baseCommandToExecute .= "\" ";
+        my $baseCommandToExecute = "elftran -vid 0x0 -capability \"%s\" ";
 
         # Actually set the capabilities of the listed binaries.
         foreach my $binaryPath(@binaries)
         {
             # Create the command line for setting the capabilities.
             my $commandToExecute = $baseCommandToExecute;
+            if (@capabilitiesSpecified)
+            {
+                $commandToExecute = sprintf($baseCommandToExecute, join(" ", @capabilitiesSpecified));
+            } else {
+                # Test which capabilities are present and then restrict them to the allowed set.
+                # This avoid raising the capabilities of apps that already have none.
+                my $dllCaps;
+                open($dllCaps, "elftran -dump s $binaryPath |") or die ("Could not execute elftran");
+                my $capsFound = 0;
+                my @capabilitiesToSet;
+                my $capabilitiesToAllow = join(" ", @capabilitiesToAllow);
+                while (<$dllCaps>) {
+                    if (!$capsFound) {
+                        $capsFound = 1 if (/Capabilities:/);
+                    } else {
+                        $_ = trim($_);
+                        if ($capabilitiesToAllow =~ /$_/) {
+                            push(@capabilitiesToSet, $_);
+                        }
+                    }
+                }
+                close($dllCaps);
+                $commandToExecute = sprintf($baseCommandToExecute, join(" ", @capabilitiesToSet));
+            }
             $commandToExecute .= $binaryPath;
 
             # Actually execute the elftran command to set the capabilities.
-            system ($commandToExecute." > NUL");
-            print ("Executed ".$commandToExecute."\n");
+            print ("Executing ".$commandToExecute."\n");
+            system ($commandToExecute." > $nullDevice");
 
             ## Create another command line to check that the set capabilities are correct.
             #$commandToExecute = "elftran -dump s ".$binaryPath;
         }
 
         print ("\n");
+        print ("NOTE: A patched package should not be used for distribution!\n");
+        print ("\n");
     }
 }
 else