From 8212dd4b23576772894b30bce0956be58d0d7773 Mon Sep 17 00:00:00 2001
From: simon987 <me@simon987.net>
Date: Sat, 27 Feb 2021 15:23:56 -0500
Subject: [PATCH] wip

---
 libscan/arc/arc.c     | 10 ++++++++--
 libscan/arc/arc.h     |  3 ++-
 libscan/comic/comic.c | 13 +++++++------
 test/main.cpp         | 14 ++++++++++++++
 4 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/libscan/arc/arc.c b/libscan/arc/arc.c
index 3e1b927..f59fcbf 100644
--- a/libscan/arc/arc.c
+++ b/libscan/arc/arc.c
@@ -47,19 +47,25 @@ int arc_read(struct vfile *f, void *buf, size_t size) {
     return read;
 }
 
-int arc_open(vfile_t *f, struct archive **a, arc_data_t *arc_data, int allow_recurse) {
+int arc_open(scan_arc_ctx_t *ctx, vfile_t *f, struct archive **a, arc_data_t *arc_data, int allow_recurse) {
     arc_data->f = f;
 
     if (f->is_fs_file) {
         *a = archive_read_new();
         archive_read_support_filter_all(*a);
         archive_read_support_format_all(*a);
+        if (ctx->passphrase[0] != 0) {
+            archive_read_add_passphrase(*a, ctx->passphrase);
+        }
 
        return archive_read_open_filename(*a, f->filepath, ARC_BUF_SIZE);
     } else if (allow_recurse) {
         *a = archive_read_new();
         archive_read_support_filter_all(*a);
         archive_read_support_format_all(*a);
+        if (ctx->passphrase[0] != 0) {
+            archive_read_add_passphrase(*a, ctx->passphrase);
+        }
 
         return archive_read_open(
                 *a, arc_data,
@@ -80,7 +86,7 @@ scan_code_t parse_archive(scan_arc_ctx_t *ctx, vfile_t *f, document_t *doc) {
     arc_data_t arc_data;
     arc_data.f = f;
 
-    int ret = arc_open(f, &a, &arc_data, ctx->mode == ARC_MODE_RECURSE);
+    int ret = arc_open(ctx, f, &a, &arc_data, ctx->mode == ARC_MODE_RECURSE);
     if (ret == ARC_SKIPPED) {
         return SCAN_OK;
     }
diff --git a/libscan/arc/arc.h b/libscan/arc/arc.h
index 5f7333b..371a4e0 100644
--- a/libscan/arc/arc.h
+++ b/libscan/arc/arc.h
@@ -20,6 +20,7 @@ typedef struct {
     log_callback_t log;
     logf_callback_t logf;
     store_callback_t store;
+    char passphrase[1024];
 } scan_arc_ctx_t;
 
 #define ARC_BUF_SIZE 8192
@@ -56,7 +57,7 @@ static int vfile_close_callback(struct archive *a, void *user_data) {
     return ARCHIVE_OK;
 }
 
-int arc_open(vfile_t *f, struct archive **a, arc_data_t *arc_data, int allow_recurse);
+int arc_open(scan_arc_ctx_t *ctx, vfile_t *f, struct archive **a, arc_data_t *arc_data, int allow_recurse);
 
 int should_parse_filtered_file(const char *filepath, int ext);
 
diff --git a/libscan/comic/comic.c b/libscan/comic/comic.c
index 9e0ffee..45bbec6 100644
--- a/libscan/comic/comic.c
+++ b/libscan/comic/comic.c
@@ -5,13 +5,14 @@
 #include <stdlib.h>
 #include <archive.h>
 
+static scan_arc_ctx_t arc_ctx = (scan_arc_ctx_t) {.passphrase = {0,}};
 
 void parse_comic(scan_comic_ctx_t *ctx, vfile_t *f, document_t *doc) {
     struct archive *a = NULL;
     struct archive_entry *entry = NULL;
     arc_data_t arc_data;
 
-    int ret = arc_open(f, &a, &arc_data, TRUE);
+    int ret = arc_open(&arc_ctx, f, &a, &arc_data, TRUE);
     if (ret != ARCHIVE_OK) {
         CTX_LOG_ERRORF(f->filepath, "(cbr.c) [%d] %s", ret, archive_error_string(a))
         archive_read_free(a);
@@ -21,17 +22,17 @@ void parse_comic(scan_comic_ctx_t *ctx, vfile_t *f, document_t *doc) {
     while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
         struct stat info = *archive_entry_stat(entry);
         if (S_ISREG(info.st_mode)) {
-            const char* utf8_name = archive_entry_pathname_utf8(entry);
-            const char* file_path = utf8_name == NULL ? archive_entry_pathname(entry) : utf8_name;
+            const char *utf8_name = archive_entry_pathname_utf8(entry);
+            const char *file_path = utf8_name == NULL ? archive_entry_pathname(entry) : utf8_name;
 
             char *p = strrchr(file_path, '.');
             if (p != NULL && strcmp(p, ".png") == 0 || strcmp(p, ".jpg") == 0 || strcmp(p, ".jpeg") == 0) {
                 size_t entry_size = archive_entry_size(entry);
-                void* buf = malloc(entry_size);
+                void *buf = malloc(entry_size);
                 int read = archive_read_data(a, buf, entry_size);
 
                 if (read != entry_size) {
-                    const char* err_str = archive_error_string(a);
+                    const char *err_str = archive_error_string(a);
                     if (err_str) {
                         CTX_LOG_ERRORF("comic.c", "Error while reading entry: %s", err_str)
                     }
@@ -39,7 +40,7 @@ void parse_comic(scan_comic_ctx_t *ctx, vfile_t *f, document_t *doc) {
                     break;
                 }
 
-                ret = store_image_thumbnail((scan_media_ctx_t*)ctx, buf, entry_size, doc, file_path);
+                ret = store_image_thumbnail((scan_media_ctx_t *) ctx, buf, entry_size, doc, file_path);
                 free(buf);
 
                 if (ret == TRUE) {
diff --git a/test/main.cpp b/test/main.cpp
index 8ad0c33..6da8840 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -595,6 +595,20 @@ TEST(Arc, Utf8) {
     cleanup(&doc, &f);
 }
 
+TEST(Arc, EncryptedZip) {
+    vfile_t f;
+    document_t doc;
+    load_doc_file("libscan-test-files/test_files/arc/encrypted.zip", &f, &doc);
+
+    size_t size_before = store_size;
+
+    parse_archive(&arc_recurse_media_ctx, &f, &doc);
+
+    ASSERT_NE(size_before, store_size);
+
+    cleanup(&doc, &f);
+}
+
 /* RAW */
 TEST(RAW, Panasonic) {
     vfile_t f;