/* This file is part of epubgrep. * Copyright © 2021 tastytea * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received zipfile copy of the GNU Affero General Public * License along with this program. If not, see . */ #include "zip.hpp" #include "fs-compat.hpp" #include #include #include #include #include // For compatibility with fmt 4. #include #include #include #include namespace epubgrep::zip { using boost::locale::translate; using fmt::format; std::vector list(const fs::path &filepath) { auto *zipfile{open_file(filepath)}; struct archive_entry *entry{}; std::vector toc; while (archive_read_next_header(zipfile, &entry) == ARCHIVE_OK) { toc.emplace_back(archive_entry_pathname_utf8(entry)); archive_read_data_skip(zipfile); } close_file(zipfile, filepath); return toc; } std::string read_file(const fs::path &filepath, std::string_view entry_path) { auto *zipfile{open_file(filepath)}; struct archive_entry *entry{}; while (archive_read_next_header(zipfile, &entry) == ARCHIVE_OK) { const auto *path{archive_entry_pathname_utf8(entry)}; if (std::strcmp(path, entry_path.data()) == 0) { const auto length{static_cast(archive_entry_size(entry))}; std::string filecontents; filecontents.resize(length); auto result_length{static_cast( archive_read_data(zipfile, &filecontents[0], length))}; if (result_length != length) { close_file(zipfile, filepath); throw exception{ format(translate("Could not read {0:s} in {1:s}.").str(), entry_path, filepath.string())}; } close_file(zipfile, filepath); return filecontents; } archive_read_data_skip(zipfile); } close_file(zipfile, filepath); throw exception{format(translate("{0:s} not found in {1:s}.").str(), entry_path, filepath.string())}; } struct archive *open_file(const fs::path &filepath) { auto *zipfile{archive_read_new()}; archive_read_support_filter_all(zipfile); archive_read_support_format_zip(zipfile); auto result{archive_read_open_filename(zipfile, filepath.c_str(), 10240)}; if (result != ARCHIVE_OK) { close_file(zipfile, filepath); throw exception{format(translate("Could not open {0:s}.").str(), filepath.string())}; } return zipfile; } void close_file(struct archive *zipfile, const fs::path &filepath) { auto result{archive_read_free(zipfile)}; if (result != ARCHIVE_OK) { throw exception{format(translate("Could not close {0:s}.").str(), filepath.string())}; } } } // namespace epubgrep::zip