fw4spl
ReadZipArchive.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwZip/ReadZipArchive.hpp"
8 
9 #include "fwZip/exception/Read.hpp"
10 
11 #include "minizip/unzip.h"
12 
13 #include <fwCore/exceptionmacros.hpp>
14 
15 #include <boost/filesystem/operations.hpp>
16 #include <boost/filesystem/path.hpp>
17 #include <boost/iostreams/categories.hpp> // source_tag
18 #include <boost/iostreams/stream.hpp>
19 
20 #include <iosfwd> // streamsize
21 
22 namespace fwZip
23 {
24 
25 //------------------------------------------------------------------------------
26 
27 void* openReadZipArchive( const ::boost::filesystem::path& archive )
28 {
29  FW_RAISE_EXCEPTION_IF(
30  ::fwZip::exception::Read("Archive '" + archive.string() + "' doesn't exist."),
31  !::boost::filesystem::exists(archive));
32 
33  void* zip = unzOpen(archive.string().c_str());
34 
35  FW_RAISE_EXCEPTION_IF(
36  ::fwZip::exception::Read("Archive '" + archive.string() + "' cannot be opened."),
37  zip == NULL);
38 
39  return zip;
40 }
41 
42 //-----------------------------------------------------------------------------
43 
44 class ZipSource
45 {
46 public:
47  typedef char char_type;
48  typedef ::boost::iostreams::source_tag category;
49 
50  ZipSource( const ::boost::filesystem::path& archive) :
51  m_zipDescriptor( openReadZipArchive(archive), &unzClose ),
52  m_archive(archive)
53  {
54 
55  }
56 
57  ZipSource( const ::boost::filesystem::path& archive, const ::boost::filesystem::path& path ) :
58  m_zipDescriptor( openReadZipArchive(archive), &unzClose ),
59  m_archive(archive),
60  m_path(path)
61  {
62  int nRet = unzLocateFile(m_zipDescriptor.get(), path.string().c_str(), 0);
63 
64  FW_RAISE_EXCEPTION_IF(
65  ::fwZip::exception::Read("File '" + path.string() + "' in archive '" +
66  archive.string() + "' doesn't exist."),
67  nRet != UNZ_OK);
68 
69  nRet = unzOpenCurrentFile(m_zipDescriptor.get());
70  FW_RAISE_EXCEPTION_IF(
71  ::fwZip::exception::Read("Cannot retrieve file '" + path.string() +
72  "' in archive '"+ archive.string() + "'."),
73  nRet != UNZ_OK);
74  }
75 
76  //------------------------------------------------------------------------------
77 
78  std::streamsize read(char* s, std::streamsize n)
79  {
80  std::streamsize nRet = unzReadCurrentFile(m_zipDescriptor.get(), s, static_cast< unsigned int >(n));
81  FW_RAISE_EXCEPTION_IF(
82  ::fwZip::exception::Read("Error occurred while reading archive '" + m_archive.string()
83  + ":" + m_path.string() + "'."),
84  nRet < 0);
85  return nRet;
86  }
87 
88  //------------------------------------------------------------------------------
89 
90  std::string getComment()
91  {
92  unz_global_info* info = new unz_global_info;
93 
94  std::streamsize nRet = unzGetGlobalInfo(m_zipDescriptor.get(), info);
95 
96  FW_RAISE_EXCEPTION_IF(
97  ::fwZip::exception::Read("Error occurred while reading information archive '" +
98  m_archive.string() + "'."),
99  nRet < 0);
100 
101  char* comment = new char[info->size_comment];
102  nRet = unzGetGlobalComment(m_zipDescriptor.get(), comment, info->size_comment);
103 
104  FW_RAISE_EXCEPTION_IF(
105  ::fwZip::exception::Read("Error occurred while reading archive's global comment '" +
106  m_archive.string() + "'."),
107  nRet < 0);
108 
109  std::string stringComment(comment, info->size_comment);
110 
111  delete info;
112  delete[] comment;
113 
114  return stringComment;
115  }
116 
117 protected:
118  SPTR(void) m_zipDescriptor;
119  ::boost::filesystem::path m_archive;
120  ::boost::filesystem::path m_path;
121 };
122 
123 //-----------------------------------------------------------------------------
124 
125 ReadZipArchive::ReadZipArchive( const ::boost::filesystem::path& archive ) :
126  m_archive(archive)
127 {
128 }
129 
130 //-----------------------------------------------------------------------------
131 
132 SPTR(std::istream) ReadZipArchive::getFile(const ::boost::filesystem::path& path)
133 {
134  SPTR(::boost::iostreams::stream<ZipSource>) is
135  = std::make_shared< ::boost::iostreams::stream<ZipSource> >(m_archive, path);
136 
137  return is;
138 }
139 
140 //-----------------------------------------------------------------------------
141 
143 {
144  SPTR(ZipSource) zip = std::make_shared<ZipSource>(m_archive);
145 
146  return zip->getComment();
147 }
148 
149 //-----------------------------------------------------------------------------
150 
151 const ::boost::filesystem::path ReadZipArchive::getArchivePath() const
152 {
153  return m_archive;
154 }
155 
156 }
#define SPTR(_cls_)
Read exception.
Definition: Read.hpp:21
This class defines functions to read a file in a zip archive.
The namespace fwZip provides IO for compress/uncompress .zip files using zlib .
Definition: Read.hpp:14
FWZIP_API std::string getComment()
Returns comment from the current archive (zip).
FWZIP_APIconst::boost::filesystem::path getArchivePath() const override
Returns archive path.