예제 #1
0
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);
}
예제 #2
0
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)));
    }
}
예제 #3
0
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();
}
예제 #4
0
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);
}
예제 #5
0
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());
    }
}
예제 #6
0
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);
}
예제 #7
0
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;
}
예제 #8
0
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)));
    }
}
예제 #9
0
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;
    }
}
예제 #10
0
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);
}
예제 #11
0
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());
    }
}
예제 #12
0
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();
}
예제 #13
0
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;
}
예제 #14
0
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.");
}