static int Lreader_locate_file(lua_State *L) { mz_zip_archive *za = luaL_checkudata(L, 1, LMZ_ZIP_READER); const char *path = luaL_checkstring(L, 2); mz_uint32 flags = (mz_uint32)luaL_optinteger(L, 3, 0); int index = mz_zip_reader_locate_file(za, path, NULL, flags); if (index < 0) return lmz_zip_pusherror(L, za, path); lua_pushinteger(L, index + 1); return 1; }
static int lmz_reader_locate_file(lua_State *L) { lmz_file_t* zip = luaL_checkudata(L, 1, "miniz_reader"); const char *path = luaL_checkstring(L, 2); mz_uint32 flags = luaL_optint(L, 3, 0); int index = mz_zip_reader_locate_file(&(zip->archive), path, NULL, flags); if (index < 0) { lua_pushnil(L); lua_pushfstring(L, "Can't find file %s.", path); return 2; } lua_pushinteger(L, index + 1); return 1; }
// open archived file bool ZipIO::openFile(const std::string &FileName){ _kfname = ""; _kready = false; if (!_kisopen) return false; // file is ready for writing if (_kmode == OpenMode::WRITE || _kmode == OpenMode::APPEND) { _kfname = FileName; _kready = true; return true; } // check for reading if ((_kfindex = mz_zip_reader_locate_file(&_kzarchive, FileName.c_str(), NULL, 0)) < 0) return false; return openFile(_kfindex); }
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; }
static int adapt_serve_zip_metadata(const char* method, struct mg_connection* connection, adapt_serving_context* context, const char* item) { if (strcmp(item, "list") == 0 && strcmp(method, "GET") == 0) { // URL-encoding may turn one character into three. char name_buffer[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE * 3 + 4]; int file_index = 0; mz_zip_archive_file_stat file_info; const char* sep = ""; mg_printf(connection, "HTTP/1.1 200 Success\r\n" "Content-Type: text/plain\r\n" "\r\n["); while (mz_zip_reader_file_stat(&context->zip, file_index, &file_info)) { ++file_index; url_encode_name(file_info.m_filename, name_buffer, sizeof name_buffer); mg_printf(connection, "%s{\"n\":\"%s\",\"m\":%d,\"c\":%llu,\"u\":%llu}", sep, name_buffer, file_info.m_method, file_info.m_comp_size, file_info.m_uncomp_size); sep = ","; } mg_printf(connection, "]\r\n"); return 1; } else if (strcmp(item, "manifest") == 0 && strcmp(method, "POST") == 0) { char file_name[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE+1]; int len = 0; char* buf = adapt_read_connection(connection, &len); if (buf) { char* s = buf; int file_index; if (!context->file_info) { int file_count = mz_zip_reader_get_num_files(&context->zip); context->file_info = (struct adapt_file_info*)calloc(sizeof(struct adapt_file_info), file_count); } while (1) { char* url = s; char* media_type; char* obfuscation_str = NULL; s = strpbrk(s, " \n"); if (!s) { break; } if (*s == '\n') { continue; } *s = '\0'; s++; url_decode_name(url, file_name, sizeof file_name); media_type = s; s = strpbrk(s, " \n"); if (!s) { break; } if (*s == ' ') { /* Have obfuscation data */ *s = '\0'; s++; obfuscation_str = s; s = strpbrk(s, " \n"); if (!s) { break; } if (*s != '\n') { /* Need to reach end of line */ *s = '\0'; s = strchr(s, '\n'); if (!s) { break; } } } *s = '\0'; s++; file_index = mz_zip_reader_locate_file(&context->zip, file_name, NULL, MZ_ZIP_FLAG_CASE_SENSITIVE); if (file_index >= 0) { struct adapt_file_info* file_info = &context->file_info[file_index]; adapt_file_info_clear(file_info); file_info->media_type = strcpy((char *)malloc(strlen(media_type) + 1), media_type); if (obfuscation_str) { char* sep = strchr(obfuscation_str, ':'); if (sep) { unsigned int length; *sep = '\0'; length = atoi(obfuscation_str); if (length < 2048) { /* Sanity check */ char* mask_hex = sep + 1; size_t mask_hex_length = strlen(mask_hex); if (mask_hex_length % 2 == 0 && mask_hex_length <= 128) { /* Sanity check */ unsigned int k; struct adapt_obfuscation* obfuscation = (struct adapt_obfuscation*)calloc(sizeof(struct adapt_obfuscation), 1); obfuscation->length = length; obfuscation->mask_length = (unsigned int)(mask_hex_length / 2); obfuscation->mask = (unsigned char *)calloc(1, obfuscation->mask_length); for (k = 0; k < mask_hex_length; k += 2) { char t[] = {mask_hex[k], mask_hex[k+1], '\0'}; obfuscation->mask[k/2] = (unsigned char)strtol(t, NULL, 16); } file_info->obfuscation = obfuscation; } } } } } } free(buf); } } return 0; }
static int adapt_serve_zip_entry(struct mg_connection* connection, adapt_serving_context* context, const char* file_name) { int file_index = mz_zip_reader_locate_file(&context->zip, file_name, NULL, MZ_ZIP_FLAG_CASE_SENSITIVE); mz_zip_archive_file_stat file_info; if (mz_zip_reader_file_stat(&context->zip, file_index, &file_info)) { if (file_index >= 0) { // Possible filters struct adapt_sink_connection sink_connection; struct adapt_sink_safari_bug filter_safari_bug; struct adapt_sink_deobfuscate filter_deobfuscate; struct adapt_sink_inflator filter_inflator; struct adapt_sink_woff filter_woff; // Build filter chain. char* media_type = context->file_info ? context->file_info[file_index].media_type : NULL; struct adapt_sink* sink = &sink_connection.super; int known_length = 1; int flush = 0; sink_connection.super.write = adapt_sink_connection_write; sink_connection.connection = connection; if (media_type && strcmp(media_type, "application/xhtml+xml") == 0) { filter_safari_bug.super.write = adapt_sink_safari_bug_write; filter_safari_bug.state = 1; filter_safari_bug.next = sink; sink = &filter_safari_bug.super; } else if (media_type && adapt_convert_to_woff && (strcmp(media_type, "application/x-font-truetype") == 0 || strcmp(media_type, "application/x-font-opentype") == 0 || strcmp(media_type, "application/vnd.ms-opentype") == 0 || strcmp(media_type, "font/truetype") == 0 || strcmp(media_type, "font/opentype") == 0)) { filter_woff.buffer = NULL; filter_woff.buffer_size = 0; filter_woff.buffer_used = 0; filter_woff.super.write = adapt_sink_woff_write; filter_woff.next = sink; sink = &filter_woff.super; known_length = 0; flush = 1; } if (context->file_info && context->file_info[file_index].obfuscation) { if (file_info.m_method == 0) { /* Stored and obfuscated: obfuscation applied after deflate. */ filter_inflator.super.write = adapt_sink_inflator_write; tinfl_init(&filter_inflator.inflator); filter_inflator.inflated_file_offset = 0; filter_inflator.buffer_offset = 0; filter_inflator.next = sink; sink = &filter_inflator.super; known_length = 0; flush = 1; } filter_deobfuscate.super.write = adapt_sink_deobfuscate_write; filter_deobfuscate.obfuscation = context->file_info[file_index].obfuscation; filter_deobfuscate.next = sink; sink = &filter_deobfuscate.super; } mg_printf(connection, "HTTP/1.1 200 Success\r\n"); if (known_length) { mg_printf(connection, "Content-Length: %d\r\n", (int)file_info.m_uncomp_size); } if (media_type) { mg_printf(connection, "Content-Type: %s\r\n\r\n", media_type); } else { mg_printf(connection, "\r\n"); } mz_zip_reader_extract_to_callback(&context->zip, file_index, adapt_sink_write, sink, MZ_ZIP_FLAG_CASE_SENSITIVE); if (flush) { sink->write(sink, (size_t)file_info.m_uncomp_size, NULL, 0); } return 1; } mg_printf(connection, "HTTP/1.1 404 Not found\r\n" "Content-Length: 0\r\n" "\r\n"); return 1; } return 0; }
bool fe_zip_open_to_buff( const char *archive, const char *filename, FE_ZIP_ALLOC_CALLBACK callback, void **buff, size_t *buff_size ) { ASSERT( buff != NULL ); mz_zip_archive zip; memset( &zip, 0, sizeof( zip ) ); if ( !mz_zip_reader_init_file( &zip, archive, 0 ) ) { std::cerr << "Error initializing zip. zip: " << archive << std::endl; return false; } int index = mz_zip_reader_locate_file( &zip, filename, NULL, 0 ); if ( index < 0 ) { std::cerr << "Error locating file. zip: " << archive << ", file: " << filename << std::endl; mz_zip_reader_end( &zip ); return false; } mz_zip_archive_file_stat file_stat; if ( !mz_zip_reader_file_stat(&zip, index, &file_stat) ) { std::cerr << "Error reading filestats. zip: " << archive << ", file: " << filename << std::endl; mz_zip_reader_end( &zip ); return false; } void *tb = callback( file_stat.m_uncomp_size ); if ( tb == NULL ) { std::cerr << "Error allocating zip buffer. zip: " << archive << ", file: " << filename << std::endl; mz_zip_reader_end( &zip ); return false; } if ( !mz_zip_reader_extract_to_mem( &zip, index, tb, file_stat.m_uncomp_size, 0 ) ) { std::cerr << "Error extracting to buffer. zip: " << archive << ", file: " << filename << std::endl; mz_zip_reader_end( &zip ); delete (char *)tb; return false; } mz_zip_reader_end( &zip ); *buff = tb; if ( buff_size ) *buff_size = file_stat.m_uncomp_size; return true; }
I32 ZipIO::searchFile(const std::string &FileName){ if (!_kisopen || _kmode == OpenMode::WRITE) return -1; return mz_zip_reader_locate_file(&_kzarchive, FileName.c_str(), NULL, 0); }