mirror of
https://github.com/CatimaLoyalty/Android.git
synced 2026-02-18 23:28:44 -05:00
Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker
This commit is contained in:
@@ -12,13 +12,14 @@ import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -47,6 +48,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity
|
||||
private String importAlertTitle;
|
||||
private String importAlertMessage;
|
||||
private DataFormat importDataFormat;
|
||||
private String exportPassword;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
@@ -88,7 +90,28 @@ public class ImportExportActivity extends CatimaAppCompatActivity
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
chooseFileWithIntent(intentCreateDocumentAction, CHOOSE_EXPORT_LOCATION);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ImportExportActivity.this);
|
||||
builder.setTitle(R.string.exportPassword);
|
||||
|
||||
FrameLayout container = new FrameLayout(ImportExportActivity.this);
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
params.leftMargin = 50;
|
||||
params.rightMargin = 50;
|
||||
|
||||
final EditText input = new EditText(ImportExportActivity.this);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
input.setLayoutParams(params);
|
||||
input.setHint(R.string.exportPasswordHint);
|
||||
|
||||
container.addView(input);
|
||||
builder.setView(container);
|
||||
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
|
||||
exportPassword = input.getText().toString();
|
||||
chooseFileWithIntent(intentCreateDocumentAction, CHOOSE_EXPORT_LOCATION);
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel());
|
||||
builder.show();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -211,7 +234,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity
|
||||
importExporter.execute();
|
||||
}
|
||||
|
||||
private void startExport(final OutputStream target, final Uri targetUri, final boolean closeWhenDone)
|
||||
private void startExport(final OutputStream target, final Uri targetUri,char[] password, final boolean closeWhenDone)
|
||||
{
|
||||
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener()
|
||||
{
|
||||
@@ -229,7 +252,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity
|
||||
};
|
||||
|
||||
importExporter = new ImportExportTask(ImportExportActivity.this,
|
||||
DataFormat.Catima, target, listener);
|
||||
DataFormat.Catima, target,password, listener);
|
||||
importExporter.execute();
|
||||
}
|
||||
|
||||
@@ -407,6 +430,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity
|
||||
{
|
||||
if (requestCode == CHOOSE_EXPORT_LOCATION)
|
||||
{
|
||||
|
||||
OutputStream writer;
|
||||
if (uri.getScheme() != null)
|
||||
{
|
||||
@@ -416,9 +440,8 @@ public class ImportExportActivity extends CatimaAppCompatActivity
|
||||
{
|
||||
writer = new FileOutputStream(new File(uri.toString()));
|
||||
}
|
||||
|
||||
Log.e(TAG, "Starting file export with: " + uri.toString());
|
||||
startExport(writer, uri, true);
|
||||
startExport(writer, uri,exportPassword.toCharArray(),true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
|
||||
/**
|
||||
* Constructor which will setup a task for exporting to the given file
|
||||
*/
|
||||
ImportExportTask(Activity activity, DataFormat format, OutputStream output,
|
||||
ImportExportTask(Activity activity, DataFormat format, OutputStream output,char[] password,
|
||||
TaskCompleteListener listener)
|
||||
{
|
||||
super();
|
||||
@@ -43,6 +43,7 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
|
||||
this.doImport = false;
|
||||
this.format = format;
|
||||
this.outputStream = output;
|
||||
this.password = password;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@@ -70,14 +71,14 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
|
||||
return importResult;
|
||||
}
|
||||
|
||||
private ImportExportResult performExport(Context context, OutputStream stream, DBHelper db)
|
||||
private ImportExportResult performExport(Context context, OutputStream stream, DBHelper db,char[] password)
|
||||
{
|
||||
ImportExportResult result = ImportExportResult.GenericFailure;
|
||||
|
||||
try
|
||||
{
|
||||
OutputStreamWriter writer = new OutputStreamWriter(stream, StandardCharsets.UTF_8);
|
||||
result = MultiFormatExporter.exportData(context, db, stream, format);
|
||||
result = MultiFormatExporter.exportData(context, db, stream, format,password);
|
||||
writer.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
@@ -118,7 +119,7 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
|
||||
}
|
||||
else
|
||||
{
|
||||
result = performExport(activity.getApplicationContext(), outputStream, db);
|
||||
result = performExport(activity.getApplicationContext(), outputStream, db,password);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.graphics.Bitmap;
|
||||
|
||||
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
|
||||
import net.lingala.zip4j.model.ZipParameters;
|
||||
import net.lingala.zip4j.model.enums.EncryptionMethod;
|
||||
import net.lingala.zip4j.util.InternalZipConstants;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
@@ -30,14 +31,21 @@ import protect.card_locker.Utils;
|
||||
*/
|
||||
public class CatimaExporter implements Exporter
|
||||
{
|
||||
public void exportData(Context context, DBHelper db, OutputStream output) throws IOException, InterruptedException
|
||||
public void exportData(Context context, DBHelper db, OutputStream output,char[] password) throws IOException, InterruptedException
|
||||
{
|
||||
// Necessary vars
|
||||
int readLen;
|
||||
byte[] readBuffer = new byte[InternalZipConstants.BUFF_SIZE];
|
||||
|
||||
// Create zip output stream
|
||||
ZipOutputStream zipOutputStream = new ZipOutputStream(output);
|
||||
ZipOutputStream zipOutputStream;
|
||||
|
||||
if(password!=null && password.length>0){
|
||||
zipOutputStream = new ZipOutputStream(output,password);
|
||||
}
|
||||
else{
|
||||
zipOutputStream = new ZipOutputStream(output);
|
||||
}
|
||||
|
||||
// Generate CSV
|
||||
ByteArrayOutputStream catimaOutputStream = new ByteArrayOutputStream();
|
||||
@@ -45,8 +53,7 @@ public class CatimaExporter implements Exporter
|
||||
writeCSV(db, catimaOutputStreamWriter);
|
||||
|
||||
// Add CSV to zip file
|
||||
ZipParameters csvZipParameters = new ZipParameters();
|
||||
csvZipParameters.setFileNameInZip("catima.csv");
|
||||
ZipParameters csvZipParameters = createZipParameters("catima.csv",password);
|
||||
zipOutputStream.putNextEntry(csvZipParameters);
|
||||
InputStream csvInputStream = new ByteArrayInputStream(catimaOutputStream.toByteArray());
|
||||
while ((readLen = csvInputStream.read(readBuffer)) != -1) {
|
||||
@@ -71,8 +78,7 @@ public class CatimaExporter implements Exporter
|
||||
// If it exists, add to the .zip file
|
||||
Bitmap image = Utils.retrieveCardImage(context, card.id, front);
|
||||
if (image != null) {
|
||||
ZipParameters imageZipParameters = new ZipParameters();
|
||||
imageZipParameters.setFileNameInZip(Utils.getCardImageFileName(card.id, front));
|
||||
ZipParameters imageZipParameters = createZipParameters(Utils.getCardImageFileName(card.id, front),password);
|
||||
zipOutputStream.putNextEntry(imageZipParameters);
|
||||
InputStream imageInputStream = new ByteArrayInputStream(Utils.bitmapToByteArray(image));
|
||||
while ((readLen = imageInputStream.read(readBuffer)) != -1) {
|
||||
@@ -86,6 +92,16 @@ public class CatimaExporter implements Exporter
|
||||
zipOutputStream.close();
|
||||
}
|
||||
|
||||
private ZipParameters createZipParameters(String fileName, char[] password){
|
||||
ZipParameters zipParameters = new ZipParameters();
|
||||
zipParameters.setFileNameInZip(fileName);
|
||||
if(password!=null && password.length>0){
|
||||
zipParameters.setEncryptFiles(true);
|
||||
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
|
||||
}
|
||||
return zipParameters;
|
||||
}
|
||||
|
||||
private void writeCSV(DBHelper db, OutputStreamWriter output) throws IOException, InterruptedException {
|
||||
CSVPrinter printer = new CSVPrinter(output, CSVFormat.RFC4180);
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public class CatimaImporter implements Importer
|
||||
bufferedInputStream.mark(100);
|
||||
|
||||
// First, check if this is a zip file
|
||||
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream);
|
||||
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream,password);
|
||||
|
||||
boolean isZipFile = false;
|
||||
|
||||
|
||||
@@ -17,5 +17,5 @@ public interface Exporter
|
||||
* Export the database to the output stream in a given format.
|
||||
* @throws IOException
|
||||
*/
|
||||
void exportData(Context context, DBHelper db, OutputStream output) throws IOException, InterruptedException;
|
||||
void exportData(Context context, DBHelper db, OutputStream output,char[] password) throws IOException, InterruptedException;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public class MultiFormatExporter
|
||||
* another ImportExportResult otherwise. If not Success, partial data may have been
|
||||
* written to the output stream, and it should be discarded.
|
||||
*/
|
||||
public static ImportExportResult exportData(Context context, DBHelper db, OutputStream output, DataFormat format)
|
||||
public static ImportExportResult exportData(Context context, DBHelper db, OutputStream output, DataFormat format,char[] password)
|
||||
{
|
||||
Exporter exporter = null;
|
||||
|
||||
@@ -40,7 +40,7 @@ public class MultiFormatExporter
|
||||
{
|
||||
try
|
||||
{
|
||||
exporter.exportData(context, db, output);
|
||||
exporter.exportData(context, db, output,password);
|
||||
return ImportExportResult.Success;
|
||||
}
|
||||
catch(IOException e)
|
||||
|
||||
@@ -196,6 +196,8 @@
|
||||
<string name="yes">Yes</string>
|
||||
<string name="no">No</string>
|
||||
<string name="passwordRequired">Please enter the password</string>
|
||||
<string name="exportPassword">Set a password to protect your export (optional)</string>
|
||||
<string name="exportPasswordHint">Enter password</string>
|
||||
<string name="failedGeneratingShareURL">Could not generate sharable URL. Please report this.</string>
|
||||
<string name="turn_flashlight_on">Turn flashlight on</string>
|
||||
<string name="turn_flashlight_off">Turn flashlight off</string>
|
||||
@@ -243,4 +245,4 @@
|
||||
<string name="rate_this_app">Rate this app</string>
|
||||
<string name="on_google_play">on Google Play</string>
|
||||
<string name="report_error">Report Error</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
||||
@@ -334,7 +334,7 @@ public class ImportExportTest
|
||||
OutputStreamWriter outStream = new OutputStreamWriter(outData);
|
||||
|
||||
// Export data to CSV format
|
||||
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima);
|
||||
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima,null);
|
||||
assertEquals(ImportExportResult.Success, result);
|
||||
outStream.close();
|
||||
|
||||
@@ -354,6 +354,39 @@ public class ImportExportTest
|
||||
TestHelpers.getEmptyDb(activity);
|
||||
}
|
||||
|
||||
public void multipleCardsExportImportPasswordProtected() throws IOException
|
||||
{
|
||||
final int NUM_CARDS = 10;
|
||||
List<char[]> passwords = Arrays.asList(null, "123456789".toCharArray());
|
||||
for(char[] password : passwords){
|
||||
addLoyaltyCards(NUM_CARDS);
|
||||
|
||||
ByteArrayOutputStream outData = new ByteArrayOutputStream();
|
||||
OutputStreamWriter outStream = new OutputStreamWriter(outData);
|
||||
|
||||
// Export data to CSV format
|
||||
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima,password);
|
||||
assertEquals(ImportExportResult.Success, result);
|
||||
outStream.close();
|
||||
|
||||
TestHelpers.getEmptyDb(activity);
|
||||
|
||||
ByteArrayInputStream inData = new ByteArrayInputStream(outData.toByteArray());
|
||||
|
||||
// Import the CSV data
|
||||
result = MultiFormatImporter.importData(activity.getApplicationContext(), db, inData, DataFormat.Catima, password);
|
||||
assertEquals(ImportExportResult.Success, result);
|
||||
|
||||
assertEquals(NUM_CARDS, db.getLoyaltyCardCount());
|
||||
|
||||
checkLoyaltyCards();
|
||||
|
||||
// Clear the database for the next format under test
|
||||
TestHelpers.getEmptyDb(activity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleCardsExportImportSomeStarred() throws IOException
|
||||
{
|
||||
@@ -365,7 +398,7 @@ public class ImportExportTest
|
||||
OutputStreamWriter outStream = new OutputStreamWriter(outData);
|
||||
|
||||
// Export data to CSV format
|
||||
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima);
|
||||
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima,null);
|
||||
assertEquals(ImportExportResult.Success, result);
|
||||
outStream.close();
|
||||
|
||||
@@ -438,7 +471,7 @@ public class ImportExportTest
|
||||
OutputStreamWriter outStream = new OutputStreamWriter(outData);
|
||||
|
||||
// Export data to CSV format
|
||||
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima);
|
||||
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima,null);
|
||||
assertEquals(ImportExportResult.Success, result);
|
||||
outStream.close();
|
||||
|
||||
@@ -482,7 +515,7 @@ public class ImportExportTest
|
||||
OutputStreamWriter outStream = new OutputStreamWriter(outData);
|
||||
|
||||
// Export into CSV data
|
||||
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima);
|
||||
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima,null);
|
||||
assertEquals(ImportExportResult.Success, result);
|
||||
outStream.close();
|
||||
|
||||
@@ -513,7 +546,7 @@ public class ImportExportTest
|
||||
OutputStreamWriter outStream = new OutputStreamWriter(outData);
|
||||
|
||||
// Export data to CSV format
|
||||
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima);
|
||||
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima,null);
|
||||
assertEquals(ImportExportResult.Success, result);
|
||||
|
||||
TestHelpers.getEmptyDb(activity);
|
||||
@@ -560,8 +593,9 @@ public class ImportExportTest
|
||||
TestTaskCompleteListener listener = new TestTaskCompleteListener();
|
||||
|
||||
// Export to the file
|
||||
final String password = "123456789";
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(exportFile);
|
||||
ImportExportTask task = new ImportExportTask(activity, DataFormat.Catima, fileOutputStream, listener);
|
||||
ImportExportTask task = new ImportExportTask(activity, DataFormat.Catima, fileOutputStream,password.toCharArray(), listener);
|
||||
task.execute();
|
||||
|
||||
// Actually run the task to completion
|
||||
@@ -579,7 +613,7 @@ public class ImportExportTest
|
||||
|
||||
FileInputStream fileStream = new FileInputStream(exportFile);
|
||||
|
||||
task = new ImportExportTask(activity, DataFormat.Catima, fileStream, null, listener);
|
||||
task = new ImportExportTask(activity, DataFormat.Catima, fileStream, password.toCharArray(), listener);
|
||||
task.execute();
|
||||
|
||||
// Actually run the task to completion
|
||||
@@ -901,7 +935,7 @@ public class ImportExportTest
|
||||
|
||||
// Export everything
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
MultiFormatExporter.exportData(activity.getApplicationContext(), db, outputStream, DataFormat.Catima);
|
||||
MultiFormatExporter.exportData(activity.getApplicationContext(), db, outputStream, DataFormat.Catima,null);
|
||||
|
||||
// Wipe database
|
||||
TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -1 +1 @@
|
||||
Catima — Den Open Source kortlommen
|
||||
Catima — for kundekort, billetter og kuponger 🎴
|
||||
|
||||
Reference in New Issue
Block a user