pax_global_header00006660000000000000000000000064135626467470014536gustar00rootroot0000000000000052 comment=5672b6edd73c86cb8f0259d5a9810a042105d3f8 pyaxmlparser-0.3.24/000077500000000000000000000000001356264674700143535ustar00rootroot00000000000000pyaxmlparser-0.3.24/.editorconfig000066400000000000000000000004131356264674700170260ustar00rootroot00000000000000root = true [*] indent_style = space indent_size = 4 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.{json}] indent_style = space indent_size = 2 [*.md] trim_trailing_whitespace = false [Makefile] indent_style = tabpyaxmlparser-0.3.24/.gitignore000066400000000000000000000020351356264674700163430ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *,cover .hypothesis/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # IPython Notebook .ipynb_checkpoints # pyenv .python-version # celery beat schedule file celerybeat-schedule # dotenv .env # virtualenv venv/ ENV/ # Spyder project settings .spyderproject # Rope project settings .ropeproject .vscode pyaxmlparser-0.3.24/LICENSE000066400000000000000000000261351356264674700153670ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. pyaxmlparser-0.3.24/MANIFEST.in000066400000000000000000000001141356264674700161050ustar00rootroot00000000000000include *.txt include *.json include *.xml include pyaxmlparser/resources/* pyaxmlparser-0.3.24/README.rst000066400000000000000000000012001356264674700160330ustar00rootroot00000000000000axmlparser =========== A simple parser to parse Android XML file. Usage ====== CLI : ==== .. code-block:: shell $ apkinfo ~/Downloads/com.hardcodedjoy.roboremo.15.apk APK: /home/chillaranand/Downloads/com.hardcodedjoy.roboremo.15.apk App name: RoboRemo Package: com.hardcodedjoy.roboremo Version name: 2.0.0 Version code: 15 Python package : ================ .. code-block:: python from pyaxmlparser import APK apk = APK('/foo/bar.apk') print(apk.package) print(apk.version_name) print(apk.version_code) print(apk.icon_info) print(apk.icon_data) print(apk.application) pyaxmlparser-0.3.24/apkinfo.1000066400000000000000000000011321356264674700160610ustar00rootroot00000000000000.\" .\" apkinfo(1) .\" .\" Copyright (C) 2018 Andres Salomon .TH apkinfo 1 "June 2018" .SH NAME apkinfo \- display information about an Android APK file .SH SYNOPSIS .B apkinfo [\fI\,OPTIONS\/\fR] \fI\,FILENAME\/\fR .SH OPTIONS .TP \fB\-\-help\fR Show a list of possible options and exit. .SH DESCRIPTION .B apkinfo is a tool to display information about a downloaded Android APK file. .B apkinfo displays APK metadata such as package, version, and naming information. This man page was contributed by Andres Salomon for the Debian GNU/Linux system (but may be used by others). pyaxmlparser-0.3.24/circle.yml000066400000000000000000000004361356264674700163420ustar00rootroot00000000000000machine: python: version: 3.6.0 dependencies: override: - pip install -r requirements.txt - pip install codecov test: override: - flake8 - coverage run --source=pyaxmlparser -m pytest -vx --ff - coverage report -m post: - codecov -t $CODECOV_TOKEN pyaxmlparser-0.3.24/examples/000077500000000000000000000000001356264674700161715ustar00rootroot00000000000000pyaxmlparser-0.3.24/examples/get_app_name.py000066400000000000000000000012301356264674700211560ustar00rootroot00000000000000""" Usage: python get_app_name.py /path/to/extracted/apk/dir """ import sys from pyaxmlparser.arscparser import ARSCParser from pyaxmlparser.axmlprinter import AXMLPrinter app_root = sys.argv[1] xml = AXMLPrinter(open("{}/AndroidManifest.xml".format(app_root), 'rb').read()).get_xml_obj() rsc = ARSCParser(open("{}/resources.arsc".format(app_root), "rb").read()) app_name_hex = xml.getElementsByTagName("application")[0].getAttribute("android:label") app_name = '0x' + app_name_hex[1:] app_name = rsc.get_string( rsc.get_packages_names()[0], rsc.get_id(rsc.get_packages_names()[0], int(app_name, 0))[1] ) print('App name is "{}"'.format(app_name[1])) pyaxmlparser-0.3.24/pyaxmlparser/000077500000000000000000000000001356264674700171025ustar00rootroot00000000000000pyaxmlparser-0.3.24/pyaxmlparser/__init__.py000066400000000000000000000000621356264674700212110ustar00rootroot00000000000000# flake8: noqa from pyaxmlparser.core import APK pyaxmlparser-0.3.24/pyaxmlparser/arscparser.py000066400000000000000000000730511356264674700216270ustar00rootroot00000000000000# This file is part of Androguard. # # Copyright (C) 2012/2013, Anthony Desnos # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS-IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import logging from pyaxmlparser import bytecode import collections from struct import unpack from pyaxmlparser.arscutil import ARSCHeader, ARSCResTablePackage, \ ARSCResTypeSpec, ARSCResType, ARSCResTableEntry, ARSCResTableConfig from pyaxmlparser.stringblock import StringBlock import pyaxmlparser.constants as const from pyaxmlparser.utils import complexToFloat from xml.sax.saxutils import escape log = logging.getLogger("pyaxmlparser.arscparser") class ARSCParser(object): """ Parser for resource.arsc files """ def __init__(self, raw_buff): self.analyzed = False self._resolved_strings = None self.buff = bytecode.BuffHandle(raw_buff) self.header = ARSCHeader(self.buff) # TODO: assert header type self.packageCount = unpack(' data_end: # this inner chunk crosses the boundary of the table chunk break if res_header.type == const.RES_STRING_POOL_TYPE and not self.stringpool_main: self.stringpool_main = StringBlock(self.buff, res_header) elif res_header.type == const.RES_TABLE_PACKAGE_TYPE: assert len(self.packages) < self.packageCount, "Got more packages than expected" current_package = ARSCResTablePackage(self.buff, res_header) package_name = current_package.get_name() package_data_end = res_header.start + res_header.size self.packages[package_name] = [] # After the Header, we have the resource type symbol table self.buff.set_idx(current_package.header.start + current_package.typeStrings) type_sp_header = ARSCHeader(self.buff) assert type_sp_header.type == const.RES_STRING_POOL_TYPE, \ "Expected String Pool header, got %x" % type_sp_header.type mTableStrings = StringBlock(self.buff, type_sp_header) # Next, we should have the resource key symbol table self.buff.set_idx(current_package.header.start + current_package.keyStrings) key_sp_header = ARSCHeader(self.buff) assert key_sp_header.type == const.RES_STRING_POOL_TYPE, \ "Expected String Pool header, got %x" % key_sp_header.type mKeyStrings = StringBlock(self.buff, key_sp_header) # Add them to the dict of read packages self.packages[package_name].append(current_package) self.packages[package_name].append(mTableStrings) self.packages[package_name].append(mKeyStrings) pc = PackageContext(current_package, self.stringpool_main, mTableStrings, mKeyStrings) # skip to the first header in this table package chunk # FIXME is this correct? We have already read the first two sections! # self.buff.set_idx(res_header.start + res_header.header_size) # this looks more like we want: (???) self.buff.set_idx(res_header.start + res_header.header_size + type_sp_header.size + key_sp_header.size) # Read all other headers while self.buff.get_idx() <= package_data_end - ARSCHeader.SIZE: pkg_chunk_header = ARSCHeader(self.buff) log.debug("Found a header: {}".format(pkg_chunk_header)) if pkg_chunk_header.start + pkg_chunk_header.size > package_data_end: # we are way off the package chunk; bail out break self.packages[package_name].append(pkg_chunk_header) if pkg_chunk_header.type == const.RES_TABLE_TYPE_SPEC_TYPE: self.packages[package_name].append(ARSCResTypeSpec(self.buff, pc)) elif pkg_chunk_header.type == const.RES_TABLE_TYPE_TYPE: a_res_type = ARSCResType(self.buff, pc) self.packages[package_name].append(a_res_type) self.resource_configs[package_name][a_res_type].add(a_res_type.config) log.debug("Config: {}".format(a_res_type.config)) entries = [] for i in range(0, a_res_type.entryCount): current_package.mResId = current_package.mResId & 0xffff0000 | i entries.append((unpack('> 24) & 0xFF), ((entry_data >> 16) & 0xFF), ((entry_data >> 8) & 0xFF), (entry_data & 0xFF)) ] def get_resource_dimen(self, ate): try: return [ ate.get_value(), "%s%s" % ( complexToFloat(ate.key.get_data()), const.DIMENSION_UNITS[ate.key.get_data() & const.COMPLEX_UNIT_MASK]) ] except IndexError: log.debug("Out of range dimension unit index for %s: %s" % ( complexToFloat(ate.key.get_data()), ate.key.get_data() & const.COMPLEX_UNIT_MASK)) return [ate.get_value(), ate.key.get_data()] # FIXME def get_resource_style(self, ate): return ["", ""] def get_packages_names(self): """ Retrieve a list of all package names, which are available in the given resources.arsc. """ return list(self.packages.keys()) def get_locales(self, package_name): """ Retrieve a list of all available locales in a given packagename. :param package_name: the package name to get locales of """ self._analyse() return list(self.values[package_name].keys()) def get_types(self, package_name, locale='\x00\x00'): """ Retrieve a list of all types which are available in the given package and locale. :param package_name: the package name to get types of :param locale: the locale to get types of (default: '\x00\x00') """ self._analyse() return list(self.values[package_name][locale].keys()) def get_public_resources(self, package_name, locale='\x00\x00'): """ Get the XML (as string) of all resources of type 'public'. The public resources table contains the IDs for each item. :param package_name: the package name to get the resources for :param locale: the locale to get the resources for (default: '\x00\x00') """ self._analyse() buff = '\n' buff += '\n' try: for i in self.values[package_name][locale]["public"]: buff += '\n' % ( i[0], i[1], i[2]) except KeyError: pass buff += '\n' return buff.encode('utf-8') def get_string_resources(self, package_name, locale='\x00\x00'): """ Get the XML (as string) of all resources of type 'string'. Read more about string resources: https://developer.android.com/guide/topics/resources/string-resource.html :param package_name: the package name to get the resources for :param locale: the locale to get the resources for (default: '\x00\x00') """ self._analyse() buff = '\n' buff += '\n' try: for i in self.values[package_name][locale]["string"]: if any(map(i[1].__contains__, '<&>')): value = '' % i[1] else: value = i[1] buff += '%s\n' % (i[0], value) except KeyError: pass buff += '\n' return buff.encode('utf-8') def get_strings_resources(self): """ Get the XML (as string) of all resources of type 'string'. This is a combined variant, which has all locales and all package names stored. """ self._analyse() buff = '\n' buff += "\n" for package_name in self.get_packages_names(): buff += "\n" % package_name for locale in self.get_locales(package_name): buff += "\n" % repr(locale) buff += '\n' try: for i in self.values[package_name][locale]["string"]: buff += '%s\n' % (i[0], escape(i[1])) except KeyError: pass buff += '\n' buff += '\n' buff += "\n" buff += "\n" return buff.encode('utf-8') def get_id_resources(self, package_name, locale='\x00\x00'): """ Get the XML (as string) of all resources of type 'id'. Read more about ID resources: https://developer.android.com/guide/topics/resources/more-resources.html#Id :param package_name: the package name to get the resources for :param locale: the locale to get the resources for (default: '\x00\x00') """ self._analyse() buff = '\n' buff += '\n' try: for i in self.values[package_name][locale]["id"]: if len(i) == 1: buff += '\n' % (i[0]) else: buff += '%s\n' % (i[0], escape(i[1])) except KeyError: pass buff += '\n' return buff.encode('utf-8') def get_bool_resources(self, package_name, locale='\x00\x00'): """ Get the XML (as string) of all resources of type 'bool'. Read more about bool resources: https://developer.android.com/guide/topics/resources/more-resources.html#Bool :param package_name: the package name to get the resources for :param locale: the locale to get the resources for (default: '\x00\x00') """ self._analyse() buff = '\n' buff += '\n' try: for i in self.values[package_name][locale]["bool"]: buff += '%s\n' % (i[0], i[1]) except KeyError: pass buff += '\n' return buff.encode('utf-8') def get_integer_resources(self, package_name, locale='\x00\x00'): """ Get the XML (as string) of all resources of type 'integer'. Read more about integer resources: https://developer.android.com/guide/topics/resources/more-resources.html#Integer :param package_name: the package name to get the resources for :param locale: the locale to get the resources for (default: '\x00\x00') """ self._analyse() buff = '\n' buff += '\n' try: for i in self.values[package_name][locale]["integer"]: buff += '%s\n' % (i[0], i[1]) except KeyError: pass buff += '\n' return buff.encode('utf-8') def get_color_resources(self, package_name, locale='\x00\x00'): """ Get the XML (as string) of all resources of type 'color'. Read more about color resources: https://developer.android.com/guide/topics/resources/more-resources.html#Color :param package_name: the package name to get the resources for :param locale: the locale to get the resources for (default: '\x00\x00') """ self._analyse() buff = '\n' buff += '\n' try: for i in self.values[package_name][locale]["color"]: buff += '%s\n' % (i[0], i[1]) except KeyError: pass buff += '\n' return buff.encode('utf-8') def get_dimen_resources(self, package_name, locale='\x00\x00'): """ Get the XML (as string) of all resources of type 'dimen'. Read more about Dimension resources: https://developer.android.com/guide/topics/resources/more-resources.html#Dimension :param package_name: the package name to get the resources for :param locale: the locale to get the resources for (default: '\x00\x00') """ self._analyse() buff = '\n' buff += '\n' try: for i in self.values[package_name][locale]["dimen"]: buff += '%s\n' % (i[0], i[1]) except KeyError: pass buff += '\n' return buff.encode('utf-8') def get_id(self, package_name, rid, locale='\x00\x00'): """ Returns the tuple (resource_type, resource_name, resource_id) for the given resource_id. :param package_name: package name to query :param rid: the resource_id :param locale: specific locale :return: tuple of (resource_type, resource_name, resource_id) """ self._analyse() try: for i in self.values[package_name][locale]["public"]: if i[2] == rid: return i except KeyError: pass return None, None, None class ResourceResolver(object): """ Resolves resources by ID """ def __init__(self, android_resources, config=None): self.resources = android_resources self.wanted_config = config def resolve(self, res_id): result = [] self._resolve_into_result(result, res_id, self.wanted_config) return result def _resolve_into_result(self, result, res_id, config): configs = self.resources.get_res_configs(res_id, config) if configs: for config, ate in configs: self.put_ate_value(result, ate, config) def put_ate_value(self, result, ate, config): if ate.is_complex(): complex_array = [] result.append((config, complex_array)) for _, item in ate.item.items: self.put_item_value(complex_array, item, config, complex_=True) else: self.put_item_value(result, ate.key, config, complex_=False) def put_item_value(self, result, item, config, complex_): if item.is_reference(): res_id = item.get_data() if res_id: self._resolve_into_result( result, item.get_data(), self.wanted_config) else: if complex_: result.append(item.format_value()) else: result.append((config, item.format_value())) def get_resolved_res_configs(self, rid, config=None): resolver = ARSCParser.ResourceResolver(self, config) return resolver.resolve(rid) def get_resolved_strings(self): self._analyse() if self._resolved_strings: return self._resolved_strings r = {} for package_name in self.get_packages_names(): r[package_name] = {} k = {} for locale in self.values[package_name]: v_locale = locale if v_locale == '\x00\x00': v_locale = 'DEFAULT' r[package_name][v_locale] = {} try: for i in self.values[package_name][locale]["public"]: if i[0] == 'string': r[package_name][v_locale][i[2]] = None k[i[1]] = i[2] except KeyError: pass try: for i in self.values[package_name][locale]["string"]: if i[0] in k: r[package_name][v_locale][k[i[0]]] = i[1] except KeyError: pass self._resolved_strings = r return r def get_res_configs(self, rid, config=None, fallback=True): """ Return the resources found with the ID `rid` and select the right one based on the configuration, or return all if no configuration was set. But we try to be generous here and at least try to resolve something: This method uses a fallback to return at least one resource (the first one in the list) if more than one items are found and the default config is used and no default entry could be found. This is usually a bad sign (i.e. the developer did not follow the android documentation: https://developer.android.com/guide/topics/resources/localization.html#failing2) In practise an app might just be designed to run on a single locale and thus only has those locales set. You can disable this fallback behaviour, to just return exactly the given result. :param rid: resource id as int :param config: a config to resolve from, or None to get all results :param fallback: Enable the fallback for resolving default configuration (default: True) :return: a list of ARSCResTableConfig: ARSCResTableEntry """ self._analyse() if not rid: raise ValueError("'rid' should be set") if not isinstance(rid, int): raise ValueError("'rid' must be an int") if rid not in self.resource_values: log.info("The requested rid could not be found in the resources.") return [] res_options = self.resource_values[rid] if len(res_options) > 1 and config: if config in res_options: return [(config, res_options[config])] elif fallback and config == ARSCResTableConfig.default_config(): log.warning("No default resource config could be found for the given rid, using fallback!") return [list(self.resource_values[rid].items())[0]] else: return [] else: return list(res_options.items()) def get_string(self, package_name, name, locale='\x00\x00'): self._analyse() try: for i in self.values[package_name][locale]["string"]: if i[0] == name: return i except KeyError: return None def get_res_id_by_key(self, package_name, resource_type, key): try: return self.resource_keys[package_name][resource_type][key] except KeyError: return None def get_items(self, package_name): self._analyse() return self.packages[package_name] def get_type_configs(self, package_name, type_name=None): if package_name is None: package_name = self.get_packages_names()[0] result = collections.defaultdict(list) for res_type, configs in list(self.resource_configs[package_name].items()): if res_type.get_package_name() == package_name and ( type_name is None or res_type.get_type() == type_name): result[res_type.get_type()].extend(configs) return result @staticmethod def parse_id(name): """ Resolves an id from a binary XML file in the form "@[package:]DEADBEEF" and returns a tuple of package name and resource id. If no package name was given, i.e. the ID has the form "@DEADBEEF", the package name is set to None. Raises a ValueError if the id is malformed. :param name: the string of the resource, as in the binary XML file :return: a tuple of (resource_id, package_name). """ if not name.startswith('@'): raise ValueError("Not a valid resource ID, must start with @: '{}'".format(name)) # remove @ name = name[1:] package = None if ':' in name: package, res_id = name.split(':', 1) else: res_id = name if len(res_id) != 8: raise ValueError("Numerical ID is not 8 characters long: '{}'".format(res_id)) try: return int(res_id, 16), package except ValueError: raise ValueError("ID is not a hex ID: '{}'".format(res_id)) def get_resource_xml_name(self, r_id, package=None): """ Returns the XML name for a resource, including the package name if package is None. A full name might look like `@com.example:string/foobar` Otherwise the name is only looked up in the specified package and is returned without the package name. The same example from about without the package name will read as `@string/foobar`. If the ID could not be found, `None` is returned. A description of the XML name can be found here: https://developer.android.com/guide/topics/resources/providing-resources#ResourcesFromXml :param r_id: numerical ID if the resource :param package: package name :return: XML name identifier """ if package: resource, name, i_id = self.get_id(package, r_id) if not i_id: return None return "@{}/{}".format(resource, name) else: for p in self.get_packages_names(): r, n, i_id = self.get_id(p, r_id) if i_id: # found the resource in this package package = p resource = r name = n break if not package: return None else: return "@{}:{}/{}".format(package, resource, name) class PackageContext(object): def __init__(self, current_package, stringpool_main, mTableStrings, mKeyStrings): self.stringpool_main = stringpool_main self.mTableStrings = mTableStrings self.mKeyStrings = mKeyStrings self.current_package = current_package def get_mResId(self): return self.current_package.mResId def set_mResId(self, mResId): self.current_package.mResId = mResId def get_package_name(self): return self.current_package.get_name() pyaxmlparser-0.3.24/pyaxmlparser/arscutil.py000066400000000000000000000550261356264674700213120ustar00rootroot00000000000000# This file is part of Androguard. # # Copyright (C) 2012/2013, Anthony Desnos # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS-IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import logging from struct import unpack import pyaxmlparser.constants as const from pyaxmlparser.utils import format_value log = logging.getLogger("pyaxmlparser.arscutil") class ARSCResTablePackage(object): """ See http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h#861 """ def __init__(self, buff, header): self.header = header self.start = buff.get_idx() self.id = unpack('= self.start + self.SIZE, "Can not read over the buffer size! Offset={}".format(self.start) self._type, self._header_size, self._size = unpack('= self.SIZE, \ "declared header size is smaller than required size of {}! Offset={}".format(self.SIZE, self.start) assert self._size >= self.SIZE, \ "declared chunk size is smaller than required size of {}! Offset={}".format(self.SIZE, self.start) assert self._size >= self._header_size, \ "declared chunk size ({}) is smaller than header size ({})! Offset={}".format(self._size, self._header_size, self.start) @property def type(self): """ Type identifier for this chunk """ return self._type @property def header_size(self): """ Size of the chunk header (in bytes). Adding this value to the address of the chunk allows you to find its associated data (if any). """ return self._header_size @property def size(self): """ Total size of this chunk (in bytes). This is the chunkSize plus the size of any data associated with the chunk. Adding this value to the chunk allows you to completely skip its contents (including any child chunks). If this value is the same as chunkSize, there is no data associated with the chunk. """ return self._size @property def end(self): """ Get the absolute offset inside the file, where the chunk ends. This is equal to `ARSCHeader.start + ARSCHeader.size`. """ return self.start + self.size def __repr__(self): return ( "" ).format(self.start, self.type, self.header_size, self.size) class ARSCResTypeSpec(object): """ See http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h#1327 """ def __init__(self, buff, parent=None): self.start = buff.get_idx() self.parent = parent self.id = unpack('= 32: # struct of # uint8_t screenLayout # uint8_t uiMode # uint16_t smallestScreenWidthDp self.screenConfig, = unpack('= 36: # struct of # uint16_t screenWidthDp # uint16_t screenHeightDp self.screenSizeDp, = unpack('= 40: # struct of # uint8_t screenLayout2 # uint8_t colorMode # uint16_t screenConfigPad2 self.screenConfig2, = unpack(" 0: log.debug("Skipping padding bytes!") self.padding = buff.read(self.exceedingSize) else: self.start = 0 self.size = 0 self.imsi = \ ((kwargs.pop('mcc', 0) & 0xffff) << 0) + \ ((kwargs.pop('mnc', 0) & 0xffff) << 16) self.locale = 0 for char_ix, char in kwargs.pop('locale', "")[0:4]: self.locale += (ord(char) << (char_ix * 8)) self.screenType = \ ((kwargs.pop('orientation', 0) & 0xff) << 0) + \ ((kwargs.pop('touchscreen', 0) & 0xff) << 8) + \ ((kwargs.pop('density', 0) & 0xffff) << 16) self.input = \ ((kwargs.pop('keyboard', 0) & 0xff) << 0) + \ ((kwargs.pop('navigation', 0) & 0xff) << 8) + \ ((kwargs.pop('inputFlags', 0) & 0xff) << 16) + \ ((kwargs.pop('inputPad0', 0) & 0xff) << 24) self.screenSize = \ ((kwargs.pop('screenWidth', 0) & 0xffff) << 0) + \ ((kwargs.pop('screenHeight', 0) & 0xffff) << 16) self.version = \ ((kwargs.pop('sdkVersion', 0) & 0xffff) << 0) + \ ((kwargs.pop('minorVersion', 0) & 0xffff) << 16) self.screenConfig = \ ((kwargs.pop('screenLayout', 0) & 0xff) << 0) + \ ((kwargs.pop('uiMode', 0) & 0xff) << 8) + \ ((kwargs.pop('smallestScreenWidthDp', 0) & 0xffff) << 16) self.screenSizeDp = \ ((kwargs.pop('screenWidthDp', 0) & 0xffff) << 0) + \ ((kwargs.pop('screenHeightDp', 0) & 0xffff) << 16) # TODO add this some day... self.screenConfig2 = 0 self.exceedingSize = 0 def _unpack_language_or_region(self, char_in, char_base): char_out = "" if char_in[0] & 0x80: first = char_in[1] & 0x1f second = ((char_in[1] & 0xe0) >> 5) + ((char_in[0] & 0x03) << 3) third = (char_in[0] & 0x7c) >> 2 char_out += chr(first + char_base) char_out += chr(second + char_base) char_out += chr(third + char_base) else: if char_in[0]: char_out += chr(char_in[0]) if char_in[1]: char_out += chr(char_in[1]) return char_out def get_language_and_region(self): """ Returns the combined language+region string or \x00\x00 for the default locale :return: """ if self.locale != 0: _language = self._unpack_language_or_region( [self.locale & 0xff, (self.locale & 0xff00) >> 8, ], ord('a')) _region = self._unpack_language_or_region( [ (self.locale & 0xff0000) >> 16, (self.locale & 0xff000000) >> 24, ], ord('0') ) return (_language + "-r" + _region) if _region else _language return "\x00\x00" def get_config_name_friendly(self): """ Here for legacy reasons. use :meth:`~get_qualifier` instead. """ return self.get_qualifier() def get_qualifier(self): """ Return resource name qualifier for the current configuration. for example * `ldpi-v4` * `hdpi-v4` All possible qualifiers are listed in table 2 of https://developer.android.com/guide /topics/resources/providing-resources FIXME: This name might not have all properties set! :return: str """ res = [] mcc = self.imsi & 0xFFFF mnc = (self.imsi & 0xFFFF0000) >> 16 if mcc != 0: res.append("mcc%d" % mcc) if mnc != 0: res.append("mnc%d" % mnc) if self.locale != 0: res.append(self.get_language_and_region()) screenLayout = self.screenConfig & 0xff if (screenLayout & const.MASK_LAYOUTDIR) != 0: if screenLayout & const.MASK_LAYOUTDIR == const.LAYOUTDIR_LTR: res.append("ldltr") elif screenLayout & const.MASK_LAYOUTDIR == const.LAYOUTDIR_RTL: res.append("ldrtl") else: res.append("layoutDir_%d" % (screenLayout & const.MASK_LAYOUTDIR)) smallestScreenWidthDp = (self.screenConfig & 0xFFFF0000) >> 16 if smallestScreenWidthDp != 0: res.append("sw%ddp" % smallestScreenWidthDp) screenWidthDp = self.screenSizeDp & 0xFFFF screenHeightDp = (self.screenSizeDp & 0xFFFF0000) >> 16 if screenWidthDp != 0: res.append("w%ddp" % screenWidthDp) if screenHeightDp != 0: res.append("h%ddp" % screenHeightDp) if (screenLayout & const.MASK_SCREENSIZE) != const.SCREENSIZE_ANY: if screenLayout & const.MASK_SCREENSIZE == const.SCREENSIZE_SMALL: res.append("small") elif screenLayout & const.MASK_SCREENSIZE == const.SCREENSIZE_NORMAL: res.append("normal") elif screenLayout & const.MASK_SCREENSIZE == const.SCREENSIZE_LARGE: res.append("large") elif screenLayout & const.MASK_SCREENSIZE == const.SCREENSIZE_XLARGE: res.append("xlarge") else: res.append("screenLayoutSize_%d" % (screenLayout & const.MASK_SCREENSIZE)) if (screenLayout & const.MASK_SCREENLONG) != 0: if screenLayout & const.MASK_SCREENLONG == const.SCREENLONG_NO: res.append("notlong") elif screenLayout & const.MASK_SCREENLONG == const.SCREENLONG_YES: res.append("long") else: res.append("screenLayoutLong_%d" % (screenLayout & const.MASK_SCREENLONG)) density = (self.screenType & 0xffff0000) >> 16 if density != const.DENSITY_DEFAULT: if density == const.DENSITY_LOW: res.append("ldpi") elif density == const.DENSITY_MEDIUM: res.append("mdpi") elif density == const.DENSITY_TV: res.append("tvdpi") elif density == const.DENSITY_HIGH: res.append("hdpi") elif density == const.DENSITY_XHIGH: res.append("xhdpi") elif density == const.DENSITY_XXHIGH: res.append("xxhdpi") elif density == const.DENSITY_XXXHIGH: res.append("xxxhdpi") elif density == const.DENSITY_NONE: res.append("nodpi") elif density == const.DENSITY_ANY: res.append("anydpi") else: res.append("%ddpi" % (density)) touchscreen = (self.screenType & 0xff00) >> 8 if touchscreen != const.TOUCHSCREEN_ANY: if touchscreen == const.TOUCHSCREEN_NOTOUCH: res.append("notouch") elif touchscreen == const.TOUCHSCREEN_FINGER: res.append("finger") elif touchscreen == const.TOUCHSCREEN_STYLUS: res.append("stylus") else: res.append("touchscreen_%d" % touchscreen) screenSize = self.screenSize if screenSize != 0: screenWidth = self.screenSize & 0xffff screenHeight = (self.screenSize & 0xffff0000) >> 16 res.append("%dx%d" % (screenWidth, screenHeight)) version = self.version if version != 0: sdkVersion = self.version & 0xffff minorVersion = (self.version & 0xffff0000) >> 16 res.append("v%d" % sdkVersion) if minorVersion != 0: res.append(".%d" % minorVersion) return "-".join(res) def get_language(self): x = self.locale & 0x0000ffff return chr(x & 0x00ff) + chr((x & 0xff00) >> 8) def get_country(self): x = (self.locale & 0xffff0000) >> 16 return chr(x & 0x00ff) + chr((x & 0xff00) >> 8) def get_density(self): x = ((self.screenType >> 16) & 0xffff) return x def is_default(self): """ Test if this is a default resource, which matches all This is indicated that all fields are zero. :return: True if default, False otherwise """ return all(map(lambda x: x == 0, self._get_tuple())) def _get_tuple(self): return ( self.imsi, self.locale, self.screenType, self.input, self.screenSize, self.version, self.screenConfig, self.screenSizeDp, self.screenConfig2, ) def __hash__(self): return hash(self._get_tuple()) def __eq__(self, other): return self._get_tuple() == other._get_tuple() def __repr__(self): return "".format(self.get_qualifier(), repr(self._get_tuple())) class ARSCResTableEntry(object): """ See https://github.com/LineageOS/android_frameworks_base/blob/ df2898d9ce306bb2fe922d3beaa34a9cf6873d27/include/androidfw/ResourceTypes.h#L1370 """ FLAG_COMPLEX = 1 FLAG_PUBLIC = 2 FLAG_WEAK = 4 def __init__(self, buff, mResId, parent=None): self.start = buff.get_idx() self.mResId = mResId self.parent = parent self.size = unpack('" ).format( self.start, self.mResId, self.size, self.flags, self.index, self.item if self.is_complex() else self.key) class ARSCComplex(object): def __init__(self, buff, parent=None): self.start = buff.get_idx() self.parent = parent self.id_parent = unpack('".format(self.start, self.id_parent, self.count) class ARSCResStringPoolRef(object): def __init__(self, buff, parent=None): self.start = buff.get_idx() self.parent = parent self.size, = unpack("".format( self.start, self.size, const.TYPE_TABLE.get(self.data_type, "0x%x" % self.data_type), self.data) def get_arsc_info(arscobj): """ Return a string containing all resources packages ordered by packagename, locale and type. :param arscobj: :class:`~ARSCParser` :return: a string """ buff = "" for package in arscobj.get_packages_names(): buff += package + ":\n" for locale in arscobj.get_locales(package): buff += "\t" + repr(locale) + ":\n" for ttype in arscobj.get_types(package, locale): buff += "\t\t" + ttype + ":\n" try: tmp_buff = getattr(arscobj, "get_" + ttype + "_resources")( package, locale).decode("utf-8", 'replace').split("\n") for i in tmp_buff: buff += "\t\t\t" + i + "\n" except AttributeError: pass return buff pyaxmlparser-0.3.24/pyaxmlparser/axmlparser.py000066400000000000000000000515561356264674700216460ustar00rootroot00000000000000# This file is part of Androguard. # # Copyright (C) 2012, Anthony Desnos # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS-IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import logging from struct import unpack import pyaxmlparser.constants as const from pyaxmlparser import bytecode from pyaxmlparser.stringblock import StringBlock from pyaxmlparser.resources import public from .arscutil import ARSCHeader log = logging.getLogger("pyaxmlparser.axmlparser") class AXMLParser(object): """ AXMLParser reads through all chunks in the AXML file and implements a state machine to return information about the current chunk, which can then be read by :class:`~AXMLPrinter`. An AXML file is a file which contains multiple chunks of data, defined by the `ResChunk_header`. There is no real file magic but as the size of the first header is fixed and the `type` of the `ResChunk_header` is set to `RES_XML_TYPE`, a file will usually start with `0x03000800`. But there are several examples where the `type` is set to something else, probably in order to fool parsers. Typically the AXMLParser is used in a loop which terminates if `m_event` is set to `END_DOCUMENT`. You can use the `next()` function to get the next chunk. Note that not all chunk types are yielded from the iterator! Some chunks are processed in the AXMLParser only. The parser will set `is_valid()` to False if it parses something not valid. Messages what is wrong are logged. See http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h#563 """ def __init__(self, raw_buff): self._reset() self._valid = True self.axml_tampered = False self.buff = bytecode.BuffHandle(raw_buff) # Minimum is a single ARSCHeader, which would be a strange edge case... if self.buff.size() < 8: log.error("Filesize is too small to be a valid AXML file! Filesize: {}".format(self.buff.size())) self._valid = False return # This would be even stranger, if an AXML file is larger than 4GB... # But this is not possible as the maximum chunk size is a unsigned 4 byte int. if self.buff.size() > 0xFFFFFFFF: log.error("Filesize is too large to be a valid AXML file! Filesize: {}".format(self.buff.size())) self._valid = False return try: axml_header = ARSCHeader(self.buff) except AssertionError as e: log.error("Error parsing first resource header: %s", e) self._valid = False return self.filesize = axml_header.size if axml_header.header_size == 28024: # Can be a common error: the file is not an AXML but a plain XML # The file will then usually start with ' self.buff.size(): log.error( "This does not look like an AXML file. " "Declared filesize does not match real size: {} vs {}".format( self.filesize, self.buff.size() ) ) self._valid = False return if self.filesize < self.buff.size(): # The file can still be parsed up to the point where the chunk should end. self.axml_tampered = True log.warning( "Declared filesize ({}) is smaller than total file size ({}). " "Was something appended to the file? Trying to parse it anyways.".format( self.filesize, self.buff.size() ) ) # Not that severe of an error, we have plenty files where this is not # set correctly if axml_header.type != const.RES_XML_TYPE: self.axml_tampered = True log.warning( "AXML file has an unusual resource type! " "Malware likes to to such stuff to anti androguard! " "But we try to parse it anyways. " "Resource Type: 0x{:04x}".format(axml_header.type) ) # Now we parse the STRING POOL try: header = ARSCHeader(self.buff) except AssertionError as e: log.error("Error parsing resource header of string pool: %s", e) self._valid = False return if header.header_size != 0x1C: log.error( "This does not look like an AXML file. String chunk header " "size does not equal 28! header size = {}".format( header.header_size ) ) self._valid = False return if header.type != const.RES_STRING_POOL_TYPE: log.error( "Expected String Pool header, got resource type 0x{:04x} " "instead".format(header.type) ) self._valid = False return self.sb = StringBlock(self.buff, header) # Stores resource ID mappings, if any self.m_resourceIDs = [] # Store a list of prefix/uri mappings encountered self.namespaces = [] def is_valid(self): """ Get the state of the AXMLPrinter. if an error happend somewhere in the process of parsing the file, this flag is set to False. """ return self._valid def _reset(self): self.m_event = -1 self.m_lineNumber = -1 self.m_name = -1 self.m_namespaceUri = -1 self.m_attributes = [] self.m_idAttribute = -1 self.m_classAttribute = -1 self.m_styleAttribute = -1 def __next__(self): self._do_next() return self.m_event next = __next__ # For Python 2 compatibility def _do_next(self): if self.m_event == const.END_DOCUMENT: return self._reset() while self._valid: # Stop at the declared filesize or at the end of the file if self.buff.end() or self.buff.get_idx() == self.filesize: self.m_event = const.END_DOCUMENT break # Again, we read an ARSCHeader try: h = ARSCHeader(self.buff) except AssertionError as e: log.error("Error parsing resource header: %s", e) self._valid = False return # Special chunk: Resource Map. This chunk might be contained inside # the file, after the string pool. if h.type == const.RES_XML_RESOURCE_MAP_TYPE: log.debug("AXML contains a RESOURCE MAP") # Check size: < 8 bytes mean that the chunk is not complete # Should be aligned to 4 bytes. if h.size < 8 or (h.size % 4) != 0: log.error("Invalid chunk size in chunk XML_RESOURCE_MAP") self._valid = False return for i in range((h.size - h.header_size) // 4): self.m_resourceIDs.append(unpack(' const.RES_XML_LAST_CHUNK_TYPE: # h.size is the size of the whole chunk including the header. # We read already 8 bytes of the header, thus we need to # subtract them. log.error("Not a XML resource chunk type: 0x{:04x}. Skipping {} bytes".format(h.type, h.size)) self.buff.set_idx(h.end) continue # Check that we read a correct header if h.header_size != 0x10: log.error( "XML Resource Type Chunk header size does not match 16! " "At chunk type 0x{:04x}, declared header size={}, " "chunk size={}".format(h.type, h.header_size, h.size) ) self._valid = False return # Line Number of the source file, only used as meta information self.m_lineNumber, = unpack(' uri {}: '{}'".format( prefix, s_prefix, uri, s_uri ) ) if s_uri == '': log.warning("Namespace prefix '{}' resolves to empty URI. " "This might be a packer.".format(s_prefix)) if (prefix, uri) in self.namespaces: log.info( "Namespace mapping ({}, {}) already seen! " "This is usually not a problem but could indicate " "packers or broken AXML compilers.".format(prefix, uri)) self.namespaces.append((prefix, uri)) # We can continue with the next chunk, as we store the namespace # mappings for each tag continue if h.type == const.RES_XML_END_NAMESPACE_TYPE: # END_PREFIX contains again prefix and uri field prefix, = unpack('> 16) - 1 self.m_attribute_count = attributeCount & 0xFFFF self.m_styleAttribute = (self.m_classAttribute >> 16) - 1 self.m_classAttribute = (self.m_classAttribute & 0xFFFF) - 1 # Now, we parse the attributes. # Each attribute has 5 fields of 4 byte for i in range(0, self.m_attribute_count * const.ATTRIBUTE_LENGHT): # Each field is linearly parsed into the array # Each Attribute contains: # * Namespace URI (String ID) # * Name (String ID) # * Value # * Type # * Data self.m_attributes.append(unpack('> 24 self.m_event = const.START_TAG break if h.type == const.RES_XML_END_ELEMENT_TYPE: self.m_namespaceUri, = unpack(' uint32_t index self.m_name, = unpack(' always zero # uint8_t dataType # uint32_t data # For now, we ingore these values size, res0, dataType, data = unpack("= len(self.m_attributes): log.warning("Invalid attribute index") return offset def getAttributeCount(self): """ Return the number of Attributes for a Tag or -1 if not in a tag """ if self.m_event != const.START_TAG: return -1 return self.m_attribute_count def getAttributeUri(self, index): """ Returns the numeric ID for the namespace URI of an attribute """ offset = self._get_attribute_offset(index) uri = self.m_attributes[offset + const.ATTRIBUTE_IX_NAMESPACE_URI] return uri def getAttributeNamespace(self, index): """ Return the Namespace URI (if any) for the attribute """ uri = self.getAttributeUri(index) # No Namespace if uri == 0xFFFFFFFF: return u'' return self.sb[uri] def getAttributeName(self, index): """ Returns the String which represents the attribute name """ offset = self._get_attribute_offset(index) name = self.m_attributes[offset + const.ATTRIBUTE_IX_NAME] res = self.sb[name] # If the result is a (null) string, we need to look it up. if not res: attr = self.m_resourceIDs[name] if attr in public.SYSTEM_RESOURCES['attributes']['inverse']: res = 'android:' + public.SYSTEM_RESOURCES['attributes']['inverse'][attr] else: # Attach the HEX Number, so for multiple missing attributes we do not run # into problems. res = 'android:UNKNOWN_SYSTEM_ATTRIBUTE_{:08x}'.format(attr) return res def getAttributeValueType(self, index): """ Return the type of the attribute at the given index :param index: index of the attribute """ offset = self._get_attribute_offset(index) return self.m_attributes[offset + const.ATTRIBUTE_IX_VALUE_TYPE] def getAttributeValueData(self, index): """ Return the data of the attribute at the given index :param index: index of the attribute """ offset = self._get_attribute_offset(index) return self.m_attributes[offset + const.ATTRIBUTE_IX_VALUE_DATA] def getAttributeValue(self, index): """ This function is only used to look up strings All other work is done by :func:`~androguard.core.bytecodes.axml.format_value` # FIXME should unite those functions :param index: index of the attribute :return: """ offset = self._get_attribute_offset(index) valueType = self.m_attributes[offset + const.ATTRIBUTE_IX_VALUE_TYPE] if valueType == const.TYPE_STRING: valueString = self.m_attributes[offset + const.ATTRIBUTE_IX_VALUE_STRING] return self.sb[valueString] return u'' pyaxmlparser-0.3.24/pyaxmlparser/axmlprinter.py000066400000000000000000000226331356264674700220270ustar00rootroot00000000000000# This file is part of Androguard. # # Copyright (C) 2012, Anthony Desnos # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS-IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import re import sys import binascii import logging from pyaxmlparser.axmlparser import AXMLParser from pyaxmlparser.utils import format_value import pyaxmlparser.constants as const from lxml import etree log = logging.getLogger("pyaxmlparser.axmlprinter") class AXMLPrinter: """ Converter for AXML Files into a lxml ElementTree, which can easily be converted into XML. A Reference Implementation can be found at http://androidxref.com/9.0.0_r3/ xref/frameworks/base/tools/aapt/XMLNode.cpp """ __charrange = None __replacement = None def __init__(self, raw_buff): self.axml = AXMLParser(raw_buff) self.root = None self.packerwarning = False cur = [] while self.axml.is_valid(): _type = next(self.axml) if _type == const.START_TAG: name = self._fix_name(self.axml.name) uri = self._print_namespace(self.axml.namespace) tag = "{}{}".format(uri, name) comment = self.axml.comment if comment: if self.root is None: log.warning("Can not attach comment with content '{}' without root!".format(comment)) else: cur[-1].append(etree.Comment(comment)) log.debug("START_TAG: {} (line={})".format(tag, self.axml.m_lineNumber)) elem = etree.Element(tag, nsmap=self.axml.nsmap) for i in range(self.axml.getAttributeCount()): uri = self._print_namespace(self.axml.getAttributeNamespace(i)) name = self._fix_name(self.axml.getAttributeName(i)) value = self._fix_value(self._get_attribute_value(i)) log.debug("found an attribute: {}{}='{}'".format(uri, name, value.encode("utf-8"))) if "{}{}".format(uri, name) in elem.attrib: log.warning("Duplicate attribute '{}{}'! Will overwrite!".format(uri, name)) elem.set("{}{}".format(uri, name), value) if self.root is None: self.root = elem else: if not cur: # looks like we lost the root? log.error("No more elements available to attach to! Is the XML malformed?") break cur[-1].append(elem) cur.append(elem) if _type == const.END_TAG: if not cur: log.warning("Too many END_TAG! No more elements available to attach to!") name = self.axml.name uri = self._print_namespace(self.axml.namespace) tag = "{}{}".format(uri, name) if cur[-1].tag != tag: log.warning( "Closing tag '{}' does not match current stack! " "At line number: {}. Is the XML malformed?".format( self.axml.name, self.axml.m_lineNumber ) ) cur.pop() if _type == const.TEXT: log.debug("TEXT for {}".format(cur[-1])) cur[-1].text = self.axml.text if _type == const.END_DOCUMENT: # Check if all namespace mappings are closed if len(self.axml.namespaces) > 0: log.warning( "Not all namespace mappings were closed! Malformed AXML?") break def get_buff(self): """ Returns the raw XML file without prettification applied. :returns: bytes, encoded as UTF-8 """ return self.get_xml(pretty=False) def get_xml(self, pretty=True): """ Get the XML as an UTF-8 string :returns: bytes encoded as UTF-8 """ return etree.tostring(self.root, encoding="utf-8", pretty_print=pretty) def get_xml_obj(self): """ Get the XML as an ElementTree object :returns: :class:`lxml.etree.Element` """ return self.root def is_valid(self): """ Return the state of the AXMLParser. If this flag is set to False, the parsing has failed, thus the resulting XML will not work or will even be empty. """ return self.axml.is_valid() def is_packed(self): """ Returns True if the AXML is likely to be packed Packers do some weird stuff and we try to detect it. Sometimes the files are not packed but simply broken or compiled with some broken version of a tool. Some file corruption might also be appear to be a packed file. :returns: True if packer detected, False otherwise """ return self.packerwarning def _get_attribute_value(self, index): """ Wrapper function for format_value to resolve the actual value of an attribute in a tag :param index: index of the current attribute :return: formatted value """ _type = self.axml.getAttributeValueType(index) _data = self.axml.getAttributeValueData(index) return format_value(_type, _data, lambda _: self.axml.getAttributeValue(index)) def _fix_name(self, name): """ Apply some fixes to element named and attribute names. Try to get conform to: > Like element names, attribute names are case-sensitive and must start with a letter or underscore. > The rest of the name can contain letters, digits, hyphens, underscores, and periods. See: https://msdn.microsoft.com/en-us/library/ms256152(v=vs.110).aspx :param name: Name of the attribute :return: a fixed version of the name """ if not name[0].isalpha() and name[0] != "_": log.warning("Invalid start for name '{}'".format(name)) self.packerwarning = True name = "_{}".format(name) if name.startswith("android:"): # Seems be a common thing... # Actually this means that the Manifest is likely to be broken, as # usually no namespace URI is set in this case. log.warning( "Name '{}' starts with 'android:' prefix! " "The Manifest seems to be broken? Removing prefix.".format( name ) ) self.packerwarning = True name = name[len("android:"):] if ":" in name: # Print out an extra warning log.warning("Name seems to contain a namespace prefix: '{}'".format(name)) if not re.match(r"^[a-zA-Z0-9._-]*$", name): log.warning("Name '{}' contains invalid characters!".format(name)) self.packerwarning = True name = re.sub(r"[^a-zA-Z0-9._-]", "_", name) return name def _fix_value(self, value): """ Return a cleaned version of a value according to the specification: > Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] See https://www.w3.org/TR/xml/#charsets :param value: a value to clean :return: the cleaned value """ if not self.__charrange or not self.__replacement: if sys.maxunicode == 0xFFFF: # Fix for python 2.x, surrogate pairs does not match in regex self.__charrange = re.compile( u'^([\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD]|[\uD800-\uDBFF][\uDC00-\uDFFF])*$') # TODO: this regex is slightly wrong... surrogates are not matched as pairs. self.__replacement = re.compile(u'[^\u0020-\uDBFF\u0009\u000A\u000D\uE000-\uFFFD\uDC00-\uDFFF]') else: self.__charrange = re.compile(u'^[\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]*$') self.__replacement = re.compile(u'[^\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]') # Reading string until \x00. This is the same as aapt does. if "\x00" in value: self.packerwarning = True log.warning( "Null byte found in attribute value at position {}: " "Value(hex): '{}'".format( value.find("\x00"), binascii.hexlify(value.encode("utf-8")) ) ) value = value[:value.find("\x00")] if not self.__charrange.match(value): log.warning("Invalid character in value found. Replacing with '_'.") self.packerwarning = True value = self.__replacement.sub('_', value) return value def _print_namespace(self, uri): if uri != "": uri = "{{{}}}".format(uri) return uri pyaxmlparser-0.3.24/pyaxmlparser/bytecode.py000066400000000000000000000172641356264674700212640ustar00rootroot00000000000000from __future__ import print_function from __future__ import absolute_import from builtins import str from builtins import object from struct import unpack, pack import logging log = logging.getLogger("pyaxmlparser.bytecode") # Handle exit message def Exit(msg): log.warning("Error : " + msg) raise Exception("oops") class SV(object): def __init__(self, size, buff): self.__size = size self.__value = unpack(self.__size, buff)[0] def _get(self): return pack(self.__size, self.__value) def __str__(self): return "0x%x" % self.__value def __int__(self): return self.__value def get_value_buff(self): return self._get() def get_value(self): return self.__value def set_value(self, attr): self.__value = attr class SVs(object): def __init__(self, size, ntuple, buff): self.__size = size self.__value = ntuple._make(unpack(self.__size, buff)) def _get(self): l = [] for i in self.__value._fields: l.append(getattr(self.__value, i)) return pack(self.__size, *l) def _export(self): return [x for x in self.__value._fields] def get_value_buff(self): return self._get() def get_value(self): return self.__value def set_value(self, attr): self.__value = self.__value._replace(**attr) def __str__(self): return self.__value.__str__() def object_to_bytes(obj): """ Convert a object to a bytearray or call get_raw() of the object if no useful type was found. """ if isinstance(obj, str): return bytearray(obj, "UTF-8") elif isinstance(obj, bool): return bytearray() elif isinstance(obj, int): return pack("= len(self.__buff) def get_buff(self): """ Return the whole buffer :rtype: bytearray """ return self.__buff def set_buff(self, buff): """ Overwrite the current buffer with the content of `buff` :param bytearray buff: the new buffer """ self.__buff = buff def save(self, filename): """ Save the current buffer to `filename` Exisiting files with the same name will be overwritten. :param str filename: the name of the file to save to """ with open(filename, "wb") as fd: fd.write(self.__buff) class Buff(object): def __init__(self, offset, buff): self.offset = offset self.buff = buff self.size = len(buff) # Here for legacy reasons. Might get removed some day... _Bytecode = BuffHandle def FormatClassToJava(i): """ Transform a java class name into the typed variant found in DEX files. example:: >>> FormatClassToJava('java.lang.Object') 'Ljava/lang/Object;' :param i: the input class name :rtype: str """ return "L" + i.replace(".", "/") + ";" def FormatClassToPython(i): """ Transform a typed class name into a form which can be used as a python attribute example:: >>> FormatClassToPython('Lfoo/bar/foo/Barfoo$InnerClass;') 'Lfoo_bar_foo_Barfoo_InnerClass' :param i: classname to transform :rtype: str """ i = i[:-1] i = i.replace("/", "_") i = i.replace("$", "_") return i def FormatNameToPython(i): """ Transform a (method) name into a form which can be used as a python attribute example:: >>> FormatNameToPython('') 'clinit' :param i: name to transform :rtype: str """ i = i.replace("<", "") i = i.replace(">", "") i = i.replace("$", "_") return i def FormatDescriptorToPython(i): """ Format a descriptor into a form which can be used as a python attribute example:: >>> FormatDescriptorToPython('(Ljava/lang/Long; Ljava/lang/Long; Z Z)V') 'Ljava_lang_LongLjava_lang_LongZZV :param i: name to transform :rtype: str """ i = i.replace("/", "_") i = i.replace(";", "") i = i.replace("[", "") i = i.replace("(", "") i = i.replace(")", "") i = i.replace(" ", "") i = i.replace("$", "") return i class Node(object): def __init__(self, n, s): self.id = n self.title = s self.children = [] pyaxmlparser-0.3.24/pyaxmlparser/cli.py000066400000000000000000000007161356264674700202270ustar00rootroot00000000000000import os import click from pyaxmlparser import APK @click.command() @click.argument('filename') def main(filename): filename = os.path.expanduser(filename) apk = APK(filename) click.echo('APK: {}'.format(filename)) click.echo('App name: {}'.format(apk.application)) click.echo('Package: {}'.format(apk.packagename)) click.echo('Version name: {}'.format(apk.version_name)) click.echo('Version code: {}'.format(apk.version_code)) pyaxmlparser-0.3.24/pyaxmlparser/constants.py000066400000000000000000000146501356264674700214760ustar00rootroot00000000000000# Type definiton for (type, data) tuples representing a value # See http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h#262 # The 'data' is either 0 or 1, specifying this resource is either # undefined or empty, respectively. TYPE_NULL = 0x00 # The 'data' holds a ResTable_ref, a reference to another resource # table entry. TYPE_REFERENCE = 0x01 # The 'data' holds an attribute resource identifier. TYPE_ATTRIBUTE = 0x02 # The 'data' holds an index into the containing resource table's # global value string pool. TYPE_STRING = 0x03 # The 'data' holds a single-precision floating point number. TYPE_FLOAT = 0x04 # The 'data' holds a complex number encoding a dimension value # such as "100in". TYPE_DIMENSION = 0x05 # The 'data' holds a complex number encoding a fraction of a # container. TYPE_FRACTION = 0x06 # The 'data' holds a dynamic ResTable_ref, which needs to be # resolved before it can be used like a TYPE_REFERENCE. TYPE_DYNAMIC_REFERENCE = 0x07 # The 'data' holds an attribute resource identifier, which needs to be resolved # before it can be used like a TYPE_ATTRIBUTE. TYPE_DYNAMIC_ATTRIBUTE = 0x08 # Beginning of integer flavors... TYPE_FIRST_INT = 0x10 # The 'data' is a raw integer value of the form n..n. TYPE_INT_DEC = 0x10 # The 'data' is a raw integer value of the form 0xn..n. TYPE_INT_HEX = 0x11 # The 'data' is either 0 or 1, for input "false" or "true" respectively. TYPE_INT_BOOLEAN = 0x12 # Beginning of color integer flavors... TYPE_FIRST_COLOR_INT = 0x1c # The 'data' is a raw integer value of the form #aarrggbb. TYPE_INT_COLOR_ARGB8 = 0x1c # The 'data' is a raw integer value of the form #rrggbb. TYPE_INT_COLOR_RGB8 = 0x1d # The 'data' is a raw integer value of the form #argb. TYPE_INT_COLOR_ARGB4 = 0x1e # The 'data' is a raw integer value of the form #rgb. TYPE_INT_COLOR_RGB4 = 0x1f # ...end of integer flavors. TYPE_LAST_COLOR_INT = 0x1f # ...end of integer flavors. TYPE_LAST_INT = 0x1f # Constants for ARSC Files # see http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h#215 RES_NULL_TYPE = 0x0000 RES_STRING_POOL_TYPE = 0x0001 RES_TABLE_TYPE = 0x0002 RES_XML_TYPE = 0x0003 RES_XML_FIRST_CHUNK_TYPE = 0x0100 RES_XML_START_NAMESPACE_TYPE = 0x0100 RES_XML_END_NAMESPACE_TYPE = 0x0101 RES_XML_START_ELEMENT_TYPE = 0x0102 RES_XML_END_ELEMENT_TYPE = 0x0103 RES_XML_CDATA_TYPE = 0x0104 RES_XML_LAST_CHUNK_TYPE = 0x017f RES_XML_RESOURCE_MAP_TYPE = 0x0180 RES_TABLE_PACKAGE_TYPE = 0x0200 RES_TABLE_TYPE_TYPE = 0x0201 RES_TABLE_TYPE_SPEC_TYPE = 0x0202 RES_TABLE_LIBRARY_TYPE = 0x0203 # Flags in the STRING Section SORTED_FLAG = 1 << 0 UTF8_FLAG = 1 << 8 # Position of the fields inside an attribute ATTRIBUTE_IX_NAMESPACE_URI = 0 ATTRIBUTE_IX_NAME = 1 ATTRIBUTE_IX_VALUE_STRING = 2 ATTRIBUTE_IX_VALUE_TYPE = 3 ATTRIBUTE_IX_VALUE_DATA = 4 ATTRIBUTE_LENGHT = 5 # Internally used state variables for AXMLParser START_DOCUMENT = 0 END_DOCUMENT = 1 START_TAG = 2 END_TAG = 3 TEXT = 4 # Table used to lookup functions to determine the value representation in ARSCParser TYPE_TABLE = { TYPE_ATTRIBUTE: "attribute", TYPE_DIMENSION: "dimension", TYPE_FLOAT: "float", TYPE_FRACTION: "fraction", TYPE_INT_BOOLEAN: "int_boolean", TYPE_INT_COLOR_ARGB4: "int_color_argb4", TYPE_INT_COLOR_ARGB8: "int_color_argb8", TYPE_INT_COLOR_RGB4: "int_color_rgb4", TYPE_INT_COLOR_RGB8: "int_color_rgb8", TYPE_INT_DEC: "int_dec", TYPE_INT_HEX: "int_hex", TYPE_NULL: "null", TYPE_REFERENCE: "reference", TYPE_STRING: "string", } RADIX_MULTS = [0.00390625, 3.051758E-005, 1.192093E-007, 4.656613E-010] DIMENSION_UNITS = ["px", "dip", "sp", "pt", "in", "mm"] FRACTION_UNITS = ["%", "%p"] COMPLEX_UNIT_MASK = 0x0F ACONFIGURATION_MCC = 0x0001 ACONFIGURATION_MNC = 0x0002 ACONFIGURATION_LOCALE = 0x0004 ACONFIGURATION_TOUCHSCREEN = 0x0008 ACONFIGURATION_KEYBOARD = 0x0010 ACONFIGURATION_KEYBOARD_HIDDEN = 0x0020 ACONFIGURATION_NAVIGATION = 0x0040 ACONFIGURATION_ORIENTATION = 0x0080 ACONFIGURATION_DENSITY = 0x0100 ACONFIGURATION_SCREEN_SIZE = 0x0200 ACONFIGURATION_VERSION = 0x0400 ACONFIGURATION_SCREEN_LAYOUT = 0x0800 ACONFIGURATION_UI_MODE = 0x1000 ACONFIGURATION_LAYOUTDIR_ANY = 0x00 ACONFIGURATION_LAYOUTDIR_LTR = 0x01 ACONFIGURATION_LAYOUTDIR_RTL = 0x02 ACONFIGURATION_SCREENSIZE_ANY = 0x00 ACONFIGURATION_SCREENSIZE_SMALL = 0x01 ACONFIGURATION_SCREENSIZE_NORMAL = 0x02 ACONFIGURATION_SCREENSIZE_LARGE = 0x03 ACONFIGURATION_SCREENSIZE_XLARGE = 0x04 ACONFIGURATION_SCREENLONG_ANY = 0x00 ACONFIGURATION_SCREENLONG_NO = 0x1 ACONFIGURATION_SCREENLONG_YES = 0x2 ACONFIGURATION_TOUCHSCREEN_ANY = 0x0000 ACONFIGURATION_TOUCHSCREEN_NOTOUCH = 0x0001 ACONFIGURATION_TOUCHSCREEN_STYLUS = 0x0002 ACONFIGURATION_TOUCHSCREEN_FINGER = 0x0003 ACONFIGURATION_DENSITY_DEFAULT = 0 ACONFIGURATION_DENSITY_LOW = 120 ACONFIGURATION_DENSITY_MEDIUM = 160 ACONFIGURATION_DENSITY_TV = 213 ACONFIGURATION_DENSITY_HIGH = 240 ACONFIGURATION_DENSITY_XHIGH = 320 ACONFIGURATION_DENSITY_XXHIGH = 480 ACONFIGURATION_DENSITY_XXXHIGH = 640 ACONFIGURATION_DENSITY_ANY = 0xfffe ACONFIGURATION_DENSITY_NONE = 0xffff MASK_LAYOUTDIR = 0xC0 MASK_SCREENSIZE = 0x0f MASK_SCREENLONG = 0x30 SHIFT_LAYOUTDIR = 6 SHIFT_SCREENLONG = 4 LAYOUTDIR_ANY = ACONFIGURATION_LAYOUTDIR_ANY << SHIFT_LAYOUTDIR LAYOUTDIR_LTR = ACONFIGURATION_LAYOUTDIR_LTR << SHIFT_LAYOUTDIR LAYOUTDIR_RTL = ACONFIGURATION_LAYOUTDIR_RTL << SHIFT_LAYOUTDIR SCREENSIZE_ANY = ACONFIGURATION_SCREENSIZE_ANY SCREENSIZE_SMALL = ACONFIGURATION_SCREENSIZE_SMALL SCREENSIZE_NORMAL = ACONFIGURATION_SCREENSIZE_NORMAL SCREENSIZE_LARGE = ACONFIGURATION_SCREENSIZE_LARGE SCREENSIZE_XLARGE = ACONFIGURATION_SCREENSIZE_XLARGE SCREENLONG_ANY = ACONFIGURATION_SCREENLONG_ANY << SHIFT_SCREENLONG SCREENLONG_NO = ACONFIGURATION_SCREENLONG_NO << SHIFT_SCREENLONG SCREENLONG_YES = ACONFIGURATION_SCREENLONG_YES << SHIFT_SCREENLONG DENSITY_DEFAULT = ACONFIGURATION_DENSITY_DEFAULT DENSITY_LOW = ACONFIGURATION_DENSITY_LOW DENSITY_MEDIUM = ACONFIGURATION_DENSITY_MEDIUM DENSITY_TV = ACONFIGURATION_DENSITY_TV DENSITY_HIGH = ACONFIGURATION_DENSITY_HIGH DENSITY_XHIGH = ACONFIGURATION_DENSITY_XHIGH DENSITY_XXHIGH = ACONFIGURATION_DENSITY_XXHIGH DENSITY_XXXHIGH = ACONFIGURATION_DENSITY_XXXHIGH DENSITY_ANY = ACONFIGURATION_DENSITY_ANY DENSITY_NONE = ACONFIGURATION_DENSITY_NONE TOUCHSCREEN_ANY = ACONFIGURATION_TOUCHSCREEN_ANY TOUCHSCREEN_NOTOUCH = ACONFIGURATION_TOUCHSCREEN_NOTOUCH TOUCHSCREEN_STYLUS = ACONFIGURATION_TOUCHSCREEN_STYLUS TOUCHSCREEN_FINGER = ACONFIGURATION_TOUCHSCREEN_FINGER pyaxmlparser-0.3.24/pyaxmlparser/core.py000066400000000000000000001432031356264674700204070ustar00rootroot00000000000000from __future__ import division from __future__ import print_function from builtins import str from builtins import object from pyaxmlparser.utils import read, format_value from pyaxmlparser.arscparser import ARSCParser from pyaxmlparser.axmlprinter import AXMLPrinter from pyaxmlparser.axmlparser import AXMLParser from pyaxmlparser.arscutil import ARSCResTableConfig from pyaxmlparser.resources import public import pyaxmlparser.constants as const import io from zlib import crc32 import os import re import zipfile import logging import hashlib import lxml.sax from xml.dom.pulldom import SAX2DOM NS_ANDROID_URI = 'http://schemas.android.com/apk/res/android' NS_ANDROID = '{{{}}}'.format(NS_ANDROID_URI) # Namespace as used by etree log = logging.getLogger("pyaxmlparser.core") def parse_lxml_dom(tree): handler = SAX2DOM() lxml.sax.saxify(tree, handler) return handler.document class Error(Exception): """Base class for exceptions in this module.""" pass class FileNotPresent(Error): pass class BrokenAPKError(Error): pass class APK(object): def __init__(self, filename, raw=False, magic_file=None, skip_analysis=False, testzip=False): """ This class can access to all elements in an APK file example:: APK("myfile.apk") APK(read("myfile.apk"), raw=True) :param filename: specify the path of the file, or raw data :param raw: specify if the filename is a path or raw data (optional) :param magic_file: specify the magic file (not used anymore - legacy only) :param skip_analysis: Skip the analysis, e.g. no manifest files are read. (default: False) :param testzip: Test the APK for integrity, e.g. if the ZIP file is broken. Throw an exception on failure (default False) :type filename: string :type raw: boolean :type magic_file: string :type skip_analysis: boolean :type testzip: boolean """ if magic_file: log.warning("You set magic_file but this parameter is actually unused. You should remove it.") self.filename = filename self.xml = {} self.axml = {} self.arsc = {} self.package = "" self.androidversion = {} self.permissions = [] self.uses_permissions = [] self.declared_permissions = {} self.valid_apk = False self._files = {} self.files_crc32 = {} if raw is True: self.__raw = bytearray(filename) self._sha256 = hashlib.sha256(self.__raw).hexdigest() # Set the filename to something sane self.filename = "raw_apk_sha256:{}".format(self._sha256) else: self.__raw = bytearray(read(filename)) self.zip = zipfile.ZipFile(io.BytesIO(self.__raw), mode="r") if testzip: # Test the zipfile for integrity before continuing. # This process might be slow, as the whole file is read. # Therefore it is possible to enable it as a separate feature. # # A short benchmark showed, that testing the zip takes about 10 times longer! # e.g. normal zip loading (skip_analysis=True) takes about 0.01s, where # testzip takes 0.1s! ret = self.zip.testzip() if ret is not None: # we could print the filename here, but there are zip which are so broken # That the filename is either very very long or does not make any sense. # Thus we do not do it, the user might find out by using other tools. raise BrokenAPKError("The APK is probably broken: testzip returned an error.") if not skip_analysis: self._apk_analysis() def _ns(self, name): """ return the name including the Android namespace """ return NS_ANDROID + name def _apk_analysis(self): """ Run analysis on the APK file. This method is usually called by __init__ except if skip_analysis is False. It will then parse the AndroidManifest.xml and set all fields in the APK class which can be extracted from the Manifest. """ i = "AndroidManifest.xml" try: manifest_data = self.zip.read(i) except KeyError: log.warning("Missing AndroidManifest.xml. Is this an APK file?") else: ap = AXMLPrinter(manifest_data) if not ap.is_valid(): log.error("Error while parsing AndroidManifest.xml - is the file valid?") return self.axml[i] = ap self.xml[i] = self.axml[i].get_xml_obj() if self.axml[i].is_packed(): log.warning("XML Seems to be packed, operations on the AndroidManifest.xml might fail.") if self.xml[i] is not None: if self.xml[i].tag != "manifest": log.error("AndroidManifest.xml does not start with a tag! Is this a valid APK?") return self.package = self.get_attribute_value("manifest", "package") self.androidversion["Code"] = self.get_attribute_value("manifest", "versionCode") self.androidversion["Name"] = self.get_attribute_value("manifest", "versionName") permission = list(self.get_all_attribute_value("uses-permission", "name")) self.permissions = list(set(self.permissions + permission)) for uses_permission in self.find_tags("uses-permission"): self.uses_permissions.append([ self.get_value_from_tag(uses_permission, "name"), self._get_permission_maxsdk(uses_permission) ]) # getting details of the declared permissions for d_perm_item in self.find_tags('permission'): d_perm_name = self._get_res_string_value( str(self.get_value_from_tag(d_perm_item, "name"))) d_perm_label = self._get_res_string_value( str(self.get_value_from_tag(d_perm_item, "label"))) d_perm_description = self._get_res_string_value( str(self.get_value_from_tag(d_perm_item, "description"))) d_perm_permissionGroup = self._get_res_string_value( str(self.get_value_from_tag(d_perm_item, "permissionGroup"))) d_perm_protectionLevel = self._get_res_string_value( str(self.get_value_from_tag(d_perm_item, "protectionLevel"))) d_perm_details = { "label": d_perm_label, "description": d_perm_description, "permissionGroup": d_perm_permissionGroup, "protectionLevel": d_perm_protectionLevel, } self.declared_permissions[d_perm_name] = d_perm_details self.valid_apk = True def __getstate__(self): """ Function for pickling APK Objects. We remove the zip from the Object, as it is not pickable And it does not make any sense to pickle it anyways. :return: the picklable APK Object without zip. """ # Upon pickling, we need to remove the ZipFile x = self.__dict__ x['axml'] = str(x['axml']) x['xml'] = str(x['xml']) del x['zip'] return x def __setstate__(self, state): """ Load a pickled APK Object and restore the state We load the zip file back by reading __raw from the Object. :param state: pickled state """ self.__dict__ = state self.zip = zipfile.ZipFile(io.BytesIO(self.__raw), mode="r") def _get_res_string_value(self, string): if not string.startswith('@string/'): return string string_key = string[8:] res_parser = self.get_android_resources() if not res_parser: return '' string_value = '' for package_name in res_parser.get_packages_names(): extracted_values = res_parser.get_string(package_name, string_key) if extracted_values: string_value = extracted_values[1] break return string_value def _get_permission_maxsdk(self, item): maxSdkVersion = None try: maxSdkVersion = int(self.get_value_from_tag(item, "maxSdkVersion")) except ValueError: log.warning(self.get_max_sdk_version() + 'is not a valid value for maxSdkVersion') except TypeError: pass return maxSdkVersion def is_valid_APK(self): """ Return true if the APK is valid, false otherwise. An APK is seen as valid, if the AndroidManifest.xml could be successful parsed. This does not mean that the APK has a valid signature nor that the APK can be installed on an Android system. :rtype: boolean """ return self.valid_apk def get_filename(self): """ Return the filename of the APK :rtype: :class:`str` """ return self.filename def get_app_name(self): """ Return the appname of the APK This name is read from the AndroidManifest.xml using the application android:label. If no label exists, the android:label of the main activity is used. If there is also no main activity label, an empty string is returned. :rtype: :class:`str` """ app_name = self.get_attribute_value('application', 'label') if app_name is None: activities = self.get_main_activities() main_activity_name = None if len(activities) > 0: main_activity_name = activities.pop() app_name = self.get_attribute_value( 'activity', 'label', name=main_activity_name ) if app_name is None: # No App name set # TODO return packagename instead? log.warning("It looks like that no app name is set for the main activity!") return "" if app_name.startswith("@"): res_parser = self.get_android_resources() if not res_parser: # TODO: What should be the correct return value here? return app_name res_id, package = res_parser.parse_id(app_name) # If the package name is the same as the APK package, # we should be able to resolve the ID. if package and package != self.get_package(): if package == 'android': # TODO: we can not resolve this, as we lack framework-res.apk # one exception would be when parsing framework-res.apk directly. log.warning("Resource ID with android package name encountered! " "Will not resolve, framework-res.apk would be required.") return app_name else: # TODO should look this up, might be in the resources log.warning("Resource ID with Package name '{}' encountered! Will not resolve".format(package)) return app_name try: app_name = res_parser.get_resolved_res_configs( res_id, ARSCResTableConfig.default_config())[0][1] except Exception as e: log.warning("Exception selecting app name: %s" % e) return app_name def get_app_icon(self, max_dpi=65536): """ Return the first icon file name, which density is not greater than max_dpi, unless exact icon resolution is set in the manifest, in which case return the exact file. This information is read from the AndroidManifest.xml From https://developer.android.com/guide/practices/screens_support.html and https://developer.android.com/ndk/reference/group___configuration.html * DEFAULT 0dpi * ldpi (low) 120dpi * mdpi (medium) 160dpi * TV 213dpi * hdpi (high) 240dpi * xhdpi (extra-high) 320dpi * xxhdpi (extra-extra-high) 480dpi * xxxhdpi (extra-extra-extra-high) 640dpi * anydpi 65534dpi (0xFFFE) * nodpi 65535dpi (0xFFFF) There is a difference between nodpi and anydpi: nodpi will be used if no other density is specified. Or the density does not match. nodpi is the fallback for everything else. If there is a resource that matches the DPI, this is used. anydpi is also valid for all densities but in this case, anydpi will overrule all other files! Therefore anydpi is usually used with vector graphics and with constraints on the API level. For example adaptive icons are usually marked as anydpi. When it comes now to selecting an icon, there is the following flow: 1) is there an anydpi icon? 2) is there an icon for the dpi of the device? 3) is there a nodpi icon? 4) (only on very old devices) is there a icon with dpi 0 (the default) For more information read here: https://stackoverflow.com/a/34370735/446140 :rtype: :class:`str` """ main_activity_name = self.get_main_activity() app_icon = self.get_attribute_value( 'activity', 'icon', name=main_activity_name) if not app_icon: app_icon = self.get_attribute_value('application', 'icon') res_parser = self.get_android_resources() if not res_parser: # Can not do anything below this point to resolve... return None if app_icon and app_icon.startswith("@android:"): android_res_id = app_icon[9:] # default icon: # https://developer.android.com/reference/android/R.mipmap#sym_def_app_icon or # https://developer.android.com/reference/android/R.drawable#sym_def_app_icon if ( public.SYSTEM_RESOURCES['mipmaps']['inverse'].get(int(android_res_id, 16)) == 'sym_def_app_icon' or public.SYSTEM_RESOURCES['drawables']['inverse'].get(int(android_res_id, 16)) == 'sym_def_app_icon' ): app_icon = None if not app_icon: res_id = res_parser.get_res_id_by_key(self.package, 'mipmap', 'ic_launcher') if res_id: app_icon = "@%x" % res_id if not app_icon: res_id = res_parser.get_res_id_by_key(self.package, 'drawable', 'ic_launcher') if res_id: app_icon = "@%x" % res_id if not app_icon: # If the icon can not be found, return now return None if app_icon.startswith("@"): res_id = int(app_icon[1:], 16) candidates = res_parser.get_resolved_res_configs(res_id) app_icon = None current_dpi = -1 try: for config, file_name in candidates: dpi = config.get_density() if current_dpi < dpi <= max_dpi: app_icon = file_name current_dpi = dpi except Exception as e: log.warning("Exception selecting app icon: %s" % e) return app_icon def get_package(self): """ Return the name of the package This information is read from the AndroidManifest.xml :rtype: :class:`str` """ return self.package def get_androidversion_code(self): """ Return the android version code This information is read from the AndroidManifest.xml :rtype: :class:`str` """ return self.androidversion["Code"] def get_androidversion_name(self): """ Return the android version name This information is read from the AndroidManifest.xml :rtype: :class:`str` """ return self.androidversion["Name"] def get_files(self): """ Return the file names inside the APK. :rtype: a list of :class:`str` """ return self.zip.namelist() def _get_file_magic_name(self, buffer): """ Return the filetype guessed for a buffer :param buffer: bytes :return: str of filetype """ default = "Unknown" ftype = None try: # Magic is optional import magic except ImportError: return default try: # There are several implementations of magic, # unfortunately all called magic # We use this one: https://github.com/ahupp/python-magic/ getattr(magic, "MagicException") except AttributeError: # Looks like no magic was installed return default try: ftype = magic.from_buffer(buffer[:1024]) except magic.MagicError as e: log.exception("Error getting the magic type!") return default if not ftype: return default else: return self._patch_magic(buffer, ftype) @property def files(self): """ Returns a dictionary of filenames and detected magic type :return: dictionary of files and their mime type """ return self.get_files_types() def get_files_types(self): """ Return the files inside the APK with their associated types (by using python-magic) :rtype: a dictionnary """ if self._files == {}: # Generate File Types / CRC List for i in self.get_files(): buffer = self.zip.read(i) self.files_crc32[i] = crc32(buffer) # FIXME why not use the crc from the zipfile? # should be validated as well. # crc = self.zip.getinfo(i).CRC self._files[i] = self._get_file_magic_name(buffer) return self._files def _patch_magic(self, buffer, orig): """ Overwrite some probably wrong detections by mime libraries :param buffer: bytes of the file to detect :param orig: guess by mime libary :return: corrected guess """ if ("Zip" in orig) or ('(JAR)' in orig): val = is_android_raw(buffer) if val == "APK": return "Android application package file" return orig def get_files_crc32(self): """ Calculates and returns a dictionary of filenames and CRC32 :return: dict of filename: CRC32 """ if self.files_crc32 == {}: for i in self.get_files(): buffer = self.zip.read(i) self.files_crc32[i] = crc32(buffer) return self.files_crc32 def get_files_information(self): """ Return the files inside the APK with their associated types and crc32 :rtype: str, str, int """ for k in self.get_files(): yield k, self.get_files_types()[k], self.get_files_crc32()[k] def get_raw(self): """ Return raw bytes of the APK :rtype: bytes """ return self.__raw def get_file(self, filename): """ Return the raw data of the specified filename inside the APK :rtype: bytes """ try: return self.zip.read(filename) except KeyError: raise FileNotPresent(filename) def get_dex(self): """ Return the raw data of the classes dex file This will give you the data of the file called `classes.dex` inside the APK. If the APK has multiple DEX files, you need to use :func:`~APK.get_all_dex`. :rtype: bytes """ try: return self.get_file("classes.dex") except FileNotPresent: return "" def get_dex_names(self): """ Return the names of all DEX files found in the APK. This method only accounts for "offical" dex files, i.e. all files in the root directory of the APK named classes.dex or classes[0-9]+.dex :rtype: a list of str """ dexre = re.compile("classes(\d*).dex") return filter(lambda x: dexre.match(x), self.get_files()) def get_all_dex(self): """ Return the raw data of all classes dex files :rtype: a generator of bytes """ for dex_name in self.get_dex_names(): yield self.get_file(dex_name) def is_multidex(self): """ Test if the APK has multiple DEX files :return: True if multiple dex found, otherwise False """ dexre = re.compile("^classes(\d+)?.dex$") return len([instance for instance in self.get_files() if dexre.search(instance)]) > 1 @DeprecationWarning def get_elements(self, tag_name, attribute, with_namespace=True): """ Deprecated: use `get_all_attribute_value()` instead Return elements in xml files which match with the tag name and the specific attribute :param tag_name: a string which specify the tag name :param attribute: a string which specify the attribute """ for i in self.xml: if self.xml[i] is None: continue for item in self.xml[i].findall('.//' + tag_name): if with_namespace: value = item.get(self._ns(attribute)) else: value = item.get(attribute) # There might be an attribute without the namespace if value: yield self._format_value(value) def _format_value(self, value): """ Format a value with packagename, if not already set :param value: :return: """ if len(value) > 0: if value[0] == ".": value = self.package + value else: v_dot = value.find(".") if v_dot == 0: value = self.package + "." + value elif v_dot == -1: value = self.package + "." + value return value @DeprecationWarning def get_element(self, tag_name, attribute, **attribute_filter): """ :Deprecated: use `get_attribute_value()` instead Return element in xml files which match with the tag name and the specific attribute :param tag_name: specify the tag name :type tag_name: string :param attribute: specify the attribute :type attribute: string :rtype: string """ for i in self.xml: if self.xml[i] is None: continue tag = self.xml[i].findall('.//' + tag_name) if len(tag) == 0: return None for item in tag: skip_this_item = False for attr, val in list(attribute_filter.items()): attr_val = item.get(self._ns(attr)) if attr_val != val: skip_this_item = True break if skip_this_item: continue value = item.get(self._ns(attribute)) if value is not None: return value return None def get_all_attribute_value( self, tag_name, attribute, format_value=True, **attribute_filter ): """ Return all the attribute values in xml files which match with the tag name and the specific attribute :param tag_name: specify the tag name :type tag_name: string :param attribute: specify the attribute :type attribute: string :param format_value: specify if the value needs to be formatted with packagename :type format_value: boolean """ tags = self.find_tags(tag_name, **attribute_filter) for tag in tags: value = tag.get(attribute) or tag.get(self._ns(attribute)) if value is not None: if format_value: yield self._format_value(value) else: yield value def get_attribute_value( self, tag_name, attribute, format_value=False, **attribute_filter ): """ Return the attribute value in xml files which matches the tag name and the specific attribute :param tag_name: specify the tag name :type tag_name: string :param attribute: specify the attribute :type attribute: string :param format_value: specify if the value needs to be formatted with packagename :type format_value: boolean """ for value in self.get_all_attribute_value( tag_name, attribute, format_value, **attribute_filter): if value is not None: return value def get_value_from_tag(self, tag, attribute): """ Return the value of the attribute in a specific tag :param tag: specify the tag element :type tag: Element :param attribute: specify the attribute :type attribute: string """ # TODO: figure out if both android:name and name tag exist which one to give preference value = tag.get(self._ns(attribute)) if value is None: log.warning("Failed to get the attribute with namespace") value = tag.get(attribute) return value def find_tags(self, tag_name, **attribute_filter): """ Return a list of all the matched tags in all available xml :param tag: specify the tag name :type tag: string """ all_tags = [ self.find_tags_from_xml( i, tag_name, **attribute_filter ) for i in self.xml ] return [tag for tag_list in all_tags for tag in tag_list] def find_tags_from_xml( self, xml_name, tag_name, **attribute_filter ): """ Return a list of all the matched tags in a specific xml :param xml_name: specify from which xml to pick the tag from :type xml_name: string :param tag_name: specify the tag name :type tag_name: string """ xml = self.xml[xml_name] if xml is None: return [] if xml.tag == tag_name: if self.is_tag_matched( xml.tag, **attribute_filter ): return [xml] return [] tags = xml.findall(".//" + tag_name) return [ tag for tag in tags if self.is_tag_matched( tag, **attribute_filter ) ] def is_tag_matched(self, tag, **attribute_filter): """ Return true if the attributes matches in attribute filter :param tag: specify the tag element :type tag: Element :param attribute: specify the attribute :type attribute: string """ if len(attribute_filter) <= 0: return True for attr, value in attribute_filter.items(): # TODO: figure out if both android:name and name tag exist which one to give preference _value = tag.get(self._ns(attr)) if _value is None: log.warning("Failed to get the attribute with namespace") _value = tag.get(attr) if _value != value: return False return True def get_main_activities(self): """ Return names of the main activities These values are read from the AndroidManifest.xml :rtype: a set of str """ x = set() y = set() for i in self.xml: if self.xml[i] is None: continue activities_and_aliases = self.xml[i].findall(".//activity") + \ self.xml[i].findall(".//activity-alias") for item in activities_and_aliases: # Some applications have more than one MAIN activity. # For example: paid and free content activityEnabled = item.get(self._ns("enabled")) if activityEnabled == "false": continue for sitem in item.findall(".//action"): val = sitem.get(self._ns("name")) if val == "android.intent.action.MAIN": activity = item.get(self._ns("name")) if activity is not None: x.add(item.get(self._ns("name"))) else: log.warning('Main activity without name') for sitem in item.findall(".//category"): val = sitem.get(self._ns("name")) if val == "android.intent.category.LAUNCHER": activity = item.get(self._ns("name")) if activity is not None: y.add(item.get(self._ns("name"))) else: log.warning('Launcher activity without name') return x.intersection(y) def get_main_activity(self): """ Return the name of the main activity This value is read from the AndroidManifest.xml :rtype: str """ activities = self.get_main_activities() if len(activities) > 0: return self._format_value(activities.pop()) return None def get_activities(self): """ Return the android:name attribute of all activities :rtype: a list of str """ return list(self.get_all_attribute_value("activity", "name")) def get_services(self): """ Return the android:name attribute of all services :rtype: a list of str """ return list(self.get_all_attribute_value("service", "name")) def get_receivers(self): """ Return the android:name attribute of all receivers :rtype: a list of string """ return list(self.get_all_attribute_value("receiver", "name")) def get_providers(self): """ Return the android:name attribute of all providers :rtype: a list of string """ return list(self.get_all_attribute_value("provider", "name")) def get_intent_filters(self, itemtype, name): """ Find intent filters for a given item and name. Intent filter are attached to activities, services or receivers. You can search for the intent filters of such items and get a dictionary of all attached actions and intent categories. :param itemtype: the type of parent item to look for, e.g. `activity`, `service` or `receiver` :param name: the `android:name` of the parent item, e.g. activity name :return: a dictionary with the keys `action` and `category` containing the `android:name` of those items """ d = {"action": [], "category": []} for i in self.xml: # TODO: this can probably be solved using a single xpath for item in self.xml[i].findall(".//" + itemtype): if self._format_value(item.get(self._ns("name"))) == name: for sitem in item.findall(".//intent-filter"): for ssitem in sitem.findall("action"): if ssitem.get(self._ns("name")) not in d["action"]: d["action"].append(ssitem.get(self._ns("name"))) for ssitem in sitem.findall("category"): if ssitem.get(self._ns("name")) not in d["category"]: d["category"].append(ssitem.get(self._ns("name"))) if not d["action"]: del d["action"] if not d["category"]: del d["category"] return d def get_permissions(self): """ Return permissions names declared in the AndroidManifest.xml. It is possible that permissions are returned multiple times, as this function does not filter the permissions, i.e. it shows you exactly what was defined in the AndroidManifest.xml. Implied permissions, which are granted automatically, are not returned here. Use :meth:`get_uses_implied_permission_list` if you need a list of implied permissions. :returns: A list of permissions :rtype: list """ return self.permissions def get_uses_implied_permission_list(self): """ Return all permissions implied by the target SDK or other permissions. :rtype: list of string """ target_sdk_version = self.get_effective_target_sdk_version() READ_CALL_LOG = 'android.permission.READ_CALL_LOG' READ_CONTACTS = 'android.permission.READ_CONTACTS' READ_EXTERNAL_STORAGE = 'android.permission.READ_EXTERNAL_STORAGE' READ_PHONE_STATE = 'android.permission.READ_PHONE_STATE' WRITE_CALL_LOG = 'android.permission.WRITE_CALL_LOG' WRITE_CONTACTS = 'android.permission.WRITE_CONTACTS' WRITE_EXTERNAL_STORAGE = 'android.permission.WRITE_EXTERNAL_STORAGE' implied = [] implied_WRITE_EXTERNAL_STORAGE = False if target_sdk_version < 4: if WRITE_EXTERNAL_STORAGE not in self.permissions: implied.append([WRITE_EXTERNAL_STORAGE, None]) implied_WRITE_EXTERNAL_STORAGE = True if READ_PHONE_STATE not in self.permissions: implied.append([READ_PHONE_STATE, None]) if (WRITE_EXTERNAL_STORAGE in self.permissions or implied_WRITE_EXTERNAL_STORAGE) \ and READ_EXTERNAL_STORAGE not in self.permissions: maxSdkVersion = None for name, version in self.uses_permissions: if name == WRITE_EXTERNAL_STORAGE: maxSdkVersion = version break implied.append([READ_EXTERNAL_STORAGE, maxSdkVersion]) if target_sdk_version < 16: if READ_CONTACTS in self.permissions \ and READ_CALL_LOG not in self.permissions: implied.append([READ_CALL_LOG, None]) if WRITE_CONTACTS in self.permissions \ and WRITE_CALL_LOG not in self.permissions: implied.append([WRITE_CALL_LOG, None]) return implied def get_details_permissions(self): """ Return permissions with details :rtype: dict of {permission: [protectionLevel, label, description]} """ l = {} for i in self.permissions: if i in self.permission_module: x = self.permission_module[i] l[i] = [x["protectionLevel"], x["label"], x["description"]] else: # FIXME: the permission might be signature, if it is defined by the app itself! l[i] = ["normal", "Unknown permission from android reference", "Unknown permission from android reference"] return l @DeprecationWarning def get_requested_permissions(self): """ Returns all requested permissions. It has the same result as :meth:`get_permissions` and might be removed in the future :rtype: list of str """ return self.get_permissions() def get_requested_aosp_permissions(self): """ Returns requested permissions declared within AOSP project. This includes several other permissions as well, which are in the platform apps. :rtype: list of str """ aosp_permissions = [] all_permissions = self.get_permissions() for perm in all_permissions: if perm in list(self.permission_module.keys()): aosp_permissions.append(perm) return aosp_permissions def get_requested_aosp_permissions_details(self): """ Returns requested aosp permissions with details. :rtype: dictionary """ l = {} for i in self.permissions: try: l[i] = self.permission_module[i] except KeyError: # if we have not found permission do nothing continue return l def get_requested_third_party_permissions(self): """ Returns list of requested permissions not declared within AOSP project. :rtype: list of strings """ third_party_permissions = [] all_permissions = self.get_permissions() for perm in all_permissions: if perm not in list(self.permission_module.keys()): third_party_permissions.append(perm) return third_party_permissions def get_declared_permissions(self): """ Returns list of the declared permissions. :rtype: list of strings """ return list(self.declared_permissions.keys()) def get_declared_permissions_details(self): """ Returns declared permissions with the details. :rtype: dict """ return self.declared_permissions def get_max_sdk_version(self): """ Return the android:maxSdkVersion attribute :rtype: string """ return self.get_attribute_value("uses-sdk", "maxSdkVersion") def get_min_sdk_version(self): """ Return the android:minSdkVersion attribute :rtype: string """ return self.get_attribute_value("uses-sdk", "minSdkVersion") def get_target_sdk_version(self): """ Return the android:targetSdkVersion attribute :rtype: string """ return self.get_attribute_value("uses-sdk", "targetSdkVersion") def get_effective_target_sdk_version(self): """ Return the effective targetSdkVersion, always returns int > 0. If the targetSdkVersion is not set, it defaults to 1. This is set based on defaults as defined in: https://developer.android.com/guide/topics/manifest/uses-sdk-element.html :rtype: int """ target_sdk_version = self.get_target_sdk_version() if not target_sdk_version: target_sdk_version = self.get_min_sdk_version() try: return int(target_sdk_version) except (ValueError, TypeError): return 1 def get_libraries(self): """ Return the android:name attributes for libraries :rtype: list """ return list(self.get_all_attribute_value("uses-library", "name")) def get_features(self): """ Return a list of all android:names found for the tag uses-feature in the AndroidManifest.xml :return: list """ return list(self.get_all_attribute_value("uses-feature", "name")) def is_wearable(self): """ Checks if this application is build for wearables by checking if it uses the feature 'android.hardware.type.watch' See: https://developer.android.com/training/wearables/apps/creating.html for more information. Not every app is setting this feature (not even the example Google provides), so it might be wise to not 100% rely on this feature. :return: True if wearable, False otherwise """ return 'android.hardware.type.watch' in self.get_features() def is_leanback(self): """ Checks if this application is build for TV (Leanback support) by checkin if it uses the feature 'android.software.leanback' :return: True if leanback feature is used, false otherwise """ return 'android.software.leanback' in self.get_features() def is_androidtv(self): """ Checks if this application does not require a touchscreen, as this is the rule to get into the TV section of the Play Store See: https://developer.android.com/training/tv/start/start.html for more information. :return: True if 'android.hardware.touchscreen' is not required, False otherwise """ return self.get_attribute_value( 'uses-feature', 'name', required="false", name="android.hardware.touchscreen" ) == "android.hardware.touchscreen" def new_zip(self, filename, deleted_files=None, new_files={}): """ Create a new zip file :param filename: the output filename of the zip :param deleted_files: a regex pattern to remove specific file :param new_files: a dictionnary of new files :type filename: string :type deleted_files: None or a string :type new_files: a dictionnary (key:filename, value:content of the file) """ zout = zipfile.ZipFile(filename, 'w') for item in self.zip.infolist(): # Block one: deleted_files, or deleted_files and new_files if deleted_files is not None: if re.match(deleted_files, item.filename) is None: # if the regex of deleted_files doesn't match the filename if new_files is not False: if item.filename in new_files: # and if the filename is in new_files zout.writestr(item, new_files[item.filename]) continue # Otherwise, write the original file. buffer = self.zip.read(item.filename) zout.writestr(item, buffer) # Block two: deleted_files is None, new_files is not empty elif new_files is not False: if item.filename in new_files: zout.writestr(item, new_files[item.filename]) else: buffer = self.zip.read(item.filename) zout.writestr(item, buffer) # Block three: deleted_files is None, new_files is empty. # Just write out the default zip else: buffer = self.zip.read(item.filename) zout.writestr(item, buffer) zout.close() def get_android_manifest_axml(self): """ Return the :class:`AXMLPrinter` object which corresponds to the AndroidManifest.xml file :rtype: :class:`~androguard.core.bytecodes.axml.AXMLPrinter` """ try: return self.axml["AndroidManifest.xml"] except KeyError: return None def get_android_manifest_xml(self): """ Return the parsed xml object which corresponds to the AndroidManifest.xml file :rtype: :class:`~lxml.etree.Element` """ try: return self.xml["AndroidManifest.xml"] except KeyError: return None def get_android_resources(self): """ Return the :class:`~androguard.core.bytecodes.axml.ARSCParser` object which corresponds to the resources.arsc file :rtype: :class:`~androguard.core.bytecodes.axml.ARSCParser` """ try: return self.arsc["resources.arsc"] except KeyError: if "resources.arsc" not in self.zip.namelist(): # There is a rare case, that no resource file is supplied. # Maybe it was added manually, thus we check here return None self.arsc["resources.arsc"] = ARSCParser(self.zip.read("resources.arsc")) return self.arsc["resources.arsc"] def show(self): self.get_files_types() print("FILES: ") for i in self.get_files(): try: print("\t", i, self._files[i], "%x" % self.files_crc32[i]) except KeyError: print("\t", i, "%x" % self.files_crc32[i]) print("DECLARED PERMISSIONS:") declared_permissions = self.get_declared_permissions() for i in declared_permissions: print("\t", i) print("REQUESTED PERMISSIONS:") requested_permissions = self.get_permissions() for i in requested_permissions: print("\t", i) print("MAIN ACTIVITY: ", self.get_main_activity()) print("ACTIVITIES: ") activities = self.get_activities() for i in activities: filters = self.get_intent_filters("activity", i) print("\t", i, filters or "") print("SERVICES: ") services = self.get_services() for i in services: filters = self.get_intent_filters("service", i) print("\t", i, filters or "") print("RECEIVERS: ") receivers = self.get_receivers() for i in receivers: filters = self.get_intent_filters("receiver", i) print("\t", i, filters or "") print("PROVIDERS: ", self.get_providers()) @property def application(self): return self.get_app_name() @property def packagename(self): return self.get_package() @property def version_name(self): return self.get_androidversion_name() @property def version_code(self): return self.get_androidversion_code() @property def icon_info(self): return self.get_app_icon() @property def icon_data(self): app_icon_file = self.get_app_icon() if not app_icon_file: return None app_icon_data = None try: app_icon_data = self.get_file(app_icon_file) except FileNotPresent: try: app_icon_data = self.get_file(app_icon_file.encode().decode('cp437')) except FileNotPresent: return None return app_icon_data def ensure_final_value(packageName, arsc, value): """Ensure incoming value is always the value, not the resid androguard will sometimes return the Android "resId" aka Resource ID instead of the actual value. This checks whether the value is actually a resId, then performs the Android Resource lookup as needed. """ if value: returnValue = value if value[0] == '@': try: # can be a literal value or a resId res_id = int('0x' + value[1:], 16) res_id = arsc.get_id(packageName, res_id)[1] returnValue = arsc.get_string(packageName, res_id)[1] except (ValueError, TypeError): pass return returnValue return '' def get_apkid(apkfile): """Read (appid, versionCode, versionName) from an APK This first tries to do quick binary XML parsing to just get the values that are needed. It will fallback to full androguard parsing, which is slow, if it can't find the versionName value or versionName is set to a Android String Resource (e.g. an integer hex value that starts with @). """ if not os.path.exists(apkfile): log.error("'{apkfile}' does not exist!".format(apkfile=apkfile)) appid = None versionCode = None versionName = None with zipfile.ZipFile(apkfile) as apk: with apk.open('AndroidManifest.xml') as manifest: axml = AXMLParser(manifest.read()) count = 0 while axml.is_valid(): _type = next(axml) count += 1 if _type == const.START_TAG: for i in range(0, axml.getAttributeCount()): name = axml.getAttributeName(i) _type = axml.getAttributeValueType(i) _data = axml.getAttributeValueData(i) value = format_value(_type, _data, lambda _: axml.getAttributeValue(i)) if appid is None and name == 'package': appid = value elif versionCode is None and name == 'versionCode': if value.startswith('0x'): versionCode = str(int(value, 16)) else: versionCode = value elif versionName is None and name == 'versionName': versionName = value if axml.name == 'manifest': break elif _type == const.END_TAG or _type == const.TEXT or _type == const.END_DOCUMENT: raise RuntimeError( '{path}: must be the first element in ' 'AndroidManifest.xml'.format(path=apkfile) ) if not versionName or versionName[0] == '@': a = APK(apkfile) versionName = ensure_final_value(a.package, a.get_android_resources(), a.get_androidversion_name()) if not versionName: versionName = '' # versionName is expected to always be a str return appid, versionCode, versionName.strip('\0') def is_android_raw(raw): """ Returns a string that describes the type of file, for common Android specific formats """ val = None # We do not check for META-INF/MANIFEST.MF, # as you also want to analyze unsigned APKs... # AndroidManifest.xml should be in every APK. # classes.dex and resources.arsc are not required! # if raw[0:2] == b"PK" and b'META-INF/MANIFEST.MF' in raw: # TODO this check might be still invalid. A ZIP file with stored APK inside would match as well. # probably it would be better to rewrite this and add more sanity checks. if raw[0:2] == b"PK" and b'AndroidManifest.xml' in raw: val = "APK" elif raw[0:3] == b"dex": val = "DEX" elif raw[0:3] == b"dey": val = "DEY" elif raw[0:4] == b"\x03\x00\x08\x00" or raw[0:4] == b"\x00\x00\x08\x00": val = "AXML" elif raw[0:4] == b"\x02\x00\x0C\x00": val = "ARSC" return val pyaxmlparser-0.3.24/pyaxmlparser/resources/000077500000000000000000000000001356264674700211145ustar00rootroot00000000000000pyaxmlparser-0.3.24/pyaxmlparser/resources/__init__.py000066400000000000000000000000001356264674700232130ustar00rootroot00000000000000pyaxmlparser-0.3.24/pyaxmlparser/resources/public.json000066400000000000000000003203711356264674700232730ustar00rootroot00000000000000{ "attr": { "theme": 16842752, "label": 16842753, "icon": 16842754, "name": 16842755, "manageSpaceActivity": 16842756, "allowClearUserData": 16842757, "permission": 16842758, "readPermission": 16842759, "writePermission": 16842760, "protectionLevel": 16842761, "permissionGroup": 16842762, "sharedUserId": 16842763, "hasCode": 16842764, "persistent": 16842765, "enabled": 16842766, "debuggable": 16842767, "exported": 16842768, "process": 16842769, "taskAffinity": 16842770, "multiprocess": 16842771, "finishOnTaskLaunch": 16842772, "clearTaskOnLaunch": 16842773, "stateNotNeeded": 16842774, "excludeFromRecents": 16842775, "authorities": 16842776, "syncable": 16842777, "initOrder": 16842778, "grantUriPermissions": 16842779, "priority": 16842780, "launchMode": 16842781, "screenOrientation": 16842782, "configChanges": 16842783, "description": 16842784, "targetPackage": 16842785, "handleProfiling": 16842786, "functionalTest": 16842787, "value": 16842788, "resource": 16842789, "mimeType": 16842790, "scheme": 16842791, "host": 16842792, "port": 16842793, "path": 16842794, "pathPrefix": 16842795, "pathPattern": 16842796, "action": 16842797, "data": 16842798, "targetClass": 16842799, "colorForeground": 16842800, "colorBackground": 16842801, "backgroundDimAmount": 16842802, "disabledAlpha": 16842803, "textAppearance": 16842804, "textAppearanceInverse": 16842805, "textColorPrimary": 16842806, "textColorPrimaryDisableOnly": 16842807, "textColorSecondary": 16842808, "textColorPrimaryInverse": 16842809, "textColorSecondaryInverse": 16842810, "textColorPrimaryNoDisable": 16842811, "textColorSecondaryNoDisable": 16842812, "textColorPrimaryInverseNoDisable": 16842813, "textColorSecondaryInverseNoDisable": 16842814, "textColorHintInverse": 16842815, "textAppearanceLarge": 16842816, "textAppearanceMedium": 16842817, "textAppearanceSmall": 16842818, "textAppearanceLargeInverse": 16842819, "textAppearanceMediumInverse": 16842820, "textAppearanceSmallInverse": 16842821, "textCheckMark": 16842822, "textCheckMarkInverse": 16842823, "buttonStyle": 16842824, "buttonStyleSmall": 16842825, "buttonStyleInset": 16842826, "buttonStyleToggle": 16842827, "galleryItemBackground": 16842828, "listPreferredItemHeight": 16842829, "expandableListPreferredItemPaddingLeft": 16842830, "expandableListPreferredChildPaddingLeft": 16842831, "expandableListPreferredItemIndicatorLeft": 16842832, "expandableListPreferredItemIndicatorRight": 16842833, "expandableListPreferredChildIndicatorLeft": 16842834, "expandableListPreferredChildIndicatorRight": 16842835, "windowBackground": 16842836, "windowFrame": 16842837, "windowNoTitle": 16842838, "windowIsFloating": 16842839, "windowIsTranslucent": 16842840, "windowContentOverlay": 16842841, "windowTitleSize": 16842842, "windowTitleStyle": 16842843, "windowTitleBackgroundStyle": 16842844, "alertDialogStyle": 16842845, "panelBackground": 16842846, "panelFullBackground": 16842847, "panelColorForeground": 16842848, "panelColorBackground": 16842849, "panelTextAppearance": 16842850, "scrollbarSize": 16842851, "scrollbarThumbHorizontal": 16842852, "scrollbarThumbVertical": 16842853, "scrollbarTrackHorizontal": 16842854, "scrollbarTrackVertical": 16842855, "scrollbarAlwaysDrawHorizontalTrack": 16842856, "scrollbarAlwaysDrawVerticalTrack": 16842857, "absListViewStyle": 16842858, "autoCompleteTextViewStyle": 16842859, "checkboxStyle": 16842860, "dropDownListViewStyle": 16842861, "editTextStyle": 16842862, "expandableListViewStyle": 16842863, "galleryStyle": 16842864, "gridViewStyle": 16842865, "imageButtonStyle": 16842866, "imageWellStyle": 16842867, "listViewStyle": 16842868, "listViewWhiteStyle": 16842869, "popupWindowStyle": 16842870, "progressBarStyle": 16842871, "progressBarStyleHorizontal": 16842872, "progressBarStyleSmall": 16842873, "progressBarStyleLarge": 16842874, "seekBarStyle": 16842875, "ratingBarStyle": 16842876, "ratingBarStyleSmall": 16842877, "radioButtonStyle": 16842878, "scrollbarStyle": 16842879, "scrollViewStyle": 16842880, "spinnerStyle": 16842881, "starStyle": 16842882, "tabWidgetStyle": 16842883, "textViewStyle": 16842884, "webViewStyle": 16842885, "dropDownItemStyle": 16842886, "spinnerDropDownItemStyle": 16842887, "dropDownHintAppearance": 16842888, "spinnerItemStyle": 16842889, "mapViewStyle": 16842890, "preferenceScreenStyle": 16842891, "preferenceCategoryStyle": 16842892, "preferenceInformationStyle": 16842893, "preferenceStyle": 16842894, "checkBoxPreferenceStyle": 16842895, "yesNoPreferenceStyle": 16842896, "dialogPreferenceStyle": 16842897, "editTextPreferenceStyle": 16842898, "ringtonePreferenceStyle": 16842899, "preferenceLayoutChild": 16842900, "textSize": 16842901, "typeface": 16842902, "textStyle": 16842903, "textColor": 16842904, "textColorHighlight": 16842905, "textColorHint": 16842906, "textColorLink": 16842907, "state_focused": 16842908, "state_window_focused": 16842909, "state_enabled": 16842910, "state_checkable": 16842911, "state_checked": 16842912, "state_selected": 16842913, "state_active": 16842914, "state_single": 16842915, "state_first": 16842916, "state_middle": 16842917, "state_last": 16842918, "state_pressed": 16842919, "state_expanded": 16842920, "state_empty": 16842921, "state_above_anchor": 16842922, "ellipsize": 16842923, "x": 16842924, "y": 16842925, "windowAnimationStyle": 16842926, "gravity": 16842927, "autoLink": 16842928, "linksClickable": 16842929, "entries": 16842930, "layout_gravity": 16842931, "windowEnterAnimation": 16842932, "windowExitAnimation": 16842933, "windowShowAnimation": 16842934, "windowHideAnimation": 16842935, "activityOpenEnterAnimation": 16842936, "activityOpenExitAnimation": 16842937, "activityCloseEnterAnimation": 16842938, "activityCloseExitAnimation": 16842939, "taskOpenEnterAnimation": 16842940, "taskOpenExitAnimation": 16842941, "taskCloseEnterAnimation": 16842942, "taskCloseExitAnimation": 16842943, "taskToFrontEnterAnimation": 16842944, "taskToFrontExitAnimation": 16842945, "taskToBackEnterAnimation": 16842946, "taskToBackExitAnimation": 16842947, "orientation": 16842948, "keycode": 16842949, "fullDark": 16842950, "topDark": 16842951, "centerDark": 16842952, "bottomDark": 16842953, "fullBright": 16842954, "topBright": 16842955, "centerBright": 16842956, "bottomBright": 16842957, "bottomMedium": 16842958, "centerMedium": 16842959, "id": 16842960, "tag": 16842961, "scrollX": 16842962, "scrollY": 16842963, "background": 16842964, "padding": 16842965, "paddingLeft": 16842966, "paddingTop": 16842967, "paddingRight": 16842968, "paddingBottom": 16842969, "focusable": 16842970, "focusableInTouchMode": 16842971, "visibility": 16842972, "fitsSystemWindows": 16842973, "scrollbars": 16842974, "fadingEdge": 16842975, "fadingEdgeLength": 16842976, "nextFocusLeft": 16842977, "nextFocusRight": 16842978, "nextFocusUp": 16842979, "nextFocusDown": 16842980, "clickable": 16842981, "longClickable": 16842982, "saveEnabled": 16842983, "drawingCacheQuality": 16842984, "duplicateParentState": 16842985, "clipChildren": 16842986, "clipToPadding": 16842987, "layoutAnimation": 16842988, "animationCache": 16842989, "persistentDrawingCache": 16842990, "alwaysDrawnWithCache": 16842991, "addStatesFromChildren": 16842992, "descendantFocusability": 16842993, "layout": 16842994, "inflatedId": 16842995, "layout_width": 16842996, "layout_height": 16842997, "layout_margin": 16842998, "layout_marginLeft": 16842999, "layout_marginTop": 16843000, "layout_marginRight": 16843001, "layout_marginBottom": 16843002, "listSelector": 16843003, "drawSelectorOnTop": 16843004, "stackFromBottom": 16843005, "scrollingCache": 16843006, "textFilterEnabled": 16843007, "transcriptMode": 16843008, "cacheColorHint": 16843009, "dial": 16843010, "hand_hour": 16843011, "hand_minute": 16843012, "format": 16843013, "checked": 16843014, "button": 16843015, "checkMark": 16843016, "foreground": 16843017, "measureAllChildren": 16843018, "groupIndicator": 16843019, "childIndicator": 16843020, "indicatorLeft": 16843021, "indicatorRight": 16843022, "childIndicatorLeft": 16843023, "childIndicatorRight": 16843024, "childDivider": 16843025, "animationDuration": 16843026, "spacing": 16843027, "horizontalSpacing": 16843028, "verticalSpacing": 16843029, "stretchMode": 16843030, "columnWidth": 16843031, "numColumns": 16843032, "src": 16843033, "antialias": 16843034, "filter": 16843035, "dither": 16843036, "scaleType": 16843037, "adjustViewBounds": 16843038, "maxWidth": 16843039, "maxHeight": 16843040, "tint": 16843041, "baselineAlignBottom": 16843042, "cropToPadding": 16843043, "textOn": 16843044, "textOff": 16843045, "baselineAligned": 16843046, "baselineAlignedChildIndex": 16843047, "weightSum": 16843048, "divider": 16843049, "dividerHeight": 16843050, "choiceMode": 16843051, "itemTextAppearance": 16843052, "horizontalDivider": 16843053, "verticalDivider": 16843054, "headerBackground": 16843055, "itemBackground": 16843056, "itemIconDisabledAlpha": 16843057, "rowHeight": 16843058, "maxRows": 16843059, "maxItemsPerRow": 16843060, "moreIcon": 16843061, "max": 16843062, "progress": 16843063, "secondaryProgress": 16843064, "indeterminate": 16843065, "indeterminateOnly": 16843066, "indeterminateDrawable": 16843067, "progressDrawable": 16843068, "indeterminateDuration": 16843069, "indeterminateBehavior": 16843070, "minWidth": 16843071, "minHeight": 16843072, "interpolator": 16843073, "thumb": 16843074, "thumbOffset": 16843075, "numStars": 16843076, "rating": 16843077, "stepSize": 16843078, "isIndicator": 16843079, "checkedButton": 16843080, "stretchColumns": 16843081, "shrinkColumns": 16843082, "collapseColumns": 16843083, "layout_column": 16843084, "layout_span": 16843085, "bufferType": 16843086, "text": 16843087, "hint": 16843088, "textScaleX": 16843089, "cursorVisible": 16843090, "maxLines": 16843091, "lines": 16843092, "height": 16843093, "minLines": 16843094, "maxEms": 16843095, "ems": 16843096, "width": 16843097, "minEms": 16843098, "scrollHorizontally": 16843099, "password": 16843100, "singleLine": 16843101, "selectAllOnFocus": 16843102, "includeFontPadding": 16843103, "maxLength": 16843104, "shadowColor": 16843105, "shadowDx": 16843106, "shadowDy": 16843107, "shadowRadius": 16843108, "numeric": 16843109, "digits": 16843110, "phoneNumber": 16843111, "inputMethod": 16843112, "capitalize": 16843113, "autoText": 16843114, "editable": 16843115, "freezesText": 16843116, "drawableTop": 16843117, "drawableBottom": 16843118, "drawableLeft": 16843119, "drawableRight": 16843120, "drawablePadding": 16843121, "completionHint": 16843122, "completionHintView": 16843123, "completionThreshold": 16843124, "dropDownSelector": 16843125, "popupBackground": 16843126, "inAnimation": 16843127, "outAnimation": 16843128, "flipInterval": 16843129, "fillViewport": 16843130, "prompt": 16843131, "startYear": 16843132, "endYear": 16843133, "mode": 16843134, "layout_x": 16843135, "layout_y": 16843136, "layout_weight": 16843137, "layout_toLeftOf": 16843138, "layout_toRightOf": 16843139, "layout_above": 16843140, "layout_below": 16843141, "layout_alignBaseline": 16843142, "layout_alignLeft": 16843143, "layout_alignTop": 16843144, "layout_alignRight": 16843145, "layout_alignBottom": 16843146, "layout_alignParentLeft": 16843147, "layout_alignParentTop": 16843148, "layout_alignParentRight": 16843149, "layout_alignParentBottom": 16843150, "layout_centerInParent": 16843151, "layout_centerHorizontal": 16843152, "layout_centerVertical": 16843153, "layout_alignWithParentIfMissing": 16843154, "layout_scale": 16843155, "visible": 16843156, "variablePadding": 16843157, "constantSize": 16843158, "oneshot": 16843159, "duration": 16843160, "drawable": 16843161, "shape": 16843162, "innerRadiusRatio": 16843163, "thicknessRatio": 16843164, "startColor": 16843165, "endColor": 16843166, "useLevel": 16843167, "angle": 16843168, "type": 16843169, "centerX": 16843170, "centerY": 16843171, "gradientRadius": 16843172, "color": 16843173, "dashWidth": 16843174, "dashGap": 16843175, "radius": 16843176, "topLeftRadius": 16843177, "topRightRadius": 16843178, "bottomLeftRadius": 16843179, "bottomRightRadius": 16843180, "left": 16843181, "top": 16843182, "right": 16843183, "bottom": 16843184, "minLevel": 16843185, "maxLevel": 16843186, "fromDegrees": 16843187, "toDegrees": 16843188, "pivotX": 16843189, "pivotY": 16843190, "insetLeft": 16843191, "insetRight": 16843192, "insetTop": 16843193, "insetBottom": 16843194, "shareInterpolator": 16843195, "fillBefore": 16843196, "fillAfter": 16843197, "startOffset": 16843198, "repeatCount": 16843199, "repeatMode": 16843200, "zAdjustment": 16843201, "fromXScale": 16843202, "toXScale": 16843203, "fromYScale": 16843204, "toYScale": 16843205, "fromXDelta": 16843206, "toXDelta": 16843207, "fromYDelta": 16843208, "toYDelta": 16843209, "fromAlpha": 16843210, "toAlpha": 16843211, "delay": 16843212, "animation": 16843213, "animationOrder": 16843214, "columnDelay": 16843215, "rowDelay": 16843216, "direction": 16843217, "directionPriority": 16843218, "factor": 16843219, "cycles": 16843220, "searchMode": 16843221, "searchSuggestAuthority": 16843222, "searchSuggestPath": 16843223, "searchSuggestSelection": 16843224, "searchSuggestIntentAction": 16843225, "searchSuggestIntentData": 16843226, "queryActionMsg": 16843227, "suggestActionMsg": 16843228, "suggestActionMsgColumn": 16843229, "menuCategory": 16843230, "orderInCategory": 16843231, "checkableBehavior": 16843232, "title": 16843233, "titleCondensed": 16843234, "alphabeticShortcut": 16843235, "numericShortcut": 16843236, "checkable": 16843237, "selectable": 16843238, "orderingFromXml": 16843239, "key": 16843240, "summary": 16843241, "order": 16843242, "widgetLayout": 16843243, "dependency": 16843244, "defaultValue": 16843245, "shouldDisableView": 16843246, "summaryOn": 16843247, "summaryOff": 16843248, "disableDependentsState": 16843249, "dialogTitle": 16843250, "dialogMessage": 16843251, "dialogIcon": 16843252, "positiveButtonText": 16843253, "negativeButtonText": 16843254, "dialogLayout": 16843255, "entryValues": 16843256, "ringtoneType": 16843257, "showDefault": 16843258, "showSilent": 16843259, "scaleWidth": 16843260, "scaleHeight": 16843261, "scaleGravity": 16843262, "ignoreGravity": 16843263, "foregroundGravity": 16843264, "tileMode": 16843265, "targetActivity": 16843266, "alwaysRetainTaskState": 16843267, "allowTaskReparenting": 16843268, "searchButtonText": 16843269, "colorForegroundInverse": 16843270, "textAppearanceButton": 16843271, "listSeparatorTextViewStyle": 16843272, "streamType": 16843273, "clipOrientation": 16843274, "centerColor": 16843275, "minSdkVersion": 16843276, "windowFullscreen": 16843277, "unselectedAlpha": 16843278, "progressBarStyleSmallTitle": 16843279, "ratingBarStyleIndicator": 16843280, "apiKey": 16843281, "textColorTertiary": 16843282, "textColorTertiaryInverse": 16843283, "listDivider": 16843284, "soundEffectsEnabled": 16843285, "keepScreenOn": 16843286, "lineSpacingExtra": 16843287, "lineSpacingMultiplier": 16843288, "listChoiceIndicatorSingle": 16843289, "listChoiceIndicatorMultiple": 16843290, "versionCode": 16843291, "versionName": 16843292, "marqueeRepeatLimit": 16843293, "windowNoDisplay": 16843294, "backgroundDimEnabled": 16843295, "inputType": 16843296, "isDefault": 16843297, "windowDisablePreview": 16843298, "privateImeOptions": 16843299, "editorExtras": 16843300, "settingsActivity": 16843301, "fastScrollEnabled": 16843302, "reqTouchScreen": 16843303, "reqKeyboardType": 16843304, "reqHardKeyboard": 16843305, "reqNavigation": 16843306, "windowSoftInputMode": 16843307, "imeFullscreenBackground": 16843308, "noHistory": 16843309, "headerDividersEnabled": 16843310, "footerDividersEnabled": 16843311, "candidatesTextStyleSpans": 16843312, "smoothScrollbar": 16843313, "reqFiveWayNav": 16843314, "keyBackground": 16843315, "keyTextSize": 16843316, "labelTextSize": 16843317, "keyTextColor": 16843318, "keyPreviewLayout": 16843319, "keyPreviewOffset": 16843320, "keyPreviewHeight": 16843321, "verticalCorrection": 16843322, "popupLayout": 16843323, "state_long_pressable": 16843324, "keyWidth": 16843325, "keyHeight": 16843326, "horizontalGap": 16843327, "verticalGap": 16843328, "rowEdgeFlags": 16843329, "codes": 16843330, "popupKeyboard": 16843331, "popupCharacters": 16843332, "keyEdgeFlags": 16843333, "isModifier": 16843334, "isSticky": 16843335, "isRepeatable": 16843336, "iconPreview": 16843337, "keyOutputText": 16843338, "keyLabel": 16843339, "keyIcon": 16843340, "keyboardMode": 16843341, "isScrollContainer": 16843342, "fillEnabled": 16843343, "updatePeriodMillis": 16843344, "initialLayout": 16843345, "voiceSearchMode": 16843346, "voiceLanguageModel": 16843347, "voicePromptText": 16843348, "voiceLanguage": 16843349, "voiceMaxResults": 16843350, "bottomOffset": 16843351, "topOffset": 16843352, "allowSingleTap": 16843353, "handle": 16843354, "content": 16843355, "animateOnClick": 16843356, "configure": 16843357, "hapticFeedbackEnabled": 16843358, "innerRadius": 16843359, "thickness": 16843360, "sharedUserLabel": 16843361, "dropDownWidth": 16843362, "dropDownAnchor": 16843363, "imeOptions": 16843364, "imeActionLabel": 16843365, "imeActionId": 16843366, "imeExtractEnterAnimation": 16843368, "imeExtractExitAnimation": 16843369, "tension": 16843370, "extraTension": 16843371, "anyDensity": 16843372, "searchSuggestThreshold": 16843373, "includeInGlobalSearch": 16843374, "onClick": 16843375, "targetSdkVersion": 16843376, "maxSdkVersion": 16843377, "testOnly": 16843378, "contentDescription": 16843379, "gestureStrokeWidth": 16843380, "gestureColor": 16843381, "uncertainGestureColor": 16843382, "fadeOffset": 16843383, "fadeDuration": 16843384, "gestureStrokeType": 16843385, "gestureStrokeLengthThreshold": 16843386, "gestureStrokeSquarenessThreshold": 16843387, "gestureStrokeAngleThreshold": 16843388, "eventsInterceptionEnabled": 16843389, "fadeEnabled": 16843390, "backupAgent": 16843391, "allowBackup": 16843392, "glEsVersion": 16843393, "queryAfterZeroResults": 16843394, "dropDownHeight": 16843395, "smallScreens": 16843396, "normalScreens": 16843397, "largeScreens": 16843398, "progressBarStyleInverse": 16843399, "progressBarStyleSmallInverse": 16843400, "progressBarStyleLargeInverse": 16843401, "searchSettingsDescription": 16843402, "textColorPrimaryInverseDisableOnly": 16843403, "autoUrlDetect": 16843404, "resizeable": 16843405, "required": 16843406, "accountType": 16843407, "contentAuthority": 16843408, "userVisible": 16843409, "windowShowWallpaper": 16843410, "wallpaperOpenEnterAnimation": 16843411, "wallpaperOpenExitAnimation": 16843412, "wallpaperCloseEnterAnimation": 16843413, "wallpaperCloseExitAnimation": 16843414, "wallpaperIntraOpenEnterAnimation": 16843415, "wallpaperIntraOpenExitAnimation": 16843416, "wallpaperIntraCloseEnterAnimation": 16843417, "wallpaperIntraCloseExitAnimation": 16843418, "supportsUploading": 16843419, "killAfterRestore": 16843420, "restoreNeedsApplication": 16843421, "smallIcon": 16843422, "accountPreferences": 16843423, "textAppearanceSearchResultSubtitle": 16843424, "textAppearanceSearchResultTitle": 16843425, "summaryColumn": 16843426, "detailColumn": 16843427, "detailSocialSummary": 16843428, "thumbnail": 16843429, "detachWallpaper": 16843430, "finishOnCloseSystemDialogs": 16843431, "scrollbarFadeDuration": 16843432, "scrollbarDefaultDelayBeforeFade": 16843433, "fadeScrollbars": 16843434, "colorBackgroundCacheHint": 16843435, "dropDownHorizontalOffset": 16843436, "dropDownVerticalOffset": 16843437, "quickContactBadgeStyleWindowSmall": 16843438, "quickContactBadgeStyleWindowMedium": 16843439, "quickContactBadgeStyleWindowLarge": 16843440, "quickContactBadgeStyleSmallWindowSmall": 16843441, "quickContactBadgeStyleSmallWindowMedium": 16843442, "quickContactBadgeStyleSmallWindowLarge": 16843443, "author": 16843444, "autoStart": 16843445, "expandableListViewWhiteStyle": 16843446, "installLocation": 16843447, "vmSafeMode": 16843448, "webTextViewStyle": 16843449, "restoreAnyVersion": 16843450, "tabStripLeft": 16843451, "tabStripRight": 16843452, "tabStripEnabled": 16843453, "logo": 16843454, "xlargeScreens": 16843455, "immersive": 16843456, "overScrollMode": 16843457, "overScrollHeader": 16843458, "overScrollFooter": 16843459, "filterTouchesWhenObscured": 16843460, "textSelectHandleLeft": 16843461, "textSelectHandleRight": 16843462, "textSelectHandle": 16843463, "textSelectHandleWindowStyle": 16843464, "popupAnimationStyle": 16843465, "screenSize": 16843466, "screenDensity": 16843467, "allContactsName": 16843468, "windowActionBar": 16843469, "actionBarStyle": 16843470, "navigationMode": 16843471, "displayOptions": 16843472, "subtitle": 16843473, "customNavigationLayout": 16843474, "hardwareAccelerated": 16843475, "measureWithLargestChild": 16843476, "animateFirstView": 16843477, "dropDownSpinnerStyle": 16843478, "actionDropDownStyle": 16843479, "actionButtonStyle": 16843480, "showAsAction": 16843481, "previewImage": 16843482, "actionModeBackground": 16843483, "actionModeCloseDrawable": 16843484, "windowActionModeOverlay": 16843485, "valueFrom": 16843486, "valueTo": 16843487, "valueType": 16843488, "propertyName": 16843489, "ordering": 16843490, "fragment": 16843491, "windowActionBarOverlay": 16843492, "fragmentOpenEnterAnimation": 16843493, "fragmentOpenExitAnimation": 16843494, "fragmentCloseEnterAnimation": 16843495, "fragmentCloseExitAnimation": 16843496, "fragmentFadeEnterAnimation": 16843497, "fragmentFadeExitAnimation": 16843498, "actionBarSize": 16843499, "imeSubtypeLocale": 16843500, "imeSubtypeMode": 16843501, "imeSubtypeExtraValue": 16843502, "splitMotionEvents": 16843503, "listChoiceBackgroundIndicator": 16843504, "spinnerMode": 16843505, "animateLayoutChanges": 16843506, "actionBarTabStyle": 16843507, "actionBarTabBarStyle": 16843508, "actionBarTabTextStyle": 16843509, "actionOverflowButtonStyle": 16843510, "actionModeCloseButtonStyle": 16843511, "titleTextStyle": 16843512, "subtitleTextStyle": 16843513, "iconifiedByDefault": 16843514, "actionLayout": 16843515, "actionViewClass": 16843516, "activatedBackgroundIndicator": 16843517, "state_activated": 16843518, "listPopupWindowStyle": 16843519, "popupMenuStyle": 16843520, "textAppearanceLargePopupMenu": 16843521, "textAppearanceSmallPopupMenu": 16843522, "breadCrumbTitle": 16843523, "breadCrumbShortTitle": 16843524, "listDividerAlertDialog": 16843525, "textColorAlertDialogListItem": 16843526, "loopViews": 16843527, "dialogTheme": 16843528, "alertDialogTheme": 16843529, "dividerVertical": 16843530, "homeAsUpIndicator": 16843531, "enterFadeDuration": 16843532, "exitFadeDuration": 16843533, "selectableItemBackground": 16843534, "autoAdvanceViewId": 16843535, "useIntrinsicSizeAsMinimum": 16843536, "actionModeCutDrawable": 16843537, "actionModeCopyDrawable": 16843538, "actionModePasteDrawable": 16843539, "textEditPasteWindowLayout": 16843540, "textEditNoPasteWindowLayout": 16843541, "textIsSelectable": 16843542, "windowEnableSplitTouch": 16843543, "indeterminateProgressStyle": 16843544, "progressBarPadding": 16843545, "animationResolution": 16843546, "state_accelerated": 16843547, "baseline": 16843548, "homeLayout": 16843549, "opacity": 16843550, "alpha": 16843551, "transformPivotX": 16843552, "transformPivotY": 16843553, "translationX": 16843554, "translationY": 16843555, "scaleX": 16843556, "scaleY": 16843557, "rotation": 16843558, "rotationX": 16843559, "rotationY": 16843560, "showDividers": 16843561, "dividerPadding": 16843562, "borderlessButtonStyle": 16843563, "dividerHorizontal": 16843564, "itemPadding": 16843565, "buttonBarStyle": 16843566, "buttonBarButtonStyle": 16843567, "segmentedButtonStyle": 16843568, "staticWallpaperPreview": 16843569, "allowParallelSyncs": 16843570, "isAlwaysSyncable": 16843571, "verticalScrollbarPosition": 16843572, "fastScrollAlwaysVisible": 16843573, "fastScrollThumbDrawable": 16843574, "fastScrollPreviewBackgroundLeft": 16843575, "fastScrollPreviewBackgroundRight": 16843576, "fastScrollTrackDrawable": 16843577, "fastScrollOverlayPosition": 16843578, "customTokens": 16843579, "nextFocusForward": 16843580, "firstDayOfWeek": 16843581, "showWeekNumber": 16843582, "minDate": 16843583, "maxDate": 16843584, "shownWeekCount": 16843585, "selectedWeekBackgroundColor": 16843586, "focusedMonthDateColor": 16843587, "unfocusedMonthDateColor": 16843588, "weekNumberColor": 16843589, "weekSeparatorLineColor": 16843590, "selectedDateVerticalBar": 16843591, "weekDayTextAppearance": 16843592, "dateTextAppearance": 16843593, "solidColor": 16843594, "spinnersShown": 16843595, "calendarViewShown": 16843596, "state_multiline": 16843597, "detailsElementBackground": 16843598, "textColorHighlightInverse": 16843599, "textColorLinkInverse": 16843600, "editTextColor": 16843601, "editTextBackground": 16843602, "horizontalScrollViewStyle": 16843603, "layerType": 16843604, "alertDialogIcon": 16843605, "windowMinWidthMajor": 16843606, "windowMinWidthMinor": 16843607, "queryHint": 16843608, "fastScrollTextColor": 16843609, "largeHeap": 16843610, "windowCloseOnTouchOutside": 16843611, "datePickerStyle": 16843612, "calendarViewStyle": 16843613, "textEditSidePasteWindowLayout": 16843614, "textEditSideNoPasteWindowLayout": 16843615, "actionMenuTextAppearance": 16843616, "actionMenuTextColor": 16843617, "textCursorDrawable": 16843618, "resizeMode": 16843619, "requiresSmallestWidthDp": 16843620, "compatibleWidthLimitDp": 16843621, "largestWidthLimitDp": 16843622, "state_hovered": 16843623, "state_drag_can_accept": 16843624, "state_drag_hovered": 16843625, "stopWithTask": 16843626, "switchTextOn": 16843627, "switchTextOff": 16843628, "switchPreferenceStyle": 16843629, "switchTextAppearance": 16843630, "track": 16843631, "switchMinWidth": 16843632, "switchPadding": 16843633, "thumbTextPadding": 16843634, "textSuggestionsWindowStyle": 16843635, "textEditSuggestionItemLayout": 16843636, "rowCount": 16843637, "rowOrderPreserved": 16843638, "columnCount": 16843639, "columnOrderPreserved": 16843640, "useDefaultMargins": 16843641, "alignmentMode": 16843642, "layout_row": 16843643, "layout_rowSpan": 16843644, "layout_columnSpan": 16843645, "actionModeSelectAllDrawable": 16843646, "isAuxiliary": 16843647, "accessibilityEventTypes": 16843648, "packageNames": 16843649, "accessibilityFeedbackType": 16843650, "notificationTimeout": 16843651, "accessibilityFlags": 16843652, "canRetrieveWindowContent": 16843653, "listPreferredItemHeightLarge": 16843654, "listPreferredItemHeightSmall": 16843655, "actionBarSplitStyle": 16843656, "actionProviderClass": 16843657, "backgroundStacked": 16843658, "backgroundSplit": 16843659, "textAllCaps": 16843660, "colorPressedHighlight": 16843661, "colorLongPressedHighlight": 16843662, "colorFocusedHighlight": 16843663, "colorActivatedHighlight": 16843664, "colorMultiSelectHighlight": 16843665, "drawableStart": 16843666, "drawableEnd": 16843667, "actionModeStyle": 16843668, "minResizeWidth": 16843669, "minResizeHeight": 16843670, "actionBarWidgetTheme": 16843671, "uiOptions": 16843672, "subtypeLocale": 16843673, "subtypeExtraValue": 16843674, "actionBarDivider": 16843675, "actionBarItemBackground": 16843676, "actionModeSplitBackground": 16843677, "textAppearanceListItem": 16843678, "textAppearanceListItemSmall": 16843679, "targetDescriptions": 16843680, "directionDescriptions": 16843681, "overridesImplicitlyEnabledSubtype": 16843682, "listPreferredItemPaddingLeft": 16843683, "listPreferredItemPaddingRight": 16843684, "requiresFadingEdge": 16843685, "publicKey": 16843686, "parentActivityName": 16843687, "isolatedProcess": 16843689, "importantForAccessibility": 16843690, "keyboardLayout": 16843691, "fontFamily": 16843692, "mediaRouteButtonStyle": 16843693, "mediaRouteTypes": 16843694, "supportsRtl": 16843695, "textDirection": 16843696, "textAlignment": 16843697, "layoutDirection": 16843698, "paddingStart": 16843699, "paddingEnd": 16843700, "layout_marginStart": 16843701, "layout_marginEnd": 16843702, "layout_toStartOf": 16843703, "layout_toEndOf": 16843704, "layout_alignStart": 16843705, "layout_alignEnd": 16843706, "layout_alignParentStart": 16843707, "layout_alignParentEnd": 16843708, "listPreferredItemPaddingStart": 16843709, "listPreferredItemPaddingEnd": 16843710, "singleUser": 16843711, "presentationTheme": 16843712, "subtypeId": 16843713, "initialKeyguardLayout": 16843714, "widgetCategory": 16843716, "permissionGroupFlags": 16843717, "labelFor": 16843718, "permissionFlags": 16843719, "checkedTextViewStyle": 16843720, "showOnLockScreen": 16843721, "format12Hour": 16843722, "format24Hour": 16843723, "timeZone": 16843724, "mipMap": 16843725, "mirrorForRtl": 16843726, "windowOverscan": 16843727, "requiredForAllUsers": 16843728, "indicatorStart": 16843729, "indicatorEnd": 16843730, "childIndicatorStart": 16843731, "childIndicatorEnd": 16843732, "restrictedAccountType": 16843733, "requiredAccountType": 16843734, "canRequestTouchExplorationMode": 16843735, "canRequestEnhancedWebAccessibility": 16843736, "canRequestFilterKeyEvents": 16843737, "layoutMode": 16843738, "keySet": 16843739, "targetId": 16843740, "fromScene": 16843741, "toScene": 16843742, "transition": 16843743, "transitionOrdering": 16843744, "fadingMode": 16843745, "startDelay": 16843746, "ssp": 16843747, "sspPrefix": 16843748, "sspPattern": 16843749, "addPrintersActivity": 16843750, "vendor": 16843751, "category": 16843752, "isAsciiCapable": 16843753, "autoMirrored": 16843754, "supportsSwitchingToNextInputMethod": 16843755, "requireDeviceUnlock": 16843756, "apduServiceBanner": 16843757, "accessibilityLiveRegion": 16843758, "windowTranslucentStatus": 16843759, "windowTranslucentNavigation": 16843760, "advancedPrintOptionsActivity": 16843761, "banner": 16843762, "windowSwipeToDismiss": 16843763, "isGame": 16843764, "allowEmbedded": 16843765, "setupActivity": 16843766, "fastScrollStyle": 16843767, "windowContentTransitions": 16843768, "windowContentTransitionManager": 16843769, "translationZ": 16843770, "tintMode": 16843771, "controlX1": 16843772, "controlY1": 16843773, "controlX2": 16843774, "controlY2": 16843775, "transitionName": 16843776, "transitionGroup": 16843777, "viewportWidth": 16843778, "viewportHeight": 16843779, "fillColor": 16843780, "pathData": 16843781, "strokeColor": 16843782, "strokeWidth": 16843783, "trimPathStart": 16843784, "trimPathEnd": 16843785, "trimPathOffset": 16843786, "strokeLineCap": 16843787, "strokeLineJoin": 16843788, "strokeMiterLimit": 16843789, "colorControlNormal": 16843817, "colorControlActivated": 16843818, "colorButtonNormal": 16843819, "colorControlHighlight": 16843820, "persistableMode": 16843821, "titleTextAppearance": 16843822, "subtitleTextAppearance": 16843823, "slideEdge": 16843824, "actionBarTheme": 16843825, "textAppearanceListItemSecondary": 16843826, "colorPrimary": 16843827, "colorPrimaryDark": 16843828, "colorAccent": 16843829, "nestedScrollingEnabled": 16843830, "windowEnterTransition": 16843831, "windowExitTransition": 16843832, "windowSharedElementEnterTransition": 16843833, "windowSharedElementExitTransition": 16843834, "windowAllowReturnTransitionOverlap": 16843835, "windowAllowEnterTransitionOverlap": 16843836, "sessionService": 16843837, "stackViewStyle": 16843838, "switchStyle": 16843839, "elevation": 16843840, "excludeId": 16843841, "excludeClass": 16843842, "hideOnContentScroll": 16843843, "actionOverflowMenuStyle": 16843844, "documentLaunchMode": 16843845, "maxRecents": 16843846, "autoRemoveFromRecents": 16843847, "stateListAnimator": 16843848, "toId": 16843849, "fromId": 16843850, "reversible": 16843851, "splitTrack": 16843852, "targetName": 16843853, "excludeName": 16843854, "matchOrder": 16843855, "windowDrawsSystemBarBackgrounds": 16843856, "statusBarColor": 16843857, "navigationBarColor": 16843858, "contentInsetStart": 16843859, "contentInsetEnd": 16843860, "contentInsetLeft": 16843861, "contentInsetRight": 16843862, "paddingMode": 16843863, "layout_rowWeight": 16843864, "layout_columnWeight": 16843865, "translateX": 16843866, "translateY": 16843867, "selectableItemBackgroundBorderless": 16843868, "elegantTextHeight": 16843869, "searchKeyphraseId": 16843870, "searchKeyphrase": 16843871, "searchKeyphraseSupportedLocales": 16843872, "windowTransitionBackgroundFadeDuration": 16843873, "overlapAnchor": 16843874, "progressTint": 16843875, "progressTintMode": 16843876, "progressBackgroundTint": 16843877, "progressBackgroundTintMode": 16843878, "secondaryProgressTint": 16843879, "secondaryProgressTintMode": 16843880, "indeterminateTint": 16843881, "indeterminateTintMode": 16843882, "backgroundTint": 16843883, "backgroundTintMode": 16843884, "foregroundTint": 16843885, "foregroundTintMode": 16843886, "buttonTint": 16843887, "buttonTintMode": 16843888, "thumbTint": 16843889, "thumbTintMode": 16843890, "fullBackupOnly": 16843891, "propertyXName": 16843892, "propertyYName": 16843893, "relinquishTaskIdentity": 16843894, "tileModeX": 16843895, "tileModeY": 16843896, "actionModeShareDrawable": 16843897, "actionModeFindDrawable": 16843898, "actionModeWebSearchDrawable": 16843899, "transitionVisibilityMode": 16843900, "minimumHorizontalAngle": 16843901, "minimumVerticalAngle": 16843902, "maximumAngle": 16843903, "searchViewStyle": 16843904, "closeIcon": 16843905, "goIcon": 16843906, "searchIcon": 16843907, "voiceIcon": 16843908, "commitIcon": 16843909, "suggestionRowLayout": 16843910, "queryBackground": 16843911, "submitBackground": 16843912, "buttonBarPositiveButtonStyle": 16843913, "buttonBarNeutralButtonStyle": 16843914, "buttonBarNegativeButtonStyle": 16843915, "popupElevation": 16843916, "actionBarPopupTheme": 16843917, "multiArch": 16843918, "touchscreenBlocksFocus": 16843919, "windowElevation": 16843920, "launchTaskBehindTargetAnimation": 16843921, "launchTaskBehindSourceAnimation": 16843922, "restrictionType": 16843923, "dayOfWeekBackground": 16843924, "dayOfWeekTextAppearance": 16843925, "headerMonthTextAppearance": 16843926, "headerDayOfMonthTextAppearance": 16843927, "headerYearTextAppearance": 16843928, "yearListItemTextAppearance": 16843929, "yearListSelectorColor": 16843930, "calendarTextColor": 16843931, "recognitionService": 16843932, "timePickerStyle": 16843933, "timePickerDialogTheme": 16843934, "headerTimeTextAppearance": 16843935, "headerAmPmTextAppearance": 16843936, "numbersTextColor": 16843937, "numbersBackgroundColor": 16843938, "numbersSelectorColor": 16843939, "amPmTextColor": 16843940, "amPmBackgroundColor": 16843941, "searchKeyphraseRecognitionFlags": 16843942, "checkMarkTint": 16843943, "checkMarkTintMode": 16843944, "popupTheme": 16843945, "toolbarStyle": 16843946, "windowClipToOutline": 16843947, "datePickerDialogTheme": 16843948, "showText": 16843949, "windowReturnTransition": 16843950, "windowReenterTransition": 16843951, "windowSharedElementReturnTransition": 16843952, "windowSharedElementReenterTransition": 16843953, "resumeWhilePausing": 16843954, "datePickerMode": 16843955, "timePickerMode": 16843956, "inset": 16843957, "letterSpacing": 16843958, "fontFeatureSettings": 16843959, "outlineProvider": 16843960, "contentAgeHint": 16843961, "country": 16843962, "windowSharedElementsUseOverlay": 16843963, "reparent": 16843964, "reparentWithOverlay": 16843965, "ambientShadowAlpha": 16843966, "spotShadowAlpha": 16843967, "navigationIcon": 16843968, "navigationContentDescription": 16843969, "fragmentExitTransition": 16843970, "fragmentEnterTransition": 16843971, "fragmentSharedElementEnterTransition": 16843972, "fragmentReturnTransition": 16843973, "fragmentSharedElementReturnTransition": 16843974, "fragmentReenterTransition": 16843975, "fragmentAllowEnterTransitionOverlap": 16843976, "fragmentAllowReturnTransitionOverlap": 16843977, "patternPathData": 16843978, "strokeAlpha": 16843979, "fillAlpha": 16843980, "windowActivityTransitions": 16843981, "colorEdgeEffect": 16843982, "resizeClip": 16843983, "collapseContentDescription": 16843984, "accessibilityTraversalBefore": 16843985, "accessibilityTraversalAfter": 16843986, "dialogPreferredPadding": 16843987, "searchHintIcon": 16843988, "revisionCode": 16843989, "drawableTint": 16843990, "drawableTintMode": 16843991, "fraction": 16843992, "trackTint": 16843993, "trackTintMode": 16843994, "start": 16843995, "end": 16843996, "breakStrategy": 16843997, "hyphenationFrequency": 16843998, "allowUndo": 16843999, "windowLightStatusBar": 16844000, "numbersInnerTextColor": 16844001, "colorBackgroundFloating": 16844002, "titleTextColor": 16844003, "subtitleTextColor": 16844004, "thumbPosition": 16844005, "scrollIndicators": 16844006, "contextClickable": 16844007, "fingerprintAuthDrawable": 16844008, "logoDescription": 16844009, "extractNativeLibs": 16844010, "fullBackupContent": 16844011, "usesCleartextTraffic": 16844012, "lockTaskMode": 16844013, "autoVerify": 16844014, "showForAllUsers": 16844015, "supportsAssist": 16844016, "supportsLaunchVoiceAssistFromKeyguard": 16844017, "listMenuViewStyle": 16844018, "subMenuArrow": 16844019, "defaultWidth": 16844020, "defaultHeight": 16844021, "resizeableActivity": 16844022, "supportsPictureInPicture": 16844023, "titleMargin": 16844024, "titleMarginStart": 16844025, "titleMarginEnd": 16844026, "titleMarginTop": 16844027, "titleMarginBottom": 16844028, "maxButtonHeight": 16844029, "buttonGravity": 16844030, "collapseIcon": 16844031, "level": 16844032, "contextPopupMenuStyle": 16844033, "textAppearancePopupMenuHeader": 16844034, "windowBackgroundFallback": 16844035, "defaultToDeviceProtectedStorage": 16844036, "directBootAware": 16844037, "preferenceFragmentStyle": 16844038, "canControlMagnification": 16844039, "languageTag": 16844040, "pointerIcon": 16844041, "tickMark": 16844042, "tickMarkTint": 16844043, "tickMarkTintMode": 16844044, "canPerformGestures": 16844045, "externalService": 16844046, "supportsLocalInteraction": 16844047, "startX": 16844048, "startY": 16844049, "endX": 16844050, "endY": 16844051, "offset": 16844052, "use32bitAbi": 16844053, "bitmap": 16844054, "hotSpotX": 16844055, "hotSpotY": 16844056, "version": 16844057, "backupInForeground": 16844058, "countDown": 16844059, "canRecord": 16844060, "tunerCount": 16844061, "fillType": 16844062, "popupEnterTransition": 16844063, "popupExitTransition": 16844064, "forceHasOverlappingRendering": 16844065, "contentInsetStartWithNavigation": 16844066, "contentInsetEndWithActions": 16844067, "numberPickerStyle": 16844068, "enableVrMode": 16844069, "hash": 16844070, "networkSecurityConfig": 16844071, "shortcutId": 16844072, "shortcutShortLabel": 16844073, "shortcutLongLabel": 16844074, "shortcutDisabledMessage": 16844075, "roundIcon": 16844076, "contextUri": 16844077, "contextDescription": 16844078, "showMetadataInPreview": 16844079, "colorSecondary": 16844080, "visibleToInstantApps": 16844081, "font": 16844082, "fontWeight": 16844083, "tooltipText": 16844084, "autoSizeTextType": 16844085, "autoSizeStepGranularity": 16844086, "autoSizePresetSizes": 16844087, "autoSizeMinTextSize": 16844088, "min": 16844089, "rotationAnimation": 16844090, "layout_marginHorizontal": 16844091, "layout_marginVertical": 16844092, "paddingHorizontal": 16844093, "paddingVertical": 16844094, "fontStyle": 16844095, "keyboardNavigationCluster": 16844096, "targetProcesses": 16844097, "nextClusterForward": 16844098, "colorError": 16844099, "focusedByDefault": 16844100, "appCategory": 16844101, "autoSizeMaxTextSize": 16844102, "recreateOnConfigChanges": 16844103, "certDigest": 16844104, "splitName": 16844105, "colorMode": 16844106, "isolatedSplits": 16844107, "targetSandboxVersion": 16844108, "canRequestFingerprintGestures": 16844109, "alphabeticModifiers": 16844110, "numericModifiers": 16844111, "fontProviderAuthority": 16844112, "fontProviderQuery": 16844113, "primaryContentAlpha": 16844114, "secondaryContentAlpha": 16844115, "requiredFeature": 16844116, "requiredNotFeature": 16844117, "autofillHints": 16844118, "fontProviderPackage": 16844119, "importantForAutofill": 16844120, "recycleEnabled": 16844121, "isStatic": 16844122, "isFeatureSplit": 16844123, "singleLineTitle": 16844124, "fontProviderCerts": 16844125, "iconTint": 16844126, "iconTintMode": 16844127, "maxAspectRatio": 16844128, "iconSpaceReserved": 16844129, "defaultFocusHighlightEnabled": 16844130, "persistentWhenFeatureAvailable": 16844131, "windowSplashscreenContent": 16844132, "requiredSystemPropertyName": 16844133, "requiredSystemPropertyValue": 16844134, "justificationMode": 16844135, "autofilledHighlight": 16844136, "showWhenLocked": 16844137, "turnScreenOn": 16844138, "classLoader": 16844139, "windowLightNavigationBar": 16844140, "navigationBarDividerColor": 16844141 }, "id": { "background": 16908288, "checkbox": 16908289, "content": 16908290, "edit": 16908291, "empty": 16908292, "hint": 16908293, "icon": 16908294, "icon1": 16908295, "icon2": 16908296, "input": 16908297, "list": 16908298, "message": 16908299, "primary": 16908300, "progress": 16908301, "selectedIcon": 16908302, "secondaryProgress": 16908303, "summary": 16908304, "tabcontent": 16908305, "tabhost": 16908306, "tabs": 16908307, "text1": 16908308, "text2": 16908309, "title": 16908310, "toggle": 16908311, "widget_frame": 16908312, "button1": 16908313, "button2": 16908314, "button3": 16908315, "extractArea": 16908316, "candidatesArea": 16908317, "inputArea": 16908318, "selectAll": 16908319, "cut": 16908320, "copy": 16908321, "paste": 16908322, "copyUrl": 16908323, "switchInputMethod": 16908324, "inputExtractEditText": 16908325, "keyboardView": 16908326, "closeButton": 16908327, "startSelectingText": 16908328, "stopSelectingText": 16908329, "addToDictionary": 16908330, "custom": 16908331, "home": 16908332, "selectTextMode": 16908333, "mask": 16908334, "statusBarBackground": 16908335, "navigationBarBackground": 16908336, "pasteAsPlainText": 16908337, "undo": 16908338, "redo": 16908339, "replaceText": 16908340, "shareText": 16908341, "accessibilityActionShowOnScreen": 16908342, "accessibilityActionScrollToPosition": 16908343, "accessibilityActionScrollUp": 16908344, "accessibilityActionScrollLeft": 16908345, "accessibilityActionScrollDown": 16908346, "accessibilityActionScrollRight": 16908347, "accessibilityActionContextClick": 16908348, "accessibilityActionSetProgress": 16908349, "icon_frame": 16908350, "list_container": 16908351, "switch_widget": 16908352, "textAssist": 16908353, "accessibilityActionMoveWindow": 16908354, "autofill": 16908355 }, "style": { "Animation": 16973824, "Animation.Activity": 16973825, "Animation.Dialog": 16973826, "Animation.Translucent": 16973827, "Animation.Toast": 16973828, "Theme": 16973829, "Theme.NoTitleBar": 16973830, "Theme.NoTitleBar.Fullscreen": 16973831, "Theme.Black": 16973832, "Theme.Black.NoTitleBar": 16973833, "Theme.Black.NoTitleBar.Fullscreen": 16973834, "Theme.Dialog": 16973835, "Theme.Light": 16973836, "Theme.Light.NoTitleBar": 16973837, "Theme.Light.NoTitleBar.Fullscreen": 16973838, "Theme.Translucent": 16973839, "Theme.Translucent.NoTitleBar": 16973840, "Theme.Translucent.NoTitleBar.Fullscreen": 16973841, "Widget": 16973842, "Widget.AbsListView": 16973843, "Widget.Button": 16973844, "Widget.Button.Inset": 16973845, "Widget.Button.Small": 16973846, "Widget.Button.Toggle": 16973847, "Widget.CompoundButton": 16973848, "Widget.CompoundButton.CheckBox": 16973849, "Widget.CompoundButton.RadioButton": 16973850, "Widget.CompoundButton.Star": 16973851, "Widget.ProgressBar": 16973852, "Widget.ProgressBar.Large": 16973853, "Widget.ProgressBar.Small": 16973854, "Widget.ProgressBar.Horizontal": 16973855, "Widget.SeekBar": 16973856, "Widget.RatingBar": 16973857, "Widget.TextView": 16973858, "Widget.EditText": 16973859, "Widget.ExpandableListView": 16973860, "Widget.ImageWell": 16973861, "Widget.ImageButton": 16973862, "Widget.AutoCompleteTextView": 16973863, "Widget.Spinner": 16973864, "Widget.TextView.PopupMenu": 16973865, "Widget.TextView.SpinnerItem": 16973866, "Widget.DropDownItem": 16973867, "Widget.DropDownItem.Spinner": 16973868, "Widget.ScrollView": 16973869, "Widget.ListView": 16973870, "Widget.ListView.White": 16973871, "Widget.ListView.DropDown": 16973872, "Widget.ListView.Menu": 16973873, "Widget.GridView": 16973874, "Widget.WebView": 16973875, "Widget.TabWidget": 16973876, "Widget.Gallery": 16973877, "Widget.PopupWindow": 16973878, "MediaButton": 16973879, "MediaButton.Previous": 16973880, "MediaButton.Next": 16973881, "MediaButton.Play": 16973882, "MediaButton.Ffwd": 16973883, "MediaButton.Rew": 16973884, "MediaButton.Pause": 16973885, "TextAppearance": 16973886, "TextAppearance.Inverse": 16973887, "TextAppearance.Theme": 16973888, "TextAppearance.DialogWindowTitle": 16973889, "TextAppearance.Large": 16973890, "TextAppearance.Large.Inverse": 16973891, "TextAppearance.Medium": 16973892, "TextAppearance.Medium.Inverse": 16973893, "TextAppearance.Small": 16973894, "TextAppearance.Small.Inverse": 16973895, "TextAppearance.Theme.Dialog": 16973896, "TextAppearance.Widget": 16973897, "TextAppearance.Widget.Button": 16973898, "TextAppearance.Widget.IconMenu.Item": 16973899, "TextAppearance.Widget.EditText": 16973900, "TextAppearance.Widget.TabWidget": 16973901, "TextAppearance.Widget.TextView": 16973902, "TextAppearance.Widget.TextView.PopupMenu": 16973903, "TextAppearance.Widget.DropDownHint": 16973904, "TextAppearance.Widget.DropDownItem": 16973905, "TextAppearance.Widget.TextView.SpinnerItem": 16973906, "TextAppearance.WindowTitle": 16973907, "Theme.InputMethod": 16973908, "Theme.NoDisplay": 16973909, "Animation.InputMethod": 16973910, "Widget.KeyboardView": 16973911, "ButtonBar": 16973912, "Theme.Panel": 16973913, "Theme.Light.Panel": 16973914, "Widget.ProgressBar.Inverse": 16973915, "Widget.ProgressBar.Large.Inverse": 16973916, "Widget.ProgressBar.Small.Inverse": 16973917, "Theme.Wallpaper": 16973918, "Theme.Wallpaper.NoTitleBar": 16973919, "Theme.Wallpaper.NoTitleBar.Fullscreen": 16973920, "Theme.WallpaperSettings": 16973921, "Theme.Light.WallpaperSettings": 16973922, "TextAppearance.SearchResult.Title": 16973923, "TextAppearance.SearchResult.Subtitle": 16973924, "TextAppearance.StatusBar.Title": 16973925, "TextAppearance.StatusBar.Icon": 16973926, "TextAppearance.StatusBar.EventContent": 16973927, "TextAppearance.StatusBar.EventContent.Title": 16973928, "Theme.WithActionBar": 16973929, "Theme.NoTitleBar.OverlayActionModes": 16973930, "Theme.Holo": 16973931, "Theme.Holo.NoActionBar": 16973932, "Theme.Holo.NoActionBar.Fullscreen": 16973933, "Theme.Holo.Light": 16973934, "Theme.Holo.Dialog": 16973935, "Theme.Holo.Dialog.MinWidth": 16973936, "Theme.Holo.Dialog.NoActionBar": 16973937, "Theme.Holo.Dialog.NoActionBar.MinWidth": 16973938, "Theme.Holo.Light.Dialog": 16973939, "Theme.Holo.Light.Dialog.MinWidth": 16973940, "Theme.Holo.Light.Dialog.NoActionBar": 16973941, "Theme.Holo.Light.Dialog.NoActionBar.MinWidth": 16973942, "Theme.Holo.DialogWhenLarge": 16973943, "Theme.Holo.DialogWhenLarge.NoActionBar": 16973944, "Theme.Holo.Light.DialogWhenLarge": 16973945, "Theme.Holo.Light.DialogWhenLarge.NoActionBar": 16973946, "Theme.Holo.Panel": 16973947, "Theme.Holo.Light.Panel": 16973948, "Theme.Holo.Wallpaper": 16973949, "Theme.Holo.Wallpaper.NoTitleBar": 16973950, "Theme.Holo.InputMethod": 16973951, "TextAppearance.Widget.PopupMenu.Large": 16973952, "TextAppearance.Widget.PopupMenu.Small": 16973953, "Widget.ActionBar": 16973954, "Widget.Spinner.DropDown": 16973955, "Widget.ActionButton": 16973956, "Widget.ListPopupWindow": 16973957, "Widget.PopupMenu": 16973958, "Widget.ActionButton.Overflow": 16973959, "Widget.ActionButton.CloseMode": 16973960, "Widget.FragmentBreadCrumbs": 16973961, "Widget.Holo": 16973962, "Widget.Holo.Button": 16973963, "Widget.Holo.Button.Small": 16973964, "Widget.Holo.Button.Inset": 16973965, "Widget.Holo.Button.Toggle": 16973966, "Widget.Holo.TextView": 16973967, "Widget.Holo.AutoCompleteTextView": 16973968, "Widget.Holo.CompoundButton.CheckBox": 16973969, "Widget.Holo.ListView.DropDown": 16973970, "Widget.Holo.EditText": 16973971, "Widget.Holo.ExpandableListView": 16973972, "Widget.Holo.GridView": 16973973, "Widget.Holo.ImageButton": 16973974, "Widget.Holo.ListView": 16973975, "Widget.Holo.PopupWindow": 16973976, "Widget.Holo.ProgressBar": 16973977, "Widget.Holo.ProgressBar.Horizontal": 16973978, "Widget.Holo.ProgressBar.Small": 16973979, "Widget.Holo.ProgressBar.Small.Title": 16973980, "Widget.Holo.ProgressBar.Large": 16973981, "Widget.Holo.SeekBar": 16973982, "Widget.Holo.RatingBar": 16973983, "Widget.Holo.RatingBar.Indicator": 16973984, "Widget.Holo.RatingBar.Small": 16973985, "Widget.Holo.CompoundButton.RadioButton": 16973986, "Widget.Holo.ScrollView": 16973987, "Widget.Holo.HorizontalScrollView": 16973988, "Widget.Holo.Spinner": 16973989, "Widget.Holo.CompoundButton.Star": 16973990, "Widget.Holo.TabWidget": 16973991, "Widget.Holo.WebTextView": 16973992, "Widget.Holo.WebView": 16973993, "Widget.Holo.DropDownItem": 16973994, "Widget.Holo.DropDownItem.Spinner": 16973995, "Widget.Holo.TextView.SpinnerItem": 16973996, "Widget.Holo.ListPopupWindow": 16973997, "Widget.Holo.PopupMenu": 16973998, "Widget.Holo.ActionButton": 16973999, "Widget.Holo.ActionButton.Overflow": 16974000, "Widget.Holo.ActionButton.TextButton": 16974001, "Widget.Holo.ActionMode": 16974002, "Widget.Holo.ActionButton.CloseMode": 16974003, "Widget.Holo.ActionBar": 16974004, "Widget.Holo.Light": 16974005, "Widget.Holo.Light.Button": 16974006, "Widget.Holo.Light.Button.Small": 16974007, "Widget.Holo.Light.Button.Inset": 16974008, "Widget.Holo.Light.Button.Toggle": 16974009, "Widget.Holo.Light.TextView": 16974010, "Widget.Holo.Light.AutoCompleteTextView": 16974011, "Widget.Holo.Light.CompoundButton.CheckBox": 16974012, "Widget.Holo.Light.ListView.DropDown": 16974013, "Widget.Holo.Light.EditText": 16974014, "Widget.Holo.Light.ExpandableListView": 16974015, "Widget.Holo.Light.GridView": 16974016, "Widget.Holo.Light.ImageButton": 16974017, "Widget.Holo.Light.ListView": 16974018, "Widget.Holo.Light.PopupWindow": 16974019, "Widget.Holo.Light.ProgressBar": 16974020, "Widget.Holo.Light.ProgressBar.Horizontal": 16974021, "Widget.Holo.Light.ProgressBar.Small": 16974022, "Widget.Holo.Light.ProgressBar.Small.Title": 16974023, "Widget.Holo.Light.ProgressBar.Large": 16974024, "Widget.Holo.Light.ProgressBar.Inverse": 16974025, "Widget.Holo.Light.ProgressBar.Small.Inverse": 16974026, "Widget.Holo.Light.ProgressBar.Large.Inverse": 16974027, "Widget.Holo.Light.SeekBar": 16974028, "Widget.Holo.Light.RatingBar": 16974029, "Widget.Holo.Light.RatingBar.Indicator": 16974030, "Widget.Holo.Light.RatingBar.Small": 16974031, "Widget.Holo.Light.CompoundButton.RadioButton": 16974032, "Widget.Holo.Light.ScrollView": 16974033, "Widget.Holo.Light.HorizontalScrollView": 16974034, "Widget.Holo.Light.Spinner": 16974035, "Widget.Holo.Light.CompoundButton.Star": 16974036, "Widget.Holo.Light.TabWidget": 16974037, "Widget.Holo.Light.WebTextView": 16974038, "Widget.Holo.Light.WebView": 16974039, "Widget.Holo.Light.DropDownItem": 16974040, "Widget.Holo.Light.DropDownItem.Spinner": 16974041, "Widget.Holo.Light.TextView.SpinnerItem": 16974042, "Widget.Holo.Light.ListPopupWindow": 16974043, "Widget.Holo.Light.PopupMenu": 16974044, "Widget.Holo.Light.ActionButton": 16974045, "Widget.Holo.Light.ActionButton.Overflow": 16974046, "Widget.Holo.Light.ActionMode": 16974047, "Widget.Holo.Light.ActionButton.CloseMode": 16974048, "Widget.Holo.Light.ActionBar": 16974049, "Widget.Holo.Button.Borderless": 16974050, "Widget.Holo.Tab": 16974051, "Widget.Holo.Light.Tab": 16974052, "Holo.ButtonBar": 16974053, "Holo.Light.ButtonBar": 16974054, "Holo.ButtonBar.AlertDialog": 16974055, "Holo.Light.ButtonBar.AlertDialog": 16974056, "Holo.SegmentedButton": 16974057, "Holo.Light.SegmentedButton": 16974058, "Widget.CalendarView": 16974059, "Widget.Holo.CalendarView": 16974060, "Widget.Holo.Light.CalendarView": 16974061, "Widget.DatePicker": 16974062, "Widget.Holo.DatePicker": 16974063, "Theme.Holo.Light.NoActionBar": 16974064, "Theme.Holo.Light.NoActionBar.Fullscreen": 16974065, "Widget.ActionBar.TabView": 16974066, "Widget.ActionBar.TabText": 16974067, "Widget.ActionBar.TabBar": 16974068, "Widget.Holo.ActionBar.TabView": 16974069, "Widget.Holo.ActionBar.TabText": 16974070, "Widget.Holo.ActionBar.TabBar": 16974071, "Widget.Holo.Light.ActionBar.TabView": 16974072, "Widget.Holo.Light.ActionBar.TabText": 16974073, "Widget.Holo.Light.ActionBar.TabBar": 16974074, "TextAppearance.Holo": 16974075, "TextAppearance.Holo.Inverse": 16974076, "TextAppearance.Holo.Large": 16974077, "TextAppearance.Holo.Large.Inverse": 16974078, "TextAppearance.Holo.Medium": 16974079, "TextAppearance.Holo.Medium.Inverse": 16974080, "TextAppearance.Holo.Small": 16974081, "TextAppearance.Holo.Small.Inverse": 16974082, "TextAppearance.Holo.SearchResult.Title": 16974083, "TextAppearance.Holo.SearchResult.Subtitle": 16974084, "TextAppearance.Holo.Widget": 16974085, "TextAppearance.Holo.Widget.Button": 16974086, "TextAppearance.Holo.Widget.IconMenu.Item": 16974087, "TextAppearance.Holo.Widget.TabWidget": 16974088, "TextAppearance.Holo.Widget.TextView": 16974089, "TextAppearance.Holo.Widget.TextView.PopupMenu": 16974090, "TextAppearance.Holo.Widget.DropDownHint": 16974091, "TextAppearance.Holo.Widget.DropDownItem": 16974092, "TextAppearance.Holo.Widget.TextView.SpinnerItem": 16974093, "TextAppearance.Holo.Widget.EditText": 16974094, "TextAppearance.Holo.Widget.PopupMenu": 16974095, "TextAppearance.Holo.Widget.PopupMenu.Large": 16974096, "TextAppearance.Holo.Widget.PopupMenu.Small": 16974097, "TextAppearance.Holo.Widget.ActionBar.Title": 16974098, "TextAppearance.Holo.Widget.ActionBar.Subtitle": 16974099, "TextAppearance.Holo.Widget.ActionMode.Title": 16974100, "TextAppearance.Holo.Widget.ActionMode.Subtitle": 16974101, "TextAppearance.Holo.WindowTitle": 16974102, "TextAppearance.Holo.DialogWindowTitle": 16974103, "TextAppearance.SuggestionHighlight": 16974104, "Theme.Holo.Light.DarkActionBar": 16974105, "Widget.Holo.Button.Borderless.Small": 16974106, "Widget.Holo.Light.Button.Borderless.Small": 16974107, "TextAppearance.Holo.Widget.ActionBar.Title.Inverse": 16974108, "TextAppearance.Holo.Widget.ActionBar.Subtitle.Inverse": 16974109, "TextAppearance.Holo.Widget.ActionMode.Title.Inverse": 16974110, "TextAppearance.Holo.Widget.ActionMode.Subtitle.Inverse": 16974111, "TextAppearance.Holo.Widget.ActionBar.Menu": 16974112, "Widget.Holo.ActionBar.Solid": 16974113, "Widget.Holo.Light.ActionBar.Solid": 16974114, "Widget.Holo.Light.ActionBar.Solid.Inverse": 16974115, "Widget.Holo.Light.ActionBar.TabBar.Inverse": 16974116, "Widget.Holo.Light.ActionBar.TabView.Inverse": 16974117, "Widget.Holo.Light.ActionBar.TabText.Inverse": 16974118, "Widget.Holo.Light.ActionMode.Inverse": 16974119, "Theme.DeviceDefault": 16974120, "Theme.DeviceDefault.NoActionBar": 16974121, "Theme.DeviceDefault.NoActionBar.Fullscreen": 16974122, "Theme.DeviceDefault.Light": 16974123, "Theme.DeviceDefault.Light.NoActionBar": 16974124, "Theme.DeviceDefault.Light.NoActionBar.Fullscreen": 16974125, "Theme.DeviceDefault.Dialog": 16974126, "Theme.DeviceDefault.Dialog.MinWidth": 16974127, "Theme.DeviceDefault.Dialog.NoActionBar": 16974128, "Theme.DeviceDefault.Dialog.NoActionBar.MinWidth": 16974129, "Theme.DeviceDefault.Light.Dialog": 16974130, "Theme.DeviceDefault.Light.Dialog.MinWidth": 16974131, "Theme.DeviceDefault.Light.Dialog.NoActionBar": 16974132, "Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth": 16974133, "Theme.DeviceDefault.DialogWhenLarge": 16974134, "Theme.DeviceDefault.DialogWhenLarge.NoActionBar": 16974135, "Theme.DeviceDefault.Light.DialogWhenLarge": 16974136, "Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar": 16974137, "Theme.DeviceDefault.Panel": 16974138, "Theme.DeviceDefault.Light.Panel": 16974139, "Theme.DeviceDefault.Wallpaper": 16974140, "Theme.DeviceDefault.Wallpaper.NoTitleBar": 16974141, "Theme.DeviceDefault.InputMethod": 16974142, "Theme.DeviceDefault.Light.DarkActionBar": 16974143, "Widget.DeviceDefault": 16974144, "Widget.DeviceDefault.Button": 16974145, "Widget.DeviceDefault.Button.Small": 16974146, "Widget.DeviceDefault.Button.Inset": 16974147, "Widget.DeviceDefault.Button.Toggle": 16974148, "Widget.DeviceDefault.Button.Borderless.Small": 16974149, "Widget.DeviceDefault.TextView": 16974150, "Widget.DeviceDefault.AutoCompleteTextView": 16974151, "Widget.DeviceDefault.CompoundButton.CheckBox": 16974152, "Widget.DeviceDefault.ListView.DropDown": 16974153, "Widget.DeviceDefault.EditText": 16974154, "Widget.DeviceDefault.ExpandableListView": 16974155, "Widget.DeviceDefault.GridView": 16974156, "Widget.DeviceDefault.ImageButton": 16974157, "Widget.DeviceDefault.ListView": 16974158, "Widget.DeviceDefault.PopupWindow": 16974159, "Widget.DeviceDefault.ProgressBar": 16974160, "Widget.DeviceDefault.ProgressBar.Horizontal": 16974161, "Widget.DeviceDefault.ProgressBar.Small": 16974162, "Widget.DeviceDefault.ProgressBar.Small.Title": 16974163, "Widget.DeviceDefault.ProgressBar.Large": 16974164, "Widget.DeviceDefault.SeekBar": 16974165, "Widget.DeviceDefault.RatingBar": 16974166, "Widget.DeviceDefault.RatingBar.Indicator": 16974167, "Widget.DeviceDefault.RatingBar.Small": 16974168, "Widget.DeviceDefault.CompoundButton.RadioButton": 16974169, "Widget.DeviceDefault.ScrollView": 16974170, "Widget.DeviceDefault.HorizontalScrollView": 16974171, "Widget.DeviceDefault.Spinner": 16974172, "Widget.DeviceDefault.CompoundButton.Star": 16974173, "Widget.DeviceDefault.TabWidget": 16974174, "Widget.DeviceDefault.WebTextView": 16974175, "Widget.DeviceDefault.WebView": 16974176, "Widget.DeviceDefault.DropDownItem": 16974177, "Widget.DeviceDefault.DropDownItem.Spinner": 16974178, "Widget.DeviceDefault.TextView.SpinnerItem": 16974179, "Widget.DeviceDefault.ListPopupWindow": 16974180, "Widget.DeviceDefault.PopupMenu": 16974181, "Widget.DeviceDefault.ActionButton": 16974182, "Widget.DeviceDefault.ActionButton.Overflow": 16974183, "Widget.DeviceDefault.ActionButton.TextButton": 16974184, "Widget.DeviceDefault.ActionMode": 16974185, "Widget.DeviceDefault.ActionButton.CloseMode": 16974186, "Widget.DeviceDefault.ActionBar": 16974187, "Widget.DeviceDefault.Button.Borderless": 16974188, "Widget.DeviceDefault.Tab": 16974189, "Widget.DeviceDefault.CalendarView": 16974190, "Widget.DeviceDefault.DatePicker": 16974191, "Widget.DeviceDefault.ActionBar.TabView": 16974192, "Widget.DeviceDefault.ActionBar.TabText": 16974193, "Widget.DeviceDefault.ActionBar.TabBar": 16974194, "Widget.DeviceDefault.ActionBar.Solid": 16974195, "Widget.DeviceDefault.Light": 16974196, "Widget.DeviceDefault.Light.Button": 16974197, "Widget.DeviceDefault.Light.Button.Small": 16974198, "Widget.DeviceDefault.Light.Button.Inset": 16974199, "Widget.DeviceDefault.Light.Button.Toggle": 16974200, "Widget.DeviceDefault.Light.Button.Borderless.Small": 16974201, "Widget.DeviceDefault.Light.TextView": 16974202, "Widget.DeviceDefault.Light.AutoCompleteTextView": 16974203, "Widget.DeviceDefault.Light.CompoundButton.CheckBox": 16974204, "Widget.DeviceDefault.Light.ListView.DropDown": 16974205, "Widget.DeviceDefault.Light.EditText": 16974206, "Widget.DeviceDefault.Light.ExpandableListView": 16974207, "Widget.DeviceDefault.Light.GridView": 16974208, "Widget.DeviceDefault.Light.ImageButton": 16974209, "Widget.DeviceDefault.Light.ListView": 16974210, "Widget.DeviceDefault.Light.PopupWindow": 16974211, "Widget.DeviceDefault.Light.ProgressBar": 16974212, "Widget.DeviceDefault.Light.ProgressBar.Horizontal": 16974213, "Widget.DeviceDefault.Light.ProgressBar.Small": 16974214, "Widget.DeviceDefault.Light.ProgressBar.Small.Title": 16974215, "Widget.DeviceDefault.Light.ProgressBar.Large": 16974216, "Widget.DeviceDefault.Light.ProgressBar.Inverse": 16974217, "Widget.DeviceDefault.Light.ProgressBar.Small.Inverse": 16974218, "Widget.DeviceDefault.Light.ProgressBar.Large.Inverse": 16974219, "Widget.DeviceDefault.Light.SeekBar": 16974220, "Widget.DeviceDefault.Light.RatingBar": 16974221, "Widget.DeviceDefault.Light.RatingBar.Indicator": 16974222, "Widget.DeviceDefault.Light.RatingBar.Small": 16974223, "Widget.DeviceDefault.Light.CompoundButton.RadioButton": 16974224, "Widget.DeviceDefault.Light.ScrollView": 16974225, "Widget.DeviceDefault.Light.HorizontalScrollView": 16974226, "Widget.DeviceDefault.Light.Spinner": 16974227, "Widget.DeviceDefault.Light.CompoundButton.Star": 16974228, "Widget.DeviceDefault.Light.TabWidget": 16974229, "Widget.DeviceDefault.Light.WebTextView": 16974230, "Widget.DeviceDefault.Light.WebView": 16974231, "Widget.DeviceDefault.Light.DropDownItem": 16974232, "Widget.DeviceDefault.Light.DropDownItem.Spinner": 16974233, "Widget.DeviceDefault.Light.TextView.SpinnerItem": 16974234, "Widget.DeviceDefault.Light.ListPopupWindow": 16974235, "Widget.DeviceDefault.Light.PopupMenu": 16974236, "Widget.DeviceDefault.Light.Tab": 16974237, "Widget.DeviceDefault.Light.CalendarView": 16974238, "Widget.DeviceDefault.Light.ActionButton": 16974239, "Widget.DeviceDefault.Light.ActionButton.Overflow": 16974240, "Widget.DeviceDefault.Light.ActionMode": 16974241, "Widget.DeviceDefault.Light.ActionButton.CloseMode": 16974242, "Widget.DeviceDefault.Light.ActionBar": 16974243, "Widget.DeviceDefault.Light.ActionBar.TabView": 16974244, "Widget.DeviceDefault.Light.ActionBar.TabText": 16974245, "Widget.DeviceDefault.Light.ActionBar.TabBar": 16974246, "Widget.DeviceDefault.Light.ActionBar.Solid": 16974247, "Widget.DeviceDefault.Light.ActionBar.Solid.Inverse": 16974248, "Widget.DeviceDefault.Light.ActionBar.TabBar.Inverse": 16974249, "Widget.DeviceDefault.Light.ActionBar.TabView.Inverse": 16974250, "Widget.DeviceDefault.Light.ActionBar.TabText.Inverse": 16974251, "Widget.DeviceDefault.Light.ActionMode.Inverse": 16974252, "TextAppearance.DeviceDefault": 16974253, "TextAppearance.DeviceDefault.Inverse": 16974254, "TextAppearance.DeviceDefault.Large": 16974255, "TextAppearance.DeviceDefault.Large.Inverse": 16974256, "TextAppearance.DeviceDefault.Medium": 16974257, "TextAppearance.DeviceDefault.Medium.Inverse": 16974258, "TextAppearance.DeviceDefault.Small": 16974259, "TextAppearance.DeviceDefault.Small.Inverse": 16974260, "TextAppearance.DeviceDefault.SearchResult.Title": 16974261, "TextAppearance.DeviceDefault.SearchResult.Subtitle": 16974262, "TextAppearance.DeviceDefault.WindowTitle": 16974263, "TextAppearance.DeviceDefault.DialogWindowTitle": 16974264, "TextAppearance.DeviceDefault.Widget": 16974265, "TextAppearance.DeviceDefault.Widget.Button": 16974266, "TextAppearance.DeviceDefault.Widget.IconMenu.Item": 16974267, "TextAppearance.DeviceDefault.Widget.TabWidget": 16974268, "TextAppearance.DeviceDefault.Widget.TextView": 16974269, "TextAppearance.DeviceDefault.Widget.TextView.PopupMenu": 16974270, "TextAppearance.DeviceDefault.Widget.DropDownHint": 16974271, "TextAppearance.DeviceDefault.Widget.DropDownItem": 16974272, "TextAppearance.DeviceDefault.Widget.TextView.SpinnerItem": 16974273, "TextAppearance.DeviceDefault.Widget.EditText": 16974274, "TextAppearance.DeviceDefault.Widget.PopupMenu": 16974275, "TextAppearance.DeviceDefault.Widget.PopupMenu.Large": 16974276, "TextAppearance.DeviceDefault.Widget.PopupMenu.Small": 16974277, "TextAppearance.DeviceDefault.Widget.ActionBar.Title": 16974278, "TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle": 16974279, "TextAppearance.DeviceDefault.Widget.ActionMode.Title": 16974280, "TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle": 16974281, "TextAppearance.DeviceDefault.Widget.ActionBar.Title.Inverse": 16974282, "TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle.Inverse": 16974283, "TextAppearance.DeviceDefault.Widget.ActionMode.Title.Inverse": 16974284, "TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle.Inverse": 16974285, "TextAppearance.DeviceDefault.Widget.ActionBar.Menu": 16974286, "DeviceDefault.ButtonBar": 16974287, "DeviceDefault.ButtonBar.AlertDialog": 16974288, "DeviceDefault.SegmentedButton": 16974289, "DeviceDefault.Light.ButtonBar": 16974290, "DeviceDefault.Light.ButtonBar.AlertDialog": 16974291, "DeviceDefault.Light.SegmentedButton": 16974292, "Widget.Holo.MediaRouteButton": 16974293, "Widget.Holo.Light.MediaRouteButton": 16974294, "Widget.DeviceDefault.MediaRouteButton": 16974295, "Widget.DeviceDefault.Light.MediaRouteButton": 16974296, "Widget.Holo.CheckedTextView": 16974297, "Widget.Holo.Light.CheckedTextView": 16974298, "Widget.DeviceDefault.CheckedTextView": 16974299, "Widget.DeviceDefault.Light.CheckedTextView": 16974300, "Theme.Holo.NoActionBar.Overscan": 16974301, "Theme.Holo.Light.NoActionBar.Overscan": 16974302, "Theme.DeviceDefault.NoActionBar.Overscan": 16974303, "Theme.DeviceDefault.Light.NoActionBar.Overscan": 16974304, "Theme.Holo.NoActionBar.TranslucentDecor": 16974305, "Theme.Holo.Light.NoActionBar.TranslucentDecor": 16974306, "Theme.DeviceDefault.NoActionBar.TranslucentDecor": 16974307, "Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor": 16974308, "Widget.FastScroll": 16974309, "Widget.StackView": 16974310, "Widget.Toolbar": 16974311, "Widget.Toolbar.Button.Navigation": 16974312, "Widget.DeviceDefault.FastScroll": 16974313, "Widget.DeviceDefault.StackView": 16974314, "Widget.DeviceDefault.Light.FastScroll": 16974315, "Widget.DeviceDefault.Light.StackView": 16974316, "TextAppearance.Material": 16974317, "TextAppearance.Material.Button": 16974318, "TextAppearance.Material.Body2": 16974319, "TextAppearance.Material.Body1": 16974320, "TextAppearance.Material.Caption": 16974321, "TextAppearance.Material.DialogWindowTitle": 16974322, "TextAppearance.Material.Display4": 16974323, "TextAppearance.Material.Display3": 16974324, "TextAppearance.Material.Display2": 16974325, "TextAppearance.Material.Display1": 16974326, "TextAppearance.Material.Headline": 16974327, "TextAppearance.Material.Inverse": 16974328, "TextAppearance.Material.Large": 16974329, "TextAppearance.Material.Large.Inverse": 16974330, "TextAppearance.Material.Medium": 16974331, "TextAppearance.Material.Medium.Inverse": 16974332, "TextAppearance.Material.Menu": 16974333, "TextAppearance.Material.Notification": 16974334, "TextAppearance.Material.Notification.Emphasis": 16974335, "TextAppearance.Material.Notification.Info": 16974336, "TextAppearance.Material.Notification.Line2": 16974337, "TextAppearance.Material.Notification.Time": 16974338, "TextAppearance.Material.Notification.Title": 16974339, "TextAppearance.Material.SearchResult.Subtitle": 16974340, "TextAppearance.Material.SearchResult.Title": 16974341, "TextAppearance.Material.Small": 16974342, "TextAppearance.Material.Small.Inverse": 16974343, "TextAppearance.Material.Subhead": 16974344, "TextAppearance.Material.Title": 16974345, "TextAppearance.Material.WindowTitle": 16974346, "TextAppearance.Material.Widget": 16974347, "TextAppearance.Material.Widget.ActionBar.Menu": 16974348, "TextAppearance.Material.Widget.ActionBar.Subtitle": 16974349, "TextAppearance.Material.Widget.ActionBar.Subtitle.Inverse": 16974350, "TextAppearance.Material.Widget.ActionBar.Title": 16974351, "TextAppearance.Material.Widget.ActionBar.Title.Inverse": 16974352, "TextAppearance.Material.Widget.ActionMode.Subtitle": 16974353, "TextAppearance.Material.Widget.ActionMode.Subtitle.Inverse": 16974354, "TextAppearance.Material.Widget.ActionMode.Title": 16974355, "TextAppearance.Material.Widget.ActionMode.Title.Inverse": 16974356, "TextAppearance.Material.Widget.Button": 16974357, "TextAppearance.Material.Widget.DropDownHint": 16974358, "TextAppearance.Material.Widget.DropDownItem": 16974359, "TextAppearance.Material.Widget.EditText": 16974360, "TextAppearance.Material.Widget.IconMenu.Item": 16974361, "TextAppearance.Material.Widget.PopupMenu": 16974362, "TextAppearance.Material.Widget.PopupMenu.Large": 16974363, "TextAppearance.Material.Widget.PopupMenu.Small": 16974364, "TextAppearance.Material.Widget.TabWidget": 16974365, "TextAppearance.Material.Widget.TextView": 16974366, "TextAppearance.Material.Widget.TextView.PopupMenu": 16974367, "TextAppearance.Material.Widget.TextView.SpinnerItem": 16974368, "TextAppearance.Material.Widget.Toolbar.Subtitle": 16974369, "TextAppearance.Material.Widget.Toolbar.Title": 16974370, "Theme.DeviceDefault.Settings": 16974371, "Theme.Material": 16974372, "Theme.Material.Dialog": 16974373, "Theme.Material.Dialog.Alert": 16974374, "Theme.Material.Dialog.MinWidth": 16974375, "Theme.Material.Dialog.NoActionBar": 16974376, "Theme.Material.Dialog.NoActionBar.MinWidth": 16974377, "Theme.Material.Dialog.Presentation": 16974378, "Theme.Material.DialogWhenLarge": 16974379, "Theme.Material.DialogWhenLarge.NoActionBar": 16974380, "Theme.Material.InputMethod": 16974381, "Theme.Material.NoActionBar": 16974382, "Theme.Material.NoActionBar.Fullscreen": 16974383, "Theme.Material.NoActionBar.Overscan": 16974384, "Theme.Material.NoActionBar.TranslucentDecor": 16974385, "Theme.Material.Panel": 16974386, "Theme.Material.Settings": 16974387, "Theme.Material.Voice": 16974388, "Theme.Material.Wallpaper": 16974389, "Theme.Material.Wallpaper.NoTitleBar": 16974390, "Theme.Material.Light": 16974391, "Theme.Material.Light.DarkActionBar": 16974392, "Theme.Material.Light.Dialog": 16974393, "Theme.Material.Light.Dialog.Alert": 16974394, "Theme.Material.Light.Dialog.MinWidth": 16974395, "Theme.Material.Light.Dialog.NoActionBar": 16974396, "Theme.Material.Light.Dialog.NoActionBar.MinWidth": 16974397, "Theme.Material.Light.Dialog.Presentation": 16974398, "Theme.Material.Light.DialogWhenLarge": 16974399, "Theme.Material.Light.DialogWhenLarge.NoActionBar": 16974400, "Theme.Material.Light.NoActionBar": 16974401, "Theme.Material.Light.NoActionBar.Fullscreen": 16974402, "Theme.Material.Light.NoActionBar.Overscan": 16974403, "Theme.Material.Light.NoActionBar.TranslucentDecor": 16974404, "Theme.Material.Light.Panel": 16974405, "Theme.Material.Light.Voice": 16974406, "ThemeOverlay": 16974407, "ThemeOverlay.Material": 16974408, "ThemeOverlay.Material.ActionBar": 16974409, "ThemeOverlay.Material.Light": 16974410, "ThemeOverlay.Material.Dark": 16974411, "ThemeOverlay.Material.Dark.ActionBar": 16974412, "Widget.Material": 16974413, "Widget.Material.ActionBar": 16974414, "Widget.Material.ActionBar.Solid": 16974415, "Widget.Material.ActionBar.TabBar": 16974416, "Widget.Material.ActionBar.TabText": 16974417, "Widget.Material.ActionBar.TabView": 16974418, "Widget.Material.ActionButton": 16974419, "Widget.Material.ActionButton.CloseMode": 16974420, "Widget.Material.ActionButton.Overflow": 16974421, "Widget.Material.ActionMode": 16974422, "Widget.Material.AutoCompleteTextView": 16974423, "Widget.Material.Button": 16974424, "Widget.Material.Button.Borderless": 16974425, "Widget.Material.Button.Borderless.Colored": 16974426, "Widget.Material.Button.Borderless.Small": 16974427, "Widget.Material.Button.Inset": 16974428, "Widget.Material.Button.Small": 16974429, "Widget.Material.Button.Toggle": 16974430, "Widget.Material.ButtonBar": 16974431, "Widget.Material.ButtonBar.AlertDialog": 16974432, "Widget.Material.CalendarView": 16974433, "Widget.Material.CheckedTextView": 16974434, "Widget.Material.CompoundButton.CheckBox": 16974435, "Widget.Material.CompoundButton.RadioButton": 16974436, "Widget.Material.CompoundButton.Star": 16974437, "Widget.Material.DatePicker": 16974438, "Widget.Material.DropDownItem": 16974439, "Widget.Material.DropDownItem.Spinner": 16974440, "Widget.Material.EditText": 16974441, "Widget.Material.ExpandableListView": 16974442, "Widget.Material.FastScroll": 16974443, "Widget.Material.GridView": 16974444, "Widget.Material.HorizontalScrollView": 16974445, "Widget.Material.ImageButton": 16974446, "Widget.Material.ListPopupWindow": 16974447, "Widget.Material.ListView": 16974448, "Widget.Material.ListView.DropDown": 16974449, "Widget.Material.MediaRouteButton": 16974450, "Widget.Material.PopupMenu": 16974451, "Widget.Material.PopupMenu.Overflow": 16974452, "Widget.Material.PopupWindow": 16974453, "Widget.Material.ProgressBar": 16974454, "Widget.Material.ProgressBar.Horizontal": 16974455, "Widget.Material.ProgressBar.Large": 16974456, "Widget.Material.ProgressBar.Small": 16974457, "Widget.Material.ProgressBar.Small.Title": 16974458, "Widget.Material.RatingBar": 16974459, "Widget.Material.RatingBar.Indicator": 16974460, "Widget.Material.RatingBar.Small": 16974461, "Widget.Material.ScrollView": 16974462, "Widget.Material.SearchView": 16974463, "Widget.Material.SeekBar": 16974464, "Widget.Material.SegmentedButton": 16974465, "Widget.Material.StackView": 16974466, "Widget.Material.Spinner": 16974467, "Widget.Material.Spinner.Underlined": 16974468, "Widget.Material.Tab": 16974469, "Widget.Material.TabWidget": 16974470, "Widget.Material.TextView": 16974471, "Widget.Material.TextView.SpinnerItem": 16974472, "Widget.Material.TimePicker": 16974473, "Widget.Material.Toolbar": 16974474, "Widget.Material.Toolbar.Button.Navigation": 16974475, "Widget.Material.WebTextView": 16974476, "Widget.Material.WebView": 16974477, "Widget.Material.Light": 16974478, "Widget.Material.Light.ActionBar": 16974479, "Widget.Material.Light.ActionBar.Solid": 16974480, "Widget.Material.Light.ActionBar.TabBar": 16974481, "Widget.Material.Light.ActionBar.TabText": 16974482, "Widget.Material.Light.ActionBar.TabView": 16974483, "Widget.Material.Light.ActionButton": 16974484, "Widget.Material.Light.ActionButton.CloseMode": 16974485, "Widget.Material.Light.ActionButton.Overflow": 16974486, "Widget.Material.Light.ActionMode": 16974487, "Widget.Material.Light.AutoCompleteTextView": 16974488, "Widget.Material.Light.Button": 16974489, "Widget.Material.Light.Button.Borderless": 16974490, "Widget.Material.Light.Button.Borderless.Colored": 16974491, "Widget.Material.Light.Button.Borderless.Small": 16974492, "Widget.Material.Light.Button.Inset": 16974493, "Widget.Material.Light.Button.Small": 16974494, "Widget.Material.Light.Button.Toggle": 16974495, "Widget.Material.Light.ButtonBar": 16974496, "Widget.Material.Light.ButtonBar.AlertDialog": 16974497, "Widget.Material.Light.CalendarView": 16974498, "Widget.Material.Light.CheckedTextView": 16974499, "Widget.Material.Light.CompoundButton.CheckBox": 16974500, "Widget.Material.Light.CompoundButton.RadioButton": 16974501, "Widget.Material.Light.CompoundButton.Star": 16974502, "Widget.Material.Light.DatePicker": 16974503, "Widget.Material.Light.DropDownItem": 16974504, "Widget.Material.Light.DropDownItem.Spinner": 16974505, "Widget.Material.Light.EditText": 16974506, "Widget.Material.Light.ExpandableListView": 16974507, "Widget.Material.Light.FastScroll": 16974508, "Widget.Material.Light.GridView": 16974509, "Widget.Material.Light.HorizontalScrollView": 16974510, "Widget.Material.Light.ImageButton": 16974511, "Widget.Material.Light.ListPopupWindow": 16974512, "Widget.Material.Light.ListView": 16974513, "Widget.Material.Light.ListView.DropDown": 16974514, "Widget.Material.Light.MediaRouteButton": 16974515, "Widget.Material.Light.PopupMenu": 16974516, "Widget.Material.Light.PopupMenu.Overflow": 16974517, "Widget.Material.Light.PopupWindow": 16974518, "Widget.Material.Light.ProgressBar": 16974519, "Widget.Material.Light.ProgressBar.Horizontal": 16974520, "Widget.Material.Light.ProgressBar.Inverse": 16974521, "Widget.Material.Light.ProgressBar.Large": 16974522, "Widget.Material.Light.ProgressBar.Large.Inverse": 16974523, "Widget.Material.Light.ProgressBar.Small": 16974524, "Widget.Material.Light.ProgressBar.Small.Inverse": 16974525, "Widget.Material.Light.ProgressBar.Small.Title": 16974526, "Widget.Material.Light.RatingBar": 16974527, "Widget.Material.Light.RatingBar.Indicator": 16974528, "Widget.Material.Light.RatingBar.Small": 16974529, "Widget.Material.Light.ScrollView": 16974530, "Widget.Material.Light.SearchView": 16974531, "Widget.Material.Light.SeekBar": 16974532, "Widget.Material.Light.SegmentedButton": 16974533, "Widget.Material.Light.StackView": 16974534, "Widget.Material.Light.Spinner": 16974535, "Widget.Material.Light.Spinner.Underlined": 16974536, "Widget.Material.Light.Tab": 16974537, "Widget.Material.Light.TabWidget": 16974538, "Widget.Material.Light.TextView": 16974539, "Widget.Material.Light.TextView.SpinnerItem": 16974540, "Widget.Material.Light.TimePicker": 16974541, "Widget.Material.Light.WebTextView": 16974542, "Widget.Material.Light.WebView": 16974543, "Theme.Leanback.FormWizard": 16974544, "Theme.DeviceDefault.Dialog.Alert": 16974545, "Theme.DeviceDefault.Light.Dialog.Alert": 16974546, "Widget.Material.Button.Colored": 16974547, "TextAppearance.Material.Widget.Button.Inverse": 16974548, "Theme.Material.Light.LightStatusBar": 16974549, "ThemeOverlay.Material.Dialog": 16974550, "ThemeOverlay.Material.Dialog.Alert": 16974551, "Theme.Material.Light.DialogWhenLarge.DarkActionBar": 16974552, "Widget.Material.SeekBar.Discrete": 16974553, "Widget.Material.CompoundButton.Switch": 16974554, "Widget.Material.Light.CompoundButton.Switch": 16974555, "Widget.Material.NumberPicker": 16974556, "Widget.Material.Light.NumberPicker": 16974557, "TextAppearance.Material.Widget.Button.Colored": 16974558, "TextAppearance.Material.Widget.Button.Borderless.Colored": 16974559 }, "string": { "cancel": 17039360, "copy": 17039361, "copyUrl": 17039362, "cut": 17039363, "defaultVoiceMailAlphaTag": 17039364, "defaultMsisdnAlphaTag": 17039365, "emptyPhoneNumber": 17039366, "httpErrorBadUrl": 17039367, "httpErrorUnsupportedScheme": 17039368, "no": 17039369, "ok": 17039370, "paste": 17039371, "search_go": 17039372, "selectAll": 17039373, "unknownName": 17039374, "untitled": 17039375, "VideoView_error_button": 17039376, "VideoView_error_text_unknown": 17039377, "VideoView_error_title": 17039378, "yes": 17039379, "dialog_alert_title": 17039380, "VideoView_error_text_invalid_progressive_playback": 17039381, "selectTextMode": 17039382, "status_bar_notification_info_overflow": 17039383, "fingerprint_icon_content_description": 17039384, "paste_as_plain_text": 17039385, "autofill": 17039386 }, "dimen": { "app_icon_size": 17104896, "thumbnail_height": 17104897, "thumbnail_width": 17104898, "dialog_min_width_major": 17104899, "dialog_min_width_minor": 17104900, "notification_large_icon_width": 17104901, "notification_large_icon_height": 17104902 }, "color": { "darker_gray": 17170432, "primary_text_dark": 17170433, "primary_text_dark_nodisable": 17170434, "primary_text_light": 17170435, "primary_text_light_nodisable": 17170436, "secondary_text_dark": 17170437, "secondary_text_dark_nodisable": 17170438, "secondary_text_light": 17170439, "secondary_text_light_nodisable": 17170440, "tab_indicator_text": 17170441, "widget_edittext_dark": 17170442, "white": 17170443, "black": 17170444, "transparent": 17170445, "background_dark": 17170446, "background_light": 17170447, "tertiary_text_dark": 17170448, "tertiary_text_light": 17170449, "holo_blue_light": 17170450, "holo_blue_dark": 17170451, "holo_green_light": 17170452, "holo_green_dark": 17170453, "holo_red_light": 17170454, "holo_red_dark": 17170455, "holo_orange_light": 17170456, "holo_orange_dark": 17170457, "holo_purple": 17170458, "holo_blue_bright": 17170459 }, "array": { "emailAddressTypes": 17235968, "imProtocols": 17235969, "organizationTypes": 17235970, "phoneTypes": 17235971, "postalAddressTypes": 17235972, "config_keySystemUuidMapping": 17235973 }, "drawable": { "alert_dark_frame": 17301504, "alert_light_frame": 17301505, "arrow_down_float": 17301506, "arrow_up_float": 17301507, "btn_default": 17301508, "btn_default_small": 17301509, "btn_dropdown": 17301510, "btn_minus": 17301511, "btn_plus": 17301512, "btn_radio": 17301513, "btn_star": 17301514, "btn_star_big_off": 17301515, "btn_star_big_on": 17301516, "button_onoff_indicator_on": 17301517, "button_onoff_indicator_off": 17301518, "checkbox_off_background": 17301519, "checkbox_on_background": 17301520, "dialog_frame": 17301521, "divider_horizontal_bright": 17301522, "divider_horizontal_textfield": 17301523, "divider_horizontal_dark": 17301524, "divider_horizontal_dim_dark": 17301525, "edit_text": 17301526, "btn_dialog": 17301527, "editbox_background": 17301528, "editbox_background_normal": 17301529, "editbox_dropdown_dark_frame": 17301530, "editbox_dropdown_light_frame": 17301531, "gallery_thumb": 17301532, "ic_delete": 17301533, "ic_lock_idle_charging": 17301534, "ic_lock_idle_lock": 17301535, "ic_lock_idle_low_battery": 17301536, "ic_media_ff": 17301537, "ic_media_next": 17301538, "ic_media_pause": 17301539, "ic_media_play": 17301540, "ic_media_previous": 17301541, "ic_media_rew": 17301542, "ic_dialog_alert": 17301543, "ic_dialog_dialer": 17301544, "ic_dialog_email": 17301545, "ic_dialog_map": 17301546, "ic_input_add": 17301547, "ic_input_delete": 17301548, "ic_input_get": 17301549, "ic_lock_idle_alarm": 17301550, "ic_lock_lock": 17301551, "ic_lock_power_off": 17301552, "ic_lock_silent_mode": 17301553, "ic_lock_silent_mode_off": 17301554, "ic_menu_add": 17301555, "ic_menu_agenda": 17301556, "ic_menu_always_landscape_portrait": 17301557, "ic_menu_call": 17301558, "ic_menu_camera": 17301559, "ic_menu_close_clear_cancel": 17301560, "ic_menu_compass": 17301561, "ic_menu_crop": 17301562, "ic_menu_day": 17301563, "ic_menu_delete": 17301564, "ic_menu_directions": 17301565, "ic_menu_edit": 17301566, "ic_menu_gallery": 17301567, "ic_menu_help": 17301568, "ic_menu_info_details": 17301569, "ic_menu_manage": 17301570, "ic_menu_mapmode": 17301571, "ic_menu_month": 17301572, "ic_menu_more": 17301573, "ic_menu_my_calendar": 17301574, "ic_menu_mylocation": 17301575, "ic_menu_myplaces": 17301576, "ic_menu_preferences": 17301577, "ic_menu_recent_history": 17301578, "ic_menu_report_image": 17301579, "ic_menu_revert": 17301580, "ic_menu_rotate": 17301581, "ic_menu_save": 17301582, "ic_menu_search": 17301583, "ic_menu_send": 17301584, "ic_menu_set_as": 17301585, "ic_menu_share": 17301586, "ic_menu_slideshow": 17301587, "ic_menu_today": 17301588, "ic_menu_upload": 17301589, "ic_menu_upload_you_tube": 17301590, "ic_menu_view": 17301591, "ic_menu_week": 17301592, "ic_menu_zoom": 17301593, "ic_notification_clear_all": 17301594, "ic_notification_overlay": 17301595, "ic_partial_secure": 17301596, "ic_popup_disk_full": 17301597, "ic_popup_reminder": 17301598, "ic_popup_sync": 17301599, "ic_search_category_default": 17301600, "ic_secure": 17301601, "list_selector_background": 17301602, "menu_frame": 17301603, "menu_full_frame": 17301604, "menuitem_background": 17301605, "picture_frame": 17301606, "presence_away": 17301607, "presence_busy": 17301608, "presence_invisible": 17301609, "presence_offline": 17301610, "presence_online": 17301611, "progress_horizontal": 17301612, "progress_indeterminate_horizontal": 17301613, "radiobutton_off_background": 17301614, "radiobutton_on_background": 17301615, "spinner_background": 17301616, "spinner_dropdown_background": 17301617, "star_big_on": 17301618, "star_big_off": 17301619, "star_on": 17301620, "star_off": 17301621, "stat_notify_call_mute": 17301622, "stat_notify_chat": 17301623, "stat_notify_error": 17301624, "stat_notify_more": 17301625, "stat_notify_sdcard": 17301626, "stat_notify_sdcard_usb": 17301627, "stat_notify_sync": 17301628, "stat_notify_sync_noanim": 17301629, "stat_notify_voicemail": 17301630, "stat_notify_missed_call": 17301631, "stat_sys_data_bluetooth": 17301632, "stat_sys_download": 17301633, "stat_sys_download_done": 17301634, "stat_sys_headset": 17301635, "stat_sys_phone_call": 17301636, "stat_sys_phone_call_forward": 17301637, "stat_sys_phone_call_on_hold": 17301638, "stat_sys_speakerphone": 17301639, "stat_sys_upload": 17301640, "stat_sys_upload_done": 17301641, "stat_sys_warning": 17301642, "status_bar_item_app_background": 17301643, "status_bar_item_background": 17301644, "sym_action_call": 17301645, "sym_action_chat": 17301646, "sym_action_email": 17301647, "sym_call_incoming": 17301648, "sym_call_missed": 17301649, "sym_call_outgoing": 17301650, "sym_def_app_icon": 17301651, "sym_contact_card": 17301652, "title_bar": 17301653, "toast_frame": 17301654, "zoom_plate": 17301655, "screen_background_dark": 17301656, "screen_background_light": 17301657, "bottom_bar": 17301658, "ic_dialog_info": 17301659, "ic_menu_sort_alphabetically": 17301660, "ic_menu_sort_by_size": 17301661, "ic_btn_speak_now": 17301668, "dark_header": 17301669, "title_bar_tall": 17301670, "stat_sys_vp_phone_call": 17301671, "stat_sys_vp_phone_call_on_hold": 17301672, "screen_background_dark_transparent": 17301673, "screen_background_light_transparent": 17301674, "stat_notify_sdcard_prepare": 17301675, "presence_video_away": 17301676, "presence_video_busy": 17301677, "presence_video_online": 17301678, "presence_audio_away": 17301679, "presence_audio_busy": 17301680, "presence_audio_online": 17301681, "dialog_holo_dark_frame": 17301682, "dialog_holo_light_frame": 17301683 }, "layout": { "activity_list_item": 17367040, "expandable_list_content": 17367041, "preference_category": 17367042, "simple_list_item_1": 17367043, "simple_list_item_2": 17367044, "simple_list_item_checked": 17367045, "simple_expandable_list_item_1": 17367046, "simple_expandable_list_item_2": 17367047, "simple_spinner_item": 17367048, "simple_spinner_dropdown_item": 17367049, "simple_dropdown_item_1line": 17367050, "simple_gallery_item": 17367051, "test_list_item": 17367052, "two_line_list_item": 17367053, "browser_link_context_header": 17367054, "simple_list_item_single_choice": 17367055, "simple_list_item_multiple_choice": 17367056, "select_dialog_item": 17367057, "select_dialog_singlechoice": 17367058, "select_dialog_multichoice": 17367059, "list_content": 17367060, "simple_selectable_list_item": 17367061, "simple_list_item_activated_1": 17367062, "simple_list_item_activated_2": 17367063 }, "anim": { "fade_in": 17432576, "fade_out": 17432577, "slide_in_left": 17432578, "slide_out_right": 17432579, "accelerate_decelerate_interpolator": 17432580, "accelerate_interpolator": 17432581, "decelerate_interpolator": 17432582, "anticipate_interpolator": 17432583, "overshoot_interpolator": 17432584, "anticipate_overshoot_interpolator": 17432585, "bounce_interpolator": 17432586, "linear_interpolator": 17432587, "cycle_interpolator": 17432588 }, "integer": { "config_shortAnimTime": 17694720, "config_mediumAnimTime": 17694721, "config_longAnimTime": 17694722, "status_bar_notification_info_maxnum": 17694723 }, "animator": { "fade_in": 17498112, "fade_out": 17498113 }, "interpolator": { "accelerate_quad": 17563648, "decelerate_quad": 17563649, "accelerate_cubic": 17563650, "decelerate_cubic": 17563651, "accelerate_quint": 17563652, "decelerate_quint": 17563653, "accelerate_decelerate": 17563654, "anticipate": 17563655, "overshoot": 17563656, "anticipate_overshoot": 17563657, "bounce": 17563658, "linear": 17563659, "cycle": 17563660, "fast_out_slow_in": 17563661, "linear_out_slow_in": 17563662, "fast_out_linear_in": 17563663 }, "mipmap": { "sym_def_app_icon": 17629184 }, "transition": { "no_transition": 17760256, "move": 17760257, "fade": 17760258, "explode": 17760259, "slide_bottom": 17760260, "slide_top": 17760261, "slide_right": 17760262, "slide_left": 17760263 }, "raw": { "loaderror": 17825792, "nodomain": 17825793 } } pyaxmlparser-0.3.24/pyaxmlparser/resources/public.py000066400000000000000000000044451356264674700227530ustar00rootroot00000000000000import os from xml.dom import minidom _public_res = None # copy the newest sdk/platforms/android-?/data/res/values/public.xml here if _public_res is None: _public_res = {} root = os.path.dirname(os.path.realpath(__file__)) xmlfile = os.path.join(root, "public.xml") if os.path.isfile(xmlfile): with open(xmlfile, "r") as fp: _xml = minidom.parseString(fp.read()) for element in _xml.getElementsByTagName("public"): _type = element.getAttribute('type') _name = element.getAttribute('name') _id = int(element.getAttribute('id'), 16) if _type not in _public_res: _public_res[_type] = {} _public_res[_type][_name] = _id else: raise Exception("need to copy the sdk/platforms/android-?/data/res/values/public.xml here") SYSTEM_RESOURCES = { "attributes": { "forward": {k: v for k, v in _public_res['attr'].items()}, "inverse": {v: k for k, v in _public_res['attr'].items()} }, "styles": { "forward": {k: v for k, v in _public_res['style'].items()}, "inverse": {v: k for k, v in _public_res['style'].items()} }, "drawables": { "forward": {k: v for k, v in _public_res['drawable'].items()}, "inverse": {v: k for k, v in _public_res['drawable'].items()} }, "mipmaps": { "forward": {k: v for k, v in _public_res['mipmap'].items()}, "inverse": {v: k for k, v in _public_res['mipmap'].items()} } } if __name__ == '__main__': import json _resources = None if _resources is None: root = os.path.dirname(os.path.realpath(__file__)) resfile = os.path.join(root, "public.json") if os.path.isfile(resfile): with open(resfile, "r") as fp: _resources = json.load(fp) else: # TODO raise error instead? _resources = {} for _type in set([] + list(_public_res.keys()) + list(_resources.keys())): for k in set([] + list(_public_res.get(_type, {}).keys()) + list(_resources.get(_type, {}).keys())): a, b = _public_res.get(_type, {}).get(k), \ _resources.get(_type, {}).get(k), if a != b: print(k, a, b) print(None) pyaxmlparser-0.3.24/pyaxmlparser/resources/public.xml000066400000000000000000005652341356264674700231330ustar00rootroot00000000000000 pyaxmlparser-0.3.24/pyaxmlparser/stringblock.py000066400000000000000000000221411356264674700217750ustar00rootroot00000000000000# This file is part of Androguard. # # Copyright (C) 2012, Anthony Desnos # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS-IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import logging from struct import unpack import pyaxmlparser.constants as const log = logging.getLogger("pyaxmlparser.stringblock") class StringBlock(object): """ StringBlock is a CHUNK inside an AXML File It contains all strings, which are used by referecing to ID's See http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h#436 """ def __init__(self, buff, header): """ :param buff: buffer which holds the string block :param header: a instance of :class:`~ARSCHeader` """ self._cache = {} self.header = header # We already read the header (which was chunk_type and chunk_size # Now, we read the string_count: self.stringCount = unpack(' 0: log.info("Styles Offset given, but styleCount is zero. " "This is not a problem but could indicate packers.") self.m_stringOffsets = [] self.m_styleOffsets = [] self.m_charbuff = "" self.m_styles = [] # Next, there is a list of string following. # This is only a list of offsets (4 byte each) for i in range(self.stringCount): self.m_stringOffsets.append(unpack(' self.stringCount: return "" offset = self.m_stringOffsets[idx] if self.m_isUTF8: self._cache[idx] = self._decode8(offset) else: self._cache[idx] = self._decode16(offset) return self._cache[idx] def getStyle(self, idx): """ Return the style associated with the index :param idx: index of the style :return: """ return self.m_styles[idx] def _decode8(self, offset): """ Decode an UTF-8 String at the given offset :param offset: offset of the string inside the data :return: str """ # UTF-8 Strings contain two lengths, as they might differ: # 1) the UTF-16 length str_len, skip = self._decode_length(offset, 1) offset += skip # 2) the utf-8 string length encoded_bytes, skip = self._decode_length(offset, 1) offset += skip data = self.m_charbuff[offset: offset + encoded_bytes] assert self.m_charbuff[offset + encoded_bytes] == 0, \ "UTF-8 String is not null terminated! At offset={}".format(offset) return self._decode_bytes(data, 'utf-8', str_len) def _decode16(self, offset): """ Decode an UTF-16 String at the given offset :param offset: offset of the string inside the data :return: str """ str_len, skip = self._decode_length(offset, 2) offset += skip # The len is the string len in utf-16 units encoded_bytes = str_len * 2 data = self.m_charbuff[offset: offset + encoded_bytes] assert self.m_charbuff[offset + encoded_bytes:offset + encoded_bytes + 2] == b"\x00\x00", \ "UTF-16 String is not null terminated! At offset={}".format(offset) return self._decode_bytes(data, 'utf-16', str_len) @staticmethod def _decode_bytes(data, encoding, str_len): """ Generic decoding with length check. The string is decoded from bytes with the given encoding, then the length of the string is checked. The string is decoded using the "replace" method. :param data: bytes :param encoding: encoding name ("utf-8" or "utf-16") :param str_len: length of the decoded string :return: str """ string = data.decode(encoding, 'replace') if len(string) != str_len: log.warning("invalid decoded string length") return string def _decode_length(self, offset, sizeof_char): """ Generic Length Decoding at offset of string The method works for both 8 and 16 bit Strings. Length checks are enforced: * 8 bit strings: maximum of 0x7FFF bytes (See http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/ResourceTypes.cpp#692) * 16 bit strings: maximum of 0x7FFFFFF bytes (See http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/ResourceTypes.cpp#670) :param offset: offset into the string data section of the beginning of the string :param sizeof_char: number of bytes per char (1 = 8bit, 2 = 16bit) :returns: tuple of (length, read bytes) """ sizeof_2chars = sizeof_char << 1 fmt = "<2{}".format('B' if sizeof_char == 1 else 'H') highbit = 0x80 << (8 * (sizeof_char - 1)) length1, length2 = unpack(fmt, self.m_charbuff[offset:(offset + sizeof_2chars)]) if (length1 & highbit) != 0: length = ((length1 & ~highbit) << (8 * sizeof_char)) | length2 size = sizeof_2chars else: length = length1 size = sizeof_char if sizeof_char == 1: assert length <= 0x7FFF, "length of UTF-8 string is too large! At offset={}".format(offset) else: assert length <= 0x7FFFFFFF, "length of UTF-16 string is too large! At offset={}".format(offset) return length, size def show(self): """ Print some information on stdout about the string table """ print("StringBlock(stringsCount=0x%x, " "stringsOffset=0x%x, " "stylesCount=0x%x, " "stylesOffset=0x%x, " "flags=0x%x" ")" % (self.stringCount, self.stringsOffset, self.styleCount, self.stylesOffset, self.flags)) if self.stringCount > 0: print() print("String Table: ") for i, s in enumerate(self): print("{:08d} {}".format(i, repr(s))) if self.styleCount > 0: print() print("Styles Table: ") for i in range(self.styleCount): print("{:08d} {}".format(i, repr(self.getStyle(i)))) pyaxmlparser-0.3.24/pyaxmlparser/utils.py000066400000000000000000000053731356264674700206240ustar00rootroot00000000000000import io import os.path from xml.dom.pulldom import SAX2DOM from zipfile import ZipFile import pyaxmlparser.constants as const from struct import unpack, pack import lxml.sax NS_ANDROID_URI = 'http://schemas.android.com/apk/res/android' NS_ANDROID = '{http://schemas.android.com/apk/res/android}' RADIX_MULTS = [0.00390625, 3.051758E-005, 1.192093E-007, 4.656613E-010] def parse_lxml_dom(tree): handler = SAX2DOM() lxml.sax.saxify(tree, handler) return handler.document def _range(a, b, step=None): if step is None: return range(int(a), int(b)) return range(int(a), int(b), step) def get_zip_file(resource): if isinstance(resource, bytes): return ZipFile(io.BytesIO(resource)) if os.path.isfile(resource): return ZipFile(resource) raise TypeError('Resource should be file or bytes stream') def is_str(item, string=False): if string: return str(item) return item def complexToFloat(xcomplex): return float(xcomplex & 0xFFFFFF00) * RADIX_MULTS[(xcomplex >> 4) & 3] def long2int(input_l): if input_l > 0x7fffffff: input_l = (0x7fffffff & input_l) - 0x80000000 return input_l def getPackage(i): if i >> 24 == 1: return "android:" return "" def format_value(_type, _data, lookup_string=lambda ix: ""): if _type == const.TYPE_STRING: return lookup_string(_data) elif _type == const.TYPE_ATTRIBUTE: return "?%s%08X" % (getPackage(_data), _data) elif _type == const.TYPE_REFERENCE: return "@%s%08X" % (getPackage(_data), _data) elif _type == const.TYPE_FLOAT: return "%f" % unpack("=f", pack("=L", _data))[0] elif _type == const.TYPE_INT_HEX: return "0x%08X" % _data elif _type == const.TYPE_INT_BOOLEAN: if _data == 0: return "false" return "true" elif _type == const.TYPE_DIMENSION: return "%f%s" % ( complexToFloat(_data), const.DIMENSION_UNITS[_data & const.COMPLEX_UNIT_MASK] ) elif _type == const.TYPE_FRACTION: return "%f%s" % ( complexToFloat(_data) * 100, const.FRACTION_UNITS[_data & const.COMPLEX_UNIT_MASK] ) elif const.TYPE_FIRST_COLOR_INT <= _type <= const.TYPE_LAST_COLOR_INT: return "#%08X" % _data elif const.TYPE_FIRST_INT <= _type <= const.TYPE_LAST_INT: return "%d" % long2int(_data) return "<0x%X, type 0x%02X>" % (_data, _type) def read(filename, binary=True): """ Open and read a file :param filename: filename to open and read :param binary: True if the file should be read as binary :return: bytes if binary is True, str otherwise """ with open(filename, 'rb' if binary else 'r') as f: return f.read() pyaxmlparser-0.3.24/requirements.txt000066400000000000000000000001161356264674700176350ustar00rootroot00000000000000lxml==3.7.3 click>=6.7 # testing pytest==3.0.6 flake8==3.3.0 coverage==4.4.1 pyaxmlparser-0.3.24/scripts/000077500000000000000000000000001356264674700160425ustar00rootroot00000000000000pyaxmlparser-0.3.24/scripts/deploy.sh000077500000000000000000000005641356264674700177020ustar00rootroot00000000000000#! /bin/bash # # deploy.sh # Copyright (C) 2015 Subho Halder # # Distributed under terms of the MIT license. # rm -rf dist/ bumpversion patch export CURRENT_BRANCH CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) git push --tags git push origin "$CURRENT_BRANCH:$CURRENT_BRANCH" python setup.py sdist python setup.py bdist_wheel twine upload dist/* pyaxmlparser-0.3.24/setup.cfg000066400000000000000000000004741356264674700162010ustar00rootroot00000000000000[bumpversion] current_version = 0.3.24 commit = True tag = True [flake8] max-line-length = 120 exclude = .tox,.git,*/migrations/*,*/static/*,docs,venv [tool:pytest] norecursedirs = .tox .git */migrations/* */static/* docs venv [importmagic] multiline = 'backslash' max_columns = 119 [bumpversion:file:setup.py] pyaxmlparser-0.3.24/setup.py000066400000000000000000000027261356264674700160740ustar00rootroot00000000000000from setuptools import find_packages, setup __VERSION__ = '0.3.24' with open("README.rst", "r") as fh: long_description = fh.read() setup( name='pyaxmlparser', version=__VERSION__, url='https://github.com/appknox/pyaxmlparser', author='Subho Halder', author_email='sunny@appknox.com', license='Apache License 2.0', data_files=[('man/man1', ['apkinfo.1'])], packages=find_packages(exclude=['tests', 'examples']), include_package_data=True, zip_safe=False, platforms='any', install_requires=['lxml', 'click>=6.7'], entry_points=''' [console_scripts] apkinfo = pyaxmlparser.cli:main ''', py_modules=['pyaxmlparser'], description="Python3 Parser for Android XML file and get Application Name without using Androguard", long_description=long_description, long_description_content_type="text/markdown", keywords='appknox axmlparser arscparser android', classifiers=[ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX', 'Operating System :: MacOS', 'Operating System :: Unix', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.5', 'Topic :: Software Development :: Build Tools', 'Topic :: Software Development :: Libraries :: Python Modules', ] ) pyaxmlparser-0.3.24/tests/000077500000000000000000000000001356264674700155155ustar00rootroot00000000000000pyaxmlparser-0.3.24/tests/test_apk/000077500000000000000000000000001356264674700173275ustar00rootroot00000000000000pyaxmlparser-0.3.24/tests/test_apk/AndroidManifest.xml000066400000000000000000000720741356264674700231320ustar00rootroot00000000000000Ž цzш\ p № com.google.android.apps.nexuslauncher.permission.READ_SETTINGS*com.lge.launcher3.permission.READ_SETTINGS5com.actionlauncher.playstore.permission.READ_SETTINGS/android.permission.ACCESS_WEATHERCLOCK_PROVIDER-com.android.launcher.permission.READ_SETTINGS.com.android.launcher3.permission.READ_SETTINGS5com.android.browser.permission.READ_HISTORY_BOOKMARKS uses-featureandroid.hardware.telephonyandroid.permission.READ_SMS android.permission.READ_CALL_LOG6com.google.android.gm.permission.READ_CONTENT_PROVIDERandroid.permission.GET_ACCOUNTS$android.permission.ACCESS_WIFI_STATEandroid.permission.BLUETOOTH android.permission.READ_CONTACTS'android.permission.ACCESS_FINE_LOCATIONandroid.permission.CALL_PHONE'android.permission.ACCESS_NETWORK_STATE"android.permission.BLUETOOTH_ADMIN#android.permission.BROADCAST_STICKYandroid.permission.INTERNETandroid.permission.READ_PROFILE)android.permission.RECEIVE_BOOT_COMPLETEDandroid.permission.VIBRATEcompatible-screensscreen)android.permission.WRITE_EXTERNAL_STORAGE#android.permission.READ_PHONE_STATE(android.permission.READ_EXTERNAL_STORAGE application'com.voxel.launcher3.LauncherApplication-com.voxel.launcher3.LauncherBackupAgentHelperactivity:com.voxel.simplesearchlauncher.activity.OnboardingActivitycom.voxel.launcher3.Launcher meta-dataandroid.support.PARENT_ACTIVITY intent-filteractionandroid.intent.action.MAINandroid.intent.action.SEARCHcategoryandroid.intent.category.HOMEandroid.intent.category.DEFAULT android.intent.category.LAUNCHERandroid.intent.category.MONKEYandroid.intent.action.ASSIST'com.android.systemui.action_assist_iconandroid.app.searchable8com.voxel.simplesearchlauncher.settings.SettingsActivityCcom.voxel.simplesearchlauncher.settings.TransparentSettingsActivity4com.voxel.simplesearchlauncher.activity.CardActivitycom.voxel.ACTION_VIEW_ENTITY!android.intent.category.BROWSABLEdata com.voxelcontent=com.voxel.simplesearchlauncher.activity.ResetLauncherActivity'com.voxel.launcher3.ToggleWeightWatcher3com.voxel.launcher3.LauncherWallpaperPickerActivity:wallpaper_chooser#android.intent.action.SET_WALLPAPER)com.voxel.launcher3.WallpaperCropActivity0android.service.wallpaper.CROP_AND_SET_WALLPAPERimage/*&com.voxel.launcher3.MemoryDumpActivityservice!com.voxel.launcher3.MemoryTrackerHcom.voxel.simplesearchlauncher.notification.service.NotificationListener5android.permission.BIND_NOTIFICATION_LISTENER_SERVICE8android.service.notification.NotificationListenerServicereceiver>com.voxel.simplesearchlauncher.receiver.DeviceAdminReceiverSub$android.permission.BIND_DEVICE_ADMINandroid.app.device_admin'android.app.action.DEVICE_ADMIN_ENABLED,com.voxel.launcher3.WallpaperChangedReceiver'android.intent.action.WALLPAPER_CHANGED+com.voxel.launcher3.InstallShortcutReceiver,com.android.launcher.action.INSTALL_SHORTCUT-com.voxel.launcher3.UninstallShortcutReceiver.com.android.launcher.action.UNINSTALL_SHORTCUT.com.voxel.launcher3.AppWidgetsRestoredReceiver0android.appwidget.action.APPWIDGET_HOST_RESTORED<com.voxel.simplesearchlauncher.receiver.NotificationReceiver(android.intent.action.BADGE_COUNT_UPDATE4com.htc.android.mail.action.update_unread_mail_count(com.htc.launcher.action.SET_NOTIFICATIONlge.intent.action.UNREAD_EMAILS)com.sonyericsson.home.action.UPDATE_BADGE0android.intent.action.APPLICATION_MESSAGE_UPDATEprovider5com.voxel.simplesearchlauncher.model.AppsInfoProvideris.shortcut.provider.appsInfo$com.voxel.launcher3.LauncherProvidercom.voxel.launcher3.settingsandroid.app.default_searchablecom.google.android.geo.API_KEYAcom.voxel.simplesearchlauncher.activity.TimeoutLockScreenActivity-com.voxel.simplesearchlauncher.activity.Dummy>com.voxel.simplesearchlauncher.activity.IncludeRecentsActivity>com.voxel.simplesearchlauncher.activity.LocationEnableActivity#com.voxel.launcher3.StartupReceiver$android.intent.action.BOOT_COMPLETED<com.voxel.simplesearchlauncher.model.LocalAppsUpdateReceiver#android.intent.action.PACKAGE_ADDED%android.intent.action.PACKAGE_REMOVED&android.intent.action.PACKAGE_REPLACED%android.intent.action.PACKAGE_CHANGED5android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE7android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE android.nfc.disable_beam_defaultcom.crashlytics.ApiKey(8c14a9d997e4a7d6f51e06c376ff25690545d08dcom.facebook.sdk.ApplicationIdcom.google.android.gms.versionAcom.google.android.gms.auth.api.signin.internal.SignInHubActivity=com.google.android.gms.auth.api.signin.RevocationBoundServiceIcom.google.android.gms.auth.api.signin.permission.REVOCATION_NOTIFICATION3com.google.android.gms.common.api.GoogleApiActivitycom.facebook.FacebookActivitycom.facebook.CustomTabActivity"com.facebook.CustomTabMainActivity*com.voxel.recyclerview.widget.TestActivityRecyclerViewTestActivitycom.evie.jigsaw.JigsawActivitycom.evie.jigsaw€Д p   ށЫЪ€гZКЏЇ$+%('Ї&џџџџ+,ˆџџџџџџџџ1,џџџџYO7,33џџџџ.22џџџџ/4џџџџ055Lџџџџџџџџ6,џџџџ,џџџџ џџџџџџџџ6ˆ џџџџџџџџ&,џџџџ2 ,77,џџџџ,88,џџџџ% џџџџџџџџ&ˆџџџџџџџџ&,џџџџ4 ,99,џџџџ,88,џџџџ' џџџџџџџџ&ˆџџџџџџџџ&,џџџџ3 ,::,џџџџ,88,џџџџ& џџџџџџџџ&ˆџџџџџџџџ&,џџџџ5 ,;;,џџџџ,88,џџџџ( "џџџџџџџџ&L#џџџџџџџџ&,<<,џџџџ%џџџџџџџџ&L&џџџџџџџџ&,==,џџџџ(џџџџџџџџ&8+џџџџџџџџ>,??+џџџџџџџџ>8.џџџџџџџџ>,@@.џџџџџџџџ>81џџџџџџџџ>,AA1џџџџџџџџ>84џџџџџџџџ>,BB4џџџџџџџџ>87џџџџџџџџ>,CC7џџџџџџџџ>8:џџџџџџџџ>,DD:џџџџџџџџ>8=џџџџџџџџ>,EE=џџџџџџџџ>8>џџџџџџџџ>,FF>џџџџџџџџ>8?џџџџџџџџ>,GG?џџџџџџџџ>8@џџџџџџџџ>,HH@џџџџџџџџ>8Aџџџџџџџџ>,IIAџџџџџџџџ>8Bџџџџџџџџ>,JJBџџџџџџџџ>8Cџџџџџџџџ>,KKCџџџџџџџџ>8Dџџџџџџџџ>,LLDџџџџџџџџ>8Iџџџџџџџџ>,MMIџџџџџџџџ>8Lџџџџџџџџ>,NNLџџџџџџџџ>8Mџџџџџџџџ>,OOMџџџџџџџџ>8Rџџџџџџџџ>,PPRџџџџџџџџ>LVџџџџџџџџQ,RR, џџџџXџџџџџџџџQ8[џџџџџџџџ>,SS[џџџџџџџџ>8^џџџџџџџџ>,TT^џџџџџџџџ>8aџџџџџџџџ>,UUaџџџџџџџџ>8bџџџџџџџџ>,VVbџџџџџџџџ>8gџџџџџџџџ>,WWgџџџџџџџџ>8hџџџџџџџџ>,XXhџџџџџџџџ>8lџџџџџџџџ>,YYlџџџџџџџџ>8nџџџџџџџџ>,ZZnџџџџџџџџ>8pџџџџџџџџ>,[[pџџџџџџџџ>8qџџџџџџџџ>,\\qџџџџџџџџ>8rџџџџџџџџ>,]]rџџџџџџџџ>8sџџџџџџџџ>,^^sџџџџџџџџ>8tџџџџџџџџ>,__tџџџџџџџџ>8uџџџџџџџџ>,``uџџџџџџџџ>8vџџџџџџџџ>,aavџџџџџџџџ>8wџџџџџџџџ>,bbwџџџџџџџџ>8xџџџџџџџџ>,::xџџџџџџџџ>8yџџџџџџџџ>,;;yџџџџџџџџ>8zџџџџџџџџ>,<<zџџџџџџџџ>8{џџџџџџџџ>,=={џџџџџџџџ>L}џџџџџџџџQ, џџџџ, џџџџџџџџџџџџџџџџQ$џџџџџџџџcL‚џџџџџџџџd, џџџџШ, џџџџЄ„џџџџџџџџdL…џџџџџџџџd, џџџџ,, џџџџЄ‡џџџџџџџџdLˆџџџџџџџџd, џџџџ, џџџџЄŠџџџџџџџџdL‹џџџџџџџџd, џџџџє, џџџџЄџџџџџџџџdŽџџџџџџџџc8џџџџ,>,eeџџџџ,>8‘џџџџ,>,ff‘џџџџ,>8’џџџџ,>,gg’џџџџ,>и”џџџџџџџџh ,џџџџD ,џџџџ2,ii,jj, џџџџ,џџџџџџџџ,џџџџџџџџ,џџџџ,џџџџœžџџџџџџџџk,џџџџ ,ll,џџџџџџџџ,џџџџџџџџ,џџџџ,mmLЅџџџџџџџџn,oo,mmЇџџџџџџџџnЈџџџџџџџџkФЉџџџџџџџџk,џџџџ ,mm,џџџџџџџџ,џџџџџџџџ,џџџџ,џџџџ,џџџџ ,џџџџ0$Вџџџџџџџџp8Гџџџџџџџџq,rrГџџџџџџџџq8Дџџџџџџџџq,ssДџџџџџџџџq8Жџџџџџџџџt,uuЖџџџџџџџџt8Зџџџџџџџџt,vvЗџџџџџџџџt8Иџџџџџџџџt,wwИџџџџџџџџt8Йџџџџџџџџt,xxЙџџџџџџџџtКџџџџџџџџp$Лџџџџџџџџp8Мџџџџџџџџq,yyМџџџџџџџџq8Оџџџџџџџџt,vvОџџџџџџџџtПџџџџџџџџpLСџџџџџџџџn,zz,џџџџ2УџџџџџџџџnLФџџџџџџџџn,{{,џџџџЦџџџџџџџџnЧџџџџџџџџkАШџџџџџџџџk,џџџџ ,џџџџЌ ,||,џџџџџџџџ,џџџџ,џџџџ,mmLаџџџџџџџџn,oo,mmвџџџџџџџџnгџџџџџџџџkАдџџџџџџџџk,џџџџ ,џџџџЌ ,}},џџџџџџџџ,џџџџ,џџџџ,mmLмџџџџџџџџn,oo,||оџџџџџџџџnпџџџџџџџџkœрџџџџџџџџk,џџџџB ,~~,џџџџ,џџџџ,џџџџ ,џџџџ0$чџџџџџџџџp8шџџџџџџџџq,шџџџџџџџџq8ъџџџџџџџџt,vvъџџџџџџџџt8ыџџџџџџџџt,€€ыџџџџџџџџtLэџџџџџџџџ,!ƒƒ, ‚‚яџџџџџџџџ№џџџџџџџџpёџџџџџџџџkLђџџџџџџџџk,„„,"џџџџ$ѕџџџџџџџџp8іџџџџџџџџq,rrіџџџџџџџџq8јџџџџџџџџt,uuјџџџџџџџџt8љџџџџџџџџt,vvљџџџџџџџџtњџџџџџџџџpћџџџџџџџџktќџџџџџџџџk,џџџџ ,џџџџ2,……,"џџџџ $џџџџџџџџp8џџџџџџџџq,rrџџџџџџџџq8џџџџџџџџt,vvџџџџџџџџtџџџџџџџџpџџџџџџџџkœџџџџџџџџk,џџџџs ,џџџџ= ,џџџџ,††,$‡‡,#џџџџџџџџ$џџџџџџџџp8џџџџџџџџq,ˆˆџџџџџџџџq8џџџџџџџџt,vvџџџџџџџџtџџџџџџџџpџџџџџџџџkœџџџџџџџџk,џџџџD ,џџџџУ ,џџџџ,‰‰,$‡‡,#џџџџџџџџ$џџџџџџџџp8џџџџџџџџq,ŠŠџџџџџџџџq8џџџџџџџџt,vvџџџџџџџџt8 џџџџџџџџ,%‹‹ џџџџџџџџ!џџџџџџџџp"џџџџџџџџkœ%џџџџџџџџk,џџџџU,џџџџЖ ,џџџџ2,ŒŒ,"џџџџ ,џџџџџџџџ$,џџџџџџџџp8-џџџџџџџџq,rr-џџџџџџџџq8/џџџџџџџџt,vv/џџџџџџџџt80џџџџџџџџt,ww0џџџџџџџџt1џџџџџџџџp2џџџџџџџџkL4џџџџџџџџ,ŽŽ,"џџџџ 6џџџџџџџџ`9џџџџџџџџ,џџџџD ,,&$=џџџџџџџџp8>џџџџџџџџq,‘‘>џџџџџџџџq?џџџџџџџџp@џџџџџџџџtBџџџџџџџџ’,џџџџЛ ,““,&””,џџџџќ LGџџџџџџџџn,••,џџџџIџџџџџџџџn$Kџџџџџџџџp8Lџџџџџџџџq,––LџџџџџџџџqMџџџџџџџџpNџџџџџџџџ’8Oџџџџџџџџ’,——$Pџџџџџџџџp8Qџџџџџџџџq,˜˜QџџџџџџџџqRџџџџџџџџpSџџџџџџџџ’LVџџџџџџџџ’,™™,&77$Yџџџџџџџџp8Zџџџџџџџџq,ššZџџџџџџџџq[џџџџџџџџp\џџџџџџџџ’L_џџџџџџџџ’,››,&99$bџџџџџџџџp8cџџџџџџџџq,œœcџџџџџџџџqdџџџџџџџџpeџџџџџџџџ’8hџџџџџџџџ’,$iџџџџџџџџp8jџџџџџџџџq,žžjџџџџџџџџqkџџџџџџџџplџџџџџџџџ’8mџџџџџџџџ’,ŸŸ$nџџџџџџџџp8qџџџџџџџџq,  qџџџџџџџџq8sџџџџџџџџq,ЁЁsџџџџџџџџq8tџџџџџџџџq,ЂЂtџџџџџџџџq8wџџџџџџџџq,ЃЃwџџџџџџџџq8yџџџџџџџџq,ЄЄyџџџџџџџџq8{џџџџџџџџq,ЅЅ{џџџџџџџџq|џџџџџџџџp}џџџџџџџџ’`џџџџџџџџІ,ЇЇ,џџџџ,'ЈЈ‚џџџџџџџџІˆƒџџџџџџџџІ,ЉЉ,(::,);;,џџџџ,'ЊЊˆџџџџџџџџІLŠџџџџџџџџn,ЋЋ,mmŒџџџџџџџџnL•џџџџџџџџn,ЌЌ,џџџџЙ —џџџџџџџџnœ™џџџџџџџџk,џџџџ{ ,­­,*ЎЎ,џџџџџџџџ,џџџџ ,џџџџŸџџџџџџџџkt џџџџџџџџk,џџџџэ ,ЏЏ,џџџџџџџџ,*--ЄџџџџџџџџkœЅџџџџџџџџk,џџџџх ,АА,џџџџ,џџџџџџџџ,џџџџ,џџџџ€Ћџџџџџџџџk8­џџџџџџџџ’,ББ$Ўџџџџџџџџp8Џџџџџџџџџq,ВВЏџџџџџџџџqАџџџџџџџџpБџџџџџџџџ’8Вџџџџџџџџ’,ГГ$Гџџџџџџџџp8Дџџџџџџџџq,ДДДџџџџџџџџq8Еџџџџџџџџq,ЕЕЕџџџџџџџџq8Жџџџџџџџџq,ЖЖЖџџџџџџџџq8Зџџџџџџџџq,ЗЗЗџџџџџџџџq8Йџџџџџџџџ,!..ЙџџџџџџџџКџџџџџџџџp$Лџџџџџџџџp8Мџџџџџџџџq,ИИМџџџџџџџџq8Нџџџџџџџџq,ЙЙНџџџџџџџџqОџџџџџџџџpПџџџџџџџџ’LСџџџџџџџџn,КК,џџџџџџџџУџџџџџџџџnLФџџџџџџџџn,ЛЛ,ММЦџџџџџџџџnLЧџџџџџџџџn,НН,џџџџИ ЩџџџџџџџџnLЮџџџџџџџџn,ОО,џџџџ7 аџџџџџџџџntвџџџџџџџџk,џџџџ,ПП,џџџџ,џџџџџџџџжџџџџџџџџk`лџџџџџџџџ,РР,&СС,џџџџџџџџоџџџџџџџџ`рџџџџџџџџk,џџџџ,ТТ,џџџџуџџџџџџџџk`фџџџџџџџџk,џџџџ,УУ,џџџџАчџџџџџџџџkLшџџџџџџџџk,ФФ,џџџџџџџџыџџџџџџџџk8ьџџџџџџџџk,ХХьџџџџџџџџkLэџџџџџџџџk,ЧЧ,ЦЦяџџџџџџџџkˆ№џџџџџџџџk,џџџџ‹ ,ШШ,џџџџ,*ЩЩ,џџџџіџџџџџџџџkїџџџџџџџџhљџџџџџџџџ1љџџџџ+,pyaxmlparser-0.3.24/tests/test_apk/resources.arsc000066400000000000000000033244601356264674700222270ustar00rootroot00000000000000 0Љ 8‡Щ*шK„Ih‡ІХфZЦќ2hž№&\’Шў=Рџ>}Мжі*D^xАі.fžж?q–Хя I Ž д ў 0 _  Т є ( R | Ї з 6 g   в  3 e “ Я IvЅг/S„Жнў De‹Бт,[Ті?gВс;pЁЬ§%UŠЗь?nœУш<g‘Нпџ Q}ЂЦє"VuŽЌа$GkЂрP|Ќа7v­бљ!=X~ЏдѓHgˆЅбш<z™БшDb…Лн 9 V  К љ %!L!w!Ђ!г!№!"8"Y"•"Й"т" #8#]#‰#Њ#д#є#$F$d$ƒ$­$ж$%%9%[%‚%Є%С%т%&B&u&š&Ф&њ&!'U't'–'Й'к' (9(m(œ(в()))X)„)Е)и)*#*J*n*œ*Я*ђ*+B+f+‹+Б+й+ў+4,R,y,œ,С,ф, -2-[-‡-Є-Ч-ч-.0.f.‘.Й.№.$/Z/‡/Ж/у/0U0”0Э0191m1Ÿ1е1 2@2u2І2к23L3o3Ÿ3д3454a4ƒ4Ќ4е45/5U5}5В5и56(6O6o66К6ы67O77Й7ы78B8n8–8П8ю8 9U9†9Й9я9:?:g:–:Ч:ю:&;Z;…;Ў;з;<'<N<<Г<ђ<*=Z=‚=К=ы=>H>y>Ї>м> ?:?_?’?Н?№?#@U@‡@Й@у@A,ANAqA“AЙAмAѕA)B]BˆBЃBЩBяBC9CZC„CЉCЩCёCDEDnDšDШDыDEBEcEƒEЉEЧEъE F2FdFŠFЇFЫFёFG>GoGЋGмGHEHqHЄHтHIQI€IКIлIJ)JKJ€JЈJнJњJK@KqKžKЦKїK!LSL…LДLмL M1MYMMБMйMN4N_NˆNЇNдNњN'OMOzOДOтOP/P`P„PЉPЪPьPQDQjQ‰QБQбQ§Q(RKRtR•RЕRйRўRSTxTЁTТTсTU'UPUtU UСUїUVFVsVЈVеV§V"WWW‚WЗWлWX1X[XˆXБXмXY9YeY‘YДYыY1ZvZЌZзZ[0[_[[Р[\)\_\‘\Щ\ї\]B]p]Є]е]^8^k^“^Ц^ќ^2_b_˜_з_ `?`o`™`У`ш`a6a[a†aЗaєa+bEbkb…bЋbђb7chc’cМcыcdKdudЋdдdeLe€eРefEffПfg@gugВgёg(hah hкhiMi‚iПi§iЯKЯЯŸЯЕЯ а'а.а:аBаIаUаfаƒаŒаїаўа1бZбzбŸбЖбХбгбєбв'веврвчвэвљв:г‡г›гєгдд д0д@дFдOд{ддЁдЫдќдее.е:еcе‡еТеЩесеїеж8ж@жYжpжˆжЁжПжЮжз&зOз€ззŸзВзНзЫззз'и9иIи›иАиэињи йй‹йšйгйрй0кHк„кЉкЕкЮкжкукѓкл ллЈлќл:м‘мЁмЖмЯмомъмёмџмнн…нšнЃнЌнГнЫно.о>оwо’опо6пTп^п|п’пЬпеп"рuр‚р‘рŸрЏрОрШргртрюр§р сс+сJсЂстсяс4тEтYтfтoтмтэт у/уKуXуbу†усу№уф$ф/ф9фaфХфжфъф§фх'хoхuх‰хх˜хЙхихсхц=цœцБцРцЪцчч3ч:чˆчЂчш,ш;шkшvшЭшиштшяш4щƒщ˜щžщ­щЗщрщ/ъBъHъXъmъsъƒъšъБъєъўъыыы#ы-ы9ыSыОыЧышы ь#ь-ьHьSьsь ьрьєь.э;эаэјэю—юНюЪюрюя я8я`яtяјя№Q№ь№bё~ё‰ёђ%ђCђUђgђšђ*ѓHѓQѓчѓѓѓєeємєъєљє%ѕ:ѕ[ѕdѕsѕ…ѕОѕпѕєѕ іZіoіщіїї%їNїoїї­їCј”јІјОјЭјчј_љtљ}љ‹љКљЦљњ#њRњ[њ|њ­њсњbћ.ќCќtќ—ќ-§K§`§ў€ўРўѓўиџeз:…ЅЯяЕhѓ~У§Кр'@wщД У т 9 R | ˜ Н ў К з V t _ Ѕ З ж :’b€‘ЉtДвэP€иOЊЕШŒБЬ&;Pe™фя `r‚Ђ§7PfnxтэBYz—БЛ(JŽœВгыєћFЌМСЪакі<E~Šц:PX`gqy‰ЕAЎк “ !3!J!|!Ј!?"R"ъ"W#j#x##Ј#Д#К#о#ї#>$­$Щ$и$%%%u%ƒ%Ž%%Ў%њ% &&‚&–&Ў&Н&Ц&е&к&'''…'š'Ѓ'Ќ'(%(<(s(†(г(C)P)q)|)Ÿ)Й)Ц)й)ь)љ)6*ћ*N+€+S,Ђ,ј,Ё-л-.T/А/с/0ч0w1Ј1Ь1є1Ё2й23A3P3д3џ3П4”5Т5Ÿ6О6ѕ6!8n8Ќ8X9v9Љ9Ш9:Ж:љ:v;œ;3<U<в<=G=u=М=Ъ=)>7>‚>‹>>№> ??x?’?™?Ѕ?а?@W@n@|@’@œ@Љ@Л@Ы@ж@о@э@ AA,A9AxA˜AЃAтAчA4BFBMBfBtBŒB—BЄBЎBЖBУBЩBеBјBC(CHCpCЃCНC_DŠDE:EKEkE”EШE:FxFќFG4GxGH/HбHўHI&IbII”IJ(J7JAJLJ”JЃJИJюJ§J”V”Š”›”Ч”д”ы”ј”•=•V•s•–9–’–—ж— ˜5˜™4™T™{™ž™Ц™н™ё™"š=šЙš›j›t›‰›Ќ›џ›\œ„œЧœ2•Здцёў4žƒžbŸz ˜ Й 'ЁRЁЁЯЁџЁ3Ђ[Ѓ›ЃкЃєЄDЅ#ІLІ8ЇxЇ™ЇУЇыЇОЈ Љ-ЉЬЉЊ^ЊЋсЋќЋ`ЌoЌ’Ќ˜ЌЁЌГЌЛЌЩЌшЌ­­y­Ф­н­і­Ў+ЎšЎўЎ Џ Џ^ЏlЏЊЏЕЏУЏЯЏкЏхЏѓЏ ААpА|А…АšАІАыА Б$Б3БIБSБbБ­БВeВzВВЋВИВГ&Г=ГRГYГuГ…ГЁГьГ0Д<ДQДZДlД{ДŠДМДЬДйД4Е=Е—ЕЖЕРЕЖ(Ж@ЖЖ З!З5ЗGЗTЗЕЗгЗнЗыЗѓЗIИRИqИ†ИŽИАИЭИлИ№ИЙMЙЁЙЌЙіЙК#КFКNКjККйКёКAЛRЛpЛ~Л‘Л›ЛНЛШЛмЛчЛ9М‚ММЂМАМОМвМпМщМњМННcН‹Н›НМНЦНЮНфНPОmОРОЧОхОѕОCПkП†П‘ПœПРР"РAРOРcРmРРмРёР]СuС‚СЉС ТТOТZТ…ТТШТеТ3У>УLУ`УДУПУЬУлУfФ{ФŠФЃФМФШФ$Х=ХcХсХqЦˆЦ”ЦЖЦгЦщЦЧNЧЗЧЦЧЯЧMШ\ШШЉШЩШцШѕШЩЩЎЩНЩмЩ ЪЪ"ЪЫ&ЫфЫќЫ2Ь…Ь‘ЬОЬњЬ"ЭRЭуЭЋЮgЯMа)б5б‚бЁбГбDввРвхвгг?г^гљгМдйде­е2жTжŽж9зи­иѓийVйvй•йДйoкBлpлыл м`мkмvмПмамсм'нnн‚н˜нЗнШншнђно!о)о=оQо\оgоОоЬо$п2п>ппнпѓпр р)р3рAр_р™рФр|сПсис№сётуМудуƒфхŠхІхСхёхGцќцNчoч#шTш щ)щњщ!ъcъ‚ъ•ытыь=ь–ь>эЖэЯэћэю•юбю8яЊяояX№t№ь№ёё&ё`ёёˆёђђ?ђRђnђzђ†ђ–ђєђѓѓ+ѓKѓTѓmѓБѓСѓ є(єDєTєyєгєцєієџєUѕiѕvѕŒѕѕѕўѕііhіЪікіљі`їlї|ї‹їЊї#ј/ј<ј„јНјлј№јйљ'њКњxћLќyќ*§j§2ў:џsџ‹џжџчџDLЏефkЂХдф№*CXe~—ЃМШую?†žє8Hn“шMŸ!+6IXfЅЯј`ж‚џ 4 [ † “ ­   Y v Š Љ И  : T З Ф г ( 5 i ƒ Њ М Щ ћ ) 6 B О 6^y˜ЅВЛы 'sz—ЋИя`x‡пяњ#3Ž˜Вбѕ†ђgŽъ9ISž­ЭјhЦЭ7Rhy–ЁНЧгнё':HSj€ЉЙгъ .@IІшї/p{Хаъ=IaƒЇЬцї:CPЏЫ$4HYvИЬ]hw€• ­ЙЦжоO& C h ‡ В д э 3!Я!€"œ"Ў"_#•#$$ž$О$d%„%В%Y&<'_'˜'Ц'ы'§'2(W(m(щ()z)н)D*W*q*€*ž*У*д*і*$+I+y+‰+Њ+в+і+$,:,Ш,р,D-U-h-’-.!.C.[.j.ƒ.–.Ё.Д.Т.ж.р.і.//*/2/>/J/U/Ї/Ж/љ/000-060e0q0‹0›0­0Ч0Я0и0<1Ž1”1Є122-272`2Ч2з2ю2ќ23P3e3q3Г3н3ю34Z4`4i4‘4Б4в4ч4 5505:5C5U5ƒ5›5Ч5л5N6e6е677С7ђ7#8Ѕ8!9Њ9У9>:\:В:Я:;a;Ћ;<#<@<…<й<љ<==3=K=U=e=o=x=Š=ъ=ј=0>?>^>x>>щ>ѓ>??5?…?—?Г?У?а?ё?@L@V@k@@Ÿ@Б@К@Ц@ц@ќ@GA‰AяABB3B=BSBДBќBoC„C’CЏCдCйCєCODЩDэD4E?EyEŽEІEўE[FFсFDGJGhGБGжGH0H;HDHPHbHnHyH‚H’HЅHБHбHмH№HјHI5I@IHISIГIЧIзIтI3JŒJЌJПJзJуJ'K1KKмKL)LKLLЏLбL9M]MwM˜MЄMБMЭMNCNЌNРNЩNгNмN-O”OЌOP#PTP†P“PуPQQ‡QЃQъQR]RІRS S-SˆS˜SрS§S#TnTuT€TЁTЎTПTШTU*U4UIU]U˜UЋUЕUШUаU№UIVYVbVбVяVWWmWW›WЎWЙWЧWвW№WXX!XAXLX]XИXУXўXBYIYiYpY‰YYиYZ{Z’ZуZюZ[[†[Ћ[М[\)\?\L\c\Ž\И\Ъ\р\ю\]]]o]{]‡]ч]ѕ]^1^P^•^Д^Щ^6_M_`_s_т_§_`$`^`n`Ж`љ`aGaNa}a‰a­aМaЦa№ablŽlЄlm#mm&nPnhn|nnфncoqo‡ooЋoнoўo1pZpsppŸpІpСpчpqq:qCqsqqДqвqэqr)rHr_rrЗrвrмrћrs.sYsЮsѓst+t>tTtvt–tВtњtufu‚u”uђuv,vIvgv…v№vw6wzw‹wХwшwЙxўxyy%yvyŸyzz z(zBzhzЁz{A{[{r{Ž{Ъ{р{я{|Ž|Ѕ|Ў|п|}}&}b}˜}В}Н}г}ћ}a~m~‰~~Ї~с~ђ~$lw—ЊМиђї"€J€p€ €Џ€ћ€$BKеє ‚}‚˜‚Ў‚Ш‚у‚ѕ‚ƒ6ƒ\ƒƒ›ƒ§ƒ'„@„U„Ж„Р„ж„э„ї„…!…­…†o†‡†•†Ѕ†С†/‡E‡‹‡Л‡Щ‡у‡џ‡ˆ;ˆSˆgˆ~ˆ”ˆІˆПˆфˆ‰:‰G‰Y‰l‰r‰‚‰“‰Ѕ‰Ќ‰Д‰р‰ъ‰ћ‰ŠŠ2Š;ŠOŠZŠ{Š™ŠЛŠтŠыŠ"‹>‹^‹‹Њ‹К‹ж‹ш‹ё‹%ŒLŒTŒgŒwŒГŒЯŒыŒѓŒ,7MViuˆ•ЇОЩйњŽŽ-Ž<Ž_ŽrŽуŽ 7нъNdƒж.‘w‘’Ў’Ъ’ъ’Z“Ч“g”N•‹•У•q–––.—h—~—š—в—ђ—Әё˜ ™;™T™Њ™Н™ušЈšКšзš›Ё›У›є› œœ'œ=œžœЗœМœЪœтœїœ™Њž!ž:žež‡ž—žЇžВž#Ÿ<ŸІŸАŸнŸ\ u ‘ А О Ы љ (Ё•ЁСЁкЁхЁЂ ЂDЂZЂkЂОЂЬЂэЂNЃYЃЩЃќЃgЄ$Ѕ—ЅБЅШЅюЅ@І\І|І‰І,Ї“ЇІЇгЇпЇўЇЈKЈ^ЈюЈЉ)ЉWЉЭЉкЉјЉ Њ"ЊQЊˆЊЊЊШЊъЊ Ћ9ЋDЋлЋшЋ"Ќ8ЌKЌrЌ‡Ќ>­е­ш­я­EЎžЎЌЎЭЎЏ(Џ9ЏHЏYЏgЏxЏ‰Џ­ЏМЏЪЏ АoА„ААЋАКАУАчАББ*Б„БŒБпБьБѕБќБ$В0В>ВMВvВтВќВ Г.Г?ГKГ˜ГЛГЧГзГыГѕГ Д7Д]ДtДнДьД3ЕKЕaЕЬЕЖ?ЖJЖ[ЖdЖОЖЪЖтЖэЖЗЗЗHЗ^ЗiЗvЗЭЗеЗѕЗИCИ“ИэИ:ЙGЙWЙoЙwЙ€Й’ЙБЙУЙбЙоЙ#КdКРКЬКзКЛ$ЛxЛ‚Л—ЛЉЛПЛсЛѓЛњЛ ММ!М6МCМNМdМoМ‹МЁМЊМгМН4НHН”НŸНОrО~О‰ОŸОЙОФОзОчО§О#ПMПЖПРHРsРŽРЈР"С0С;СUСbСmСzС„СмС№СТТТ+Т<ТZТ‚ТтТяТћТYУnУ­УдУфУэУќУ8Ф@Ф]ФeФqФ|ФЮФхФёФ§ФKХ`ХoХХЦЦЉЦNЧЧаЧJШpШƒШ”Ш6ЩдЩєЩ2ЪУЪЫЫ&Ы\ЫмЫэЫЬpЬŽЬ7ЭVЭŠЭРЭЭЭlЮЯjЯУЯёЯ?аіа бѕбШвџг6дІдђдеепжзfз~з™зНз‚ийиъийй?й}йюйRк_кƒкЋкЛкл2л?лЄлњлмgмpм•мžмОмрмюм>нwндн;о|оЃоЖоТоп/п@п`пoпxп†п•п пЗпЦпвпупћпрuр€р›рірVс€сћсXт}тьт у$уTу{уŠуœуУуЯуіу#фJфeф†ф•фЙфЫфьфіфхeхŠхИхЧхђх9цaцnц}цПцъц ч?чrчЇчрчш*ш?шFшSшlшyшˆш”шІшЗшРшжшушщ щщ\щŠщСщцщћщ)ъ;ъ\ъ„ъІъуъы,ыAыlы‹ыІыГыТыЯыџыь+ьQь\ьgьˆь ьРьоьяьэ.эNэxэЎэсэю2юGюkю’юЙюдюяяCя[яŽяІяѕя №№*№z№•№х№7ёdё€ёЇёЏёИёљёђ'ђtђƒђ’ђуђ$ѓ9ѓHѓQѓ_ѓhѓqѓzѓ“ѓœѓЋѓКѓгѓтѓёѓњѓєPєeєnєzє‰є’єІєЏєЫєдєнєљєѕ-ѕXѕˆѕЊѕвѕъѕіAіvі іЙісіњі ї!їSї‹їЃїХїдїчїј'ј:јTјrјŽј­јЦјцјћјљ=љbљƒљЇљЎљТљпљюљњњ>њIњuњ‘њŸњГњЪњтњћћћ.ћ8ћIћ^ћ{ћƒћ”ћ ћБћХћпћшћќќ(ќ>ќOќsќќЉќНќЬќъќљќ §*§L§h§‚§•§Е§й§ўXў‰ўРўвўџ*џyџ†џДџоџќџ&D~Р~—Ілї 7S\eЋХд.7=OXЂПШзў Q`ЄЦв%>Gavоч№љXt†—ІЛф№ќ4Mzƒ–ЏОэќ(Ww“Љд N ‚ Є Щ л ъ  B d  — П о $ I z “ б џ 6 Q • Ж и  5 p Њ № &Qo™ю"G_qБКи1kУиф![ЄЬS_zДўBЊоѓ&2ožАич%WcГйј3Ut Йию*Ikz“Мтю=i{ЎЧі1Qmƒ‘ЉКЧмі:Ydw›Бп AfЃфIk–н$aЋЯё"0RqЬtл [ { ž !!!+!E!Q![!c!p!Š!ž!К!Щ!ѕ!""y"р"!#:#J#^#o#x##Ž#Ї#М#а#м#я#ћ# $$*$L$\$e$x$„$$›$Њ$Е$Н$Ч$а$х$ю$% %%,%z%Ÿ%П%р%ї%&P&š&В&'…'Ћ'Ж'й'ч'ё'(!((Ѕ(Н(щ(ќ(e))ь)і) *h*q*“*+.+O+Ÿ+С+Э+з+п+њ+,1,G,,ё,a-‚-с-ё-.#.r.‚.”.ф.G/t/‰/ž/п/.0=0l0ˆ0š0М0й0ѕ0ў01E1ƒ1д1262L2j2Š2Ѕ2Н2к2ц2№2303?3\3l3–3Ж3Щ3444$474C4W4^4u4„4—4Ѓ4Г4Ц4н4ф4љ455.575F5T5h5}5’5І5В5У5Ю5с5ю5џ5656Q6^6‰6Ї6Х6ъ6ћ67&757E7R7v7ˆ77Ј7О7Я7з7х7ѕ7 88!8*8=8Q8e8y88Ё8 0@P`p€ АРар№ 0@P`p€ АРар№ 0@P`p€Tap ALLOW on the %1$s prompt%'Toque PERMITIR na solicitaУЇУЃo de %1$sTap ALLOW on the %1$s promptTap ALLOW on the %1$s promptTap ALLOW on the %1$s promptTap ALLOW on the %1$s promptTap ALLOW on the %1$s prompt33Everything is only a tap away. Tap on a result now.<="Tudo a um toque de distУЂncia. Toque em um resultado agora."33Everything is only a tap away. Tap on a result now.33Everything is only a tap away. Tap on a result now.33Everything is only a tap away. Tap on a result now.33Everything is only a tap away. Tap on a result now.33Everything is only a tap away. Tap on a result now.33Universal search for your phone. Swipe down to try.OO"Pesquisa universal para o seu telefone. Deslize para baixo para experimentar."33Universal search for your phone. Swipe down to try.33Universal search for your phone. Swipe down to try.33Universal search for your phone. Swipe down to try.33Universal search for your phone. Swipe down to try.33Universal search for your phone. Swipe down to try.<