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