multi-decrypt: implement save operation (missing actual copy)

This commit is contained in:
Vincent Breitmoser 2015-06-03 17:01:29 +02:00
parent 6db9de221c
commit fa61438306
3 changed files with 86 additions and 53 deletions

View File

@ -56,6 +56,11 @@ public class TemporaryStorageProvider extends ContentProvider {
return context.getContentResolver().insert(BASE_URI, contentValues); return context.getContentResolver().insert(BASE_URI, contentValues);
} }
public static Uri createFile(Context context) {
ContentValues contentValues = new ContentValues();
return context.getContentResolver().insert(BASE_URI, contentValues);
}
public static int cleanUp(Context context) { public static int cleanUp(Context context) {
return context.getContentResolver().delete(BASE_URI, COLUMN_TIME + "< ?", return context.getContentResolver().delete(BASE_URI, COLUMN_TIME + "< ?",
new String[]{Long.toString(System.currentTimeMillis() - Constants.TEMPFILE_TTL)}); new String[]{Long.toString(System.currentTimeMillis() - Constants.TEMPFILE_TTL)});

View File

@ -18,7 +18,9 @@
package org.sufficientlysecure.keychain.ui; package org.sufficientlysecure.keychain.ui;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@ -28,6 +30,7 @@ import android.content.Intent;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
@ -57,10 +60,12 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler; import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler.MessageStatus; import org.sufficientlysecure.keychain.service.ServiceProgressHandler.MessageStatus;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.DecryptFilesListFragment.DecryptFilesAdapter.ViewModel;
import org.sufficientlysecure.keychain.ui.adapter.SpacesItemDecoration; import org.sufficientlysecure.keychain.ui.adapter.SpacesItemDecoration;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment; import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils; import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
@ -77,13 +82,11 @@ public class DecryptFilesListFragment extends CryptoOperationFragment implements
private static final int REQUEST_CODE_OUTPUT = 0x00007007; private static final int REQUEST_CODE_OUTPUT = 0x00007007;
private ArrayList<Uri> mInputUris; private ArrayList<Uri> mInputUris;
private ArrayList<Uri> mOutputUris; private HashMap<Uri, Uri> mOutputUris;
private ArrayList<Uri> mPendingInputUris; private ArrayList<Uri> mPendingInputUris;
private Uri mCurrentInputUri, mCurrentOutputUri; private Uri mCurrentInputUri;
private boolean mDecryptingMetadata;
private RecyclerView mFilesList;
private DecryptFilesAdapter mAdapter; private DecryptFilesAdapter mAdapter;
/** /**
@ -106,16 +109,16 @@ public class DecryptFilesListFragment extends CryptoOperationFragment implements
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.decrypt_files_list_fragment, container, false); View view = inflater.inflate(R.layout.decrypt_files_list_fragment, container, false);
mFilesList = (RecyclerView) view.findViewById(R.id.decrypted_files_list); RecyclerView vFilesList = (RecyclerView) view.findViewById(R.id.decrypted_files_list);
mFilesList.addItemDecoration(new SpacesItemDecoration( vFilesList.addItemDecoration(new SpacesItemDecoration(
FormattingUtils.dpToPx(getActivity(), 4))); FormattingUtils.dpToPx(getActivity(), 4)));
mFilesList.setHasFixedSize(true); vFilesList.setHasFixedSize(true);
mFilesList.setLayoutManager(new LinearLayoutManager(getActivity())); vFilesList.setLayoutManager(new LinearLayoutManager(getActivity()));
mFilesList.setItemAnimator(new DefaultItemAnimator()); vFilesList.setItemAnimator(new DefaultItemAnimator());
mAdapter = new DecryptFilesAdapter(getActivity(), this); mAdapter = new DecryptFilesAdapter(getActivity(), this);
mFilesList.setAdapter(mAdapter); vFilesList.setAdapter(mAdapter);
return view; return view;
} }
@ -143,21 +146,48 @@ public class DecryptFilesListFragment extends CryptoOperationFragment implements
return name; return name;
} }
private void askForOutputFilename(Uri inputUri, String originalFilename, String mimeType) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
File file = new File(inputUri.getPath());
File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR;
File targetFile = new File(parentDir, originalFilename);
FileHelper.saveFile(this, getString(R.string.title_decrypt_to_file),
getString(R.string.specify_file_to_decrypt_to), targetFile, REQUEST_CODE_OUTPUT);
} else {
FileHelper.saveDocument(this, mimeType, originalFilename, REQUEST_CODE_OUTPUT);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_OUTPUT: {
// This happens after output file was selected, so start our operation
if (resultCode == Activity.RESULT_OK && data != null) {
Uri saveUri = data.getData();
Uri outputUri = mOutputUris.get(mCurrentInputUri);
// TODO save from outputUri to saveUri
mCurrentInputUri = null;
}
return;
}
default: {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
private void displayInputUris(ArrayList<Uri> uris) { private void displayInputUris(ArrayList<Uri> uris) {
mInputUris = uris; mInputUris = uris;
// mOutputUris = new ArrayList<>(uris.size()); mOutputUris = new HashMap<>(uris.size());
for (Uri uri : uris) { for (Uri uri : uris) {
mAdapter.add(uri); mAdapter.add(uri);
/* mOutputUris.put(uri, TemporaryStorageProvider.createFile(getActivity()));
String targetName = (mEncryptFilenames ? String.valueOf(filenameCounter) : FileHelper.getFilename(getActivity(), model.inputUri))
+ (mUseArmor ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN);
mOutputUris.add(TemporaryStorageProvider.createFile(getActivity(), targetName));
filenameCounter++;
*/
} }
mPendingInputUris = uris; mPendingInputUris = uris;
mDecryptingMetadata = true;
cryptoOperation(); cryptoOperation();
} }
@ -183,25 +213,32 @@ public class DecryptFilesListFragment extends CryptoOperationFragment implements
onKeyClick = new OnClickListener() { onKeyClick = new OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(getActivity(), ViewKeyActivity.class); Activity activity = getActivity();
if (activity == null) {
return;
}
Intent intent = new Intent(activity, ViewKeyActivity.class);
intent.setData(KeyRings.buildUnifiedKeyRingUri(keyId)); intent.setData(KeyRings.buildUnifiedKeyRingUri(keyId));
getActivity().startActivity(intent); activity.startActivity(intent);
} }
}; };
} }
} }
if (result.success()) { if (result.success() && result.getDecryptMetadata() != null) {
final OpenPgpMetadata metadata = result.getDecryptMetadata();
onFileClick = new OnClickListener() { onFileClick = new OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
if (mCurrentInputUri != null) { Activity activity = getActivity();
if (activity == null || mCurrentInputUri != null) {
return; return;
} }
mCurrentInputUri = uri; Uri outputUri = mOutputUris.get(uri);
mDecryptingMetadata = false; Intent intent = new Intent();
cryptoOperation(); intent.setDataAndType(outputUri, metadata.getMimeType());
activity.startActivity(intent);
} }
}; };
} }
@ -236,10 +273,10 @@ public class DecryptFilesListFragment extends CryptoOperationFragment implements
// data // data
Log.d(Constants.TAG, "mInputUri=" + mCurrentInputUri + ", mOutputUri=" + mCurrentOutputUri); Uri currentOutputUri = mOutputUris.get(mCurrentInputUri);
Log.d(Constants.TAG, "mInputUri=" + mCurrentInputUri + ", mOutputUri=" + currentOutputUri);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(mCurrentInputUri, mCurrentOutputUri) PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(mCurrentInputUri, currentOutputUri)
// .setDecryptMetadataOnly(true)
.setAllowSymmetricDecryption(true); .setAllowSymmetricDecryption(true);
data.putParcelable(KeychainIntentService.DECRYPT_VERIFY_PARCEL, input); data.putParcelable(KeychainIntentService.DECRYPT_VERIFY_PARCEL, input);
@ -318,24 +355,6 @@ public class DecryptFilesListFragment extends CryptoOperationFragment implements
super.onCreateContextMenu(menu, v, menuInfo); super.onCreateContextMenu(menu, v, menuInfo);
} }
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_OUTPUT: {
// This happens after output file was selected, so start our operation
if (resultCode == Activity.RESULT_OK && data != null) {
// mCurrentOutputUri = data.getData();
// startDecrypt();
}
return;
}
default: {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
@Override @Override
public boolean onMenuItemClick(MenuItem menuItem) { public boolean onMenuItemClick(MenuItem menuItem) {
if (mAdapter.mMenuClickedModel == null || !mAdapter.mMenuClickedModel.hasResult()) { if (mAdapter.mMenuClickedModel == null || !mAdapter.mMenuClickedModel.hasResult()) {
@ -346,7 +365,8 @@ public class DecryptFilesListFragment extends CryptoOperationFragment implements
return false; return false;
} }
DecryptVerifyResult result = mAdapter.mMenuClickedModel.mResult; ViewModel model = mAdapter.mMenuClickedModel;
DecryptVerifyResult result = model.mResult;
switch (menuItem.getItemId()) { switch (menuItem.getItemId()) {
case R.id.view_log: case R.id.view_log:
Intent intent = new Intent(activity, LogDisplayActivity.class); Intent intent = new Intent(activity, LogDisplayActivity.class);
@ -354,7 +374,12 @@ public class DecryptFilesListFragment extends CryptoOperationFragment implements
activity.startActivity(intent); activity.startActivity(intent);
return true; return true;
case R.id.decrypt_save: case R.id.decrypt_save:
Notify.create(activity, "decrypt/save not yet implemented", Style.ERROR).show(this); OpenPgpMetadata metadata = result.getDecryptMetadata();
if (metadata == null) {
return true;
}
mCurrentInputUri = model.mInputUri;
askForOutputFilename(model.mInputUri, metadata.getFilename(), metadata.getMimeType());
return true; return true;
case R.id.decrypt_delete: case R.id.decrypt_delete:
Notify.create(activity, "decrypt/delete not yet implemented", Style.ERROR).show(this); Notify.create(activity, "decrypt/delete not yet implemented", Style.ERROR).show(this);
@ -371,7 +396,7 @@ public class DecryptFilesListFragment extends CryptoOperationFragment implements
public class ViewModel { public class ViewModel {
Context mContext; Context mContext;
Uri mUri; Uri mInputUri;
DecryptVerifyResult mResult; DecryptVerifyResult mResult;
Drawable mIcon; Drawable mIcon;
@ -383,7 +408,7 @@ public class DecryptFilesListFragment extends CryptoOperationFragment implements
ViewModel(Context context, Uri uri) { ViewModel(Context context, Uri uri) {
mContext = context; mContext = context;
mUri = uri; mInputUri = uri;
mProgress = 0; mProgress = 0;
mMax = 100; mMax = 100;
} }
@ -658,6 +683,7 @@ public class DecryptFilesListFragment extends CryptoOperationFragment implements
final List<ResolveInfo> matches = getActivity() final List<ResolveInfo> matches = getActivity()
.getPackageManager().queryIntentActivities(intent, 0); .getPackageManager().queryIntentActivities(intent, 0);
//noinspection LoopStatementThatDoesntLoop
for (ResolveInfo match : matches) { for (ResolveInfo match : matches) {
return match.loadIcon(getActivity().getPackageManager()); return match.loadIcon(getActivity().getPackageManager());
} }

View File

@ -54,7 +54,8 @@
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
tools:ignore="UseCompoundDrawables">
<ImageView <ImageView
android:id="@+id/result_encryption_icon" android:id="@+id/result_encryption_icon"
@ -81,7 +82,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingRight="4dp" android:paddingRight="4dp"
android:paddingLeft="4dp" android:paddingLeft="4dp"
> tools:ignore="UseCompoundDrawables">
<ImageView <ImageView
android:id="@+id/result_signature_icon" android:id="@+id/result_signature_icon"
@ -156,7 +157,8 @@
android:drawableRight="@drawable/ic_vpn_key_grey_24dp" android:drawableRight="@drawable/ic_vpn_key_grey_24dp"
android:drawablePadding="8dp" android:drawablePadding="8dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="Show" android:text=""
tools:text="Show"
/> />
</LinearLayout> </LinearLayout>