chiark / gitweb /
Merge branch 'permission-parsing' into 'master'
authorHans-Christoph Steiner <hans@guardianproject.info>
Tue, 9 Aug 2016 15:33:19 +0000 (15:33 +0000)
committerHans-Christoph Steiner <hans@guardianproject.info>
Tue, 9 Aug 2016 15:33:19 +0000 (15:33 +0000)
Parse maxSdkVersion and -23 permission tags

Parse maxSdkVersion and uses-permission-sdk-23 tags and insert them into the index.

AndroidManifest:
```xml
    <uses-permission android:name="android.permission.READ_CALENDAR" />

    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="18" />

    <uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" />
```

new index format:
```xml
<package>
            <version>1.0</version>
            <versioncode>1</versioncode>
            <apkname>maxmin.apk</apkname>
            <hash type="sha256">526eb6d643050c3fae42fb6c001c704006046db52e98998b21f7646ecae3dae5
            </hash>
            <sig>893fc1f22301c902d05c938b29d21648</sig>
            <size>8681</size>
            <sdkver>14</sdkver>
            <targetSdkVersion>24</targetSdkVersion>
            <added>2016-08-01</added>
            <permissions>READ_EXTERNAL_STORAGE,READ_CALENDAR,WRITE_EXTERNAL_STORAGE</permissions>
                <uses-permission name="android.permission.WRITE_EXTERNAL_STORAGE"
                    maxSdkVersion="18" />
                <uses-permission name="android.permission.READ_CALENDAR" />
                <uses-permission name="android.permission.READ_EXTERNAL_STORAGE" />
                <uses-permission-sdk-23 name="android.permission.ACCESS_FINE_LOCATION" />
</package>
```

old format:
```xml
<permissions>READ_CALENDAR,ACCESS_FINE_LOCATION,WRITE_EXTERNAL_STORAGE</permissions>
```

This generates both formats for backward compatibility with old clients.

Also increase version of index format.

This is a proposal for the issues discussed in https://gitlab.com/fdroid/fdroidclient/issues/704

@eighthave @mvdan

See merge request !150

1  2 
fdroidserver/update.py

diff --combined fdroidserver/update.py
index 9c7bcbadc2c8a2f9494a13717c653377ca9c3571,f8646e2a258932cd4ce17d7cdd724afd27aa54e1..07c8db3024422f34522f108ae971a96fe16da715
@@@ -31,6 -31,8 +31,8 @@@ from datetime import datetime, timedelt
  from xml.dom.minidom import Document
  from argparse import ArgumentParser
  import time
+ import collections
  from pyasn1.error import PyAsn1Error
  from pyasn1.codec.der import decoder, encoder
  from pyasn1_modules import rfc2315
@@@ -44,12 -46,15 +46,15 @@@ from . import metadat
  from .common import FDroidPopen, FDroidPopenBytes, SdkToolsPopen
  from .metadata import MetaDataException
  
- METADATA_VERSION = 16
+ METADATA_VERSION = 17
  
  screen_densities = ['640', '480', '320', '240', '160', '120']
  
  all_screen_densities = ['0'] + screen_densities
  
+ UsesPermission = collections.namedtuple('UsesPermission', ['name', 'maxSdkVersion'])
+ UsesPermissionSdk23 = collections.namedtuple('UsesPermissionSdk23', ['name', 'maxSdkVersion'])
  
  def dpi_to_px(density):
      return (int(density) * 48) / 160
@@@ -238,8 -243,6 +243,8 @@@ def update_wiki(apps, sortedids, apks)
          apppagename = apppagename.replace('{', '')
          apppagename = apppagename.replace('}', ' ')
          apppagename = apppagename.replace(':', ' ')
 +        apppagename = apppagename.replace('[', ' ')
 +        apppagename = apppagename.replace(']', ' ')
          # Drop double spaces caused mostly by replacing ':' above
          apppagename = apppagename.replace('  ', ' ')
          for expagename in site.allpages(prefix=apppagename,
@@@ -530,7 -533,8 +535,8 @@@ def scan_apks(apps, apkcache, repodir, 
      icon_pat = re.compile(".*application-icon-([0-9]+):'([^']+?)'.*")
      icon_pat_nodpi = re.compile(".*icon='([^']+?)'.*")
      sdkversion_pat = re.compile(".*'([0-9]*)'.*")
-     string_pat = re.compile(".* name='([^']*)'.*")
+     permission_pat = re.compile(".*(name='(?P<name>.*?)')(.*maxSdkVersion='(?P<maxSdkVersion>.*?)')?.*")
+     feature_pat = re.compile(".*name='([^']*)'.*")
      for apkfile in glob.glob(os.path.join(repodir, '*.apk')):
  
          apkfilename = apkfile[len(repodir) + 1:]
              if os.path.exists(os.path.join(repodir, srcfilename)):
                  apk['srcname'] = srcfilename
              apk['size'] = os.path.getsize(apkfile)
-             apk['permissions'] = set()
+             apk['uses-permission'] = set()
+             apk['uses-permission-sdk-23'] = set()
              apk['features'] = set()
              apk['icons_src'] = {}
              apk['icons'] = {}
                      apk['nativecode'] = []
                      for arch in line[13:].split(' '):
                          apk['nativecode'].append(arch[1:-1])
-                 elif line.startswith("uses-permission:"):
-                     perm = re.match(string_pat, line).group(1)
-                     if perm.startswith("android.permission."):
-                         perm = perm[19:]
-                     apk['permissions'].add(perm)
-                 elif line.startswith("uses-feature:"):
-                     perm = re.match(string_pat, line).group(1)
+                 elif line.startswith('uses-permission:'):
+                     perm_match = re.match(permission_pat, line).groupdict()
+                     permission = UsesPermission(
+                         perm_match['name'],
+                         perm_match['maxSdkVersion']
+                     )
+                     apk['uses-permission'].add(permission)
+                 elif line.startswith('uses-permission-sdk-23:'):
+                     perm_match = re.match(permission_pat, line).groupdict()
+                     permission_sdk_23 = UsesPermissionSdk23(
+                         perm_match['name'],
+                         perm_match['maxSdkVersion']
+                     )
+                     apk['uses-permission-sdk-23'].add(permission_sdk_23)
+                 elif line.startswith('uses-feature:'):
+                     feature = re.match(feature_pat, line).group(1)
                      # Filter out this, it's only added with the latest SDK tools and
                      # causes problems for lots of apps.
-                     if perm != "android.hardware.screen.portrait" \
-                             and perm != "android.hardware.screen.landscape":
-                         if perm.startswith("android.feature."):
-                             perm = perm[16:]
-                         apk['features'].add(perm)
+                     if feature != "android.hardware.screen.portrait" \
+                             and feature != "android.hardware.screen.landscape":
+                         if feature.startswith("android.feature."):
+                             feature = feature[16:]
+                         apk['features'].add(feature)
  
              if 'minSdkVersion' not in apk:
                  logging.warn("No SDK version information found in {0}".format(apkfile))
@@@ -1048,7 -1067,28 +1069,28 @@@ def make_index(apps, sortedids, apks, r
              addElementNonEmpty('obbPatchFileSha256', apk.get('obbPatchFileSha256'), doc, apkel)
              if 'added' in apk:
                  addElement('added', time.strftime('%Y-%m-%d', apk['added']), doc, apkel)
-             addElementNonEmpty('permissions', ','.join(apk['permissions']), doc, apkel)
+             # TODO: remove old permission format
+             old_permissions = set()
+             for perm in apk['uses-permission']:
+                 perm_name = perm.name
+                 if perm_name.startswith("android.permission."):
+                     perm_name = perm_name[19:]
+                 old_permissions.add(perm_name)
+             addElementNonEmpty('permissions', ','.join(old_permissions), doc, apkel)
+             for permission in apk['uses-permission']:
+                 permel = doc.createElement('uses-permission')
+                 permel.setAttribute('name', permission.name)
+                 if permission.maxSdkVersion is not None:
+                     permel.setAttribute('maxSdkVersion', permission.maxSdkVersion)
+                     apkel.appendChild(permel)
+             for permission_sdk_23 in apk['uses-permission-sdk-23']:
+                 permel = doc.createElement('uses-permission-sdk-23')
+                 permel.setAttribute('name', permission_sdk_23.name)
+                 if permission_sdk_23.maxSdkVersion is not None:
+                     permel.setAttribute('maxSdkVersion', permission_sdk_23.maxSdkVersion)
+                     apkel.appendChild(permel)
              if 'nativecode' in apk:
                  addElement('nativecode', ','.join(apk['nativecode']), doc, apkel)
              addElementNonEmpty('features', ','.join(apk['features']), doc, apkel)