/* * Copyright (C) 2012-2014 Dominik Schürmann * Copyright (C) 2014 Vincent Breitmoser * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package org.sufficientlysecure.keychain.service; import android.app.Service; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import com.textuality.keybase.lib.Proof; import com.textuality.keybase.lib.prover.Prover; import org.json.JSONObject; import org.spongycastle.openpgp.PGPUtil; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; import org.sufficientlysecure.keychain.keyimport.Keyserver; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.operations.*; import org.sufficientlysecure.keychain.operations.results.*; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel; import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.ServiceProgressHandler.MessageStatus; import org.sufficientlysecure.keychain.util.Log; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.List; /** * This Service contains all important long lasting operations for OpenKeychain. It receives Intents with * data from the activities or other apps, executes them, and stops itself after doing them. */ public class KeychainService extends Service implements Progressable { /* extras that can be given by intent */ public static final String EXTRA_MESSENGER = "messenger"; public static final String EXTRA_DATA = "data"; Messenger mMessenger; @Override public IBinder onBind(Intent intent) { return null; } /** * This is run on the main thread, we need to spawn a runnable which runs on another thread for the actual operation */ @Override public int onStartCommand(final Intent intent, int flags, int startId) { return START_NOT_STICKY; } private void sendProofError(List log, String label) { String msg = null; label = (label == null) ? "" : label + ": "; for (String m : log) { Log.e(Constants.TAG, label + m); msg = m; } sendProofError(label + msg); } private void sendProofError(String msg) { Bundle bundle = new Bundle(); bundle.putString(ServiceProgressHandler.DATA_ERROR, msg); sendMessageToHandler(MessageStatus.OKAY, bundle); } private void sendErrorToHandler(Exception e) { // TODO: Implement a better exception handling here // contextualize the exception, if necessary String message; if (e instanceof PgpGeneralMsgIdException) { e = ((PgpGeneralMsgIdException) e).getContextualized(KeychainService.this); message = e.getMessage(); } else { message = e.getMessage(); } Log.d(Constants.TAG, "KeychainService Exception: ", e); Bundle data = new Bundle(); data.putString(ServiceProgressHandler.DATA_ERROR, message); sendMessageToHandler(MessageStatus.EXCEPTION, null, data); } private void sendMessageToHandler(MessageStatus status, Integer arg2, Bundle data) { Message msg = Message.obtain(); assert msg != null; msg.arg1 = status.ordinal(); if (arg2 != null) { msg.arg2 = arg2; } if (data != null) { msg.setData(data); } try { mMessenger.send(msg); } catch (RemoteException e) { Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); } catch (NullPointerException e) { Log.w(Constants.TAG, "Messenger is null!", e); } } private void sendMessageToHandler(MessageStatus status, OperationResult data) { Bundle bundle = new Bundle(); bundle.putParcelable(OperationResult.EXTRA_RESULT, data); sendMessageToHandler(status, null, bundle); } private void sendMessageToHandler(MessageStatus status, Bundle data) { sendMessageToHandler(status, null, data); } private void sendMessageToHandler(MessageStatus status) { sendMessageToHandler(status, null, null); } /** * Set progress of ProgressDialog by sending message to handler on UI thread */ @Override public void setProgress(String message, int progress, int max) { Log.d(Constants.TAG, "Send message by setProgress with progress=" + progress + ", max=" + max); Bundle data = new Bundle(); if (message != null) { data.putString(ServiceProgressHandler.DATA_MESSAGE, message); } data.putInt(ServiceProgressHandler.DATA_PROGRESS, progress); data.putInt(ServiceProgressHandler.DATA_PROGRESS_MAX, max); sendMessageToHandler(MessageStatus.UPDATE_PROGRESS, null, data); } @Override public void setProgress(int resourceId, int progress, int max) { setProgress(getString(resourceId), progress, max); } @Override public void setProgress(int progress, int max) { setProgress(null, progress, max); } @Override public void setPreventCancel() { sendMessageToHandler(MessageStatus.PREVENT_CANCEL); } }