crawlserv++  [under development]
Application for crawling and analyzing textual content of websites.
ZipArchive.hpp
Go to the documentation of this file.
1 /*
2  *
3  * ---
4  *
5  * Copyright (C) 2020 Anselm Schmidt (ans[ät]ohai.su)
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version in addition to the terms of any
11  * licences already herein identified.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  *
21  * ---
22  *
23  * ZipArchive.hpp
24  *
25  * Wrapper for pointer to a libzip archive.
26  * Does NOT have ownership of the pointer, but takes care of its deletion!
27  *
28  * Created on: Jan 4, 2021
29  * Author: ans
30  */
31 
32 #ifndef WRAPPER_ZIPARCHIVE_HPP_
33 #define WRAPPER_ZIPARCHIVE_HPP_
34 
35 #include "ZipSource.hpp"
36 
37 #include <zip.h>
38 
39 #include <string> // std::string
40 
41 namespace crawlservpp::Wrapper {
42 
43  /*
44  * DECLARATION
45  */
46 
48 
65  class ZipArchive {
66  public:
69 
70  ZipArchive();
71  virtual ~ZipArchive();
72 
76 
77  [[nodiscard]] struct zip * get() noexcept;
78  [[nodiscard]] const struct zip * getc() const noexcept;
79  [[nodiscard]] bool valid() const noexcept;
80  [[nodiscard]] std::string getError();
81 
85 
86  bool addEmptyDirectory(const std::string& name);
87 
88  bool addFile(
89  const std::string& fileName,
90  const std::string& content,
91  bool overwrite
92  );
93 
97 
98  void close() noexcept;
99  void close(std::string& dumpTo);
100 
102 
105 
108  ZipArchive(ZipArchive&) = delete;
109 
111  ZipArchive& operator=(ZipArchive&) = delete;
112 
113  ZipArchive(ZipArchive&& other) noexcept;
114  ZipArchive& operator=(ZipArchive&& other) noexcept;
115 
117 
118  private:
119  // underlying source
120  ZipSource source;
121 
122  // underlying pointer to ZIP archive
123  struct zip * ptr{nullptr};
124 
125  // last occured error
126  zip_error_t error{};
127 
128  // internal static helper function
129  static void copyError(const zip_error_t * from, zip_error_t& to);
130  };
131 
132  /*
133  * IMPLEMENTATION
134  */
135 
136  /*
137  * CONSTRUCTION AND DESTRUCTION
138  */
139 
142  // check whether empty source has been created
143  if(!(this->source.valid())) {
144  this->error = this->source.getError();
145 
146  return;
147  }
148 
149  // create archive from empty source
150  this->ptr = zip_open_from_source(this->source.get(), ZIP_TRUNCATE, &(this->error));
151 
152  if(this->ptr != nullptr) {
153  // keep the source (to be cleared by its wrapper)
154  zip_source_keep(this->source.get());
155  }
156  }
157 
160  this->close();
161  }
162 
163  /*
164  * GETTERS
165  */
166 
168 
172  inline struct zip * ZipArchive::get() noexcept {
173  return this->ptr;
174  }
175 
177 
182  inline const struct zip * ZipArchive::getc() const noexcept {
183  return this->ptr;
184  }
185 
187 
194  inline bool ZipArchive::valid() const noexcept {
195  return this->ptr != nullptr;
196  }
197 
199 
205  inline std::string ZipArchive::getError() {
206  return zip_error_strerror(&(this->error));
207  }
208 
209  /*
210  * ARCHIVE FUNCTIONALITY
211  */
212 
214 
229  inline bool ZipArchive::addEmptyDirectory(const std::string& name) {
230  if(this->ptr == nullptr) {
231  return false;
232  }
233 
234  const auto result{
235  zip_add_dir(this->ptr, name.c_str())
236  };
237 
238  if(result < 0) {
239  // copy error from archive
240  ZipArchive::copyError(
241  zip_get_error(this->ptr),
242  this->error
243  );
244 
245  return false;
246  }
247 
248  return true;
249  }
250 
252 
270  inline bool ZipArchive::addFile(
271  const std::string& name,
272  const std::string& content,
273  bool overwrite
274  ) {
275  if(this->ptr == nullptr) {
276  return false;
277  }
278 
279  ZipSource fileSource(content.data(), content.size());
280 
281  // keep the source (to be cleared by its wrapper)
282  zip_source_keep(fileSource.get());
283 
284  const auto result{
285  zip_file_add(
286  this->ptr,
287  name.c_str(),
288  fileSource.get(),
289  ZIP_FL_ENC_UTF_8 | (overwrite ? ZIP_FL_OVERWRITE : 0)
290  )
291  };
292 
293  if(result < 0) {
294  // decrement reference count as it has not been used on error
295  zip_source_free(fileSource.get());
296 
297  ZipArchive::copyError(zip_get_error(this->ptr), this->error);
298 
299  return false;
300  }
301 
302  return true;
303  }
304 
305  /*
306  * CLEANUP
307  */
308 
310 
319  inline void ZipArchive::close() noexcept {
320  if(this->ptr != nullptr) {
321  zip_close(this->ptr);
322 
323  this->ptr = nullptr;
324  }
325 
326  zip_error_fini(&(this->error));
327  }
328 
330 
340  inline void ZipArchive::close(std::string& dumpTo) {
341  if(this->ptr == nullptr) {
342  return;
343  }
344 
345  this->close();
346 
347  if(this->source.valid()) {
348  zip_source_open(this->source.get());
349 
350  zip_source_seek(this->source.get(), 0, SEEK_END);
351 
352  const zip_int64_t size{
353  zip_source_tell(this->source.get())
354  };
355 
356  zip_source_seek(this->source.get(), 0, SEEK_SET);
357 
358  dumpTo.resize(size);
359 
360  zip_source_read(
361  this->source.get(),
362  static_cast<void*>(dumpTo.data()),
363  size
364  );
365  }
366  }
367 
368  /*
369  * COPY AND MOVE
370  */
371 
373 
385  inline ZipArchive::ZipArchive(ZipArchive&& other) noexcept : ptr(other.ptr) {
386  other.ptr = nullptr;
387  }
388 
390 
409  inline ZipArchive& ZipArchive::operator=(ZipArchive&& other) noexcept {
410  if(&other != this) {
411  this->close();
412 
413  this->ptr = other.ptr;
414 
415  other.ptr = nullptr;
416  }
417 
418  return *this;
419  }
420 
421  /*
422  * INTERNAL STATIC HELPER FUNCTION (private)
423  */
424 
425  // copy error
426  inline void ZipArchive::copyError(const zip_error_t * from, zip_error_t& to) {
427  zip_error_fini(&to);
428  zip_error_init(&to);
429 
430  to.sys_err = from->sys_err;
431  to.zip_err = from->zip_err;
432  }
433 
434 } /* namespace crawlservpp::Wrapper */
435 
436 #endif /* WRAPPER_ZIPARCHIVE_HPP_ */
ZipArchive & operator=(ZipArchive &)=delete
Deleted copy assignment operator.
struct zip * get() noexcept
Gets a pointer to the underlying archive.
Definition: ZipArchive.hpp:172
bool valid() const noexcept
Checks whether the underlying archive is valid.
Definition: ZipArchive.hpp:194
virtual ~ZipArchive()
Destructor clearing the archive if necessary.
Definition: ZipArchive.hpp:159
bool addFile(const std::string &fileName, const std::string &content, bool overwrite)
Adds a file to the archive.
Definition: ZipArchive.hpp:270
ZipArchive()
Constructor creating an archive from an empty source.
Definition: ZipArchive.hpp:141
RAII wrapper for ZIP archives used by libzip.
Definition: ZipArchive.hpp:65
Namespace for RAII wrappers and Wrapper::Database.
Definition: Database.hpp:109
std::string getError()
Get the last occurred error as string.
Definition: ZipArchive.hpp:205
void close() noexcept
Closes the underlying archive if necessary.
Definition: ZipArchive.hpp:319
bool addEmptyDirectory(const std::string &name)
Adds an empty directory to the archive.
Definition: ZipArchive.hpp:229
bool valid() const noexcept
Checks whether the underlying source is valid.
Definition: ZipSource.hpp:165
const struct zip * getc() const noexcept
Gets a const pointer to the underlying archive.
Definition: ZipArchive.hpp:182
zip_error_t getError() const
Get the last occurred error.
Definition: ZipSource.hpp:176
RAII wrapper for sources used by libzip.
Definition: ZipSource.hpp:61
zip_source_t * get() noexcept
Gets a pointer to the underlying source.
Definition: ZipSource.hpp:143