# Copyright 2015 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.

import os
import shutil
import stat
import sys
import zipfile

from dependency_manager import exceptions


def _WinReadOnlyHandler(func, path, execinfo):
  if not os.access(path, os.W_OK):
    os.chmod(path, stat.S_IWRITE)
    func(path)
  else:
    raise execinfo[0], execinfo[1], execinfo[2]


def RemoveDir(dir_path):
  if os.path.isdir(dir_path):
    shutil.rmtree(dir_path, onerror=_WinReadOnlyHandler)


def VerifySafeArchive(archive):
  def ResolvePath(path_name):
    return os.path.realpath(os.path.abspath(path_name))
  # Must add pathsep to avoid false positives.
  # Ex: /tmp/abc/bad_file.py starts with /tmp/a but not /tmp/a/
  base_path = ResolvePath(os.getcwd()) + os.path.sep
  for member in archive.namelist():
    if not ResolvePath(os.path.join(base_path, member)).startswith(base_path):
      raise exceptions.ArchiveError(
          'Archive %s contains a bad member: %s.' % (archive.filename, member))


def GetModeFromPath(file_path):
  return stat.S_IMODE(os.stat(file_path).st_mode)


def GetModeFromZipInfo(zip_info):
  return zip_info.external_attr >> 16


def SetUnzippedDirPermissions(archive, unzipped_dir):
  """Set the file permissions in an unzipped archive.

     Designed to be called right after extractall() was called on |archive|.
     Noop on Win. Otherwise sets the executable bit on files where needed.

     Args:
         archive: A zipfile.ZipFile object opened for reading.
         unzipped_dir: A path to a directory containing the unzipped contents
             of |archive|.
  """
  if sys.platform.startswith('win'):
    # Windows doesn't have an executable bit, so don't mess with the ACLs.
    return
  for zip_info in archive.infolist():
    archive_acls = GetModeFromZipInfo(zip_info)
    if archive_acls & stat.S_IXUSR:
      # Only preserve owner execurable permissions.
      unzipped_path = os.path.abspath(
          os.path.join(unzipped_dir, zip_info.filename))
      mode = GetModeFromPath(unzipped_path)
      os.chmod(unzipped_path, mode | stat.S_IXUSR)


def UnzipArchive(archive_path, unzip_path):
  """Unzips a file if it is a zip file.

  Args:
      archive_path: The downloaded file to unzip.
      unzip_path: The destination directory to unzip to.

  Raises:
      ValueError: If |archive_path| is not a zipfile.
  """
  # TODO(aiolos): Add tests once the refactor is completed. crbug.com/551158
  if not (archive_path and zipfile.is_zipfile(archive_path)):
    raise ValueError(
        'Attempting to unzip a non-archive file at %s' % archive_path)
  if not os.path.exists(unzip_path):
    os.makedirs(unzip_path)
  try:
    with zipfile.ZipFile(archive_path, 'r') as archive:
      VerifySafeArchive(archive)
      archive.extractall(path=unzip_path)
      SetUnzippedDirPermissions(archive, unzip_path)
  except:
    if unzip_path and os.path.isdir(unzip_path):
      RemoveDir(unzip_path)
    raise
