chiark / gitweb /
Merge branch 'apk-extension-obb-support' into 'master'
[fdroidserver.git] / wp-fdroid / android-permissions.php
1 <?php
2 // Class that provides PHP-friendly android permissions information from the raw Andoid source XML files that describes the permissions.
3 class AndroidPermissions
4 {
5
6         // Path to the AndroidManifest.xml-file from the Android source. Get it from https://raw.github.com/android/platform_frameworks_base/master/core/res/AndroidManifest.xml for example.
7         private $android_manifest_file_path;
8         // Path to the strings.xml-file from the Android source. Get it from https://raw.github.com/android/platform_frameworks_base/master/core/res/res/values/strings.xml for example.
9         private $android_strings_file_path;
10         // Path to the file where the resulting permissions data will be cached. NOTE: Must be writable by PHP!
11         private $cache_file_path;
12
13         public function __construct($android_manifest_file_path_in = 'AndroidManifest.xml', $android_strings_file_path_in = 'strings.xml', $cache_file_path_in = 'android-permissions.cache') {
14                 $this->android_manifest_file_path = $android_manifest_file_path_in;
15                 $this->android_strings_file_path = $android_strings_file_path_in;
16                 $this->cache_file_path = $cache_file_path_in;
17         }
18
19         // Returns an associative array with android permissions and data about them
20         function get_permissions_array() {
21
22                 // Check status of cache
23                 $android_manifest_file_stat = stat($this->android_manifest_file_path);
24                 $android_manifest_file_mtime = $android_manifest_file_stat['mtime'];
25                 $android_strings_file_stat = stat($this->android_strings_file_path);
26                 $android_strings_file_mtime = $android_strings_file_stat['mtime'];
27                 $cache_file_mtime = 0;
28                 if(file_exists($this->cache_file_path)) {
29                         $cache_file_stat = stat($this->cache_file_path);
30                         $cache_file_mtime = $cache_file_stat['mtime'];
31                 }
32
33                 // If the cache is fresh, use it instead
34                 if($android_manifest_file_mtime < $cache_file_mtime && $android_strings_file_mtime < $cache_file_mtime ) {
35                         $cache_file_handle = fopen($this->cache_file_path, 'r');
36                         $cache_file_content = fread($cache_file_handle, filesize($this->cache_file_path));
37                         fclose($cache_file_handle);
38
39                         $permissions = unserialize($cache_file_content);
40
41                         return $permissions;
42                 }
43
44                 // We are updating the cache, touch the file (note: race condition possible between stating the cache file above and this line...)
45                 touch($this->cache_file_path);
46
47                 // Get permission raw data from XML
48                 $manifestDoc = new DOMDocument;
49                 $manifestDoc->load($this->android_manifest_file_path);
50                 $manifestXpath = new DOMXPath($manifestDoc);
51
52                 $stringsDoc = new DOMDocument;
53                 $stringsDoc->load($this->android_strings_file_path);
54                 $stringsXpath = new DOMXPath($stringsDoc);
55
56                 $comment = '';
57                 foreach ($manifestXpath->query('node()') as $node) {
58                         // Save permissions and permission groups from tags
59                         if($node->nodeName == 'permission-group' || $node->nodeName == 'permission') {
60                                 $name = $node->attributes->getNamedItem('name')->value;
61                                 $name = substr(strrchr($name,'.'), 1);
62
63                                 // Lookup the human readable title
64                                 $labelObject = $node->attributes->getNamedItem('label');
65                                 $labelString = $name;
66                                 if( $labelObject !== NULL ) {
67                                         $labelName = substr(strrchr($labelObject->value,'/'),1);
68                                         $labelStringObject = $stringsXpath->query('//string[@name="'.$labelName.'"]');
69                                         $labelString = ucfirst($labelStringObject->item(0)->nodeValue);
70                                 }
71
72                                 // Lookup the human readable description
73                                 $descriptionObject = $node->attributes->getNamedItem('description');
74                                 $descriptionString = '(Description missing)';
75                                 if($descriptionObject !== NULL) {
76                                         $descriptionName = substr(strrchr($descriptionObject->value,'/'),1);
77                                         $descriptionStringObject = $stringsXpath->query('//string[@name="'.$descriptionName.'"]');
78                                         $descriptionString = ucfirst($descriptionStringObject->item(0)->nodeValue);
79                                 }
80
81                                 $permissions[$node->nodeName][$name]['label'] = stripslashes($labelString);
82                                 $permissions[$node->nodeName][$name]['description'] = stripslashes($descriptionString);
83                                 $permissions[$node->nodeName][$name]['comment'] = stripslashes(str_replace(array("\r\n", "\r", "\n", "\t", '  '), '', $comment));
84
85                                 if($node->nodeName == 'permission') {
86                                         $permissionGroupObject = $node->attributes->getNamedItem('permissionGroup');
87                                         $permissionGroup = 'none';
88                                         if($permissionGroupObject !== NULL) {
89                                                 $permissionGroup = substr(strrchr($permissionGroupObject->value,'.'), 1);
90                                         }
91
92                                         $permissions[$node->nodeName][$name]['permissionGroup'] = $permissionGroup;
93                                         $permissions[$node->nodeName][$name]['protectionLevel'] = $node->attributes->getNamedItem('protectionLevel')->value;
94                                 }
95                         }
96
97                         // Cache descriptions from comments preceding the tags
98                         if($node->nodeName == '#comment') {
99                                 $comment .= $node->textContent;
100                         }
101                         elseif($node->nodeName != '#text') {
102                                 $comment = '';
103                         }
104                 }
105
106                 // Update cache with serialized permissions
107                 $cache_file_handle = fopen($this->cache_file_path, 'w');
108                 fwrite($cache_file_handle, serialize($permissions));
109                 fclose($cache_file_handle);
110
111                 return $permissions;
112         }
113 }
114 ?>