Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • dev
  • master
  • v0.1
3 results

Target

Select target project
  • juanitobananas/scrambler
  • artectrex/scrambler
2 results
Select Git revision
  • dev
  • dev-20221127-lossless-rotation
  • master
  • v0.1
  • v0.1.1
  • v0.1.3
  • v0.1.4
7 results
Show changes
Commits on Source (8)
......@@ -4,13 +4,12 @@ plugins {
}
android {
compileSdk 35
namespace 'com.jarsilio.android.scrambler'
compileSdk 34
defaultConfig {
minSdk 15
targetSdk 34
targetSdk 35
versionCode 4
versionName "0.1.3"
multiDexEnabled true
......@@ -23,6 +22,9 @@ android {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
staging {
initWith debug
}
}
buildFeatures {
buildConfig = true
......@@ -34,12 +36,16 @@ android {
kotlinOptions {
jvmTarget = '11'
}
buildFeatures {
buildConfig true
}
namespace 'com.jarsilio.android.scrambler'
}
dependencies {
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-core:5.5.0'
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
......
......@@ -30,7 +30,7 @@ fun getImageType(file: File): ImageType {
}
}
private fun getImageType(inputStream: InputStream?): ImageType {
fun getImageType(inputStream: InputStream?): ImageType {
val magicNumbers = getMagicNumbers(inputStream!!)
val imageType: ImageType
......
package com.jarsilio.android.scrambler
import android.content.ContentResolver
import android.net.Uri
import com.jarsilio.android.scrambler.exceptions.InvalidJpegException
import com.jarsilio.android.scrambler.exceptions.InvalidPngException
import com.jarsilio.android.scrambler.exceptions.UnsupportedFileFormatException
......@@ -10,6 +12,7 @@ import okio.sink
import okio.source
import timber.log.Timber
import java.io.File
import java.io.InputStream
import java.nio.charset.Charset
/**
......@@ -36,13 +39,10 @@ object ScramblerConfig {
*/
@Suppress("unused")
@ExperimentalUnsignedTypes
fun stripMetadata(
inputFile: File,
outputFile: File,
) {
when (val imageType = getImageType(inputFile)) {
ImageType.JPG -> JpegStripper.scramble(inputFile, outputFile)
ImageType.PNG -> PngStripper.scramble(inputFile, outputFile)
fun stripMetadata(inputFile: Uri, outputFile: File, contentResolver: ContentResolver) {
when (val imageType = getImageType(contentResolver.openInputStream(inputFile)!!)) {
ImageType.JPG -> JpegStripper.scramble(contentResolver.openInputStream(inputFile)!!, outputFile)
ImageType.PNG -> PngStripper.scramble(contentResolver.openInputStream(inputFile)!!, outputFile)
else -> {
Timber.e("Only JPEG and PNG images are supported (image is $imageType).")
throw UnsupportedFileFormatException("Only JPEG and PNG images are supported (image is $imageType).")
......@@ -57,14 +57,10 @@ internal object JpegStripper {
private val jpegStartOfStream = 0xDA.toByte()
@ExperimentalUnsignedTypes
fun scramble(
inputFile: File,
outputFile: File,
) {
fun scramble(inputFile: InputStream, outputFile: File) {
outputFile.sink().buffer().use { sink ->
inputFile.inputStream().source().buffer().use { source ->
// This writes the first (empty) start of image segment FFD8 (actually, JPEG allows for segments without payload. This code isn't really (yet?) compatible with that).
sink.write(source, 2)
inputFile.source().buffer().use { source ->
sink.write(source, 2) // This writes the first (empty) start of image segment FFD8 (actually, JPEG allows for segments without payload. This code isn't really (yet?) compatible with that).
while (!source.exhausted()) {
var marker = source.readByte()
......@@ -127,12 +123,9 @@ internal object PngStripper {
private val pngCriticalChunks = listOf("IHDR", "PLTE", "IDAT", "IEND")
@ExperimentalUnsignedTypes
fun scramble(
inputFile: File,
outputFile: File,
) {
fun scramble(inputFile: InputStream, outputFile: File) {
outputFile.sink().buffer().use { sink ->
inputFile.inputStream().source().buffer().use { source ->
inputFile.source().buffer().use { source ->
val byteArray = source.readByteArray(8)
if (byteArray contentEquals pngSignature) {
sink.write(byteArray)
......
package com.jarsilio.android.scrambler
import android.content.ContentResolver
import android.net.Uri
import org.junit.Assert.assertTrue
import org.junit.Test
import org.mockito.Mockito
import org.mockito.Mockito.mock
import java.io.File
import java.io.FileInputStream
import java.nio.file.Files
import java.nio.file.Path
......@@ -23,21 +28,45 @@ class ScramblerUnitTest {
@ExperimentalUnsignedTypes
@Test
fun testScrambleJpeg() {
val unscrambledFile = File(javaClass.getResource("/marvincito.jpg")!!.path)
val mockResolver: ContentResolver = mock()
// Create a test file and InputStream
val testFile = File(javaClass.getResource("/marvincito.jpg")!!.path)
val testInputStream = FileInputStream(testFile)
// Define the behavior for openInputStream
val unscrambledFileUri = Uri.fromFile(testFile)
Mockito.`when`(mockResolver.openInputStream(unscrambledFileUri)).thenReturn(testInputStream)
val expectedScrambledFile = File(javaClass.getResource("/marvincito-scrambled.jpg")!!.path)
val scrambledFile = Files.createTempFile("scrambler-", ".jpg").toFile()
stripMetadata(unscrambledFile, scrambledFile)
stripMetadata(
unscrambledFileUri,
scrambledFile,
mockResolver
)
assertTrue(isFileEqual(expectedScrambledFile.toPath(), scrambledFile.toPath()))
Files.delete(scrambledFile.toPath())
testInputStream.close()
}
@ExperimentalUnsignedTypes
@Test
fun testScramblePng() {
val unscrambledFile = File(javaClass.getResource("/marvincito.png")!!.path)
val mockResolver: ContentResolver = mock()
// Create a test file and InputStream
val testFile = File(javaClass.getResource("/marvincito.jpg")!!.path)
val testInputStream = FileInputStream(testFile)
// Define the behavior for openInputStream
val unscrambledFileUri = Uri.fromFile(testFile)
Mockito.`when`(mockResolver.openInputStream(unscrambledFileUri)).thenReturn(testInputStream)
val expectedScrambledFile = File(javaClass.getResource("/marvincito-scrambled.png")!!.path)
val scrambledFile = Files.createTempFile("scrambler-", ".png").toFile()
stripMetadata(unscrambledFile, scrambledFile)
stripMetadata(unscrambledFileUri, scrambledFile, mockResolver)
assertTrue(isFileEqual(expectedScrambledFile.toPath(), scrambledFile.toPath()))
Files.delete(scrambledFile.toPath())
}
......