#!/usr/bin/env python
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""A tool for interacting with .pak files.

For details on the pak file format, see:
https://dev.chromium.org/developers/design-documents/linuxresourcesandlocalizedstrings
"""

import argparse
import hashlib
import os
import sys

from grit.format import data_pack


def _RepackMain(args):
  data_pack.RePack(args.output_pak_file, args.input_pak_files, args.whitelist,
                   args.suppress_removed_key_output)


def _ExtractMain(args):
  pak = data_pack.ReadDataPack(args.pak_file)

  for resource_id, payload in pak.resources.iteritems():
    path = os.path.join(args.output_dir, str(resource_id))
    with open(path, 'w') as f:
      f.write(payload)


def _PrintMain(args):
  pak = data_pack.ReadDataPack(args.pak_file)
  encoding = 'binary'
  if pak.encoding == 1:
    encoding = 'utf-8'
  elif pak.encoding == 2:
    encoding = 'utf-16'
  else:
    encoding = '?' + str(pak.encoding)
  print 'Encoding:', encoding

  try_decode = encoding.startswith('utf')
  # Print IDs in ascending order, since that's the order in which they appear in
  # the file (order is lost by Python dict).
  for resource_id in sorted(pak.resources):
    data = pak.resources[resource_id]
    desc = '<binary>'
    if try_decode:
      try:
        desc = unicode(data, encoding)
        if len(desc) > 60:
          desc = desc[:60] + u'...'
        desc = desc.replace('\n', '\\n')
      except UnicodeDecodeError:
        pass
    sha1 = hashlib.sha1(data).hexdigest()[:10]
    line = u'Entry(id={}, len={}, sha1={}): {}'.format(
        resource_id, len(data), sha1, desc)
    print line.encode('utf-8')


def _ListMain(args):
  resources, _ = data_pack.ReadDataPack(args.pak_file)
  for resource_id in sorted(resources.keys()):
    args.output.write('%d\n' % resource_id)


def main():
  parser = argparse.ArgumentParser(
      description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
  sub_parsers = parser.add_subparsers()

  sub_parser = sub_parsers.add_parser('repack',
      help='Combines several .pak files into one.')
  sub_parser.add_argument('output_pak_file', help='File to create.')
  sub_parser.add_argument('input_pak_files', nargs='+',
      help='Input .pak files.')
  sub_parser.add_argument('--whitelist',
      help='Path to a whitelist used to filter output pak file resource IDs.')
  sub_parser.add_argument('--suppress-removed-key-output', action='store_true',
      help='Do not log which keys were removed by the whitelist.')
  sub_parser.set_defaults(func=_RepackMain)

  sub_parser = sub_parsers.add_parser('extract', help='Extracts pak file')
  sub_parser.add_argument('pak_file')
  sub_parser.add_argument('-o', '--output-dir', default='.',
                          help='Directory to extract to.')
  sub_parser.set_defaults(func=_ExtractMain)

  sub_parser = sub_parsers.add_parser('print',
      help='Prints all pak IDs and contents. Useful for diffing.')
  sub_parser.add_argument('pak_file')
  sub_parser.set_defaults(func=_PrintMain)
  
  sub_parser = sub_parsers.add_parser('list-id',
      help='Outputs all resource IDs to a file.')
  sub_parser.add_argument('pak_file')
  sub_parser.add_argument('--output', type=argparse.FileType('w'),
      default=sys.stdout,
      help='The resource list path to write (default stdout)')
  sub_parser.set_defaults(func=_ListMain)

  if len(sys.argv) == 1:
    parser.print_help()
    sys.exit(1)
  elif len(sys.argv) == 2 and sys.argv[1] in actions:
    parser.parse_args(sys.argv[1:] + ['-h'])
    sys.exit(1)

  args = parser.parse_args()
  args.func(args)


if __name__ == '__main__':
  main()

#!/usr/bin/env python
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""A tool for interacting with .pak files.

For details on the pak file format, see:
https://dev.chromium.org/developers/design-documents/linuxresourcesandlocalizedstrings
"""

import argparse
import hashlib
import os
import sys

from grit.format import data_pack


def _RepackMain(args):
  data_pack.RePack(args.output_pak_file, args.input_pak_files, args.whitelist,
                   args.suppress_removed_key_output)


def _ExtractMain(args):
  pak = data_pack.ReadDataPack(args.pak_file)

  for resource_id, payload in pak.resources.iteritems():
    path = os.path.join(args.output_dir, str(resource_id))
    with open(path, 'w') as f:
      f.write(payload)


def _PrintMain(args):
  pak = data_pack.ReadDataPack(args.pak_file)
  encoding = 'binary'
  if pak.encoding == 1:
    encoding = 'utf-8'
  elif pak.encoding == 2:
    encoding = 'utf-16'
  else:
    encoding = '?' + str(pak.encoding)
  print 'Encoding:', encoding

  try_decode = encoding.startswith('utf')
  # Print IDs in ascending order, since that's the order in which they appear in
  # the file (order is lost by Python dict).
  for resource_id in sorted(pak.resources):
    data = pak.resources[resource_id]
    desc = '<binary>'
    if try_decode:
      try:
        desc = unicode(data, encoding)
        if len(desc) > 60:
          desc = desc[:60] + u'...'
        desc = desc.replace('\n', '\\n')
      except UnicodeDecodeError:
        pass
    sha1 = hashlib.sha1(data).hexdigest()[:10]
    line = u'Entry(id={}, len={}, sha1={}): {}'.format(
        resource_id, len(data), sha1, desc)
    print line.encode('utf-8')


def _ListMain(args):
  resources, _ = data_pack.ReadDataPack(args.pak_file)
  for resource_id in sorted(resources.keys()):
    args.output.write('%d\n' % resource_id)


def main():
  parser = argparse.ArgumentParser(
      description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
  sub_parsers = parser.add_subparsers()

  sub_parser = sub_parsers.add_parser('repack',
      help='Combines several .pak files into one.')
  sub_parser.add_argument('output_pak_file', help='File to create.')
  sub_parser.add_argument('input_pak_files', nargs='+',
      help='Input .pak files.')
  sub_parser.add_argument('--whitelist',
      help='Path to a whitelist used to filter output pak file resource IDs.')
  sub_parser.add_argument('--suppress-removed-key-output', action='store_true',
      help='Do not log which keys were removed by the whitelist.')
  sub_parser.set_defaults(func=_RepackMain)

  sub_parser = sub_parsers.add_parser('extract', help='Extracts pak file')
  sub_parser.add_argument('pak_file')
  sub_parser.add_argument('-o', '--output-dir', default='.',
                          help='Directory to extract to.')
  sub_parser.set_defaults(func=_ExtractMain)

  sub_parser = sub_parsers.add_parser('print',
      help='Prints all pak IDs and contents. Useful for diffing.')
  sub_parser.add_argument('pak_file')
  sub_parser.set_defaults(func=_PrintMain)
  
  sub_parser = sub_parsers.add_parser('list-id',
      help='Outputs all resource IDs to a file.')
  sub_parser.add_argument('pak_file')
  sub_parser.add_argument('--output', type=argparse.FileType('w'),
      default=sys.stdout,
      help='The resource list path to write (default stdout)')
  sub_parser.set_defaults(func=_ListMain)

  if len(sys.argv) == 1:
    parser.print_help()
    sys.exit(1)
  elif len(sys.argv) == 2 and sys.argv[1] in actions:
    parser.parse_args(sys.argv[1:] + ['-h'])
    sys.exit(1)

  args = parser.parse_args()
  args.func(args)


if __name__ == '__main__':
  main()

#!/usr/bin/env python # Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. A tool for interacting with .pak files.  For details on the pak file format, see: https://dev.chromium.org/developers/design-documents/linuxresourcesandlocalizedstrings # Print IDs in ascending order, since that's the order in which they appear in # the file (order is lost by Python dict).