VFS_NAMESPACE_START // From miniz.c //#define MZ_ZIP_MODE_READING 2 static bool zip_reader_reopen_vfsfile(mz_zip_archive *pZip, mz_uint32 flags) { if(!(pZip && pZip->m_pIO_opaque && pZip->m_pRead)) return false; VFSFile *vf = (VFSFile*)pZip->m_pIO_opaque; if(!vf->isopen()) if(!vf->open("rb")) return false; if(pZip->m_zip_mode == MZ_ZIP_MODE_READING) return true; mz_uint64 file_size = vf->size(); if(!file_size) { vf->close(); return false; } if (!mz_zip_reader_init(pZip, file_size, flags)) { vf->close(); return false; } return true; }
ZipReader::ZipReader(const Path &p) : _path(p), _in(FileUtils::openInputStream(p)) { if (!_in) FAIL("Failed to construct ZipReader: Input stream is invalid"); uint64 size = FileUtils::fileSize(p); if (size == 0) FAIL("Failed to construct ZipReader: Error reading file size"); std::memset(&_archive, 0, sizeof(mz_zip_archive)); _archive.m_pRead = &minizFileReadFunc; _archive.m_pIO_opaque = _in.get(); if (!mz_zip_reader_init(&_archive, size, 0)) FAIL("Initializing zip reader failed"); int count = mz_zip_reader_get_num_files(&_archive); for (int i = 0; i < count; ++i) { mz_zip_archive_file_stat stat; mz_zip_reader_file_stat(&_archive, i, &stat); ZipEntry entry; entry.fullPath = Path(stat.m_filename); entry.name = entry.fullPath.fileName(); entry.size = stat.m_uncomp_size; entry.isDirectory = !entry.fullPath.empty() && entry.fullPath.asString().back() == '/'; entry.archiveIndex = i; addPath(Path(stat.m_filename).stripSeparator(), std::move(entry)); } }
static bool zip_reader_init_vfsfile(mz_zip_archive *pZip, VFSFile *vf, mz_uint32 flags) { if(!(pZip || vf)) return false; vf->open("rb"); mz_uint64 file_size = vf->size(); if(!file_size) { vf->close(); return false; } pZip->m_pRead = zip_read_func; pZip->m_pIO_opaque = vf; if (!mz_zip_reader_init(pZip, file_size, flags)) { vf->close(); return false; } return true; }
static int lmz_reader_init(lua_State* L) { const char* path = luaL_checkstring(L, 1); mz_uint32 flags = luaL_optint(L, 2, 0); mz_uint64 size; lmz_file_t* zip = lua_newuserdata(L, sizeof(*zip)); mz_zip_archive* archive = &(zip->archive); luaL_getmetatable(L, "miniz_reader"); lua_setmetatable(L, -2); memset(archive, 0, sizeof(*archive)); zip->loop = uv_default_loop(); zip->fd = uv_fs_open(zip->loop, &(zip->req), path, O_RDONLY, 0644, NULL); uv_fs_fstat(zip->loop, &(zip->req), zip->fd, NULL); size = zip->req.statbuf.st_size; archive->m_pRead = lmz_file_read; archive->m_pIO_opaque = zip; if (!mz_zip_reader_init(archive, size, flags)) { lua_pushnil(L); lua_pushfstring(L, "read %s fail because of %s", path, mz_zip_get_error_string(mz_zip_get_last_error(archive))); return 2; } return 1; }
adapt_serving_context* adapt_start_serving(adapt_callback* callback) { int tries; int file_index; char* rewrites = 0; char* document_root = 0; adapt_serving_context* context = (adapt_serving_context*)calloc(sizeof(adapt_serving_context), 1); time_t timeval; adapt_resource_init(); time(&timeval); sprintf(context->content_prefix, "/E%lx/", timeval); sprintf(context->html_prefix, "/H%lx/", timeval); sprintf(context->msg_url, "/M%lx", timeval); context->callback = callback; if (callback->packaging_type == ADAPT_PACKAGE_ZIP) { context->zip.m_pRead = adapt_file_read_func; context->zip.m_pIO_opaque = callback; if (!mz_zip_reader_init(&context->zip, callback->content_length, MZ_ZIP_FLAG_CASE_SENSITIVE)) { free(context); return NULL; } // Check if this is an epub file. file_index = mz_zip_reader_locate_file(&context->zip, "META-INF/container.xml", NULL, MZ_ZIP_FLAG_CASE_SENSITIVE); context->content_type = TYPE_UNKNOWN; if (file_index >= 0) { // This looks like epub context->content_type = TYPE_OPF; } else { // This is not an epub. Maybe fb2.zip? mz_zip_archive_file_stat file_info; if (mz_zip_reader_file_stat(&context->zip, 0, &file_info)) { const char* filename = file_info.m_filename; size_t len = strlen(filename); if (len > 4 && strcmp(filename + len - 4, ".fb2") == 0) { // This is FB2 file context->content_type = TYPE_XML; context->content = strcpy((char*)malloc(strlen(filename) + 1), filename); } } } } else if (callback->packaging_type == ADAPT_PACKAGE_FILE_SYSTEM) { size_t len; char* container_name; char* end; if (!callback->base_path) { free(context); return NULL; } // Go through the parent folder chain trying to find META-INF/container.xml (that will serve as // the package root) len = strlen(callback->base_path); container_name = (char*)malloc(len + 25); strcpy(container_name, callback->base_path); end = container_name + len; do { char * q = end - 1; while (container_name + 3 < q && *q != '/') { q--; } if (*q != '/') { break; } end = q; strcpy(end + 1, "META-INF/container.xml"); } while (!file_exists(container_name)); if (*end != '/') { free(context); return NULL; } if (len < 4 || strcmp(callback->base_path + len - 4, ".opf") == 0) { context->content_type = TYPE_OPF; } else { size_t prefix_len = (end - container_name + 1); const char* path = callback->base_path + prefix_len; context->content = strcpy((char*)malloc(strlen(path) + 1), path); context->content_type = TYPE_XML; context->prefix_len = prefix_len; } end[1] = '\0'; rewrites = (char*)malloc(strlen(container_name) + strlen(context->content_prefix) + 2); sprintf(rewrites, "%s=%s", context->content_prefix, container_name); document_root = container_name; } else if (callback->packaging_type == ADAPT_PACKAGE_SINGLE_FILE) { // Assume it's FB2 context->content_type = TYPE_XML; context->content = strcpy((char*)malloc(9), "file.fb2"); } if (context->content_type == TYPE_UNKNOWN) { adapt_stop_serving(context); return NULL; } context->server_callbacks.begin_request = adapt_serve; context->options = (char**)calloc(sizeof(char*), 7); context->options[0] = strcpy((char*)malloc(16), "listening_ports"); context->options[1] = (char*)calloc(100, 1); if (rewrites) { context->options[2] = strcpy((char*)malloc(24), "url_rewrite_patterns"); context->options[3] = rewrites; context->options[4] = strcpy((char*)malloc(24), "document_root"); context->options[5] = document_root; } tries = 0; do { sprintf(context->options[1], "127.0.0.1:%d", adapt_port); context->server_context = mg_start(&context->server_callbacks, context, (const char**)context->options); sprintf(context->bootstrap_url, "http://127.0.0.1:%d%sdriver.xhtml", adapt_port, context->html_prefix); adapt_port++; tries++; } while (!context->server_context && tries < 10); return context; }