#!/usr/bin/env vpython3
# encoding: utf-8
# Copyright 2019 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""A script to parse and dump localized strings in resource.arsc files."""


import argparse
import collections
import contextlib
import cProfile
import os
import re
import subprocess
import sys
import zipfile

# pylint: disable=bare-except

# Assuming this script is located under build/android, try to import
# build/android/gyp/bundletool.py to get the default path to the bundletool
# jar file. If this fail, using --bundletool-path will be required to parse
# bundles, allowing this script to be relocated or reused somewhere else.
try:
  sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'gyp'))
  import bundletool

  _DEFAULT_BUNDLETOOL_PATH = bundletool.BUNDLETOOL_JAR_PATH
except:
  _DEFAULT_BUNDLETOOL_PATH = None

# Try to get the path of the aapt build tool from catapult/devil.
try:
  import devil_chromium  # pylint: disable=unused-import
  from devil.android.sdk import build_tools
  _AAPT_DEFAULT_PATH = build_tools.GetPath('aapt')
except:
  _AAPT_DEFAULT_PATH = None


def AutoIndentStringList(lines, indentation=2):
  """Auto-indents a input list of text lines, based on open/closed braces.

  For example, the following input text:

    'Foo {',
    'Bar {',
    'Zoo',
    '}',
    '}',

  Will return the following:

    'Foo {',
    '  Bar {',
    '    Zoo',
    '  }',
    '}',

  The rules are pretty simple:
    - A line that ends with an open brace ({) increments indentation.
    - A line that starts with a closing brace (}) decrements it.

  The main idea is to make outputting structured text data trivial,
  since it can be assumed that the final output will be passed through
  this function to make it human-readable.

  Args:
    lines: an iterator over input text lines. They should not contain
      line terminator (e.g. '\n').
  Returns:
    A new list of text lines, properly auto-indented.
  """
  margin = ''
  result = []
  # NOTE: Intentional but significant speed optimizations in this function:
  #   - |line and line[0] == <char>| instead of |line.startswith(<char>)|.
  #   - |line and line[-1] == <char>| instead of |line.endswith(<char>)|.
  for line in lines:
    if line and line[0] == '}':
      margin = margin[:-indentation]
    result.append(margin + line)
    if line and line[-1] == '{':
      margin += ' ' * indentation

  return result


# pylint: disable=line-too-long

# NOTE: aapt dump will quote the following characters only: \n, \ and "
# see https://cs.android.com/search?q=f:ResourceTypes.cpp

# pylint: enable=line-too-long


def UnquoteString(s):
  """Unquote a given string from aapt dump.

  Args:
    s: An UTF-8 encoded string that contains backslashes for quotes, as found
      in the output of 'aapt dump resources --values'.
  Returns:
    The unquoted version of the input string.
  """
  if not '\\' in s:
    return s

  result = ''
  start = 0
  size = len(s)
  while start < size:
    pos = s.find('\\', start)
    if pos < 0:
      break

    result += s[start:pos]
    count = 1
    while pos + count < size and s[pos + count] == '\\':
      count += 1

    result += '\\' * (count // 2)
    start = pos + count
    if count & 1:
      if start < size:
        ch = s[start]
        if ch == 'n':  # \n is the only non-printable character supported.
          ch = '\n'
        result += ch
        start += 1
      else:
        result += '\\'

  result += s[start:]
  return result


assert UnquoteString(r'foo bar') == 'foo bar'
assert UnquoteString(r'foo\nbar') == 'foo\nbar'
assert UnquoteString(r'foo\\nbar') == 'foo\\nbar'
assert UnquoteString(r'foo\\\nbar') == 'foo\\\nbar'
assert UnquoteString(r'foo\n\nbar') == 'foo\n\nbar'
assert UnquoteString(r'foo\\bar') == r'foo\bar'


def QuoteString(s):
  """Quote a given string for external output.

  Args:
    s: An input UTF-8 encoded string.
  Returns:
    A quoted version of the string, using the same rules as 'aapt dump'.
  """
  # NOTE: Using repr() would escape all non-ASCII bytes in the string, which
  # is undesirable.
  return s.replace('\\', r'\\').replace('"', '\\"').replace('\n', '\\n')


assert QuoteString(r'foo "bar"') == 'foo \\"bar\\"'
assert QuoteString('foo\nbar') == 'foo\\nbar'


def ReadStringMapFromRTxt(r_txt_path):
  """Read all string resource IDs and names from an R.txt file.

  Args:
    r_txt_path: Input file path.
  Returns:
    A {res_id -> res_name} dictionary corresponding to the string resources
    from the input R.txt file.
  """
  # NOTE: Typical line of interest looks like:
  # int string AllowedDomainsForAppsTitle 0x7f130001
  result = {}
  prefix = 'int string '
  with open(r_txt_path) as f:
    for line in f:
      line = line.rstrip()
      if line.startswith(prefix):
        res_name, res_id = line[len(prefix):].split(' ')
        result[int(res_id, 0)] = res_name
  return result


class ResourceStringValues:
  """Models all possible values for a named string."""

  def __init__(self):
    self.res_name = None
    self.res_values = {}

  def AddValue(self, res_name, res_config, res_value):
    """Add a new value to this entry.

    Args:
      res_name: Resource name. If this is not the first time this method
        is called with the same resource name, then |res_name| should match
        previous parameters for sanity checking.
      res_config: Config associated with this value. This can actually be
        anything that can be converted to a string.
      res_value: UTF-8 encoded string value.
    """
    if res_name is not self.res_name and res_name != self.res_name:
      if self.res_name is None:
        self.res_name = res_name
      else:
        # Sanity check: the resource name should be the same for all chunks.
        # Resource ID is redefined with a different name!!
        print('WARNING: Resource key ignored (%s, should be %s)' %
              (res_name, self.res_name))

    if self.res_values.setdefault(res_config, res_value) is not res_value:
      print('WARNING: Duplicate value definition for [config %s]: %s ' \
            '(already has %s)' % (
                res_config, res_value, self.res_values[res_config]))

  def ToStringList(self, res_id):
    """Convert entry to string list for human-friendly output."""
    values = sorted([(str(config), value)
                     for config, value in self.res_values.items()])
    if res_id is None:
      # res_id will be None when the resource ID should not be part
      # of the output.
      result = ['name=%s count=%d {' % (self.res_name, len(values))]
    else:
      result = [
          'res_id=0x%08x name=%s count=%d {' % (res_id, self.res_name,
                                                len(values))
      ]
    for config, value in values:
      result.append('%-16s "%s"' % (config, QuoteString(value)))
    result.append('}')
    return result


class ResourceStringMap:
  """Convenience class to hold the set of all localized strings in a table.

  Usage is the following:
     1) Create new (empty) instance.
     2) Call AddValue() repeatedly to add new values.
     3) Eventually call RemapResourceNames() to remap resource names.
     4) Call ToStringList() to convert the instance to a human-readable
        list of strings that can later be used with AutoIndentStringList()
        for example.
  """

  def __init__(self):
    self._res_map = collections.defaultdict(ResourceStringValues)

  def AddValue(self, res_id, res_name, res_config, res_value):
    self._res_map[res_id].AddValue(res_name, res_config, res_value)

  def RemapResourceNames(self, id_name_map):
    """Rename all entries according to a given {res_id -> res_name} map."""
    for res_id, res_name in id_name_map.items():
      if res_id in self._res_map:
        self._res_map[res_id].res_name = res_name

  def ToStringList(self, omit_ids=False):
    """Dump content to a human-readable string list.

    Note that the strings are ordered by their resource name first, and
    resource id second.

    Args:
      omit_ids: If True, do not put resource IDs in the result. This might
        be useful when comparing the outputs of two different builds of the
        same APK, or two related APKs (e.g. ChromePublic.apk vs Chrome.apk)
        where the resource IDs might be slightly different, but not the
        string contents.
    Return:
      A list of strings that can later be sent to AutoIndentStringList().
    """
    result = ['Resource strings (count=%d) {' % len(self._res_map)]
    res_map = self._res_map

    # Compare two (res_id, values) tuples by resource name first, then resource
    # ID.
    for res_id, _ in sorted(res_map.items(),
                            key=lambda x: (x[1].res_name, x[0])):
      result += res_map[res_id].ToStringList(None if omit_ids else res_id)
    result.append('}  # Resource strings')
    return result


@contextlib.contextmanager
def ManagedOutput(output_file):
  """Create an output File object that will be closed on exit if necessary.

  Args:
    output_file: Optional output file path.
  Yields:
    If |output_file| is empty, this simply yields sys.stdout. Otherwise, this
    opens the file path for writing text, and yields its File object. The
    context will ensure that the object is always closed on scope exit.
  """
  close_output = False
  if output_file:
    output = open(output_file, 'wt')
    close_output = True
  else:
    output = sys.stdout
  try:
    yield output
  finally:
    if close_output:
      output.close()


@contextlib.contextmanager
def ManagedPythonProfiling(enable_profiling, sort_key='tottime'):
  """Enable Python profiling if needed.

  Args:
    enable_profiling: Boolean flag. True to enable python profiling.
    sort_key: Sorting key for the final stats dump.
  Yields:
    If |enable_profiling| is False, this yields False. Otherwise, this
    yields a new Profile instance just after enabling it. The manager
    ensures that profiling stops and prints statistics on scope exit.
  """
  pr = None
  if enable_profiling:
    pr = cProfile.Profile()
    pr.enable()
  try:
    yield pr
  finally:
    if pr:
      pr.disable()
      pr.print_stats(sort=sort_key)


def IsFilePathABundle(input_file):
  """Return True iff |input_file| holds an Android app bundle."""
  try:
    with zipfile.ZipFile(input_file) as input_zip:
      _ = input_zip.getinfo('BundleConfig.pb')
      return True
  except:
    return False


# Example output from 'bundletool dump resources --values' corresponding
# to strings:
#
# 0x7F1200A0 - string/abc_action_menu_overflow_description
#         (default) - [STR] "More options"
#         locale: "ca" - [STR] "Més opcions"
#         locale: "da" - [STR] "Flere muligheder"
#         locale: "fa" - [STR] " گزینه<U+200C>های بیشتر"
#         locale: "ja" - [STR] "その他のオプション"
#         locale: "ta" - [STR] "மேலும் விருப்பங்கள்"
#         locale: "nb" - [STR] "Flere alternativer"
#         ...
#
# Fun fact #1: Bundletool uses <lang>-<REGION> instead of <lang>-r<REGION>
#              for locales!
#
# Fun fact #2: The <U+200C> is terminal output for \u200c, the output is
#              really UTF-8 encoded when it is read by this script.
#
# Fun fact #3: Bundletool quotes \n, \\ and \" just like aapt since 0.8.0.
#
_RE_BUNDLE_STRING_RESOURCE_HEADER = re.compile(
    r'^0x([0-9A-F]+)\s\-\sstring/(\w+)$')
assert _RE_BUNDLE_STRING_RESOURCE_HEADER.match(
    '0x7F1200A0 - string/abc_action_menu_overflow_description')

_RE_BUNDLE_STRING_DEFAULT_VALUE = re.compile(
    r'^\s+\(default\) - \[STR\] "(.*)"$')
assert _RE_BUNDLE_STRING_DEFAULT_VALUE.match(
    '        (default) - [STR] "More options"')
assert _RE_BUNDLE_STRING_DEFAULT_VALUE.match(
    '        (default) - [STR] "More options"').group(1) == "More options"

_RE_BUNDLE_STRING_LOCALIZED_VALUE = re.compile(
    r'^\s+locale: "([0-9a-zA-Z-]+)" - \[STR\] "(.*)"$')
assert _RE_BUNDLE_STRING_LOCALIZED_VALUE.match(
    '        locale: "ar" - [STR] "گزینه\u200cهای بیشتر"')


def ParseBundleResources(bundle_tool_jar_path, bundle_path):
  """Use bundletool to extract the localized strings of a given bundle.

  Args:
    bundle_tool_jar_path: Path to bundletool .jar executable.
    bundle_path: Path to input bundle.
  Returns:
    A new ResourceStringMap instance populated with the bundle's content.
  """
  cmd_args = [
      'java', '-jar', bundle_tool_jar_path, 'dump', 'resources', '--bundle',
      bundle_path, '--values'
  ]
  p = subprocess.Popen(cmd_args, bufsize=1, stdout=subprocess.PIPE)
  res_map = ResourceStringMap()
  current_resource_id = None
  current_resource_name = None
  keep_parsing = True
  need_value = False
  while keep_parsing:
    line = p.stdout.readline()
    if not line:
      break
    # Do not use rstrip(), since this should only remove trailing newlines
    # but not trailing whitespace that happen to be embedded in the string
    # value for some reason.
    line = line.rstrip('\n\r')
    m = _RE_BUNDLE_STRING_RESOURCE_HEADER.match(line)
    if m:
      current_resource_id = int(m.group(1), 16)
      current_resource_name = m.group(2)
      need_value = True
      continue

    if not need_value:
      continue

    resource_config = None
    m = _RE_BUNDLE_STRING_DEFAULT_VALUE.match(line)
    if m:
      resource_config = 'config (default)'
      resource_value = m.group(1)
    else:
      m = _RE_BUNDLE_STRING_LOCALIZED_VALUE.match(line)
      if m:
        resource_config = 'config %s' % m.group(1)
        resource_value = m.group(2)

    if resource_config is None:
      need_value = False
      continue

    res_map.AddValue(current_resource_id, current_resource_name,
                     resource_config, UnquoteString(resource_value))
  return res_map


# Name of the binary resources table file inside an APK.
RESOURCES_FILENAME = 'resources.arsc'


def IsFilePathAnApk(input_file):
  """Returns True iff a ZipFile instance is for a regular APK."""
  try:
    with zipfile.ZipFile(input_file) as input_zip:
      _ = input_zip.getinfo(RESOURCES_FILENAME)
      return True
  except:
    return False


# pylint: disable=line-too-long

# Example output from 'aapt dump resources --values' corresponding
# to strings:
#
#      config zh-rHK
#        resource 0x7f12009c org.chromium.chrome:string/0_resource_name_obfuscated: t=0x03 d=0x0000caa9 (s=0x0008 r=0x00)
#          (string8) "瀏覽首頁"
#        resource 0x7f12009d org.chromium.chrome:string/0_resource_name_obfuscated: t=0x03 d=0x0000c8e0 (s=0x0008 r=0x00)
#          (string8) "向上瀏覽"
#

# The following are compiled regular expressions used to recognize each
# of line and extract relevant information.
#
_RE_AAPT_CONFIG = re.compile(r'^\s+config (.+):$')
assert _RE_AAPT_CONFIG.match('   config (default):')
assert _RE_AAPT_CONFIG.match('   config zh-rTW:')

# Match an ISO 639-1 or ISO 639-2 locale.
_RE_AAPT_ISO_639_LOCALE = re.compile(r'^[a-z]{2,3}(-r[A-Z]{2,3})?$')
assert _RE_AAPT_ISO_639_LOCALE.match('de')
assert _RE_AAPT_ISO_639_LOCALE.match('zh-rTW')
assert _RE_AAPT_ISO_639_LOCALE.match('fil')
assert not _RE_AAPT_ISO_639_LOCALE.match('land')

_RE_AAPT_BCP47_LOCALE = re.compile(r'^b\+[a-z][a-zA-Z0-9\+]+$')
assert _RE_AAPT_BCP47_LOCALE.match('b+sr')
assert _RE_AAPT_BCP47_LOCALE.match('b+sr+Latn')
assert _RE_AAPT_BCP47_LOCALE.match('b+en+US')
assert not _RE_AAPT_BCP47_LOCALE.match('b+')
assert not _RE_AAPT_BCP47_LOCALE.match('b+1234')

_RE_AAPT_STRING_RESOURCE_HEADER = re.compile(
    r'^\s+resource 0x([0-9a-f]+) [a-zA-Z][a-zA-Z0-9.]+:string/(\w+):.*$')
assert _RE_AAPT_STRING_RESOURCE_HEADER.match(
    r'  resource 0x7f12009c org.chromium.chrome:string/0_resource_name_obfuscated: t=0x03 d=0x0000caa9 (s=0x0008 r=0x00)'
)

_RE_AAPT_STRING_RESOURCE_VALUE = re.compile(r'^\s+\(string8\) "(.*)"$')
assert _RE_AAPT_STRING_RESOURCE_VALUE.match(r'       (string8) "瀏覽首頁"')

# pylint: enable=line-too-long


def _ConvertAaptLocaleToBcp47(locale):
  """Convert a locale name from 'aapt dump' to its BCP-47 form."""
  if locale.startswith('b+'):
    return '-'.join(locale[2:].split('+'))
  lang, _, region = locale.partition('-r')
  if region:
    return '%s-%s' % (lang, region)
  return lang


assert _ConvertAaptLocaleToBcp47('(default)') == '(default)'
assert _ConvertAaptLocaleToBcp47('en') == 'en'
assert _ConvertAaptLocaleToBcp47('en-rUS') == 'en-US'
assert _ConvertAaptLocaleToBcp47('en-US') == 'en-US'
assert _ConvertAaptLocaleToBcp47('fil') == 'fil'
assert _ConvertAaptLocaleToBcp47('b+sr+Latn') == 'sr-Latn'


def ParseApkResources(aapt_path, apk_path):
  """Use aapt to extract the localized strings of a given bundle.

  Args:
    bundle_tool_jar_path: Path to bundletool .jar executable.
    bundle_path: Path to input bundle.
  Returns:
    A new ResourceStringMap instance populated with the bundle's content.
  """
  cmd_args = [aapt_path, 'dump', '--values', 'resources', apk_path]
  p = subprocess.Popen(cmd_args, bufsize=1, stdout=subprocess.PIPE)

  res_map = ResourceStringMap()
  current_locale = None
  current_resource_id = -1  # represents undefined.
  current_resource_name = None
  need_value = False
  while True:
    try:
      line = p.stdout.readline().rstrip().decode('utf8')
    except UnicodeDecodeError:
      continue

    if not line:
      break
    m = _RE_AAPT_CONFIG.match(line)
    if m:
      locale = None
      aapt_locale = m.group(1)
      if aapt_locale == '(default)':
        locale = aapt_locale
      elif _RE_AAPT_ISO_639_LOCALE.match(aapt_locale):
        locale = aapt_locale
      elif _RE_AAPT_BCP47_LOCALE.match(aapt_locale):
        locale = aapt_locale
      if locale is not None:
        current_locale = _ConvertAaptLocaleToBcp47(locale)
      continue

    if current_locale is None:
      continue

    if need_value:
      m = _RE_AAPT_STRING_RESOURCE_VALUE.match(line)
      if not m:
        # Should not happen
        sys.stderr.write('WARNING: Missing value for string ID 0x%08x "%s"' %
                         (current_resource_id, current_resource_name))
        resource_value = '<MISSING_STRING_%08x>' % current_resource_id
      else:
        resource_value = UnquoteString(m.group(1))

      res_map.AddValue(current_resource_id, current_resource_name,
                       'config %s' % current_locale, resource_value)
      need_value = False
    else:
      m = _RE_AAPT_STRING_RESOURCE_HEADER.match(line)
      if m:
        current_resource_id = int(m.group(1), 16)
        current_resource_name = m.group(2)
        need_value = True

  return res_map


def main(args):
  parser = argparse.ArgumentParser(
      description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
  parser.add_argument(
      'input_file',
      help='Input file path. This can be either an APK, or an app bundle.')
  parser.add_argument('--output', help='Optional output file path.')
  parser.add_argument(
      '--omit-ids',
      action='store_true',
      help='Omit resource IDs in the output. This is useful '
      'to compare the contents of two distinct builds of the '
      'same APK.')
  parser.add_argument(
      '--aapt-path',
      default=_AAPT_DEFAULT_PATH,
      help='Path to aapt executable. Optional for APKs.')
  parser.add_argument(
      '--r-txt-path',
      help='Path to an optional input R.txt file used to translate resource '
      'IDs to string names. Useful when resources names in the input files '
      'were obfuscated. NOTE: If ${INPUT_FILE}.R.txt exists, if will be used '
      'automatically by this script.')
  parser.add_argument(
      '--bundletool-path',
      default=_DEFAULT_BUNDLETOOL_PATH,
      help='Path to alternate bundletool .jar file. Only used for bundles.')
  parser.add_argument(
      '--profile', action='store_true', help='Enable Python profiling.')

  options = parser.parse_args(args)

  # Create a {res_id -> res_name} map for unobfuscation, if needed.
  res_id_name_map = {}
  r_txt_path = options.r_txt_path
  if not r_txt_path:
    candidate_r_txt_path = options.input_file + '.R.txt'
    if os.path.exists(candidate_r_txt_path):
      r_txt_path = candidate_r_txt_path

  if r_txt_path:
    res_id_name_map = ReadStringMapFromRTxt(r_txt_path)

  # Create a helper lambda that creates a new ResourceStringMap instance
  # based on the input file's type.
  if IsFilePathABundle(options.input_file):
    if not options.bundletool_path:
      parser.error(
          '--bundletool-path <BUNDLETOOL_JAR> is required to parse bundles.')

    # use bundletool to parse the bundle resources.
    def create_string_map():
      return ParseBundleResources(options.bundletool_path, options.input_file)

  elif IsFilePathAnApk(options.input_file):
    if not options.aapt_path:
      parser.error('--aapt-path <AAPT> is required to parse APKs.')

    # Use aapt dump to parse the APK resources.
    def create_string_map():
      return ParseApkResources(options.aapt_path, options.input_file)

  else:
    parser.error('Unknown file format: %s' % options.input_file)

  # Print everything now.
  with ManagedOutput(options.output) as output:
    with ManagedPythonProfiling(options.profile):
      res_map = create_string_map()
      res_map.RemapResourceNames(res_id_name_map)
      lines = AutoIndentStringList(res_map.ToStringList(options.omit_ids))
      for line in lines:
        output.write(line)
        output.write('\n')


if __name__ == "__main__":
  main(sys.argv[1:])
