mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			283 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			283 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // 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 "include/cef_stream.h"
 | |
| 
 | |
| // Static functions
 | |
| 
 | |
| // static
 | |
| CefRefPtr<CefZipReader> CefZipReader::Create(
 | |
|     CefRefPtr<CefStreamReader> stream) {
 | |
|   CefRefPtr<CefZipReaderImpl> impl(new CefZipReaderImpl());
 | |
|   if (!impl->Initialize(stream))
 | |
|     return NULL;
 | |
|   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_(NULL),
 | |
|       has_fileopen_(false),
 | |
|       has_fileinfo_(false),
 | |
|       filesize_(0),
 | |
|       filemodified_(0) {}
 | |
| 
 | |
| CefZipReaderImpl::~CefZipReaderImpl() {
 | |
|   if (reader_ != NULL) {
 | |
|     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 = NULL;
 | |
|   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_ != NULL);
 | |
| }
 | |
| 
 | |
| 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_ = NULL;
 | |
|   return (result == UNZ_OK);
 | |
| }
 | |
| 
 | |
| CefString CefZipReaderImpl::GetFileName() {
 | |
|   if (!VerifyContext() || !GetFileInfo())
 | |
|     return CefString();
 | |
| 
 | |
|   return filename_;
 | |
| }
 | |
| 
 | |
| int64 CefZipReaderImpl::GetFileSize() {
 | |
|   if (!VerifyContext() || !GetFileInfo())
 | |
|     return -1;
 | |
| 
 | |
|   return filesize_;
 | |
| }
 | |
| 
 | |
| CefTime CefZipReaderImpl::GetFileLastModified() {
 | |
|   CefTime time;
 | |
|   if (!VerifyContext() || !GetFileInfo())
 | |
|     return time;
 | |
| 
 | |
|   cef_time_from_timet(filemodified_, &time);
 | |
|   return time;
 | |
| }
 | |
| 
 | |
| 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_ != NULL);
 | |
| }
 |