Skip to content

Commit 85831df

Browse files
dcalhounclaude
andcommitted
fix: strip location only from ExifInterface-writable image formats
EXIF_MIME_TYPES gated the copy-and-strip branch on formats that can carry GPS, but androidx ExifInterface.saveAttributes() can only rewrite JPEG, PNG, and WebP. The set omitted PNG (so location-bearing PNGs uploaded un-stripped, a regression vs. the legacy pipeline) and included HEIC/HEIF (where saveAttributes throws an IOException that stripLocation swallows, uploading a still-geotagged copy while appearing to honor the setting). Correct the set to {JPEG, PNG, WebP} and cover the PNG-stripped and HEIC-passthrough cases in the decision-table tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 70cf911 commit 85831df

2 files changed

Lines changed: 37 additions & 2 deletions

File tree

WordPress/src/main/java/org/wordpress/android/ui/posts/editor/GBKMediaUploadProcessor.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,13 @@ class GBKMediaUploadProcessor(
240240
private const val MIME_MP4 = "video/mp4"
241241
private const val MIME_OCTET_STREAM = "application/octet-stream"
242242

243-
/** Image formats that can carry EXIF GPS metadata. */
244-
private val EXIF_MIME_TYPES = setOf(MIME_JPEG, "image/heic", "image/heif", "image/webp")
243+
/**
244+
* Formats androidx ExifInterface can actually strip GPS from: saveAttributes() supports
245+
* only JPEG, PNG, and WebP. HEIC/HEIF are deliberately excluded — the library throws an
246+
* IOException (swallowed by stripLocation), so listing them would make a doomed copy and
247+
* upload a still-geotagged file while appearing to honor the strip-location setting.
248+
*/
249+
private val EXIF_MIME_TYPES = setOf(MIME_JPEG, MIME_PNG, "image/webp")
245250
}
246251
}
247252

WordPress/src/test/java/org/wordpress/android/ui/posts/editor/GBKMediaUploadProcessorTest.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,36 @@ class GBKMediaUploadProcessorTest : BaseUnitTest() {
119119
verify(mediaUtilsWrapper).stripImageLocation(optimized.absolutePath)
120120
}
121121

122+
@Test
123+
fun `png gps is stripped onto a copy when strip enabled and optimization off`() = test {
124+
val pngStaged = tempFolder.newFile("art.png")
125+
whenever(mediaUtilsWrapper.getOptimizedMedia(pngStaged.absolutePath, false)).thenReturn(null)
126+
whenever(appPrefsWrapper.isStripImageLocation).thenReturn(true)
127+
128+
// androidx ExifInterface can write PNG, so PNG must take the copy-and-strip branch.
129+
val result = createProcessor(wpComSite()).processFile(pngStaged, "image/png", "art.png")
130+
131+
assertThat(result).isInstanceOf(ProcessedProxyFile.Processed::class.java)
132+
result as ProcessedProxyFile.Processed
133+
assertThat(result.file.absolutePath).isNotEqualTo(pngStaged.absolutePath)
134+
verify(mediaUtilsWrapper).stripImageLocation(result.file.absolutePath)
135+
result.file.delete()
136+
}
137+
138+
@Test
139+
fun `heic passes through when strip enabled and optimization off`() = test {
140+
val heicStaged = tempFolder.newFile("photo.heic")
141+
whenever(mediaUtilsWrapper.getOptimizedMedia(heicStaged.absolutePath, false)).thenReturn(null)
142+
whenever(appPrefsWrapper.isStripImageLocation).thenReturn(true)
143+
144+
// androidx ExifInterface cannot write HEIF, so copy-and-strip would silently fail and
145+
// upload a still-geotagged copy — HEIC must not take the strip branch.
146+
val result = createProcessor(wpComSite()).processFile(heicStaged, "image/heic", "photo.heic")
147+
148+
assertThat(result).isEqualTo(ProcessedProxyFile.Original)
149+
verify(mediaUtilsWrapper, never()).stripImageLocation(any())
150+
}
151+
122152
@Test
123153
fun `heic reports jpeg mime type and extension after optimization`() = test {
124154
val heicStaged = tempFolder.newFile("photo.heic")

0 commit comments

Comments
 (0)