From 220ff7ae4178cbf1c04e6ab47197a25514c50555 Mon Sep 17 00:00:00 2001 From: Thomas Taschauer <128734+TomTasche@users.noreply.github.com> Date: Sun, 21 Dec 2025 10:24:41 +0100 Subject: [PATCH 1/2] add test to verify if sheet names are used for tab labels --- .../androidTest/assets/spreadsheet-test.ods | Bin 0 -> 8567 bytes .../at/tomtasche/reader/test/CoreTest.java | 32 ++++++++++++++++++ app/src/main/cpp/core_wrapper.cpp | 13 +++++++ 3 files changed, 45 insertions(+) create mode 100644 app/src/androidTest/assets/spreadsheet-test.ods diff --git a/app/src/androidTest/assets/spreadsheet-test.ods b/app/src/androidTest/assets/spreadsheet-test.ods new file mode 100644 index 0000000000000000000000000000000000000000..993fe107568f00e944aa0c1c4124a75c6f397ce4 GIT binary patch literal 8567 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 XmVz|=BYJuCk&i!uM}#2>dg}cTY>7T| literal 0 HcmV?d00001 diff --git a/app/src/androidTest/java/at/tomtasche/reader/test/CoreTest.java b/app/src/androidTest/java/at/tomtasche/reader/test/CoreTest.java index 7ed1d192b4e7..28a4ba4decff 100644 --- a/app/src/androidTest/java/at/tomtasche/reader/test/CoreTest.java +++ b/app/src/androidTest/java/at/tomtasche/reader/test/CoreTest.java @@ -26,6 +26,7 @@ public class CoreTest { private File m_testFile; private File m_passwordTestFile; + private File m_spreadsheetTestFile; @Before public void initializeCore() { @@ -47,6 +48,10 @@ public void extractTestFile() throws IOException { try (InputStream inputStream = assetManager.open("password-test.odt")) { copy(inputStream, m_passwordTestFile); } + m_spreadsheetTestFile = new File(appCtx.getCacheDir(), "spreadsheet-test.ods"); + try (InputStream inputStream = assetManager.open("spreadsheet-test.ods")) { + copy(inputStream, m_spreadsheetTestFile); + } } @After @@ -57,6 +62,9 @@ public void cleanupTestFile() { if (null != m_passwordTestFile) { m_passwordTestFile.delete(); } + if (null != m_spreadsheetTestFile) { + m_spreadsheetTestFile.delete(); + } } private static void copy(InputStream src, File dst) throws IOException { @@ -142,4 +150,28 @@ public void testPasswordProtectedDocumentWithCorrectPassword() { CoreWrapper.CoreResult coreResult = CoreWrapper.parse(coreOptions); Assert.assertEquals(0, coreResult.errorCode); } + + @Test + public void testSpreadsheetSheetNames() { + File cacheDir = InstrumentationRegistry.getInstrumentation().getTargetContext().getCacheDir(); + File outputPath = new File(cacheDir, "spreadsheet_output"); + File cachePath = new File(cacheDir, "spreadsheet_cache"); + + CoreWrapper.CoreOptions coreOptions = new CoreWrapper.CoreOptions(); + coreOptions.inputPath = m_spreadsheetTestFile.getAbsolutePath(); + coreOptions.outputPath = outputPath.getPath(); + coreOptions.editable = false; + coreOptions.cachePath = cachePath.getPath(); + + CoreWrapper.CoreResult coreResult = CoreWrapper.parse(coreOptions); + Assert.assertEquals("CoreWrapper should successfully parse the ODS file", 0, coreResult.errorCode); + + // Verify we have exactly 3 sheets + Assert.assertEquals("ODS file should contain 3 sheets", 3, coreResult.pageNames.size()); + + // Verify sheet names match the actual sheet names from the ODS file + Assert.assertEquals("First sheet should be named 'hey'", "hey", coreResult.pageNames.get(0)); + Assert.assertEquals("Second sheet should be named 'ho'", "ho", coreResult.pageNames.get(1)); + Assert.assertEquals("Third sheet should be named 'Sheet3'", "Sheet3", coreResult.pageNames.get(2)); + } } diff --git a/app/src/main/cpp/core_wrapper.cpp b/app/src/main/cpp/core_wrapper.cpp index 372b19ebbfdf..5575d9328bda 100644 --- a/app/src/main/cpp/core_wrapper.cpp +++ b/app/src/main/cpp/core_wrapper.cpp @@ -221,6 +221,19 @@ Java_at_tomtasche_reader_background_CoreWrapper_parseNative(JNIEnv *env, jclass std::filesystem::remove_all(cachePathCpp); for (const odr::HtmlPage &page: html.pages()) { + // Filter out unwanted views based on document type + if (file.is_document_file() && ( + (((file.as_document_file().document_type() == + odr::DocumentType::presentation) || + (file.as_document_file().document_type() == + odr::DocumentType::drawing)) && + (page.name != "document")) || + ((file.as_document_file().document_type() == + odr::DocumentType::spreadsheet) && + (page.name == "document")))) { + continue; + } + jstring pageName = env->NewStringUTF(page.name.c_str()); env->CallBooleanMethod(pageNames, addMethod, pageName); From 1b400c9b93a81367c83395d8128bb435148b3b06 Mon Sep 17 00:00:00 2001 From: Thomas Taschauer <128734+TomTasche@users.noreply.github.com> Date: Sun, 21 Dec 2025 10:43:47 +0100 Subject: [PATCH 2/2] remove core file mode --- .../at/tomtasche/reader/test/CoreTest.java | 51 +++++- app/src/main/cpp/core_wrapper.cpp | 156 ------------------ app/src/main/cpp/core_wrapper.hpp | 4 - .../reader/background/CoreLoader.java | 76 +++------ .../reader/background/CoreWrapper.java | 31 ---- .../reader/background/LoaderService.java | 2 +- .../reader/background/RawLoader.java | 5 +- 7 files changed, 68 insertions(+), 257 deletions(-) diff --git a/app/src/androidTest/java/at/tomtasche/reader/test/CoreTest.java b/app/src/androidTest/java/at/tomtasche/reader/test/CoreTest.java index 28a4ba4decff..88ff51c4435b 100644 --- a/app/src/androidTest/java/at/tomtasche/reader/test/CoreTest.java +++ b/app/src/androidTest/java/at/tomtasche/reader/test/CoreTest.java @@ -8,8 +8,10 @@ import androidx.test.platform.app.InstrumentationRegistry; import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -24,14 +26,49 @@ @LargeTest @RunWith(AndroidJUnit4.class) public class CoreTest { + private static Thread serverThread; private File m_testFile; private File m_passwordTestFile; private File m_spreadsheetTestFile; - @Before - public void initializeCore() { + @BeforeClass + public static void startServer() throws InterruptedException { Context appCtx = InstrumentationRegistry.getInstrumentation().getTargetContext(); CoreWrapper.initialize(appCtx); + + // Create server cache directory + File serverCacheDir = new File(appCtx.getCacheDir(), "core/server"); + if (!serverCacheDir.isDirectory()) { + serverCacheDir.mkdirs(); + } + CoreWrapper.createServer(serverCacheDir.getAbsolutePath()); + + // Start server in background thread + serverThread = new Thread(() -> { + try { + CoreWrapper.listenServer(29665); + } catch (Exception e) { + e.printStackTrace(); + } + }); + serverThread.setDaemon(true); + serverThread.start(); + + // Give server time to start + Thread.sleep(1000); + } + + @AfterClass + public static void stopServer() { + CoreWrapper.stopServer(); + if (serverThread != null) { + serverThread.interrupt(); + } + } + + @Before + public void initializeCore() { + // Server is already initialized in @BeforeClass } @Before @@ -89,7 +126,7 @@ public void test() { coreOptions.editable = true; coreOptions.cachePath = cachePath.getPath(); - CoreWrapper.CoreResult coreResult = CoreWrapper.parse(coreOptions); + CoreWrapper.CoreResult coreResult = CoreWrapper.hostFile("test", coreOptions); Assert.assertEquals(0, coreResult.errorCode); File resultFile = new File(cacheDir, "result"); @@ -113,7 +150,7 @@ public void testPasswordProtectedDocumentWithoutPassword() { coreOptions.editable = false; coreOptions.cachePath = cachePath.getPath(); - CoreWrapper.CoreResult coreResult = CoreWrapper.parse(coreOptions); + CoreWrapper.CoreResult coreResult = CoreWrapper.hostFile("password-test-no-pw", coreOptions); Assert.assertEquals(-2, coreResult.errorCode); } @@ -130,7 +167,7 @@ public void testPasswordProtectedDocumentWithWrongPassword() { coreOptions.editable = false; coreOptions.cachePath = cachePath.getPath(); - CoreWrapper.CoreResult coreResult = CoreWrapper.parse(coreOptions); + CoreWrapper.CoreResult coreResult = CoreWrapper.hostFile("password-test-wrong-pw", coreOptions); Assert.assertEquals(-2, coreResult.errorCode); } @@ -147,7 +184,7 @@ public void testPasswordProtectedDocumentWithCorrectPassword() { coreOptions.editable = false; coreOptions.cachePath = cachePath.getPath(); - CoreWrapper.CoreResult coreResult = CoreWrapper.parse(coreOptions); + CoreWrapper.CoreResult coreResult = CoreWrapper.hostFile("password-test-correct-pw", coreOptions); Assert.assertEquals(0, coreResult.errorCode); } @@ -163,7 +200,7 @@ public void testSpreadsheetSheetNames() { coreOptions.editable = false; coreOptions.cachePath = cachePath.getPath(); - CoreWrapper.CoreResult coreResult = CoreWrapper.parse(coreOptions); + CoreWrapper.CoreResult coreResult = CoreWrapper.hostFile("spreadsheet-test", coreOptions); Assert.assertEquals("CoreWrapper should successfully parse the ODS file", 0, coreResult.errorCode); // Verify we have exactly 3 sheets diff --git a/app/src/main/cpp/core_wrapper.cpp b/app/src/main/cpp/core_wrapper.cpp index 5575d9328bda..f0aafa601c4b 100644 --- a/app/src/main/cpp/core_wrapper.cpp +++ b/app/src/main/cpp/core_wrapper.cpp @@ -111,162 +111,6 @@ Java_at_tomtasche_reader_background_CoreWrapper_mimetypeNative(JNIEnv *env, jcla return mimetype; } -JNIEXPORT jobject JNICALL -Java_at_tomtasche_reader_background_CoreWrapper_parseNative(JNIEnv *env, jclass clazz, - jobject options) { - std::error_code ec; - auto logger = std::make_shared(); - - jclass resultClass = env->FindClass("at/tomtasche/reader/background/CoreWrapper$CoreResult"); - jmethodID resultConstructor = env->GetMethodID(resultClass, "", "()V"); - jobject result = env->NewObject(resultClass, resultConstructor); - - jfieldID errorField = env->GetFieldID(resultClass, "errorCode", "I"); - - jclass optionsClass = env->GetObjectClass(options); - std::string inputPathCpp = getStringField(env, optionsClass, options, "inputPath"); - - try { - std::optional passwordCpp; - jfieldID passwordField = env->GetFieldID(optionsClass, "password", "Ljava/lang/String;"); - auto password = (jstring) env->GetObjectField(options, passwordField); - if (password != nullptr) { - passwordCpp = convertString(env, password); - } - - jfieldID editableField = env->GetFieldID(optionsClass, "editable", "Z"); - jboolean editable = env->GetBooleanField(options, editableField); - - std::string outputPathCpp = getStringField(env, optionsClass, options, "outputPath"); - std::string cachePathCpp = getStringField(env, optionsClass, options, "cachePath"); - - jclass listClass = env->FindClass("java/util/List"); - jmethodID addMethod = env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z"); - - jfieldID pageNamesField = env->GetFieldID(resultClass, "pageNames", "Ljava/util/List;"); - auto pageNames = (jobject) env->GetObjectField(result, pageNamesField); - - jfieldID pagePathsField = env->GetFieldID(resultClass, "pagePaths", "Ljava/util/List;"); - auto pagePaths = (jobject) env->GetObjectField(result, pagePathsField); - - jfieldID ooxmlField = env->GetFieldID(optionsClass, "ooxml", "Z"); - jboolean ooxml = env->GetBooleanField(options, ooxmlField); - - jfieldID txtField = env->GetFieldID(optionsClass, "txt", "Z"); - jboolean txt = env->GetBooleanField(options, txtField); - - jfieldID pdfField = env->GetFieldID(optionsClass, "pdf", "Z"); - jboolean pdf = env->GetBooleanField(options, pdfField); - - jfieldID pagingField = env->GetFieldID(optionsClass, "paging", "Z"); - jboolean paging = env->GetBooleanField(options, pagingField); - - try { - odr::FileType fileType; - try { - const auto types = odr::list_file_types(inputPathCpp, *logger); - if (types.empty()) { - env->SetIntField(result, errorField, -5); - return result; - } - - fileType = types.back(); - } catch (odr::UnsupportedFileType &e) { - fileType = e.file_type; - } - - std::string extensionCpp = odr::file_type_to_string(fileType); - jstring extension = env->NewStringUTF(extensionCpp.c_str()); - jfieldID extensionField = env->GetFieldID(resultClass, "extension", - "Ljava/lang/String;"); - env->SetObjectField(result, extensionField, extension); - - __android_log_print(ANDROID_LOG_VERBOSE, "smn", "Open %s", inputPathCpp.c_str()); - - auto file = odr::open(inputPathCpp, *logger); - - if (file.password_encrypted()) { - if (!passwordCpp.has_value()) { - env->SetIntField(result, errorField, -2); - return result; - } - try { - file = file.decrypt(passwordCpp.value()); - } catch (...) { - env->SetIntField(result, errorField, -2); - return result; - } - } - - // .doc-files are not real documents in core - if (file.is_document_file() && fileType != odr::FileType::legacy_word_document) { - // TODO this will cause a second load - s_document = file.as_document_file().document(); - } - - extensionCpp = odr::file_type_to_string(file.file_type()); - extension = env->NewStringUTF(extensionCpp.c_str()); - env->SetObjectField(result, extensionField, extension); - - odr::HtmlConfig htmlConfig; - htmlConfig.editable = editable; - htmlConfig.text_document_margin = paging; - - __android_log_print(ANDROID_LOG_VERBOSE, "smn", "Translate to HTML"); - - std::filesystem::remove_all(cachePathCpp, ec); - std::filesystem::create_directories(cachePathCpp); - odr::HtmlService service = odr::html::translate(file, cachePathCpp, htmlConfig, logger); - odr::Html html = service.bring_offline(outputPathCpp); - std::filesystem::remove_all(cachePathCpp); - - for (const odr::HtmlPage &page: html.pages()) { - // Filter out unwanted views based on document type - if (file.is_document_file() && ( - (((file.as_document_file().document_type() == - odr::DocumentType::presentation) || - (file.as_document_file().document_type() == - odr::DocumentType::drawing)) && - (page.name != "document")) || - ((file.as_document_file().document_type() == - odr::DocumentType::spreadsheet) && - (page.name == "document")))) { - continue; - } - - jstring pageName = env->NewStringUTF(page.name.c_str()); - env->CallBooleanMethod(pageNames, addMethod, pageName); - - jstring pagePath = env->NewStringUTF(page.path.c_str()); - env->CallBooleanMethod(pagePaths, addMethod, pagePath); - } - } catch (const odr::UnknownFileType &e) { - __android_log_print(ANDROID_LOG_ERROR, "smn", "Unknown file type: %s", e.what()); - env->SetIntField(result, errorField, -5); - return result; - } catch (const odr::UnsupportedFileType &e) { - __android_log_print(ANDROID_LOG_ERROR, "smn", "Unsupported file type: %s", e.what()); - env->SetIntField(result, errorField, -5); - return result; - } catch (const std::exception &e) { - __android_log_print(ANDROID_LOG_ERROR, "smn", "Unhandled C++ exception: %s", e.what()); - env->SetIntField(result, errorField, -4); - return result; - } catch (...) { - __android_log_print(ANDROID_LOG_ERROR, "smn", - "Unhandled C++ exception without further information"); - env->SetIntField(result, errorField, -4); - return result; - } - } catch (...) { - env->SetIntField(result, errorField, -3); - return result; - } - - env->SetIntField(result, errorField, 0); - return result; -} - JNIEXPORT jobject JNICALL Java_at_tomtasche_reader_background_CoreWrapper_backtranslateNative(JNIEnv *env, jclass clazz, jobject options, diff --git a/app/src/main/cpp/core_wrapper.hpp b/app/src/main/cpp/core_wrapper.hpp index 8804ba1293a1..e79b7478dc5b 100644 --- a/app/src/main/cpp/core_wrapper.hpp +++ b/app/src/main/cpp/core_wrapper.hpp @@ -12,10 +12,6 @@ JNIEXPORT jstring JNICALL Java_at_tomtasche_reader_background_CoreWrapper_mimetypeNative(JNIEnv *env, jclass clazz, jstring path); -JNIEXPORT jobject JNICALL -Java_at_tomtasche_reader_background_CoreWrapper_parseNative(JNIEnv *env, jclass clazz, - jobject options); - JNIEXPORT jobject JNICALL Java_at_tomtasche_reader_background_CoreWrapper_backtranslateNative(JNIEnv *env, jclass clazz, jobject options, diff --git a/app/src/main/java/at/tomtasche/reader/background/CoreLoader.java b/app/src/main/java/at/tomtasche/reader/background/CoreLoader.java index 93701f9f124b..b753173c7560 100644 --- a/app/src/main/java/at/tomtasche/reader/background/CoreLoader.java +++ b/app/src/main/java/at/tomtasche/reader/background/CoreLoader.java @@ -19,38 +19,34 @@ public class CoreLoader extends FileLoader { private CoreWrapper.CoreOptions lastCoreOptions; private final boolean doOoxml; - private final boolean doHttp; private Thread httpThread; - public CoreLoader(Context context, ConfigManager configManager, boolean doOoxml, boolean doHttp) { + public CoreLoader(Context context, ConfigManager configManager, boolean doOoxml) { super(context, LoaderType.CORE); this.configManager = configManager; this.doOoxml = doOoxml; - this.doHttp = doHttp; CoreWrapper.initialize(context); } @Override public void initialize(FileLoaderListener listener, Handler mainHandler, Handler backgroundHandler, AnalyticsManager analyticsManager, CrashManager crashManager) { - if (doHttp) { - File serverCacheDir = new File(context.getCacheDir(), "core/server"); - if (!serverCacheDir.isDirectory() && !serverCacheDir.mkdirs()) { - Log.e("CoreLoader", "Failed to create cache directory for CoreWrapper server: " + serverCacheDir.getAbsolutePath()); - } - CoreWrapper.createServer(serverCacheDir.getAbsolutePath()); - - httpThread = new Thread(() -> { - try { - CoreWrapper.listenServer(29665); - } catch (Throwable e) { - crashManager.log(e); - } - }); - httpThread.start(); + File serverCacheDir = new File(context.getCacheDir(), "core/server"); + if (!serverCacheDir.isDirectory() && !serverCacheDir.mkdirs()) { + Log.e("CoreLoader", "Failed to create cache directory for CoreWrapper server: " + serverCacheDir.getAbsolutePath()); } + CoreWrapper.createServer(serverCacheDir.getAbsolutePath()); + + httpThread = new Thread(() -> { + try { + CoreWrapper.listenServer(29665); + } catch (Throwable e) { + crashManager.log(e); + } + }); + httpThread.start(); super.initialize(listener, mainHandler, backgroundHandler, analyticsManager, crashManager); } @@ -113,45 +109,15 @@ private void translate(Options options, Result result) throws Exception { lastCoreOptions = coreOptions; - if (doHttp) { - CoreWrapper.CoreResult coreResult = CoreWrapper.hostFile("odr", coreOptions); - - if (coreResult.exception != null) { - throw coreResult.exception; - } - - for (int i = 0; i < coreResult.pagePaths.size(); i++) { - result.partTitles.add(coreResult.pageNames.get(i)); - result.partUris.add(Uri.parse(coreResult.pagePaths.get(i))); - } - } else { - CoreWrapper.CoreResult coreResult = CoreWrapper.parse(coreOptions); - - String coreExtension = coreResult.extension; - if (coreResult.exception == null && "pdf".equals(coreExtension)) { - // some PDFs do not cause an error in the core - // https://github.com/opendocument-app/OpenDocument.droid/issues/348#issuecomment-2446888981 - throw new CoreWrapper.CoreCouldNotTranslateException(); - } else if (!"unnamed".equals(coreExtension)) { - // "unnamed" refers to default of Meta::typeToString - options.fileExtension = coreExtension; - - String fileType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(coreExtension); - if (fileType != null) { - options.fileType = fileType; - } - } + CoreWrapper.CoreResult coreResult = CoreWrapper.hostFile("odr", coreOptions); - if (coreResult.exception != null) { - throw coreResult.exception; - } - - for (int i = 0; i < coreResult.pagePaths.size(); i++) { - File entryFile = new File(coreResult.pagePaths.get(i)); + if (coreResult.exception != null) { + throw coreResult.exception; + } - result.partTitles.add(coreResult.pageNames.get(i)); - result.partUris.add(Uri.fromFile(entryFile)); - } + for (int i = 0; i < coreResult.pagePaths.size(); i++) { + result.partTitles.add(coreResult.pageNames.get(i)); + result.partUris.add(Uri.parse(coreResult.pagePaths.get(i))); } } diff --git a/app/src/main/java/at/tomtasche/reader/background/CoreWrapper.java b/app/src/main/java/at/tomtasche/reader/background/CoreWrapper.java index 37cbe6085a91..cfe2a2cbe068 100644 --- a/app/src/main/java/at/tomtasche/reader/background/CoreWrapper.java +++ b/app/src/main/java/at/tomtasche/reader/background/CoreWrapper.java @@ -74,37 +74,6 @@ public static class CoreOptions { public String cachePath; } - public static CoreResult parse(CoreOptions options) { - CoreResult result = parseNative(options); - - switch (result.errorCode) { - case 0: - break; - case -1: - result.exception = new CoreCouldNotOpenException(); - break; - case -2: - result.exception = new CoreEncryptedException(); - break; - case -3: - result.exception = new CoreUnknownErrorException(); - break; - case -4: - result.exception = new CoreCouldNotTranslateException(); - break; - case -5: - result.exception = new CoreUnexpectedFormatException(); - break; - default: - result.exception = new CoreUnexpectedErrorCodeException(); - break; - } - - return result; - } - - private static native CoreResult parseNative(CoreOptions options); - public static CoreResult backtranslate(CoreOptions options, String htmlDiff) { CoreResult result = backtranslateNative(options, htmlDiff); diff --git a/app/src/main/java/at/tomtasche/reader/background/LoaderService.java b/app/src/main/java/at/tomtasche/reader/background/LoaderService.java index cc9a574ac851..de8df8a428f1 100644 --- a/app/src/main/java/at/tomtasche/reader/background/LoaderService.java +++ b/app/src/main/java/at/tomtasche/reader/background/LoaderService.java @@ -57,7 +57,7 @@ public synchronized void onCreate() { metadataLoader = new MetadataLoader(context); metadataLoader.initialize(this, mainHandler, backgroundHandler, analyticsManager, crashManager); - coreLoader = new CoreLoader(context, configManager, true, true); + coreLoader = new CoreLoader(context, configManager, true); coreLoader.initialize(this, mainHandler, backgroundHandler, analyticsManager, crashManager); rawLoader = new RawLoader(context); diff --git a/app/src/main/java/at/tomtasche/reader/background/RawLoader.java b/app/src/main/java/at/tomtasche/reader/background/RawLoader.java index d274d5b53cdf..44584930fecf 100644 --- a/app/src/main/java/at/tomtasche/reader/background/RawLoader.java +++ b/app/src/main/java/at/tomtasche/reader/background/RawLoader.java @@ -141,13 +141,12 @@ public void loadSync(Options options) { coreOptions.txt = true; coreOptions.pdf = false; - CoreWrapper.CoreResult coreResult = lastCore.parse(coreOptions); + CoreWrapper.CoreResult coreResult = CoreWrapper.hostFile("raw-text", coreOptions); if (coreResult.exception != null) { throw coreResult.exception; } - File entryFile = new File(coreResult.pagePaths.get(0)); - finalUri = Uri.fromFile(entryFile); + finalUri = Uri.parse(coreResult.pagePaths.get(0)); } else if (fileType.startsWith("application/zip")) { File htmlFile = new File(cacheDirectory, "zip.html"); InputStream htmlPrefixStream = context.getAssets().open("zip-prefix.html");