Skip to content

Commit

Permalink
[Feature] Support creating encrypted ZIP archives.
Browse files Browse the repository at this point in the history
  • Loading branch information
zhanghai committed Oct 1, 2023
1 parent d30e85f commit 8e90a96
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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() {
Expand Down Expand Up @@ -50,6 +53,8 @@ class CreateArchiveDialogFragment : FileNameDialogFragment() {
}
name?.let { binding.nameEdit.setTextWithSelection(it) }
}
binding.typeGroup.setOnCheckedChangeListener { _, _ -> updatePasswordLayoutVisibility() }
updatePasswordLayoutVisibility()
return dialog
}

Expand All @@ -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 {
Expand All @@ -93,15 +114,18 @@ 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 {
val binding = CreateArchiveDialogBinding.inflate(inflater)
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
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions app/src/main/res/layout/create_archive_dialog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/abc_dialog_title_divider_material">
Expand Down Expand Up @@ -61,6 +62,23 @@
android:textAppearance="?textAppearanceListItem"
android:visibility="@integer/create_archive_type_seven_z_visibility" />
</me.zhanghai.android.files.filelist.CreateArchiveTypeRadioGroup>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/passwordLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="?dialogPreferredPadding"
android:layout_marginEnd="?dialogPreferredPadding"
android:layout_marginTop="4dp"
android:hint="@string/file_create_archive_password"
app:passwordToggleEnabled="true">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/passwordEdit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</FrameLayout>
1 change: 1 addition & 0 deletions app/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@
<string name="file_create_archive_type_zip">.zip</string>
<string name="file_create_archive_type_tar_xz">.tar.xz</string>
<string name="file_create_archive_type_7z">.7z</string>
<string name="file_create_archive_password">密码(可选)</string>
<string name="file_add_bookmark_success">已添加书签</string>
<string name="file_create_file_title">新建文件</string>
<string name="file_create_directory_title">新建文件夹</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@
<string name="file_create_archive_type_zip">.zip</string>
<string name="file_create_archive_type_tar_xz">.tar.xz</string>
<string name="file_create_archive_type_7z">.7z</string>
<string name="file_create_archive_password">密碼(選填)</string>
<string name="file_add_bookmark_success">已新增書籤</string>
<string name="file_create_file_title">新檔案</string>
<string name="file_create_directory_title">新資料夾</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@
<string name="file_create_archive_type_zip">.zip</string>
<string name="file_create_archive_type_tar_xz">.tar.xz</string>
<string name="file_create_archive_type_7z">.7z</string>
<string name="file_create_archive_password">Password (optional)</string>
<string name="file_add_bookmark_success">Bookmark added</string>
<string name="file_create_file_title">New file</string>
<string name="file_create_directory_title">New folder</string>
Expand Down

0 comments on commit 8e90a96

Please sign in to comment.