From 8e90a9624c8dbcb26a0eb258a6c46f072fe7c3cc Mon Sep 17 00:00:00 2001 From: Hai Zhang Date: Sat, 30 Sep 2023 19:45:48 -0700 Subject: [PATCH] [Feature] Support creating encrypted ZIP archives. --- .../filelist/CreateArchiveDialogFragment.kt | 38 +++++++++++++++---- .../provider/archive/archiver/WriteArchive.kt | 4 ++ .../main/res/layout/create_archive_dialog.xml | 18 +++++++++ app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values-zh-rTW/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 6 files changed, 56 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/me/zhanghai/android/files/filelist/CreateArchiveDialogFragment.kt b/app/src/main/java/me/zhanghai/android/files/filelist/CreateArchiveDialogFragment.kt index 15263dc32..08e10d092 100644 --- a/app/src/main/java/me/zhanghai/android/files/filelist/CreateArchiveDialogFragment.kt +++ b/app/src/main/java/me/zhanghai/android/files/filelist/CreateArchiveDialogFragment.kt @@ -12,7 +12,9 @@ import android.view.View import android.widget.EditText import android.widget.RadioGroup import androidx.annotation.StringRes +import androidx.core.view.isGone import androidx.fragment.app.Fragment +import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputLayout import kotlinx.parcelize.Parcelize import me.zhanghai.android.files.R @@ -23,6 +25,7 @@ import me.zhanghai.android.files.util.args import me.zhanghai.android.files.util.putArgs import me.zhanghai.android.files.util.setTextWithSelection import me.zhanghai.android.files.util.show +import me.zhanghai.android.files.util.takeIfNotEmpty import me.zhanghai.android.libarchive.Archive class CreateArchiveDialogFragment : FileNameDialogFragment() { @@ -50,6 +53,8 @@ class CreateArchiveDialogFragment : FileNameDialogFragment() { } name?.let { binding.nameEdit.setTextWithSelection(it) } } + binding.typeGroup.setOnCheckedChangeListener { _, _ -> updatePasswordLayoutVisibility() } + updatePasswordLayoutVisibility() return dialog } @@ -61,23 +66,39 @@ class CreateArchiveDialogFragment : FileNameDialogFragment() { override val name: String get() { - val extension = when (val typeId = binding.typeGroup.checkedRadioButtonId) { + val extension = when (val checkedId = binding.typeGroup.checkedRadioButtonId) { R.id.zipRadio -> "zip" R.id.tarXzRadio -> "tar.xz" R.id.sevenZRadio -> "7z" - else -> throw AssertionError(typeId) + else -> throw AssertionError(checkedId) } return "${super.name}.$extension" } + private val isPasswordSupported: Boolean + get() = when (val checkedId = binding.typeGroup.checkedRadioButtonId) { + R.id.zipRadio -> true + R.id.tarXzRadio, R.id.sevenZRadio -> false + else -> throw AssertionError(checkedId) + } + + private fun updatePasswordLayoutVisibility() { + binding.passwordLayout.isGone = !isPasswordSupported + } + override fun onOk(name: String) { - val (format, filter) = when (val typeId = binding.typeGroup.checkedRadioButtonId) { + val (format, filter) = when (val checkedId = binding.typeGroup.checkedRadioButtonId) { R.id.zipRadio -> Archive.FORMAT_ZIP to Archive.FILTER_NONE R.id.tarXzRadio -> Archive.FORMAT_TAR to Archive.FILTER_XZ R.id.sevenZRadio -> Archive.FORMAT_7ZIP to Archive.FILTER_NONE - else -> throw AssertionError(typeId) + else -> throw AssertionError(checkedId) + } + val password = if (isPasswordSupported) { + binding.passwordEdit.text!!.toString().takeIfNotEmpty() + } else { + null } - listener.archive(args.files, name, format, filter, null) + listener.archive(args.files, name, format, filter, password) } companion object { @@ -93,7 +114,9 @@ class CreateArchiveDialogFragment : FileNameDialogFragment() { root: View, nameLayout: TextInputLayout, nameEdit: EditText, - val typeGroup: RadioGroup + val typeGroup: RadioGroup, + val passwordLayout: TextInputLayout, + val passwordEdit: TextInputEditText ) : NameDialogFragment.Binding(root, nameLayout, nameEdit) { companion object { fun inflate(inflater: LayoutInflater): Binding { @@ -101,7 +124,8 @@ class CreateArchiveDialogFragment : FileNameDialogFragment() { val bindingRoot = binding.root val nameBinding = NameDialogNameIncludeBinding.bind(bindingRoot) return Binding( - bindingRoot, nameBinding.nameLayout, nameBinding.nameEdit, binding.typeGroup + bindingRoot, nameBinding.nameLayout, nameBinding.nameEdit, binding.typeGroup, + binding.passwordLayout, binding.passwordEdit ) } } diff --git a/app/src/main/java/me/zhanghai/android/files/provider/archive/archiver/WriteArchive.kt b/app/src/main/java/me/zhanghai/android/files/provider/archive/archiver/WriteArchive.kt index 42781ef8a..c17424201 100644 --- a/app/src/main/java/me/zhanghai/android/files/provider/archive/archiver/WriteArchive.kt +++ b/app/src/main/java/me/zhanghai/android/files/provider/archive/archiver/WriteArchive.kt @@ -37,7 +37,11 @@ class WriteArchive @Throws(ArchiveException::class) constructor( Archive.writeSetFormat(archive, format) Archive.writeAddFilter(archive, filter) if (password != null) { + require(format == Archive.FORMAT_ZIP) Archive.writeSetPassphrase(archive, password.toByteArray()) + Archive.writeSetFormatOption( + archive, null, "encryption".toByteArray(), "zipcrypt".toByteArray() + ) } Archive.writeOpen( archive, null, null, { _, _, buffer -> channel.write(buffer) }, null diff --git a/app/src/main/res/layout/create_archive_dialog.xml b/app/src/main/res/layout/create_archive_dialog.xml index a6cfeffb6..724e0a007 100644 --- a/app/src/main/res/layout/create_archive_dialog.xml +++ b/app/src/main/res/layout/create_archive_dialog.xml @@ -7,6 +7,7 @@ @@ -61,6 +62,23 @@ android:textAppearance="?textAppearanceListItem" android:visibility="@integer/create_archive_type_seven_z_visibility" /> + + + + + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index d9fdfa08b..44d8225cf 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -230,6 +230,7 @@ .zip .tar.xz .7z + 密码(可选) 已添加书签 新建文件 新建文件夹 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 9694ed0f0..223befefa 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -230,6 +230,7 @@ .zip .tar.xz .7z + 密碼(選填) 已新增書籤 新檔案 新資料夾 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7d99bffff..47efb246a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -259,6 +259,7 @@ .zip .tar.xz .7z + Password (optional) Bookmark added New file New folder