diff --git a/app/src/main/java/com/kunzisoft/keepass/adapters/EntryAttachmentsItemsAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/adapters/EntryAttachmentsItemsAdapter.kt index 0836ca0f3..5564af29b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/adapters/EntryAttachmentsItemsAdapter.kt +++ b/app/src/main/java/com/kunzisoft/keepass/adapters/EntryAttachmentsItemsAdapter.kt @@ -20,7 +20,10 @@ package com.kunzisoft.keepass.adapters import android.content.Context +import android.content.res.TypedArray +import android.graphics.Color import android.text.format.Formatter +import android.util.TypedValue import android.view.View import android.view.ViewGroup import android.widget.ImageView @@ -33,11 +36,24 @@ import com.kunzisoft.keepass.model.AttachmentState import com.kunzisoft.keepass.model.EntryAttachmentState import com.kunzisoft.keepass.model.StreamDirection + class EntryAttachmentsItemsAdapter(context: Context) : AnimatedItemsAdapter(context) { var onItemClickListener: ((item: EntryAttachmentState)->Unit)? = null + private var mTitleColor: Int + + init { + // Get the primary text color of the theme + val typedValue = TypedValue() + context.theme.resolveAttribute(android.R.attr.textColorPrimary, typedValue, true) + val typedArray: TypedArray = context.obtainStyledAttributes(typedValue.data, intArrayOf( + android.R.attr.textColor)) + mTitleColor = typedArray.getColor(0, -1) + typedArray.recycle() + } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EntryBinariesViewHolder { return EntryBinariesViewHolder(inflater.inflate(R.layout.item_attachment, parent, false)) } @@ -46,7 +62,20 @@ class EntryAttachmentsItemsAdapter(context: Context) val entryAttachmentState = itemsList[position] holder.itemView.visibility = View.VISIBLE + holder.binaryFileBroken.apply { + setColorFilter(Color.RED) + visibility = if (entryAttachmentState.attachment.binaryAttachment.isCorrupted) { + View.VISIBLE + } else { + View.GONE + } + } holder.binaryFileTitle.text = entryAttachmentState.attachment.name + if (entryAttachmentState.attachment.binaryAttachment.isCorrupted) { + holder.binaryFileTitle.setTextColor(Color.RED) + } else { + holder.binaryFileTitle.setTextColor(mTitleColor) + } holder.binaryFileSize.text = Formatter.formatFileSize(context, entryAttachmentState.attachment.binaryAttachment.length()) holder.binaryFileCompression.apply { @@ -107,6 +136,7 @@ class EntryAttachmentsItemsAdapter(context: Context) class EntryBinariesViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + var binaryFileBroken: ImageView = itemView.findViewById(R.id.item_attachment_broken) var binaryFileTitle: TextView = itemView.findViewById(R.id.item_attachment_title) var binaryFileSize: TextView = itemView.findViewById(R.id.item_attachment_size) var binaryFileCompression: TextView = itemView.findViewById(R.id.item_attachment_compression) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/database/BinaryAttachment.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/database/BinaryAttachment.kt index a4dd67aa2..5e237f9f2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/database/BinaryAttachment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/database/BinaryAttachment.kt @@ -32,6 +32,7 @@ class BinaryAttachment : Parcelable { private set var isProtected: Boolean = false private set + var isCorrupted: Boolean = false private var dataFile: File? = null fun length(): Long { @@ -43,11 +44,7 @@ class BinaryAttachment : Parcelable { /** * Empty protected binary */ - constructor() { - this.isCompressed = false - this.isProtected = false - this.dataFile = null - } + constructor() constructor(dataFile: File, enableProtection: Boolean = false, compressed: Boolean = false) { this.isCompressed = compressed @@ -59,6 +56,7 @@ class BinaryAttachment : Parcelable { val compressedByte = parcel.readByte().toInt() isCompressed = compressedByte != 0 isProtected = parcel.readByte().toInt() != 0 + isCorrupted = parcel.readByte().toInt() != 0 parcel.readString()?.let { dataFile = File(it) } @@ -164,6 +162,7 @@ class BinaryAttachment : Parcelable { return isCompressed == other.isCompressed && isProtected == other.isProtected + && isCorrupted == other.isCorrupted && sameData } @@ -172,6 +171,7 @@ class BinaryAttachment : Parcelable { var result = 0 result = 31 * result + if (isCompressed) 1 else 0 result = 31 * result + if (isProtected) 1 else 0 + result = 31 * result + if (isCorrupted) 1 else 0 result = 31 * result + dataFile!!.hashCode() return result } @@ -187,6 +187,7 @@ class BinaryAttachment : Parcelable { override fun writeToParcel(dest: Parcel, flags: Int) { dest.writeByte((if (isCompressed) 1 else 0).toByte()) dest.writeByte((if (isProtected) 1 else 0).toByte()) + dest.writeByte((if (isCorrupted) 1 else 0).toByte()) dest.writeString(dataFile?.absolutePath) } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/file/input/DatabaseInputKDBX.kt b/app/src/main/java/com/kunzisoft/keepass/database/file/input/DatabaseInputKDBX.kt index 74654e0ec..e234f7a4c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/file/input/DatabaseInputKDBX.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/file/input/DatabaseInputKDBX.kt @@ -995,6 +995,7 @@ class DatabaseInputKDBX(cacheDirectory: File, } } catch (e: Exception) { Log.e(TAG, "Unable to read base 64 attachment", e) + binaryAttachment.isCorrupted = true binaryAttachment.getOutputDataStream().use { outputStream -> outputStream.write(base64.toByteArray()) } diff --git a/app/src/main/res/drawable/ic_attach_file_broken_white_24dp.xml b/app/src/main/res/drawable/ic_attach_file_broken_white_24dp.xml new file mode 100644 index 000000000..59c32bbe5 --- /dev/null +++ b/app/src/main/res/drawable/ic_attach_file_broken_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/item_attachment.xml b/app/src/main/res/layout/item_attachment.xml index 7a15729a3..056f57b6e 100644 --- a/app/src/main/res/layout/item_attachment.xml +++ b/app/src/main/res/layout/item_attachment.xml @@ -27,11 +27,21 @@ android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + +