Merge pull request #336 from misaochan/prevent-duplicates

Fix #77
This commit is contained in:
Josephine Lim 2016-12-15 15:52:24 +13:00 committed by GitHub
commit 84475ef9c6
6 changed files with 179 additions and 2 deletions

View file

@ -3,6 +3,7 @@ package fr.free.nrw.commons;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
@ -16,10 +17,16 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@ -32,8 +39,49 @@ import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import fr.free.nrw.commons.upload.ShareActivity;
public class Utils {
private static final String TAG = Utils.class.getName();
// Get SHA1 of file from input stream
public static String getSHA1(InputStream is) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA1");
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "Exception while getting Digest", e);
return "";
}
byte[] buffer = new byte[8192];
int read;
try {
while ((read = is.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}
byte[] md5sum = digest.digest();
BigInteger bigInt = new BigInteger(1, md5sum);
String output = bigInt.toString(16);
// Fill to 40 chars
output = String.format("%40s", output).replace(' ', '0');
Log.i(TAG, "File SHA1: " + output);
return output;
} catch (IOException e) {
Log.e(TAG, "IO Exception", e);
return "";
} finally {
try {
is.close();
} catch (IOException e) {
Log.e(TAG, "Exception on closing MD5 input stream", e);
}
}
}
public static Date parseMWDate(String mwDate) {
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); // Assuming MW always gives me UTC
try {

View file

@ -72,7 +72,7 @@ public class ContributionController {
shareIntent.setAction(Intent.ACTION_SEND);
switch(requestCode) {
case SELECT_FROM_GALLERY:
//FIXME: Handles image picked from gallery (from Google Photos)
//Handles image picked from gallery
Uri imageData = data.getData();
shareIntent.setType(activity.getContentResolver().getType(imageData));
shareIntent.putExtra(Intent.EXTRA_STREAM, imageData);

View file

@ -0,0 +1,102 @@
package fr.free.nrw.commons.upload;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.util.Log;
import org.mediawiki.api.ApiResult;
import org.mediawiki.api.MWApi;
import java.io.IOException;
import java.util.ArrayList;
import android.support.v7.app.AlertDialog;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.ContributionsActivity;
/**
* Sends asynchronous queries to the Commons MediaWiki API to check that file doesn't already exist
* Displays a warning to the user if the file already exists on Commons
*/
public class ExistingFileAsync extends AsyncTask<Void, Void, Boolean> {
private static final String TAG = fr.free.nrw.commons.upload.ExistingFileAsync.class.getName();
private String fileSHA1;
private Context context;
public ExistingFileAsync(String fileSHA1, Context context) {
super();
this.fileSHA1 = fileSHA1;
this.context = context;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Boolean doInBackground(Void... voids) {
MWApi api = CommonsApplication.createMWApi();
ApiResult result;
// https://commons.wikimedia.org/w/api.php?action=query&list=allimages&format=xml&aisha1=801957214aba50cb63bb6eb1b0effa50188900ba
try {
result = api.action("query")
.param("format", "xml")
.param("list", "allimages")
.param("aisha1", fileSHA1)
.get();
Log.d(TAG, "Searching Commons API for existing file: " + result.toString());
} catch (IOException e) {
Log.e(TAG, "IO Exception: ", e);
return false;
}
ArrayList<ApiResult> resultNodes = result.getNodes("/api/query/allimages/img");
Log.d(TAG, "Result nodes: " + resultNodes);
boolean fileExists;
if (!resultNodes.isEmpty()) {
fileExists = true;
} else {
fileExists = false;
}
Log.d(TAG, "File already exists in Commons:" + fileExists);
return fileExists;
}
@Override
protected void onPostExecute(Boolean fileExists) {
super.onPostExecute(fileExists);
// If file exists, display warning to user.
// Use soft warning for now (user able to choose to proceed) until have determined that implementation works without bugs
if (fileExists) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(R.string.file_exists)
.setTitle(R.string.warning);
builder.setPositiveButton(R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//Go back to ContributionsActivity
Intent intent = new Intent(context, ContributionsActivity.class);
context.startActivity(intent);
}
});
builder.setNegativeButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//No need to do anything, user remains on upload screen
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
}
}

View file

@ -21,12 +21,17 @@ import android.widget.Toast;
import com.nostra13.universalimageloader.core.ImageLoader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.EventLog;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.auth.AuthenticatedActivity;
import fr.free.nrw.commons.auth.WikiAccountAuthenticator;
import fr.free.nrw.commons.category.CategorizationFragment;
@ -117,7 +122,6 @@ public class ShareActivity
Log.d(TAG, "Cache the categories found");
}
//TODO: Pass in coords here? Need to be in format 37.51136|-77.602615 , which decimalCoords appears to be
uploadController.startUpload(title, mediaUri, description, mimeType, source, decimalCoords, new UploadController.ContributionUploadProgress() {
public void onUploadStarted(Contribution contribution) {
ShareActivity.this.contribution = contribution;
@ -220,6 +224,7 @@ public class ShareActivity
app = (CommonsApplication)this.getApplicationContext();
backgroundImageView = (ImageView)findViewById(R.id.backgroundImage);
//Receive intent from ContributionController.java when user selects picture to upload
Intent intent = getIntent();
if(intent.getAction().equals(Intent.ACTION_SEND)) {
@ -235,6 +240,20 @@ public class ShareActivity
if (mediaUri != null) {
mediaUriString = mediaUri.toString();
ImageLoader.getInstance().displayImage(mediaUriString, backgroundImageView);
//Test SHA1 of image to see if it matches SHA1 of a file on Commons
try {
InputStream inputStream = getContentResolver().openInputStream(mediaUri);
Log.d(TAG, "Input stream created from " + mediaUriString);
String fileSHA1 = Utils.getSHA1(inputStream);
Log.d(TAG, "File SHA1 is: " + fileSHA1);
ExistingFileAsync fileAsyncTask = new ExistingFileAsync(fileSHA1, this);
fileAsyncTask.execute();
} catch (IOException e) {
Log.d(TAG, "IO Exception: ", e);
}
}
if(savedInstanceState != null) {

View file

@ -74,6 +74,7 @@ public class UploadController {
contribution.setTag("mimeType", mimeType);
contribution.setSource(source);
//Calls the next overloaded method
startUpload(contribution, onComplete);
}
@ -81,6 +82,7 @@ public class UploadController {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
//Set creator, desc, and license
if(TextUtils.isEmpty(contribution.getCreator())) {
contribution.setCreator(app.getCurrentAccount().name);
}
@ -154,6 +156,7 @@ public class UploadController {
@Override
protected void onPostExecute(Contribution contribution) {
super.onPostExecute(contribution);
//Starts the upload. If commented out, user can proceed to next Fragment but upload doesn't happen
uploadService.queue(UploadService.ACTION_UPLOAD_FILE, contribution);
onComplete.onUploadStarted(contribution);
}

View file

@ -168,4 +168,9 @@
<string name="location_permission_rationale">Optional permission: Get current location for category suggestions</string>
<string name="ok">OK</string>
<string name="title_activity_nearby">Nearby Places</string>
<string name="warning">Warning</string>
<string name="file_exists">This file already exists on Commons. Are you sure you want to proceed?</string>
<string name="yes">Yes</string>
<string name="no">No</string>
</resources>