• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4 
5 #include "include/wrapper/cef_zip_archive.h"
6 
7 #include <algorithm>
8 
9 #include "include/base/cef_logging.h"
10 #include "include/base/cef_macros.h"
11 #include "include/base/cef_scoped_ptr.h"
12 #include "include/cef_stream.h"
13 #include "include/cef_zip_reader.h"
14 #include "include/wrapper/cef_byte_read_handler.h"
15 
16 #if defined(OS_LINUX)
17 #include <wctype.h>
18 #endif
19 
20 namespace {
21 
22 // Convert |str| to lowercase in a Unicode-friendly manner.
ToLower(const CefString & str)23 CefString ToLower(const CefString& str) {
24   std::wstring wstr = str;
25   std::transform(wstr.begin(), wstr.end(), wstr.begin(), towlower);
26   return wstr;
27 }
28 
29 class CefZipFile : public CefZipArchive::File {
30  public:
CefZipFile()31   CefZipFile() : data_size_(0) {}
32 
Initialize(size_t data_size)33   bool Initialize(size_t data_size) {
34     data_.reset(new unsigned char[data_size]);
35     if (data_) {
36       data_size_ = data_size;
37       return true;
38     } else {
39       DLOG(ERROR) << "Failed to allocate " << data_size << " bytes of memory";
40       data_size_ = 0;
41       return false;
42     }
43   }
44 
GetData() const45   virtual const unsigned char* GetData() const OVERRIDE { return data_.get(); }
46 
GetDataSize() const47   virtual size_t GetDataSize() const OVERRIDE { return data_size_; }
48 
GetStreamReader() const49   virtual CefRefPtr<CefStreamReader> GetStreamReader() const OVERRIDE {
50     CefRefPtr<CefReadHandler> handler(new CefByteReadHandler(
51         data_.get(), data_size_, const_cast<CefZipFile*>(this)));
52     return CefStreamReader::CreateForHandler(handler);
53   }
54 
data()55   unsigned char* data() { return data_.get(); }
56 
57  private:
58   size_t data_size_;
59   scoped_ptr<unsigned char[]> data_;
60 
61   IMPLEMENT_REFCOUNTING(CefZipFile);
62   DISALLOW_COPY_AND_ASSIGN(CefZipFile);
63 };
64 
65 }  // namespace
66 
67 // CefZipArchive implementation
68 
CefZipArchive()69 CefZipArchive::CefZipArchive() {}
70 
~CefZipArchive()71 CefZipArchive::~CefZipArchive() {}
72 
Load(CefRefPtr<CefStreamReader> stream,const CefString & password,bool overwriteExisting)73 size_t CefZipArchive::Load(CefRefPtr<CefStreamReader> stream,
74                            const CefString& password,
75                            bool overwriteExisting) {
76   base::AutoLock lock_scope(lock_);
77 
78   CefRefPtr<CefZipReader> reader(CefZipReader::Create(stream));
79   if (!reader.get())
80     return 0;
81 
82   if (!reader->MoveToFirstFile())
83     return 0;
84 
85   FileMap::iterator it;
86   size_t count = 0;
87 
88   do {
89     const size_t size = static_cast<size_t>(reader->GetFileSize());
90     if (size == 0) {
91       // Skip directories and empty files.
92       continue;
93     }
94 
95     if (!reader->OpenFile(password))
96       break;
97 
98     const CefString& name = ToLower(reader->GetFileName());
99 
100     it = contents_.find(name);
101     if (it != contents_.end()) {
102       if (overwriteExisting)
103         contents_.erase(it);
104       else  // Skip files that already exist.
105         continue;
106     }
107 
108     CefRefPtr<CefZipFile> contents = new CefZipFile();
109     if (!contents->Initialize(size))
110       continue;
111     unsigned char* data = contents->data();
112     size_t offset = 0;
113 
114     // Read the file contents.
115     do {
116       offset += reader->ReadFile(data + offset, size - offset);
117     } while (offset < size && !reader->Eof());
118 
119     DCHECK(offset == size);
120 
121     reader->CloseFile();
122     count++;
123 
124     // Add the file to the map.
125     contents_.insert(std::make_pair(name, contents.get()));
126   } while (reader->MoveToNextFile());
127 
128   return count;
129 }
130 
Clear()131 void CefZipArchive::Clear() {
132   base::AutoLock lock_scope(lock_);
133   contents_.clear();
134 }
135 
GetFileCount() const136 size_t CefZipArchive::GetFileCount() const {
137   base::AutoLock lock_scope(lock_);
138   return contents_.size();
139 }
140 
HasFile(const CefString & fileName) const141 bool CefZipArchive::HasFile(const CefString& fileName) const {
142   base::AutoLock lock_scope(lock_);
143   FileMap::const_iterator it = contents_.find(ToLower(fileName));
144   return (it != contents_.end());
145 }
146 
GetFile(const CefString & fileName) const147 CefRefPtr<CefZipArchive::File> CefZipArchive::GetFile(
148     const CefString& fileName) const {
149   base::AutoLock lock_scope(lock_);
150   FileMap::const_iterator it = contents_.find(ToLower(fileName));
151   if (it != contents_.end())
152     return it->second;
153   return nullptr;
154 }
155 
RemoveFile(const CefString & fileName)156 bool CefZipArchive::RemoveFile(const CefString& fileName) {
157   base::AutoLock lock_scope(lock_);
158   FileMap::iterator it = contents_.find(ToLower(fileName));
159   if (it != contents_.end()) {
160     contents_.erase(it);
161     return true;
162   }
163   return false;
164 }
165 
GetFiles(FileMap & map) const166 size_t CefZipArchive::GetFiles(FileMap& map) const {
167   base::AutoLock lock_scope(lock_);
168   map = contents_;
169   return contents_.size();
170 }
171