Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class SettingsActivity : SimpleActivity() {
setupManageHiddenFolders()
setupSearchAllFiles()
setupShowHiddenItems()
setupStripMetadataOnShare()
setupAutoplayVideos()
setupRememberLastVideo()
setupLoopVideos()
Expand Down Expand Up @@ -260,6 +261,14 @@ class SettingsActivity : SimpleActivity() {
config.showHiddenMedia = binding.settingsShowHiddenItems.isChecked
}

private fun setupStripMetadataOnShare() {
binding.settingsStripMetadataOnShare.isChecked = config.stripMetadataOnShare
binding.settingsStripMetadataOnShareHolder.setOnClickListener {
binding.settingsStripMetadataOnShare.toggle()
config.stripMetadataOnShare = binding.settingsStripMetadataOnShare.isChecked
}
}

private fun setupSearchAllFiles() {
binding.settingsSearchAllFiles.isChecked = config.searchAllFilesByDefault
binding.settingsSearchAllFilesHolder.setOnClickListener {
Expand Down
18 changes: 16 additions & 2 deletions app/src/main/kotlin/org/fossify/gallery/extensions/Activity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,25 @@ fun Activity.sharePaths(paths: ArrayList<String>) {
}

fun Activity.shareMediumPath(path: String) {
sharePath(path)
val finalPath = if (config.stripMetadataOnShare && org.fossify.gallery.helpers.MetadataStripper.isSupported(path)) {
org.fossify.gallery.helpers.MetadataStripper.stripToCacheCopy(this, path) ?: path
} else {
path
}
sharePath(finalPath)
}

fun Activity.shareMediaPaths(paths: ArrayList<String>) {
sharePaths(paths)
val finalPaths = if (config.stripMetadataOnShare) {
ArrayList(paths.map { sourcePath ->
if (org.fossify.gallery.helpers.MetadataStripper.isSupported(sourcePath)) {
org.fossify.gallery.helpers.MetadataStripper.stripToCacheCopy(this, sourcePath) ?: sourcePath
} else sourcePath
})
} else {
paths
}
sharePaths(finalPaths)
}

fun Activity.setAs(path: String) {
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/kotlin/org/fossify/gallery/helpers/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -602,4 +602,8 @@ class Config(context: Context) : BaseConfig(context) {
var showPermissionRationale: Boolean
get() = prefs.getBoolean(SHOW_PERMISSION_RATIONALE, false)
set(showPermissionRationale) = prefs.edit().putBoolean(SHOW_PERMISSION_RATIONALE, showPermissionRationale).apply()

var stripMetadataOnShare: Boolean
get() = prefs.getBoolean(STRIP_METADATA_ON_SHARE, false)
set(value) = prefs.edit().putBoolean(STRIP_METADATA_ON_SHARE, value).apply()
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const val DIRECTORY_SORT_ORDER = "directory_sort_order"
const val GROUP_FOLDER_PREFIX = "group_folder_"
const val VIEW_TYPE_PREFIX = "view_type_folder_"
const val SHOW_HIDDEN_MEDIA = "show_hidden_media"
const val STRIP_METADATA_ON_SHARE = "strip_metadata_on_share"
const val TEMPORARILY_SHOW_HIDDEN = "temporarily_show_hidden"
const val TEMPORARILY_SHOW_EXCLUDED = "temporarily_show_excluded"
const val EXCLUDED_PASSWORD_PROTECTION = "excluded_password_protection"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package org.fossify.gallery.helpers

import android.content.Context
import androidx.exifinterface.media.ExifInterface
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.util.Locale

object MetadataStripper {
private val SENSITIVE_TAGS = arrayOf(
ExifInterface.TAG_GPS_LATITUDE,
ExifInterface.TAG_GPS_LATITUDE_REF,
ExifInterface.TAG_GPS_LONGITUDE,
ExifInterface.TAG_GPS_LONGITUDE_REF,
ExifInterface.TAG_GPS_ALTITUDE,
ExifInterface.TAG_GPS_ALTITUDE_REF,
ExifInterface.TAG_GPS_TIMESTAMP,
ExifInterface.TAG_GPS_DATESTAMP,
ExifInterface.TAG_GPS_PROCESSING_METHOD,
ExifInterface.TAG_GPS_AREA_INFORMATION,
ExifInterface.TAG_GPS_DEST_BEARING,
ExifInterface.TAG_GPS_DEST_BEARING_REF,
ExifInterface.TAG_GPS_DEST_DISTANCE,
ExifInterface.TAG_GPS_DEST_DISTANCE_REF,
ExifInterface.TAG_GPS_DEST_LATITUDE,
ExifInterface.TAG_GPS_DEST_LATITUDE_REF,
ExifInterface.TAG_GPS_DEST_LONGITUDE,
ExifInterface.TAG_GPS_DEST_LONGITUDE_REF,
ExifInterface.TAG_GPS_IMG_DIRECTION,
ExifInterface.TAG_GPS_IMG_DIRECTION_REF,
ExifInterface.TAG_GPS_SPEED,
ExifInterface.TAG_GPS_SPEED_REF,
ExifInterface.TAG_GPS_TRACK,
ExifInterface.TAG_GPS_TRACK_REF,
ExifInterface.TAG_DATETIME,
ExifInterface.TAG_DATETIME_ORIGINAL,
ExifInterface.TAG_DATETIME_DIGITIZED,
ExifInterface.TAG_OFFSET_TIME,
ExifInterface.TAG_OFFSET_TIME_ORIGINAL,
ExifInterface.TAG_OFFSET_TIME_DIGITIZED,
ExifInterface.TAG_MAKE,
ExifInterface.TAG_MODEL,
ExifInterface.TAG_SOFTWARE,
ExifInterface.TAG_ARTIST,
ExifInterface.TAG_COPYRIGHT,
ExifInterface.TAG_USER_COMMENT,
ExifInterface.TAG_IMAGE_DESCRIPTION,
ExifInterface.TAG_SUBJECT_LOCATION,
ExifInterface.TAG_SUBJECT_AREA,
ExifInterface.TAG_BODY_SERIAL_NUMBER,
ExifInterface.TAG_LENS_SERIAL_NUMBER,
ExifInterface.TAG_CAMERA_OWNER_NAME,
)

private val SUPPORTED_EXTENSIONS = setOf("jpg", "jpeg", "heic", "heif", "webp", "tiff", "tif", "png", "dng")

fun isSupported(path: String?): Boolean {
if (path.isNullOrBlank()) return false
val dotIndex = path.lastIndexOf('.')
if (dotIndex < 0) return false
val extension = path.substring(dotIndex + 1).lowercase(Locale.ROOT)
return extension in SUPPORTED_EXTENSIONS
}

fun stripToCacheCopy(context: Context, sourcePath: String): String? {
val source = File(sourcePath)
if (!source.exists() || !source.canRead()) return null
val cacheDir = File(context.cacheDir, "metadata-stripped").apply { mkdirs() }
val copy = File(cacheDir, "${System.currentTimeMillis()}-${source.name}")
FileInputStream(source).use { input ->
FileOutputStream(copy).use { output -> input.copyTo(output) }
}
runCatching {
val exif = ExifInterface(copy)
for (tag in SENSITIVE_TAGS) {
if (exif.getAttribute(tag) != null) exif.setAttribute(tag, null)
}
exif.saveAttributes()
}
return copy.absolutePath
}
}
15 changes: 15 additions & 0 deletions app/src/main/res/layout/activity_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,21 @@

</RelativeLayout>

<RelativeLayout
android:id="@+id/settings_strip_metadata_on_share_holder"
style="@style/SettingsHolderSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<org.fossify.commons.views.MyMaterialSwitch
android:id="@+id/settings_strip_metadata_on_share"
style="@style/SettingsSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/strip_metadata_on_share" />

</RelativeLayout>

<RelativeLayout
android:id="@+id/settings_search_all_files_holder"
style="@style/SettingsHolderSwitchStyle"
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 @@ -299,6 +299,7 @@
<string name="faq_17_text">That stopped working due to the system changes that came with Android 11 too, the app cannot browse real folders anymore, it relies on the so called MediaStore at fetching data.</string>
<string name="faq_18_title">Why do I see ads during video playback?</string>
<string name="faq_18_text">Our apps have no ads whatsoever. If you see them during video playback, you must be using some other apps video player. Try finding your default video player in the device settings, then do a \"Clear defaults\" on it. The next time you invoke some video intent you will see an app picker prompt, where you can select what app you want to use.</string>
<string name="strip_metadata_on_share">Strip GPS/EXIF metadata when sharing photos</string>
<!--
Haven't found some strings? There's more at
https://github.com/FossifyOrg/Commons/tree/master/commons/src/main/res
Expand Down
Loading