replaced icafe with metadata extractor (#2546)

* replaced icafe with metadata extractor

* replaced icafe with metadata extractor

* removed icafe from gradle

* removed icafe from gradle

* Revert: travis commented code

* Use original content URI

* merged pr

* commit after merge

* modified unit tests
This commit is contained in:
Vanshika Arora 2019-03-12 00:20:47 +05:30 committed by Vivek Maskara
parent 2e23658b77
commit 6389b35b49
8 changed files with 67 additions and 29 deletions

View file

@ -28,7 +28,7 @@ before_script:
- emulator -avd test -no-audio -no-window -no-boot-anim &
- android-wait-for-emulator
script:
#- "./gradlew clean check connectedCheck jacocoTestReport"
- "./gradlew clean check connectedCheck jacocoTestReport"
- if [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then
mkdir -p app/src/prodRelease/play/release-notes/en-US;
fi

View file

@ -90,7 +90,8 @@ dependencies {
//swipe_layout
implementation 'com.daimajia.swipelayout:library:1.2.0@aar'
implementation 'com.nineoldandroids:library:2.4.0'
implementation files('libs/icafe-1.1-SNAPSHOT.jar')
//metadata extractor
implementation 'com.drewnoakes:metadata-extractor:2.11.0'
}
android {

Binary file not shown.

View file

@ -50,6 +50,10 @@ public class UploadableFile implements Parcelable {
file = (File) in.readSerializable();
}
public Uri getContentUri() {
return contentUri;
}
public File getFile() {
return file;
}

View file

@ -1,5 +1,8 @@
package fr.free.nrw.commons.upload;
import android.content.Context;
import android.net.Uri;
import java.io.IOException;
import javax.inject.Inject;
@ -20,7 +23,10 @@ import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK;
/**
* Methods for pre-processing images to be uploaded
*/
*//*if (dataInBytes[0] == 70 && dataInBytes[1] == 66 && dataInBytes[2] == 77 && dataInBytes[3] == 68) {
Timber.d("Contains FBMD");
return Single.just(ImageUtils.FILE_FBMD);
}*/
@Singleton
public class ImageProcessingService {
private final FileUtilsWrapper fileUtilsWrapper;
@ -56,11 +62,13 @@ public class ImageProcessingService {
}
Timber.d("Checking the validity of image");
String filePath = uploadItem.getMediaUri().getPath();
Uri contentUri=uploadItem.getContentUri();
Context context=uploadItem.getContext();
Single<Integer> duplicateImage = checkDuplicateImage(filePath);
Single<Integer> wrongGeoLocation = checkImageGeoLocation(uploadItem.getPlace(), filePath);
Single<Integer> darkImage = checkDarkImage(filePath);
Single<Integer> itemTitle = checkTitle ? validateItemTitle(uploadItem) : Single.just(ImageUtils.IMAGE_OK);
Single<Integer> checkFBMD = checkFBMD(filePath);
Single<Integer> checkFBMD = checkFBMD(context,contentUri);
Single<Integer> zipResult = Single.zip(duplicateImage, wrongGeoLocation, darkImage, itemTitle,
(duplicate, wrongGeo, dark, title) -> {
@ -84,9 +92,9 @@ public class ImageProcessingService {
* Thus we successfully protect common's from Facebook's copyright violation
*/
public Single<Integer> checkFBMD(String filePath) {
public Single<Integer> checkFBMD(Context context,Uri contentUri) {
try {
return readFBMD.processMetadata(filePath);
return readFBMD.processMetadata(context,contentUri);
} catch (IOException e) {
return Single.just(ImageUtils.FILE_FBMD);
}

View file

@ -1,43 +1,54 @@
package fr.free.nrw.commons.upload;
import com.icafe4j.image.meta.Metadata;
import com.icafe4j.image.meta.MetadataType;
import com.icafe4j.image.meta.iptc.IPTC;
import android.content.Context;
import android.net.Uri;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.drew.metadata.iptc.IptcDirectory;
import java.io.IOException;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import fr.free.nrw.commons.utils.ImageUtils;
import io.reactivex.Single;
import timber.log.Timber;
@Singleton
public class ReadFBMD {
@Inject
public ReadFBMD(){
public ReadFBMD() {
}
public Single<Integer> processMetadata(String path) throws IOException {
Map<MetadataType, Metadata> metadataMap = Metadata.readMetadata(path);
Metadata metadata = metadataMap.get(MetadataType.IPTC);
byte[] dataInBytes = new byte[0];
public Single<Integer> processMetadata(Context context, Uri contentUri) throws IOException {
Metadata readMetadata = null;
try {
dataInBytes = ((IPTC) metadata).getDataSets().get("SpecialInstructions").get(0).getData();
} catch (NullPointerException e) {
readMetadata = ImageMetadataReader.readMetadata(context.getContentResolver().openInputStream(contentUri));
} catch (ImageProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
IptcDirectory iptcDirectory = readMetadata != null ? readMetadata.getFirstDirectoryOfType(IptcDirectory.class) : null;
if (iptcDirectory == null) {
return Single.just(ImageUtils.IMAGE_OK);
}
/**
* The byte array so obtained is used is tested to contain FBMD data
* Note: Any image downloaded from Facebook contains the ASCII code of the letters 'FBMD' in this bytecode extracted from it's IPTC metadata
* */
if (dataInBytes[0] == 70 && dataInBytes[1] == 66 && dataInBytes[2] == 77 && dataInBytes[3] == 68) {
Timber.d("Contains FBMD");
* We parse through all the tags in the IPTC directory if the tagname equals "Special Instructions".
* And the description string starts with FBMD.
* Then the source of image is facebook
* */
for (Tag tag : iptcDirectory.getTags()) {
if (tag.getTagName().equals("Special Instructions") && tag.getDescription().substring(0, 4).equals("FBMD")) {
return Single.just(ImageUtils.FILE_FBMD);
}
}
return Single.just(ImageUtils.IMAGE_OK);
}
}

View file

@ -1,8 +1,11 @@
package fr.free.nrw.commons.upload;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -38,7 +41,7 @@ import timber.log.Timber;
public class UploadModel {
private static UploadItem DUMMY = new UploadItem(
Uri.EMPTY,
Uri.EMPTY, Uri.EMPTY,
"",
"",
GPSExtractor.DUMMY,
@ -54,7 +57,7 @@ public class UploadModel {
private boolean bottomCardState = true;
private boolean rightCardState = true;
private int currentStepIndex = 0;
private Context context;
public static Context context;
private Disposable badImageSubscription;
private SessionManager sessionManager;
@ -108,7 +111,7 @@ public class UploadModel {
}
Timber.d("File created date is %d", fileCreatedDate);
GPSExtractor gpsExtractor = fileProcessor.processFileCoordinates(similarImageInterface);
return new UploadItem(Uri.parse(uploadableFile.getFilePath()), uploadableFile.getMimeType(context), source, gpsExtractor, place, fileCreatedDate, createdTimestampSource);
return new UploadItem(uploadableFile.getContentUri(), Uri.parse(uploadableFile.getFilePath()), uploadableFile.getMimeType(context), source, gpsExtractor, place, fileCreatedDate, createdTimestampSource);
}
void onItemsProcessed(Place place, List<UploadItem> uploadItems) {
@ -327,6 +330,7 @@ public class UploadModel {
@SuppressWarnings("WeakerAccess")
static class UploadItem {
private final Uri originalContentUri;
private final Uri mediaUri;
private final String mimeType;
private final String source;
@ -344,10 +348,12 @@ public class UploadModel {
private BehaviorSubject<Integer> imageQuality;
@SuppressLint("CheckResult")
UploadItem(Uri mediaUri, String mimeType, String source, GPSExtractor gpsCoords,
UploadItem(Uri originalContentUri,
Uri mediaUri, String mimeType, String source, GPSExtractor gpsCoords,
@Nullable Place place,
long createdTimestamp,
String createdTimestampSource) {
this.originalContentUri = originalContentUri;
this.createdTimestampSource = createdTimestampSource;
title = new Title();
descriptions = new ArrayList<>();
@ -428,6 +434,14 @@ public class UploadModel {
public Place getPlace() {
return place;
}
public Uri getContentUri() {
return originalContentUri;
}
public Context getContext(){
return UploadModel.context;
}
}
}
}

View file

@ -82,7 +82,7 @@ class u {
.thenReturn(false)
`when`(mwApi!!.fileExistsWithName(ArgumentMatchers.anyString()))
.thenReturn(false)
`when`(readFBMD?.processMetadata(ArgumentMatchers.anyString()))
`when`(readFBMD?.processMetadata(ArgumentMatchers.any(),ArgumentMatchers.any()))
.thenReturn(Single.just(ImageUtils.IMAGE_OK))
}