"Fossies" - the Fresh Open Source Software Archive

Member "google-gadgets-for-linux-0.11.2/ggadget/zip_file_manager.cc" (15 Mar 2009, 21601 Bytes) of package /linux/misc/old/google-gadgets-for-linux-0.11.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2   Copyright 2008 Google Inc.
    3 
    4   Licensed under the Apache License, Version 2.0 (the "License");
    5   you may not use this file except in compliance with the License.
    6   You may obtain a copy of the License at
    7 
    8        http://www.apache.org/licenses/LICENSE-2.0
    9 
   10   Unless required by applicable law or agreed to in writing, software
   11   distributed under the License is distributed on an "AS IS" BASIS,
   12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13   See the License for the specific language governing permissions and
   14   limitations under the License.
   15 */
   16 
   17 #include "zip_file_manager.h"
   18 
   19 #include <sys/types.h>
   20 #include <sys/stat.h>
   21 #include <unistd.h>
   22 #include <cstring>
   23 #include <vector>
   24 #include <string>
   25 #include <cstdio>
   26 #include <cerrno>
   27 #include <ctime>
   28 
   29 #include <third_party/unzip/zip.h>
   30 #include <third_party/unzip/unzip.h>
   31 #include "common.h"
   32 #include "logger.h"
   33 #include "gadget_consts.h"
   34 #include "slot.h"
   35 #include "string_utils.h"
   36 #include "system_utils.h"
   37 #include "small_object.h"
   38 
   39 namespace ggadget {
   40 
   41 #ifdef GADGET_CASE_SENSITIVE
   42 static const int kZipCaseSensitivity = 1;
   43 #else
   44 static const int kZipCaseSensitivity = 2;
   45 #endif
   46 
   47 static const uLong kMaxFieldSize = 200000;
   48 static const char kZipGlobalComment[] = "Created by Google Gadgets for Linux.";
   49 static const char kZipReadMeFile[] = ".readme";
   50 static const char kTempZipFile[] = "%%Temp%%.zip";
   51 
   52 class ZipFileManager::Impl : public SmallObject<> {
   53  public:
   54   Impl() : unzip_handle_(NULL), zip_handle_(NULL) {
   55   }
   56 
   57   ~Impl() {
   58     Finalize();
   59   }
   60 
   61   void Finalize() {
   62     if (temp_dir_.length())
   63       RemoveDirectory(temp_dir_.c_str(), true);
   64 
   65     temp_dir_.clear();
   66     base_path_.clear();
   67 
   68     if (unzip_handle_)
   69       unzClose(unzip_handle_);
   70     if (zip_handle_)
   71       zipClose(zip_handle_, kZipGlobalComment);
   72 
   73     unzip_handle_ = NULL;
   74     zip_handle_ = NULL;
   75   }
   76 
   77   bool IsValid() {
   78     return !base_path_.empty() && (zip_handle_ || unzip_handle_);
   79   }
   80 
   81   bool Init(const char *base_path, bool create) {
   82     if (!base_path || !base_path[0]) {
   83       LOG("Base path is empty.");
   84       return false;
   85     }
   86 
   87     std::string path(base_path);
   88 
   89     // Use absolute path.
   90     if (*base_path != kDirSeparator)
   91       path = BuildFilePath(GetCurrentDirectory().c_str(), base_path, NULL);
   92 
   93     path = NormalizeFilePath(path.c_str());
   94 
   95     unzFile unzip_handle = NULL;
   96     zipFile zip_handle = NULL;
   97     struct stat stat_value;
   98     memset(&stat_value, 0, sizeof(stat_value));
   99     if (::stat(path.c_str(), &stat_value) == 0) {
  100       if (!S_ISREG(stat_value.st_mode)) {
  101         DLOG("Not a regular file: %s", path.c_str());
  102         return false;
  103       }
  104 
  105       if (::access(path.c_str(), R_OK) != 0) {
  106         LOG("No permission to access the file %s", path.c_str());
  107         return false;
  108       }
  109 
  110       unzip_handle = unzOpen(path.c_str());
  111       if (!unzip_handle) {
  112         LOG("Failed to open zip file %s for reading", path.c_str());
  113         return false;
  114       }
  115     } else if (errno == ENOENT && create) {
  116       zip_handle = zipOpen(path.c_str(), APPEND_STATUS_CREATE);
  117       if (!zip_handle) {
  118         LOG("Failed to open zip file %s for writing", path.c_str());
  119         return false;
  120       }
  121       AddReadMeFileInZip(zip_handle, path.c_str());
  122     } else {
  123       LOG("Failed to open zip file %s: %s", path.c_str(), strerror(errno));
  124       return false;
  125     }
  126 
  127     DLOG("ZipFileManager was initialized successfully for path %s",
  128          path.c_str());
  129 
  130     Finalize();
  131 
  132     unzip_handle_ = unzip_handle;
  133     zip_handle_ = zip_handle;
  134     base_path_ = path;
  135     return true;
  136   }
  137 
  138   bool ReadFile(const char *file, std::string *data) {
  139     ASSERT(data);
  140     if (data) data->clear();
  141 
  142     std::string relative_path;
  143     if (!CheckFilePath(file, &relative_path, NULL))
  144       return false;
  145 
  146     if (!SwitchToRead())
  147       return false;
  148 
  149     if (unzLocateFile(unzip_handle_, relative_path.c_str(),
  150                       kZipCaseSensitivity) != UNZ_OK)
  151       return false;
  152 
  153     if (unzOpenCurrentFile(unzip_handle_) != UNZ_OK) {
  154       LOG("Can't open file %s for reading in zip archive %s.",
  155           relative_path.c_str(), base_path_.c_str());
  156       return false;
  157     }
  158 
  159     bool result = true;
  160     const int kChunkSize = 2048;
  161     char buffer[kChunkSize];
  162     while (true) {
  163       int read_size = unzReadCurrentFile(unzip_handle_, buffer, kChunkSize);
  164       if (read_size > 0) {
  165         data->append(buffer, read_size);
  166         if (data->length() > kMaxFileSize) {
  167           LOG("File %s is too big", relative_path.c_str());
  168           data->clear();
  169           result = false;
  170           break;
  171         }
  172       } else if (read_size < 0) {
  173         LOG("Error reading file: %s in zip archive %s",
  174             relative_path.c_str(), base_path_.c_str());
  175         data->clear();
  176         result = false;
  177         break;
  178       } else {
  179         break;
  180       }
  181     }
  182 
  183     if (unzCloseCurrentFile(unzip_handle_) != UNZ_OK) {
  184       LOG("CRC error in file: %s in zip file: %s",
  185           relative_path.c_str(), base_path_.c_str());
  186       data->clear();
  187       result = false;
  188     }
  189     return result;
  190   }
  191 
  192   bool WriteFile(const char *file, const std::string &data, bool overwrite) {
  193     std::string relative_path;
  194     if (!CheckFilePath(file, &relative_path, NULL))
  195       return false;
  196 
  197     if (FileExists(file, NULL)) {
  198       if (!overwrite) {
  199         LOG("Can't overwrite an existing file %s in zip archive %s.",
  200             relative_path.c_str(), base_path_.c_str());
  201         return false;
  202       }
  203       if (!RemoveFile(file))
  204         return false;
  205     }
  206 
  207     if (!SwitchToWrite())
  208       return false;
  209 
  210     return AddFileInZip(zip_handle_, base_path_.c_str(), relative_path.c_str(),
  211                         data.c_str(), data.length());
  212   }
  213 
  214   class CopyZipFile {
  215    public:
  216     CopyZipFile(Impl *impl, zipFile dest, const char *excluded_file)
  217         : impl_(impl), dest_(dest), excluded_file_(excluded_file) {
  218     }
  219     bool Copy(const char *filename) {
  220       if (GadgetStrCmp(filename, excluded_file_) == 0) {
  221         // Don't copy this excluded file;
  222         return true;
  223       }
  224 
  225       unz_file_info unz_info;
  226       if (unzGetCurrentFileInfo(impl_->unzip_handle_, &unz_info,
  227                                 NULL, 0, NULL, 0, NULL, 0) != UNZ_OK ||
  228           unz_info.size_file_extra > kMaxFieldSize ||
  229           unz_info.size_file_comment > kMaxFieldSize)
  230         return false;
  231       char *extra = new char[unz_info.size_file_extra];
  232       char *comment = new char[unz_info.size_file_comment + 1];
  233       if (unzGetCurrentFileInfo(impl_->unzip_handle_, &unz_info, NULL, 0,
  234                                 extra, unz_info.size_file_extra,
  235                                 comment, unz_info.size_file_comment + 1)
  236           != UNZ_OK) {
  237         delete [] extra;
  238         delete [] comment;
  239         return false;
  240       }
  241 
  242       zip_fileinfo zip_info;
  243       memset(&zip_info, 0, sizeof(zip_info));
  244       zip_info.dosDate = unz_info.dosDate;
  245       zip_info.internal_fa = unz_info.internal_fa;
  246       zip_info.external_fa = unz_info.external_fa;
  247       std::string content;
  248       bool result = zipOpenNewFileInZip(
  249                         dest_, filename, &zip_info, extra,
  250                         static_cast<uInt>(unz_info.size_file_extra),
  251                         NULL, 0, comment,
  252                         static_cast<int>(unz_info.compression_method),
  253                         Z_DEFAULT_COMPRESSION) == ZIP_OK &&
  254                     impl_->ReadFile(filename, &content) &&
  255                     zipWriteInFileInZip(
  256                         dest_, content.c_str(),
  257                         static_cast<unsigned>(content.size())) == UNZ_OK;
  258       if (!result)
  259         LOG("Failed to copy file %s from zip to temp zip", filename);
  260       delete [] extra;
  261       delete [] comment;
  262       zipCloseFileInZip(dest_);
  263       return result;
  264     }
  265    private:
  266     Impl *impl_;
  267     zipFile dest_;
  268     const char *excluded_file_;
  269   };
  270 
  271   bool RemoveFile(const char *file) {
  272     if (!FileExists(file, NULL) || !SwitchToRead() || !EnsureTempDirectory())
  273       return false;
  274 
  275     unz_global_info global_info;
  276     char *global_comment = NULL;
  277     if (unzGetGlobalInfo(unzip_handle_, &global_info) == UNZ_OK &&
  278         global_info.size_comment <= kMaxFieldSize) {
  279       global_comment = new char[global_info.size_comment + 1];
  280       if (unzGetGlobalComment(unzip_handle_, global_comment,
  281                               global_info.size_comment + 1) < 0) {
  282         delete [] global_comment;
  283         global_comment = NULL;
  284       }
  285     }
  286 
  287     std::string temp_file = BuildFilePath(temp_dir_.c_str(),
  288                                           kTempZipFile, NULL);
  289     unlink(temp_file.c_str());
  290     zipFile temp_zip = zipOpen(temp_file.c_str(), APPEND_STATUS_CREATE);
  291     if (!temp_zip) {
  292       LOG("Can't create temp zip file: %s", temp_file.c_str());
  293       return false;
  294     }
  295     AddReadMeFileInZip(temp_zip, temp_file.c_str());
  296 
  297     CopyZipFile copy_zip_file(this, temp_zip, file);
  298     bool res =
  299         EnumerateFiles("", NewSlot(&copy_zip_file, &CopyZipFile::Copy)) == 0;
  300     zipClose(temp_zip, global_comment);
  301     delete [] global_comment;
  302 
  303     if (res) {
  304       // Copy the temp zip file over the original zip.
  305       unzClose(unzip_handle_);
  306       unzip_handle_ = NULL;
  307       res = unlink(base_path_.c_str()) == 0 &&
  308             CopyFile(temp_file.c_str(), base_path_.c_str());
  309       if (!res) {
  310         LOG("Failed to copy temp zip file %s to original zip file %s: %s",
  311             temp_file.c_str(), base_path_.c_str(), strerror(errno));
  312       }
  313     }
  314     unlink(temp_file.c_str());
  315     return res;
  316   }
  317 
  318   bool ExtractFile(const char *file, std::string *into_file) {
  319     ASSERT(into_file);
  320 
  321     std::string relative_path;
  322     if (!CheckFilePath(file, &relative_path, NULL))
  323       return false;
  324 
  325     if (!SwitchToRead())
  326       return false;
  327 
  328     if (unzLocateFile(unzip_handle_, relative_path.c_str(),
  329                       kZipCaseSensitivity) != UNZ_OK)
  330       return false;
  331 
  332     if (into_file->empty()) {
  333       if (!EnsureTempDirectory())
  334         return false;
  335 
  336       // Creates the relative sub directories under temp direcotry.
  337       std::string dir, file_name;
  338       SplitFilePath(relative_path.c_str(), &dir, &file_name);
  339 
  340       dir = BuildFilePath(temp_dir_.c_str(), dir.c_str(), NULL);
  341       if (!EnsureDirectories(dir.c_str()))
  342         return false;
  343 
  344       *into_file = BuildFilePath(dir.c_str(), file_name.c_str(), NULL);
  345     }
  346 
  347     unlink(into_file->c_str());
  348     FILE *out_fp = fopen(into_file->c_str(), "w");
  349     if (!out_fp) {
  350       LOG("Can't open file %s for writing.", into_file->c_str());
  351       return false;
  352     }
  353 
  354     if (unzOpenCurrentFile(unzip_handle_) != UNZ_OK) {
  355       LOG("Can't open file %s for reading in zip archive %s.",
  356           relative_path.c_str(), base_path_.c_str());
  357       fclose(out_fp);
  358       return false;
  359     }
  360 
  361     bool result = true;
  362     const int kChunkSize = 8192;
  363     char buffer[kChunkSize];
  364     while(true) {
  365       int read_size = unzReadCurrentFile(unzip_handle_, buffer, kChunkSize);
  366       if (read_size > 0) {
  367         if (fwrite(buffer, read_size, 1, out_fp) != 1) {
  368           result = false;
  369           LOG("Error when writing to file %s", into_file->c_str());
  370           break;
  371         }
  372       } else if (read_size < 0) {
  373         LOG("Error reading file: %s in zip archive %s",
  374             relative_path.c_str(), base_path_.c_str());
  375         result = false;
  376         break;
  377       } else {
  378         break;
  379       }
  380     }
  381 
  382     if (unzCloseCurrentFile(unzip_handle_) != UNZ_OK) {
  383       LOG("CRC error in file: %s in zip file: %s",
  384           relative_path.c_str(), base_path_.c_str());
  385       result = false;
  386     }
  387     // fclose() is placed first to ensure it's always called.
  388     result = (fclose(out_fp) == 0 && result);
  389 
  390     if (!result)
  391       unlink(into_file->c_str());
  392 
  393     return result;
  394   }
  395 
  396   bool FileExists(const char *file, std::string *path) {
  397     std::string full_path, relative_path;
  398     bool result = CheckFilePath(file, &relative_path, &full_path);
  399     if (path) *path = full_path;
  400 
  401     return result && SwitchToRead() &&
  402            unzLocateFile(unzip_handle_, relative_path.c_str(),
  403                          kZipCaseSensitivity) == UNZ_OK;
  404   }
  405 
  406   bool IsDirectlyAccessible(const char *file, std::string *path) {
  407     CheckFilePath(file, NULL, path);
  408     return false;
  409   }
  410 
  411   std::string GetFullPath(const char *file) {
  412     std::string path;
  413     if (!file || !*file)
  414       return base_path_;
  415     else if (CheckFilePath(file, NULL, &path))
  416       return path;
  417     return std::string("");
  418   }
  419 
  420   uint64_t GetLastModifiedTime(const char *file) {
  421     std::string full_path, relative_path;
  422     bool result = CheckFilePath(file, &relative_path, &full_path);
  423 
  424     unz_file_info file_info;
  425     if (result && SwitchToRead() &&
  426         unzLocateFile(unzip_handle_, relative_path.c_str(),
  427                       kZipCaseSensitivity) == UNZ_OK &&
  428         unzGetCurrentFileInfo(unzip_handle_, &file_info,
  429                               NULL, 0, NULL, 0, NULL, 0) == UNZ_OK) {
  430       struct tm tm;
  431       memset(&tm, 0, sizeof(tm));
  432       tm.tm_year = file_info.tmu_date.tm_year - 1900;
  433       tm.tm_mon = file_info.tmu_date.tm_mon;
  434       tm.tm_mday = file_info.tmu_date.tm_mday;
  435       tm.tm_hour = file_info.tmu_date.tm_hour;
  436       tm.tm_min = file_info.tmu_date.tm_min;
  437       tm.tm_sec = file_info.tmu_date.tm_sec;
  438       return mktime(&tm) * UINT64_C(1000);
  439     }
  440     return 0;
  441   }
  442 
  443   // Returns -1 on error, 0 on success, 1 on canceled.
  444   int EnumerateFiles(const char *dir, Slot1<bool, const char *> *callback) {
  445     ASSERT(dir);
  446     std::string dir_name(dir);
  447     // Make sure dir_name is ended with '/' if it is not empty to make the
  448     // prefix matching works for files under the directory.
  449     if (!dir_name.empty() && dir_name[dir_name.size() - 1] != kDirSeparator)
  450       dir_name += kDirSeparator;
  451 
  452     if (!SwitchToRead())
  453       return -1;
  454 
  455     int res = unzGoToFirstFile(unzip_handle_);
  456     while (res == UNZ_OK) {
  457       unz_file_info file_info;
  458       char filename[256];
  459       res = unzGetCurrentFileInfo(unzip_handle_, &file_info,
  460                                   filename, sizeof(filename),
  461                                   NULL, 0, NULL, 0);
  462       if (res != UNZ_OK)
  463         break;
  464       char *filename_ptr = filename;
  465       size_t filename_size = static_cast<size_t>(file_info.size_filename + 1);
  466       // In most cases filename buffer is big enough to contain the file name.
  467       if (filename_size > sizeof(filename)) {
  468         filename_ptr = new char[filename_size];
  469         res = unzGetCurrentFileInfo(unzip_handle_, &file_info,
  470                                     filename_ptr, filename_size,
  471                                     NULL, 0, NULL, 0);
  472         if (res != UNZ_OK)
  473           break;
  474       }
  475       if (filename_ptr[filename_size - 1] != kDirSeparator &&
  476           strcmp(filename_ptr, kZipReadMeFile) != 0 &&
  477           GadgetStrNCmp(dir_name.c_str(), filename_ptr, dir_name.size()) == 0 &&
  478           !(*callback)(filename_ptr + dir_name.size())) {
  479         if (filename_ptr != filename) delete [] filename_ptr;
  480         delete callback;
  481         return 1;
  482       }
  483       if (filename_ptr != filename) delete [] filename_ptr;
  484       res = unzGoToNextFile(unzip_handle_);
  485     }
  486     delete callback;
  487     return res == UNZ_OK || res == UNZ_END_OF_LIST_OF_FILE ? 0 : -1;
  488   }
  489 
  490   // Check if the given file path is valid and return the full path and
  491   // relative path.
  492   bool CheckFilePath(const char *file, std::string *relative_path,
  493                      std::string *full_path) {
  494     if (relative_path) relative_path->clear();
  495     if (full_path) full_path->clear();
  496 
  497     if (base_path_.empty()) {
  498       LOG("ZipFileManager hasn't been initialized.");
  499       return false;
  500     }
  501 
  502     // Can't read a file from an absolute path.
  503     // The file must be a relative path under base_path.
  504     if (!file || !*file || *file == kDirSeparator) {
  505       LOG("Invalid file path: %s", (file ? file : "(NULL)"));
  506       return false;
  507     }
  508 
  509     std::string path;
  510     path = BuildFilePath(base_path_.c_str(), file, NULL);
  511     path = NormalizeFilePath(path.c_str());
  512 
  513     if (full_path) *full_path = path;
  514 
  515     // Check if the normalized path is starting from base_path.
  516     if (path.length() <= base_path_.length() ||
  517         strncmp(base_path_.c_str(), path.c_str(), base_path_.length()) != 0 ||
  518         path[base_path_.length()] != kDirSeparator) {
  519       LOG("Invalid file path: %s", file);
  520       return false;
  521     }
  522 
  523     if (relative_path)
  524       relative_path->assign(path.begin() + base_path_.length()+1, path.end());
  525 
  526     return true;
  527   }
  528 
  529   bool EnsureTempDirectory() {
  530     if (temp_dir_.length())
  531       return EnsureDirectories(temp_dir_.c_str());
  532 
  533     if (base_path_.length()) {
  534       std::string path, name;
  535       SplitFilePath(base_path_.c_str(), &path, &name);
  536 
  537       if (CreateTempDirectory(name.c_str(), &path)) {
  538         temp_dir_ = path;
  539         DLOG("A temporary directory has been created: %s", path.c_str());
  540         return true;
  541       }
  542     }
  543 
  544     return false;
  545   }
  546 
  547   bool SwitchToRead() {
  548     if (base_path_.empty())
  549       return false;
  550 
  551     if (unzip_handle_) {
  552       // unzGoToFirstFile can reset error flags of the handle.
  553       if (unzGoToFirstFile(unzip_handle_) == UNZ_OK)
  554         return true;
  555       // The unzip handle is not usable. Reopen it.
  556       unzClose(unzip_handle_);
  557     }
  558 
  559     if (zip_handle_) {
  560       zipClose(zip_handle_, kZipGlobalComment);
  561       zip_handle_ = NULL;
  562     }
  563 
  564     unzip_handle_ = unzOpen(base_path_.c_str());
  565     if (!unzip_handle_)
  566       LOG("Can't open zip archive %s for reading.", base_path_.c_str());
  567 
  568     return unzip_handle_ != NULL;
  569   }
  570 
  571   bool SwitchToWrite() {
  572     if (base_path_.empty())
  573       return false;
  574 
  575     if (zip_handle_)
  576       return true;
  577 
  578     if (unzip_handle_) {
  579       unzClose(unzip_handle_);
  580       unzip_handle_ = NULL;
  581     }
  582 
  583     // If the file already exists, then try to open in append mode,
  584     // otherwise open in create mode.
  585     if (::access(base_path_.c_str(), F_OK) == 0) {
  586       zip_handle_ = zipOpen(base_path_.c_str(), APPEND_STATUS_ADDINZIP);
  587     } else {
  588       zip_handle_ = zipOpen(base_path_.c_str(), APPEND_STATUS_CREATE);
  589       if (zip_handle_)
  590         AddReadMeFileInZip(zip_handle_, base_path_.c_str());
  591     }
  592 
  593     if (!zip_handle_)
  594       LOG("Can't open zip archive %s for writing.", base_path_.c_str());
  595 
  596     return zip_handle_ != NULL;
  597   }
  598 
  599   bool AddFileInZip(zipFile zip, const char *zip_path,
  600                     const char *file, const char *data, size_t size) {
  601     ASSERT(zip);
  602     zip_fileinfo info;
  603     memset(&info, 0, sizeof(info));
  604     time_t t = time(NULL);
  605     struct tm *tm = localtime(&t);
  606     info.tmz_date.tm_sec = tm->tm_sec;
  607     info.tmz_date.tm_min = tm->tm_min;
  608     info.tmz_date.tm_hour = tm->tm_hour;
  609     info.tmz_date.tm_mday = tm->tm_mday;
  610     info.tmz_date.tm_mon = tm->tm_mon;
  611     info.tmz_date.tm_year = tm->tm_year + 1900;
  612     if (zipOpenNewFileInZip(zip, file, &info, NULL, 0, NULL, 0, NULL,
  613                             Z_DEFLATED, Z_DEFAULT_COMPRESSION) != ZIP_OK) {
  614       LOG("Can't add new file %s in zip archive %s.", file, zip_path);
  615       return false;
  616     }
  617 
  618     int result = zipWriteInFileInZip(zip, data, static_cast<unsigned>(size));
  619     zipCloseFileInZip(zip);
  620     if (result != ZIP_OK) {
  621       LOG("Error when adding %s file in zip archive %s.", file, zip_path);
  622       return false;
  623     }
  624     return true;
  625   }
  626 
  627   // At least one file must be added to an empty zip archive, otherwise the
  628   // archive will become invalid and can't be opened again.
  629   bool AddReadMeFileInZip(zipFile zip, const char *zip_path) {
  630     return AddFileInZip(zip, zip_path, kZipReadMeFile,
  631                         kZipGlobalComment, sizeof(kZipGlobalComment) - 1);
  632   }
  633 
  634   std::string temp_dir_;
  635   std::string base_path_;
  636 
  637   unzFile unzip_handle_;
  638   zipFile zip_handle_;
  639 };
  640 
  641 
  642 ZipFileManager::ZipFileManager()
  643   : impl_(new Impl()){
  644 }
  645 
  646 ZipFileManager::~ZipFileManager() {
  647   delete impl_;
  648 }
  649 
  650 bool ZipFileManager::IsValid() {
  651   return impl_->IsValid();
  652 }
  653 
  654 bool ZipFileManager::Init(const char *base_path, bool create) {
  655   return impl_->Init(base_path, create);
  656 }
  657 
  658 bool ZipFileManager::ReadFile(const char *file, std::string *data) {
  659   return impl_->ReadFile(file, data);
  660 }
  661 
  662 bool ZipFileManager::WriteFile(const char *file, const std::string &data,
  663                                bool overwrite) {
  664   return impl_->WriteFile(file, data, overwrite);
  665 }
  666 
  667 bool ZipFileManager::RemoveFile(const char *file) {
  668   return impl_->RemoveFile(file);
  669 }
  670 
  671 bool ZipFileManager::ExtractFile(const char *file, std::string *into_file) {
  672   return impl_->ExtractFile(file, into_file);
  673 }
  674 
  675 bool ZipFileManager::FileExists(const char *file, std::string *path) {
  676   return impl_->FileExists(file, path);
  677 }
  678 
  679 bool ZipFileManager::IsDirectlyAccessible(const char *file,
  680                                           std::string *path) {
  681   return impl_->IsDirectlyAccessible(file, path);
  682 }
  683 
  684 std::string ZipFileManager::GetFullPath(const char *file) {
  685   return impl_->GetFullPath(file);
  686 }
  687 
  688 uint64_t ZipFileManager::GetLastModifiedTime(const char *file) {
  689   return impl_->GetLastModifiedTime(file);
  690 }
  691 
  692 bool ZipFileManager::EnumerateFiles(const char *dir,
  693                                     Slot1<bool, const char *> *callback) {
  694   // Errors during enumeration are ignored.
  695   return impl_->EnumerateFiles(dir, callback) != 1;
  696 }
  697 
  698 FileManagerInterface *ZipFileManager::Create(const char *base_path,
  699                                              bool create) {
  700   FileManagerInterface *fm = new ZipFileManager();
  701   if (fm->Init(base_path, create))
  702     return fm;
  703 
  704   delete fm;
  705   return NULL;
  706 }
  707 
  708 } // namespace ggadget