ConversationFragment.java

  1package eu.siacs.conversations.ui;
  2
  3import java.io.FileNotFoundException;
  4import java.util.ArrayList;
  5import java.util.HashMap;
  6import java.util.Hashtable;
  7import java.util.LinkedList;
  8import java.util.List;
  9import java.util.Set;
 10
 11import net.java.otr4j.session.SessionStatus;
 12
 13import eu.siacs.conversations.R;
 14import eu.siacs.conversations.crypto.PgpEngine.OpenPgpException;
 15import eu.siacs.conversations.crypto.PgpEngine.UserInputRequiredException;
 16import eu.siacs.conversations.entities.Account;
 17import eu.siacs.conversations.entities.Contact;
 18import eu.siacs.conversations.entities.Conversation;
 19import eu.siacs.conversations.entities.Message;
 20import eu.siacs.conversations.entities.MucOptions;
 21import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
 22import eu.siacs.conversations.services.XmppConnectionService;
 23import eu.siacs.conversations.utils.UIHelper;
 24import android.app.AlertDialog;
 25import android.app.Fragment;
 26import android.content.Context;
 27import android.content.DialogInterface;
 28import android.content.Intent;
 29import android.content.IntentSender;
 30import android.content.SharedPreferences;
 31import android.content.IntentSender.SendIntentException;
 32import android.graphics.Bitmap;
 33import android.graphics.Typeface;
 34import android.os.AsyncTask;
 35import android.os.Bundle;
 36import android.preference.PreferenceManager;
 37import android.util.DisplayMetrics;
 38import android.util.Log;
 39import android.view.LayoutInflater;
 40import android.view.View;
 41import android.view.View.OnClickListener;
 42import android.view.ViewGroup;
 43import android.widget.ArrayAdapter;
 44import android.widget.EditText;
 45import android.widget.LinearLayout;
 46import android.widget.ListView;
 47import android.widget.ImageButton;
 48import android.widget.ImageView;
 49import android.widget.TextView;
 50import android.widget.Toast;
 51
 52public class ConversationFragment extends Fragment {
 53
 54	protected Conversation conversation;
 55	protected ListView messagesView;
 56	protected LayoutInflater inflater;
 57	protected List<Message> messageList = new ArrayList<Message>();
 58	protected ArrayAdapter<Message> messageListAdapter;
 59	protected Contact contact;
 60	protected BitmapCache mBitmapCache = new BitmapCache();
 61
 62	protected String queuedPqpMessage = null;
 63
 64	private EditText chatMsg;
 65	private String pastedText = null;
 66
 67	protected Bitmap selfBitmap;
 68	
 69	private boolean useSubject = true;
 70
 71	private IntentSender askForPassphraseIntent = null;
 72
 73	private OnClickListener sendMsgListener = new OnClickListener() {
 74
 75		@Override
 76		public void onClick(View v) {
 77			if (chatMsg.getText().length() < 1)
 78				return;
 79			Message message = new Message(conversation, chatMsg.getText()
 80					.toString(), conversation.nextMessageEncryption);
 81			if (conversation.nextMessageEncryption == Message.ENCRYPTION_OTR) {
 82				sendOtrMessage(message);
 83			} else if (conversation.nextMessageEncryption == Message.ENCRYPTION_PGP) {
 84				sendPgpMessage(message);
 85			} else {
 86				sendPlainTextMessage(message);
 87			}
 88		}
 89	};
 90	protected OnClickListener clickToDecryptListener = new OnClickListener() {
 91
 92		@Override
 93		public void onClick(View v) {
 94			if (askForPassphraseIntent != null) {
 95				try {
 96					getActivity().startIntentSenderForResult(
 97							askForPassphraseIntent,
 98							ConversationActivity.REQUEST_DECRYPT_PGP, null, 0,
 99							0, 0);
100				} catch (SendIntentException e) {
101					Log.d("xmppService", "couldnt fire intent");
102				}
103			}
104		}
105	};
106
107	private LinearLayout pgpInfo;
108	private LinearLayout mucError;
109	private TextView mucErrorText;
110	private OnClickListener clickToMuc = new OnClickListener() {
111
112		@Override
113		public void onClick(View v) {
114			Intent intent = new Intent(getActivity(), MucDetailsActivity.class);
115			intent.setAction(MucDetailsActivity.ACTION_VIEW_MUC);
116			intent.putExtra("uuid", conversation.getUuid());
117			startActivity(intent);
118		}
119	};
120	private ConversationActivity activity;
121
122	public void hidePgpPassphraseBox() {
123		pgpInfo.setVisibility(View.GONE);
124	}
125
126	public void updateChatMsgHint() {
127		if (conversation.getMode() == Conversation.MODE_MULTI) {
128			chatMsg.setHint(getString(R.string.send_message_to_conference));
129		} else {
130			switch (conversation.nextMessageEncryption) {
131			case Message.ENCRYPTION_NONE:
132				chatMsg.setHint(getString(R.string.send_plain_text_message));
133				break;
134			case Message.ENCRYPTION_OTR:
135				chatMsg.setHint(getString(R.string.send_otr_message));
136				break;
137			case Message.ENCRYPTION_PGP:
138				chatMsg.setHint(getString(R.string.send_pgp_message));
139				break;
140			case Message.ENCRYPTION_DECRYPTED:
141				chatMsg.setHint(getString(R.string.send_pgp_message));
142				break;
143			default:
144				break;
145			}
146		}
147	}
148
149	@Override
150	public View onCreateView(final LayoutInflater inflater,
151			ViewGroup container, Bundle savedInstanceState) {
152
153		final DisplayMetrics metrics = getResources().getDisplayMetrics();
154		
155		this.inflater = inflater;
156
157		final View view = inflater.inflate(R.layout.fragment_conversation,
158				container, false);
159		chatMsg = (EditText) view.findViewById(R.id.textinput);
160		
161		if (pastedText!=null) {
162			chatMsg.setText(pastedText);
163		}
164		
165		ImageButton sendButton = (ImageButton) view
166				.findViewById(R.id.textSendButton);
167		sendButton.setOnClickListener(this.sendMsgListener);
168
169		pgpInfo = (LinearLayout) view.findViewById(R.id.pgp_keyentry);
170		pgpInfo.setOnClickListener(clickToDecryptListener);
171		mucError = (LinearLayout) view.findViewById(R.id.muc_error);
172		mucError.setOnClickListener(clickToMuc);
173		mucErrorText = (TextView) view.findViewById(R.id.muc_error_msg);
174
175		messagesView = (ListView) view.findViewById(R.id.messages_view);
176
177		messageListAdapter = new ArrayAdapter<Message>(this.getActivity()
178				.getApplicationContext(), R.layout.message_sent,
179				this.messageList) {
180
181			private static final int SENT = 0;
182			private static final int RECIEVED = 1;
183
184			@Override
185			public int getViewTypeCount() {
186				return 2;
187			}
188
189			@Override
190			public int getItemViewType(int position) {
191				if (getItem(position).getStatus() <= Message.STATUS_RECIEVED) {
192					return RECIEVED;
193				} else {
194					return SENT;
195				}
196			}
197
198			@Override
199			public View getView(int position, View view, ViewGroup parent) {
200				Message item = getItem(position);
201				int type = getItemViewType(position);
202				ViewHolder viewHolder;
203				if (view == null) {
204					viewHolder = new ViewHolder();
205					switch (type) {
206					case SENT:
207						view = (View) inflater.inflate(R.layout.message_sent,
208								null);
209						viewHolder.contact_picture = (ImageView) view
210								.findViewById(R.id.message_photo);
211						viewHolder.contact_picture.setImageBitmap(selfBitmap);
212						break;
213					case RECIEVED:
214						view = (View) inflater.inflate(
215								R.layout.message_recieved, null);
216						viewHolder.contact_picture = (ImageView) view
217								.findViewById(R.id.message_photo);
218						
219						if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
220
221							viewHolder.contact_picture.setImageBitmap(mBitmapCache
222									.get(item.getConversation().getName(useSubject), item
223											.getConversation().getContact(),
224											getActivity()
225													.getApplicationContext()));
226
227						}
228						break;
229					default:
230						viewHolder = null;
231						break;
232					}
233					viewHolder.indicator = (ImageView) view.findViewById(R.id.security_indicator);
234					viewHolder.image = (ImageView) view.findViewById(R.id.message_image);
235					viewHolder.messageBody = (TextView) view
236							.findViewById(R.id.message_body);
237					viewHolder.time = (TextView) view
238							.findViewById(R.id.message_time);
239					view.setTag(viewHolder);
240				} else {
241					viewHolder = (ViewHolder) view.getTag();
242				}
243				if (type == RECIEVED) {
244					if (item.getConversation().getMode() == Conversation.MODE_MULTI) {
245						if (item.getCounterpart() != null) {
246							viewHolder.contact_picture.setImageBitmap(mBitmapCache
247									.get(item.getCounterpart(), null,
248											getActivity()
249													.getApplicationContext()));
250						} else {
251							viewHolder.contact_picture.setImageBitmap(mBitmapCache
252									.get(item.getConversation().getName(useSubject),
253											null, getActivity()
254													.getApplicationContext()));
255						}
256					}
257				}
258				
259				if (item.getEncryption() == Message.ENCRYPTION_NONE) {
260					viewHolder.indicator.setVisibility(View.GONE);
261				} else {
262					viewHolder.indicator.setVisibility(View.VISIBLE);
263				}
264				
265				
266				if (item.getType() == Message.TYPE_IMAGE) {
267					if (item.getStatus() == Message.STATUS_PREPARING) {
268						viewHolder.image.setVisibility(View.GONE);
269						viewHolder.messageBody.setVisibility(View.VISIBLE);
270						viewHolder.messageBody.setText(getString(R.string.preparing_image));
271						viewHolder.messageBody.setTextColor(0xff33B5E5);
272						viewHolder.messageBody.setTypeface(null,Typeface.ITALIC);
273					} else if (item.getStatus() == Message.STATUS_RECIEVING) {
274						viewHolder.image.setVisibility(View.GONE);
275						viewHolder.messageBody.setVisibility(View.GONE);
276						viewHolder.messageBody.setVisibility(View.VISIBLE);
277						viewHolder.messageBody.setText(getString(R.string.receiving_image));
278						viewHolder.messageBody.setTextColor(0xff33B5E5);
279						viewHolder.messageBody.setTypeface(null,Typeface.ITALIC);
280					} else {
281						try {
282							Bitmap thumbnail = activity.xmppConnectionService.getFileBackend().getThumbnailFromMessage(item,(int) (metrics.density * 288));
283							viewHolder.image.setImageBitmap(thumbnail);
284							viewHolder.messageBody.setVisibility(View.GONE);
285							viewHolder.image.setVisibility(View.VISIBLE);
286						} catch (FileNotFoundException e) {
287							viewHolder.image.setVisibility(View.GONE);
288							viewHolder.messageBody.setText("error loading image file");
289							viewHolder.messageBody.setVisibility(View.VISIBLE);
290						}
291					}
292				} else {
293					viewHolder.image.setVisibility(View.GONE);
294					viewHolder.messageBody.setVisibility(View.VISIBLE);
295					String body = item.getBody();
296					if (body != null) {
297						if (item.getEncryption() == Message.ENCRYPTION_PGP) {
298							viewHolder.messageBody
299									.setText(getString(R.string.encrypted_message));
300							viewHolder.messageBody.setTextColor(0xff33B5E5);
301							viewHolder.messageBody.setTypeface(null,
302									Typeface.ITALIC);
303						} else if ((item.getEncryption() == Message.ENCRYPTION_OTR)||(item.getEncryption() == Message.ENCRYPTION_DECRYPTED)) {
304							viewHolder.messageBody.setText(body.trim());
305							viewHolder.messageBody.setTextColor(0xff333333);
306							viewHolder.messageBody.setTypeface(null,
307									Typeface.NORMAL);
308						} else {
309							viewHolder.messageBody.setText(body.trim());
310							viewHolder.messageBody.setTextColor(0xff333333);
311							viewHolder.messageBody.setTypeface(null,
312									Typeface.NORMAL);
313						}
314					}
315				}
316				switch (item.getStatus()) {
317				case Message.STATUS_UNSEND:
318					viewHolder.time.setTypeface(null, Typeface.ITALIC);
319					viewHolder.time.setTextColor(0xFF8e8e8e);
320					viewHolder.time.setText("sending\u2026");
321					break;
322				case Message.STATUS_SEND_FAILED:
323					viewHolder.time.setText(getString(R.string.send_failed) + " \u00B7 " + UIHelper.readableTimeDifference(item
324							.getTimeSent()));
325					viewHolder.time.setTextColor(0xFFe92727);
326					viewHolder.time.setTypeface(null,Typeface.NORMAL);
327					break;
328				case Message.STATUS_SEND_REJECTED:
329					viewHolder.time.setText(getString(R.string.send_rejected));
330					viewHolder.time.setTextColor(0xFFe92727);
331					viewHolder.time.setTypeface(null,Typeface.NORMAL);
332					break;
333				default:
334					viewHolder.time.setTypeface(null, Typeface.NORMAL);
335					viewHolder.time.setTextColor(0xFF8e8e8e);
336					if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
337						viewHolder.time.setText(UIHelper
338								.readableTimeDifference(item.getTimeSent()));
339					} else {
340						viewHolder.time.setText(item.getCounterpart()
341								+ " \u00B7 "
342								+ UIHelper.readableTimeDifference(item
343										.getTimeSent()));
344					}
345					break;
346				}
347				return view;
348			}
349		};
350		messagesView.setAdapter(messageListAdapter);
351
352		return view;
353	}
354
355	protected Bitmap findSelfPicture() {
356		SharedPreferences sharedPref = PreferenceManager
357				.getDefaultSharedPreferences(getActivity()
358						.getApplicationContext());
359		boolean showPhoneSelfContactPicture = sharedPref.getBoolean(
360				"show_phone_selfcontact_picture", true);
361
362		return UIHelper.getSelfContactPicture(conversation.getAccount(), 48,
363				showPhoneSelfContactPicture, getActivity());
364	}
365
366	@Override
367	public void onStart() {
368		super.onStart();
369		this.activity = (ConversationActivity) getActivity();
370		SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
371		this.useSubject = preferences.getBoolean("use_subject_in_muc", true);
372		if (activity.xmppConnectionServiceBound) {
373			this.onBackendConnected();
374		}
375	}
376
377	public void onBackendConnected() {
378		this.conversation = activity.getSelectedConversation();
379		if (this.conversation == null) {
380			return;
381		}
382		this.selfBitmap = findSelfPicture();
383		updateMessages();
384		// rendering complete. now go tell activity to close pane
385		if (activity.getSlidingPaneLayout().isSlideable()) {
386			if (!activity.shouldPaneBeOpen()) {
387				activity.getSlidingPaneLayout().closePane();
388				activity.getActionBar().setDisplayHomeAsUpEnabled(true);
389				activity.getActionBar().setTitle(conversation.getName(useSubject));
390				activity.invalidateOptionsMenu();
391
392			}
393		}
394		if (queuedPqpMessage != null) {
395			this.conversation.nextMessageEncryption = Message.ENCRYPTION_PGP;
396			Message message = new Message(conversation, queuedPqpMessage,
397					Message.ENCRYPTION_PGP);
398			sendPgpMessage(message);
399		}
400		if (conversation.getMode() == Conversation.MODE_MULTI) {
401			activity.xmppConnectionService
402					.setOnRenameListener(new OnRenameListener() {
403
404						@Override
405						public void onRename(final boolean success) {
406							activity.xmppConnectionService.updateConversation(conversation);
407							getActivity().runOnUiThread(new Runnable() {
408
409								@Override
410								public void run() {
411									if (success) {
412										Toast.makeText(
413												getActivity(),
414												getString(R.string.your_nick_has_been_changed),
415												Toast.LENGTH_SHORT).show();
416									} else {
417										Toast.makeText(getActivity(),
418												getString(R.string.nick_in_use),
419												Toast.LENGTH_SHORT).show();
420									}
421								}
422							});
423						}
424					});
425		}
426	}
427
428	public void updateMessages() {
429		ConversationActivity activity = (ConversationActivity) getActivity();
430		if (this.conversation != null) {
431			List<Message> encryptedMessages = new LinkedList<Message>();
432			for (Message message : this.conversation.getMessages()) {
433				if (message.getEncryption() == Message.ENCRYPTION_PGP) {
434					encryptedMessages.add(message);
435				}
436			}
437			if (encryptedMessages.size() > 0) {
438				DecryptMessage task = new DecryptMessage();
439				Message[] msgs = new Message[encryptedMessages.size()];
440				task.execute(encryptedMessages.toArray(msgs));
441			}
442			this.messageList.clear();
443			this.messageList.addAll(this.conversation.getMessages());
444			this.messageListAdapter.notifyDataSetChanged();
445			if (conversation.getMode() == Conversation.MODE_SINGLE) {
446				if (messageList.size() >= 1) {
447					int latestEncryption = this.conversation.getLatestMessage()
448							.getEncryption();
449					if (latestEncryption == Message.ENCRYPTION_DECRYPTED) {
450						conversation.nextMessageEncryption = Message.ENCRYPTION_PGP;
451					} else {
452						conversation.nextMessageEncryption = latestEncryption;
453					}
454					makeFingerprintWarning(latestEncryption);
455				}
456			} else {
457				if (conversation.getMucOptions().getError() != 0) {
458					mucError.setVisibility(View.VISIBLE);
459					if (conversation.getMucOptions().getError() == MucOptions.ERROR_NICK_IN_USE) {
460						mucErrorText.setText(getString(R.string.nick_in_use));
461					}
462				} else {
463					mucError.setVisibility(View.GONE);
464				}
465			}
466			getActivity().invalidateOptionsMenu();
467			updateChatMsgHint();
468			int size = this.messageList.size();
469			if (size >= 1)
470				messagesView.setSelection(size - 1);
471			if (!activity.shouldPaneBeOpen()) {
472				conversation.markRead();
473				// TODO update notifications
474				UIHelper.updateNotification(getActivity(),
475						activity.getConversationList(), null, false);
476				activity.updateConversationList();
477			}
478		}
479	}
480
481	protected void makeFingerprintWarning(int latestEncryption) {
482		final LinearLayout fingerprintWarning = (LinearLayout) getView()
483				.findViewById(R.id.new_fingerprint);
484		if (conversation.getContact() != null) {
485			Set<String> knownFingerprints = conversation.getContact()
486					.getOtrFingerprints();
487			if ((latestEncryption == Message.ENCRYPTION_OTR)
488					&& (conversation.hasValidOtrSession()
489							&& (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
490								.contains(conversation.getOtrFingerprint())))) {
491				fingerprintWarning.setVisibility(View.VISIBLE);
492				TextView fingerprint = (TextView) getView().findViewById(
493						R.id.otr_fingerprint);
494				fingerprint.setText(conversation.getOtrFingerprint());
495				fingerprintWarning.setOnClickListener(new OnClickListener() {
496
497					@Override
498					public void onClick(View v) {
499						AlertDialog dialog = UIHelper
500								.getVerifyFingerprintDialog(
501										(ConversationActivity) getActivity(),
502										conversation, fingerprintWarning);
503						dialog.show();
504					}
505				});
506			} else {
507				fingerprintWarning.setVisibility(View.GONE);
508			}
509		} else {
510			fingerprintWarning.setVisibility(View.GONE);
511		}
512	}
513
514	protected void sendPlainTextMessage(Message message) {
515		ConversationActivity activity = (ConversationActivity) getActivity();
516		activity.xmppConnectionService.sendMessage(message, null);
517		chatMsg.setText("");
518	}
519
520	protected void sendPgpMessage(final Message message) {
521		ConversationActivity activity = (ConversationActivity) getActivity();
522		final XmppConnectionService xmppService = activity.xmppConnectionService;
523		Contact contact = message.getConversation().getContact();
524		Account account = message.getConversation().getAccount();
525		if (activity.hasPgp()) {
526			if (contact.getPgpKeyId() != 0) {
527				try {
528					message.setEncryptedBody(xmppService.getPgpEngine().encrypt(account, contact.getPgpKeyId(), message.getBody()));
529					xmppService.sendMessage(message, null);
530					chatMsg.setText("");
531				} catch (UserInputRequiredException e) {
532					try {
533						getActivity().startIntentSenderForResult(e.getPendingIntent().getIntentSender(),
534								ConversationActivity.REQUEST_SEND_MESSAGE, null, 0,
535								0, 0);
536					} catch (SendIntentException e1) {
537						Log.d("xmppService","failed to start intent to send message");
538					}
539				} catch (OpenPgpException e) {
540					Log.d("xmppService","error encrypting with pgp: "+e.getOpenPgpError().getMessage());
541				}
542			} else {
543				AlertDialog.Builder builder = new AlertDialog.Builder(
544						getActivity());
545				builder.setTitle("No openPGP key found");
546				builder.setIconAttribute(android.R.attr.alertDialogIcon);
547				builder.setMessage("There is no openPGP key associated with this contact");
548				builder.setNegativeButton("Cancel", null);
549				builder.setPositiveButton("Send plain text",
550						new DialogInterface.OnClickListener() {
551
552							@Override
553							public void onClick(DialogInterface dialog,
554									int which) {
555								conversation.nextMessageEncryption = Message.ENCRYPTION_NONE;
556								message.setEncryption(Message.ENCRYPTION_NONE);
557								xmppService.sendMessage(message, null);
558								chatMsg.setText("");
559							}
560						});
561				builder.create().show();
562			}
563		}
564	}
565
566	protected void sendOtrMessage(final Message message) {
567		ConversationActivity activity = (ConversationActivity) getActivity();
568		final XmppConnectionService xmppService = activity.xmppConnectionService;
569		if (conversation.hasValidOtrSession()) {
570			activity.xmppConnectionService.sendMessage(message, null);
571			chatMsg.setText("");
572		} else {
573			Hashtable<String, Integer> presences;
574			if (conversation.getContact() != null) {
575				presences = conversation.getContact().getPresences();
576			} else {
577				presences = null;
578			}
579			if ((presences == null) || (presences.size() == 0)) {
580				AlertDialog.Builder builder = new AlertDialog.Builder(
581						getActivity());
582				builder.setTitle("Contact is offline");
583				builder.setIconAttribute(android.R.attr.alertDialogIcon);
584				builder.setMessage("Sending OTR encrypted messages to an offline contact is impossible.");
585				builder.setPositiveButton("Send plain text",
586						new DialogInterface.OnClickListener() {
587
588							@Override
589							public void onClick(DialogInterface dialog,
590									int which) {
591								conversation.nextMessageEncryption = Message.ENCRYPTION_NONE;
592								message.setEncryption(Message.ENCRYPTION_NONE);
593								xmppService.sendMessage(message, null);
594								chatMsg.setText("");
595							}
596						});
597				builder.setNegativeButton("Cancel", null);
598				builder.create().show();
599			} else if (presences.size() == 1) {
600				xmppService.sendMessage(message, (String) presences.keySet()
601						.toArray()[0]);
602				chatMsg.setText("");
603			} else {
604				AlertDialog.Builder builder = new AlertDialog.Builder(
605						getActivity());
606				builder.setTitle("Choose Presence");
607				final String[] presencesArray = new String[presences.size()];
608				presences.keySet().toArray(presencesArray);
609				builder.setItems(presencesArray,
610						new DialogInterface.OnClickListener() {
611
612							@Override
613							public void onClick(DialogInterface dialog,
614									int which) {
615								xmppService.sendMessage(message,
616										presencesArray[which]);
617								chatMsg.setText("");
618							}
619						});
620				builder.create().show();
621			}
622		}
623	}
624
625	private static class ViewHolder {
626
627		protected ImageView image;
628		protected ImageView indicator;
629		protected TextView time;
630		protected TextView messageBody;
631		protected ImageView contact_picture;
632
633	}
634
635	private class BitmapCache {
636		private HashMap<String, Bitmap> bitmaps = new HashMap<String, Bitmap>();
637		private Bitmap error = null;
638
639		public Bitmap get(String name, Contact contact, Context context) {
640			if (bitmaps.containsKey(name)) {
641				return bitmaps.get(name);
642			} else {
643				Bitmap bm;
644				if (contact != null){
645					bm = UIHelper.getContactPicture(contact, 48, context, false);
646				} else {
647					bm = UIHelper.getContactPicture(name, 48, context, false);
648				}
649				bitmaps.put(name, bm);
650				return bm;
651			}
652		}
653
654		public Bitmap getError() {
655			if (error == null) {
656				error = UIHelper.getErrorPicture(200);
657			}
658			return error;
659		}
660	}
661
662	class DecryptMessage extends AsyncTask<Message, Void, Boolean> {
663
664		@Override
665		protected Boolean doInBackground(Message... params) {
666			final ConversationActivity activity = (ConversationActivity) getActivity();
667			askForPassphraseIntent = null;
668			for (int i = 0; i < params.length; ++i) {
669				if (params[i].getEncryption() == Message.ENCRYPTION_PGP) {
670					String body = params[i].getBody();
671					String decrypted = null;
672					if (activity == null) {
673						return false;
674					} else if (!activity.xmppConnectionServiceBound) {
675						return false;
676					}
677					try {
678						decrypted = activity.xmppConnectionService
679								.getPgpEngine().decrypt(conversation.getAccount(),body);
680					} catch (UserInputRequiredException e) {
681						askForPassphraseIntent = e.getPendingIntent()
682								.getIntentSender();
683						activity.runOnUiThread(new Runnable() {
684
685							@Override
686							public void run() {
687								pgpInfo.setVisibility(View.VISIBLE);
688							}
689						});
690
691						return false;
692
693					} catch (OpenPgpException e) {
694						Log.d("gultsch", "error decrypting pgp");
695					}
696					if (decrypted != null) {
697						params[i].setBody(decrypted);
698						params[i].setEncryption(Message.ENCRYPTION_DECRYPTED);
699						activity.xmppConnectionService.updateMessage(params[i]);
700					}
701					if (activity != null) {
702						activity.runOnUiThread(new Runnable() {
703
704							@Override
705							public void run() {
706								messageListAdapter.notifyDataSetChanged();
707							}
708						});
709					}
710				}
711				if (activity != null) {
712					activity.runOnUiThread(new Runnable() {
713
714						@Override
715						public void run() {
716							activity.updateConversationList();
717						}
718					});
719				}
720			}
721			return true;
722		}
723
724	}
725
726	public void setText(String text) {
727		this.pastedText = text;
728	}
729}