summaryrefslogtreecommitdiff
path: root/libcef/browser/zip_reader_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libcef/browser/zip_reader_impl.cc')
-rw-r--r--libcef/browser/zip_reader_impl.cc303
1 files changed, 303 insertions, 0 deletions
diff --git a/libcef/browser/zip_reader_impl.cc b/libcef/browser/zip_reader_impl.cc
new file mode 100644
index 00000000..74643c6c
--- /dev/null
+++ b/libcef/browser/zip_reader_impl.cc
@@ -0,0 +1,303 @@
+// Copyright (c) 2012 The Chromium Embedded Framework 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 "libcef/browser/zip_reader_impl.h"
+#include <time.h>
+#include "base/logging.h"
+#include "base/notreached.h"
+#include "base/time/time.h"
+#include "include/cef_stream.h"
+
+// Static functions
+
+// static
+CefRefPtr<CefZipReader> CefZipReader::Create(
+ CefRefPtr<CefStreamReader> stream) {
+ CefRefPtr<CefZipReaderImpl> impl(new CefZipReaderImpl());
+ if (!impl->Initialize(stream)) {
+ return nullptr;
+ }
+ return impl.get();
+}
+
+// CefZipReaderImpl
+
+namespace {
+
+voidpf ZCALLBACK zlib_open_callback OF((voidpf opaque,
+ const void* filename,
+ int mode)) {
+ // The stream is already implicitly open so just return the pointer.
+ return opaque;
+}
+
+uLong ZCALLBACK zlib_read_callback
+OF((voidpf opaque, voidpf stream, void* buf, uLong size)) {
+ CefRefPtr<CefStreamReader> reader(static_cast<CefStreamReader*>(opaque));
+ return reader->Read(buf, 1, size);
+}
+
+ZPOS64_T ZCALLBACK zlib_tell_callback OF((voidpf opaque, voidpf stream)) {
+ CefRefPtr<CefStreamReader> reader(static_cast<CefStreamReader*>(opaque));
+ return reader->Tell();
+}
+
+long ZCALLBACK zlib_seek_callback
+OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)) {
+ CefRefPtr<CefStreamReader> reader(static_cast<CefStreamReader*>(opaque));
+ int whence;
+ switch (origin) {
+ case ZLIB_FILEFUNC_SEEK_CUR:
+ whence = SEEK_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END:
+ whence = SEEK_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET:
+ whence = SEEK_SET;
+ break;
+ default:
+ NOTREACHED();
+ return -1;
+ }
+ return reader->Seek(offset, whence);
+}
+
+int ZCALLBACK zlib_close_callback OF((voidpf opaque, voidpf stream)) {
+ CefRefPtr<CefStreamReader> reader(static_cast<CefStreamReader*>(opaque));
+ // Release the reference added by CefZipReaderImpl::Initialize().
+ reader->Release();
+ return 0;
+}
+
+int ZCALLBACK zlib_error_callback OF((voidpf opaque, voidpf stream)) {
+ return 0;
+}
+
+} // namespace
+
+CefZipReaderImpl::CefZipReaderImpl()
+ : supported_thread_id_(base::PlatformThread::CurrentId()),
+ reader_(nullptr),
+ has_fileopen_(false),
+ has_fileinfo_(false),
+ filesize_(0),
+ filemodified_(0) {}
+
+CefZipReaderImpl::~CefZipReaderImpl() {
+ if (reader_ != nullptr) {
+ if (!VerifyContext()) {
+ // Close() is supposed to be called directly. We'll try to free the reader
+ // now on the wrong thread but there's no guarantee this call won't crash.
+ if (has_fileopen_) {
+ unzCloseCurrentFile(reader_);
+ }
+ unzClose(reader_);
+ } else {
+ Close();
+ }
+ }
+}
+
+bool CefZipReaderImpl::Initialize(CefRefPtr<CefStreamReader> stream) {
+ zlib_filefunc64_def filefunc_def;
+ filefunc_def.zopen64_file = zlib_open_callback;
+ filefunc_def.zread_file = zlib_read_callback;
+ filefunc_def.zwrite_file = nullptr;
+ filefunc_def.ztell64_file = zlib_tell_callback;
+ filefunc_def.zseek64_file = zlib_seek_callback;
+ filefunc_def.zclose_file = zlib_close_callback;
+ filefunc_def.zerror_file = zlib_error_callback;
+ filefunc_def.opaque = stream.get();
+
+ // Add a reference that will be released by zlib_close_callback().
+ stream->AddRef();
+
+ reader_ = unzOpen2_64("", &filefunc_def);
+ return (reader_ != nullptr);
+}
+
+bool CefZipReaderImpl::MoveToFirstFile() {
+ if (!VerifyContext()) {
+ return false;
+ }
+
+ if (has_fileopen_) {
+ CloseFile();
+ }
+
+ has_fileinfo_ = false;
+
+ return (unzGoToFirstFile(reader_) == UNZ_OK);
+}
+
+bool CefZipReaderImpl::MoveToNextFile() {
+ if (!VerifyContext()) {
+ return false;
+ }
+
+ if (has_fileopen_) {
+ CloseFile();
+ }
+
+ has_fileinfo_ = false;
+
+ return (unzGoToNextFile(reader_) == UNZ_OK);
+}
+
+bool CefZipReaderImpl::MoveToFile(const CefString& fileName,
+ bool caseSensitive) {
+ if (!VerifyContext()) {
+ return false;
+ }
+
+ if (has_fileopen_) {
+ CloseFile();
+ }
+
+ has_fileinfo_ = false;
+
+ std::string fileNameStr = fileName;
+ return (unzLocateFile(reader_, fileNameStr.c_str(),
+ (caseSensitive ? 1 : 2)) == UNZ_OK);
+}
+
+bool CefZipReaderImpl::Close() {
+ if (!VerifyContext()) {
+ return false;
+ }
+
+ if (has_fileopen_) {
+ CloseFile();
+ }
+
+ int result = unzClose(reader_);
+ reader_ = nullptr;
+ return (result == UNZ_OK);
+}
+
+CefString CefZipReaderImpl::GetFileName() {
+ if (!VerifyContext() || !GetFileInfo()) {
+ return CefString();
+ }
+
+ return filename_;
+}
+
+int64 CefZipReaderImpl::GetFileSize() {
+ if (!VerifyContext() || !GetFileInfo()) {
+ return -1;
+ }
+
+ return filesize_;
+}
+
+CefBaseTime CefZipReaderImpl::GetFileLastModified() {
+ if (!VerifyContext() || !GetFileInfo()) {
+ return CefBaseTime();
+ }
+
+ return base::Time::FromTimeT(filemodified_);
+}
+
+bool CefZipReaderImpl::OpenFile(const CefString& password) {
+ if (!VerifyContext()) {
+ return false;
+ }
+
+ if (has_fileopen_) {
+ CloseFile();
+ }
+
+ bool ret;
+
+ if (password.empty()) {
+ ret = (unzOpenCurrentFile(reader_) == UNZ_OK);
+ } else {
+ std::string passwordStr = password;
+ ret = (unzOpenCurrentFilePassword(reader_, passwordStr.c_str()) == UNZ_OK);
+ }
+
+ if (ret) {
+ has_fileopen_ = true;
+ }
+ return ret;
+}
+
+bool CefZipReaderImpl::CloseFile() {
+ if (!VerifyContext() || !has_fileopen_) {
+ return false;
+ }
+
+ has_fileopen_ = false;
+ has_fileinfo_ = false;
+
+ return (unzCloseCurrentFile(reader_) == UNZ_OK);
+}
+
+int CefZipReaderImpl::ReadFile(void* buffer, size_t bufferSize) {
+ if (!VerifyContext() || !has_fileopen_) {
+ return -1;
+ }
+
+ return unzReadCurrentFile(reader_, buffer, bufferSize);
+}
+
+int64 CefZipReaderImpl::Tell() {
+ if (!VerifyContext() || !has_fileopen_) {
+ return -1;
+ }
+
+ return unztell64(reader_);
+}
+
+bool CefZipReaderImpl::Eof() {
+ if (!VerifyContext() || !has_fileopen_) {
+ return true;
+ }
+
+ return (unzeof(reader_) == 1 ? true : false);
+}
+
+bool CefZipReaderImpl::GetFileInfo() {
+ if (has_fileinfo_) {
+ return true;
+ }
+
+ char file_name[512] = {0};
+ unz_file_info file_info;
+ memset(&file_info, 0, sizeof(file_info));
+
+ if (unzGetCurrentFileInfo(reader_, &file_info, file_name, sizeof(file_name),
+ NULL, 0, NULL, 0) != UNZ_OK) {
+ return false;
+ }
+
+ has_fileinfo_ = true;
+ filename_ = std::string(file_name);
+ filesize_ = file_info.uncompressed_size;
+
+ struct tm time;
+ memset(&time, 0, sizeof(time));
+ time.tm_sec = file_info.tmu_date.tm_sec;
+ time.tm_min = file_info.tmu_date.tm_min;
+ time.tm_hour = file_info.tmu_date.tm_hour;
+ time.tm_mday = file_info.tmu_date.tm_mday;
+ time.tm_mon = file_info.tmu_date.tm_mon;
+ time.tm_year = file_info.tmu_date.tm_year - 1900; // Years since 1900.
+ filemodified_ = mktime(&time);
+ DCHECK_NE(filemodified_, (time_t)-1);
+
+ return true;
+}
+
+bool CefZipReaderImpl::VerifyContext() {
+ if (base::PlatformThread::CurrentId() != supported_thread_id_) {
+ // This object should only be accessed from the thread that created it.
+ NOTREACHED();
+ return false;
+ }
+
+ return (reader_ != nullptr);
+}