Clone of chromium aad1ce808763f59c7a3753e08f1500a104ecc6fd refs/remotes/origin/HEAD
diff --git a/third_party/zlib/google/zip.cc b/third_party/zlib/google/zip.cc
new file mode 100644
index 0000000..726df33
--- /dev/null
+++ b/third_party/zlib/google/zip.cc
@@ -0,0 +1,204 @@
+// Copyright (c) 2012 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.
+
+#include "third_party/zlib/google/zip.h"
+
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/files/file.h"
+#include "base/files/file_enumerator.h"
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "third_party/zlib/google/zip_internal.h"
+#include "third_party/zlib/google/zip_reader.h"
+
+#if defined(USE_SYSTEM_MINIZIP)
+#include <minizip/unzip.h>
+#include <minizip/zip.h>
+#else
+#include "third_party/zlib/contrib/minizip/unzip.h"
+#include "third_party/zlib/contrib/minizip/zip.h"
+#endif
+
+namespace {
+
+bool AddFileToZip(zipFile zip_file, const base::FilePath& src_dir) {
+  base::File file(src_dir, base::File::FLAG_OPEN | base::File::FLAG_READ);
+  if (!file.IsValid()) {
+    DLOG(ERROR) << "Could not open file for path " << src_dir.value();
+    return false;
+  }
+
+  int num_bytes;
+  char buf[zip::internal::kZipBufSize];
+  do {
+    num_bytes = file.ReadAtCurrentPos(buf, zip::internal::kZipBufSize);
+    if (num_bytes > 0) {
+      if (ZIP_OK != zipWriteInFileInZip(zip_file, buf, num_bytes)) {
+        DLOG(ERROR) << "Could not write data to zip for path "
+                    << src_dir.value();
+        return false;
+      }
+    }
+  } while (num_bytes > 0);
+
+  return true;
+}
+
+bool AddEntryToZip(zipFile zip_file, const base::FilePath& path,
+                   const base::FilePath& root_path) {
+  base::FilePath relative_path;
+  bool result = root_path.AppendRelativePath(path, &relative_path);
+  DCHECK(result);
+  std::string str_path = relative_path.AsUTF8Unsafe();
+#if defined(OS_WIN)
+  ReplaceSubstringsAfterOffset(&str_path, 0u, "\\", "/");
+#endif
+
+  bool is_directory = base::DirectoryExists(path);
+  if (is_directory)
+    str_path += "/";
+
+  zip_fileinfo file_info = zip::internal::GetFileInfoForZipping(path);
+  if (!zip::internal::ZipOpenNewFileInZip(zip_file, str_path, &file_info))
+    return false;
+
+  bool success = true;
+  if (!is_directory) {
+    success = AddFileToZip(zip_file, path);
+  }
+
+  if (ZIP_OK != zipCloseFileInZip(zip_file)) {
+    DLOG(ERROR) << "Could not close zip file entry " << str_path;
+    return false;
+  }
+
+  return success;
+}
+
+bool ExcludeNoFilesFilter(const base::FilePath& file_path) {
+  return true;
+}
+
+bool ExcludeHiddenFilesFilter(const base::FilePath& file_path) {
+  return file_path.BaseName().value()[0] != '.';
+}
+
+}  // namespace
+
+namespace zip {
+
+bool Unzip(const base::FilePath& src_file, const base::FilePath& dest_dir) {
+  ZipReader reader;
+  if (!reader.Open(src_file)) {
+    DLOG(WARNING) << "Failed to open " << src_file.value();
+    return false;
+  }
+  while (reader.HasMore()) {
+    if (!reader.OpenCurrentEntryInZip()) {
+      DLOG(WARNING) << "Failed to open the current file in zip";
+      return false;
+    }
+    if (reader.current_entry_info()->is_unsafe()) {
+      DLOG(WARNING) << "Found an unsafe file in zip "
+                    << reader.current_entry_info()->file_path().value();
+      return false;
+    }
+    if (!reader.ExtractCurrentEntryIntoDirectory(dest_dir)) {
+      DLOG(WARNING) << "Failed to extract "
+                    << reader.current_entry_info()->file_path().value();
+      return false;
+    }
+    if (!reader.AdvanceToNextEntry()) {
+      DLOG(WARNING) << "Failed to advance to the next file";
+      return false;
+    }
+  }
+  return true;
+}
+
+bool ZipWithFilterCallback(const base::FilePath& src_dir,
+                           const base::FilePath& dest_file,
+                           const FilterCallback& filter_cb) {
+  DCHECK(base::DirectoryExists(src_dir));
+
+  zipFile zip_file = internal::OpenForZipping(dest_file.AsUTF8Unsafe(),
+                                              APPEND_STATUS_CREATE);
+
+  if (!zip_file) {
+    DLOG(WARNING) << "couldn't create file " << dest_file.value();
+    return false;
+  }
+
+  bool success = true;
+  base::FileEnumerator file_enumerator(src_dir, true /* recursive */,
+      base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
+  for (base::FilePath path = file_enumerator.Next(); !path.value().empty();
+       path = file_enumerator.Next()) {
+    if (!filter_cb.Run(path)) {
+      continue;
+    }
+
+    if (!AddEntryToZip(zip_file, path, src_dir)) {
+      success = false;
+      break;
+    }
+  }
+
+  if (ZIP_OK != zipClose(zip_file, NULL)) {
+    DLOG(ERROR) << "Error closing zip file " << dest_file.value();
+    return false;
+  }
+
+  return success;
+}
+
+bool Zip(const base::FilePath& src_dir, const base::FilePath& dest_file,
+         bool include_hidden_files) {
+  if (include_hidden_files) {
+    return ZipWithFilterCallback(
+        src_dir, dest_file, base::Bind(&ExcludeNoFilesFilter));
+  } else {
+    return ZipWithFilterCallback(
+        src_dir, dest_file, base::Bind(&ExcludeHiddenFilesFilter));
+  }
+}
+
+#if defined(OS_POSIX)
+bool ZipFiles(const base::FilePath& src_dir,
+              const std::vector<base::FilePath>& src_relative_paths,
+              int dest_fd) {
+  DCHECK(base::DirectoryExists(src_dir));
+  zipFile zip_file = internal::OpenFdForZipping(dest_fd, APPEND_STATUS_CREATE);
+
+  if (!zip_file) {
+    DLOG(ERROR) << "couldn't create file for fd " << dest_fd;
+    return false;
+  }
+
+  bool success = true;
+  for (std::vector<base::FilePath>::const_iterator iter =
+           src_relative_paths.begin();
+      iter != src_relative_paths.end(); ++iter) {
+    const base::FilePath& path = src_dir.Append(*iter);
+    if (!AddEntryToZip(zip_file, path, src_dir)) {
+      // TODO(hshi): clean up the partial zip file when error occurs.
+      success = false;
+      break;
+    }
+  }
+
+  if (ZIP_OK != zipClose(zip_file, NULL)) {
+    DLOG(ERROR) << "Error closing zip file for fd " << dest_fd;
+    success = false;
+  }
+
+  return success;
+}
+#endif  // defined(OS_POSIX)
+
+}  // namespace zip