size_t zip_archive_stream_fd::size() const { if (fseeko(m_stream, 0, SEEK_END)) throw zip_error("failed to set seek position to the end of stream."); return ftello(m_stream); }
void ZipFileReader::initialize(ZipArchive& archive, const struct zip_stat& st) { _path.assign(utf8::decode(st.name)); zip_file* file = zip_fopen_index(archive.c_obj(), st.index, 0); if (file == NULL) { throw Exception(format( "{0}: {1}: {2}", archive.path(), _path, zip_error(archive.c_obj()))); } AutoCloseZipFile close(file); _data.resize(st.size); int bytes_read = zip_fread(file, _data.data(), _data.size()); if ((bytes_read < 0) || (bytes_read - _data.size() != 0)) { throw Exception(format("{0}: {1}: {2}", archive.path(), _path, zip_error(file))); } }
zip_archive_impl::zip_archive_impl(zip_archive_stream* stream) : m_stream(stream), m_stream_size(0), m_central_dir_pos(0) { if (!m_stream) throw zip_error("null stream is not allowed."); m_stream_size = m_stream->size(); }
ZipFileReader::ZipFileReader(ZipArchive& archive, int index) { struct zip_stat st; if (zip_stat_index(archive.c_obj(), index, 0, &st) != 0) { throw Exception(format( "{0}: {1}: {2}", archive.path(), index, zip_error(archive.c_obj()))); } initialize(archive, st); }
void zip_archive_stream_fd::seek(size_t pos) { if (fseeko(m_stream, pos, SEEK_SET)) { ostringstream os; os << "failed to set seek position to " << pos << "."; throw zip_error(os.str()); } }
ZipFileReader::ZipFileReader(ZipArchive& archive, const StringSlice& path) { struct zip_stat st; CString c_str(path); if (zip_stat(archive.c_obj(), c_str.data(), 0, &st) != 0) { throw Exception(format( "{0}: {1}: {2}", archive.path(), path, zip_error(archive.c_obj()))); } initialize(archive, st); }
void zip_archive_stream_blob::seek(size_t pos) { if (pos > m_size) { ostringstream os; os << "failed to seek position to " << pos << "."; throw zip_error(os.str()); } m_cur = m_blob + pos; }
ZipArchive::ZipArchive(const StringSlice& path, int flags) : _path(path) { int error; CString c_str(path); const char* c_path = reinterpret_cast<const char*>(c_str.data()); _c_obj = zip_open(c_path, 0, &error); if (_c_obj == NULL) { throw Exception(format("{0}: {1}", path, zip_error(error, errno))); } }
void zip_archive_impl::dump_file_entry(size_t pos) const { if (pos >= m_file_params.size()) throw zip_error("invalid file entry index."); const zip_file_param& param = m_file_params[pos]; cout << "-- filename: " << param.filename << endl; zip_stream_parser file_header(m_stream, param.offset_file_header); uint32_t v32 = file_header.read_4bytes(); printf(" header signature: 0x%8.8x\n", v32); uint16_t v16 = file_header.read_2bytes(); cout << " version needed to extract: " << v16 << endl; v16 = file_header.read_2bytes(); printf(" general purpose bit flag: 0x%4.4x\n", v16); v16 = file_header.read_2bytes(); cout << " compression method: " << v16 << endl; v16 = file_header.read_2bytes(); cout << " file last modified time: " << v16 << endl; v16 = file_header.read_2bytes(); cout << " file last modified date: " << v16 << endl; v32 = file_header.read_4bytes(); printf(" crc32: 0x%8.8x\n", v32); v32 = file_header.read_4bytes(); cout << " compressed size: " << v32 << endl; v32 = file_header.read_4bytes(); cout << " uncompressed size: " << v32 << endl; size_t filename_len = file_header.read_2bytes(); cout << " filename length: " << filename_len << endl; uint16_t extra_field_len = file_header.read_2bytes(); cout << " extra field length: " << extra_field_len << endl; if (filename_len) { string filename = file_header.read_string(filename_len); cout << " filename: '" << filename << "'" << endl; } if (extra_field_len) { // Ignore extra field. file_header.skip_bytes(extra_field_len); } // Header followed by the actual data bytes. m_stream->seek(file_header.tell()); vector<unsigned char> buf; if (read_file_entry(param.filename, buf)) { cout << "-- data section" << endl; cout << &buf[0] << endl; cout << "--" << endl; } }
void zip_archive_stream_blob::read(unsigned char* buffer, size_t length) const { if (!length) return; // First, make sure we have enough blob to satisfy the requested stream length. const size_t length_available = m_size - tell(); if (length_available < length) throw zip_error("There is not enough stream left to fill requested length."); memcpy(buffer, m_cur, length); }
zip_archive_stream_fd::zip_archive_stream_fd(const char* filepath) : m_stream(fopen(filepath, "rb")) { if (!m_stream) { // Fail early at instantiation time. ostringstream os; os << "failed to open " << filepath << " for reading"; throw zip_error(os.str()); } }
void zip_archive_impl::load() { size_t central_dir_end_pos = seek_central_dir(); if (!central_dir_end_pos) throw zip_error(); m_central_dir_end = zip_stream_parser(m_stream, central_dir_end_pos); // Read the end part of the central directory. read_central_dir_end(); // Read file entries that are in the front part of the central directory. read_file_entries(); }
bool zip_archive_impl::read_file_entry(const pstring& entry_name, vector<unsigned char>& buf) const { pstring name(entry_name); filename_map_type::const_iterator it = m_filenames.find(name); if (it == m_filenames.end()) // entry name not found. return false; size_t index = it->second; if (index >= m_file_params.size()) // entry index is out of bound. return false; const zip_file_param& param = m_file_params[index]; // Skip the file header section. zip_stream_parser file_header(m_stream, param.offset_file_header); file_header.skip_bytes(4); file_header.skip_bytes(2); file_header.skip_bytes(2); file_header.skip_bytes(2); file_header.skip_bytes(2); file_header.skip_bytes(2); file_header.skip_bytes(4); file_header.skip_bytes(4); file_header.skip_bytes(4); uint16_t filename_len = file_header.read_2bytes(); uint16_t extra_field_len = file_header.read_2bytes(); file_header.skip_bytes(filename_len); file_header.skip_bytes(extra_field_len); // Data section is immediately followed by the header section. m_stream->seek(file_header.tell()); vector<unsigned char> raw_buf(param.size_compressed+1, 0); m_stream->read(&raw_buf[0], param.size_compressed); switch (param.compress_method) { case zip_file_param::stored: // Not compressed at all. buf.swap(raw_buf); return true; case zip_file_param::deflated: { // deflate compression vector<unsigned char> zip_buf(param.size_uncompressed+1, 0); // null-terminated zip_inflater inflater(raw_buf, zip_buf, param); if (!inflater.init()) break; if (!inflater.inflate()) throw zip_error("error during inflate."); buf.swap(zip_buf); return true; } default: ; } return false; }
void zip_archive_stream_fd::read(unsigned char* buffer, size_t length) const { size_t size_read = fread(buffer, 1, length, m_stream); if (size_read != length) throw zip_error("actual size read doesn't match what was expected."); }