1package eu.siacs.conversations.entities;
2
3import android.content.ContentValues;
4import android.database.Cursor;
5
6import java.net.MalformedURLException;
7import java.net.URL;
8import java.util.Arrays;
9
10import eu.siacs.conversations.Config;
11import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
12import eu.siacs.conversations.utils.GeoHelper;
13import eu.siacs.conversations.utils.MimeUtils;
14import eu.siacs.conversations.utils.UIHelper;
15import eu.siacs.conversations.xmpp.jid.InvalidJidException;
16import eu.siacs.conversations.xmpp.jid.Jid;
17
18public class Message extends AbstractEntity {
19
20 public static final String TABLENAME = "messages";
21
22 public static final String MERGE_SEPARATOR = " \u200B\n\n";
23
24 public static final int STATUS_RECEIVED = 0;
25 public static final int STATUS_UNSEND = 1;
26 public static final int STATUS_SEND = 2;
27 public static final int STATUS_SEND_FAILED = 3;
28 public static final int STATUS_WAITING = 5;
29 public static final int STATUS_OFFERED = 6;
30 public static final int STATUS_SEND_RECEIVED = 7;
31 public static final int STATUS_SEND_DISPLAYED = 8;
32
33 public static final int ENCRYPTION_NONE = 0;
34 public static final int ENCRYPTION_PGP = 1;
35 public static final int ENCRYPTION_OTR = 2;
36 public static final int ENCRYPTION_DECRYPTED = 3;
37 public static final int ENCRYPTION_DECRYPTION_FAILED = 4;
38 public static final int ENCRYPTION_AXOLOTL = 5;
39
40 public static final int TYPE_TEXT = 0;
41 public static final int TYPE_IMAGE = 1;
42 public static final int TYPE_FILE = 2;
43 public static final int TYPE_STATUS = 3;
44 public static final int TYPE_PRIVATE = 4;
45
46 public static final String CONVERSATION = "conversationUuid";
47 public static final String COUNTERPART = "counterpart";
48 public static final String TRUE_COUNTERPART = "trueCounterpart";
49 public static final String BODY = "body";
50 public static final String TIME_SENT = "timeSent";
51 public static final String ENCRYPTION = "encryption";
52 public static final String STATUS = "status";
53 public static final String TYPE = "type";
54 public static final String CARBON = "carbon";
55 public static final String EDITED = "edited";
56 public static final String REMOTE_MSG_ID = "remoteMsgId";
57 public static final String SERVER_MSG_ID = "serverMsgId";
58 public static final String RELATIVE_FILE_PATH = "relativeFilePath";
59 public static final String FINGERPRINT = "axolotl_fingerprint";
60 public static final String READ = "read";
61 public static final String ME_COMMAND = "/me ";
62
63
64 public boolean markable = false;
65 protected String conversationUuid;
66 protected Jid counterpart;
67 protected Jid trueCounterpart;
68 protected String body;
69 protected String encryptedBody;
70 protected long timeSent;
71 protected int encryption;
72 protected int status;
73 protected int type;
74 protected boolean carbon = false;
75 protected String edited = null;
76 protected String relativeFilePath;
77 protected boolean read = true;
78 protected String remoteMsgId = null;
79 protected String serverMsgId = null;
80 protected Conversation conversation = null;
81 protected Transferable transferable = null;
82 private Message mNextMessage = null;
83 private Message mPreviousMessage = null;
84 private String axolotlFingerprint = null;
85
86 private Message() {
87
88 }
89
90 public Message(Conversation conversation, String body, int encryption) {
91 this(conversation, body, encryption, STATUS_UNSEND);
92 }
93
94 public Message(Conversation conversation, String body, int encryption, int status) {
95 this(java.util.UUID.randomUUID().toString(),
96 conversation.getUuid(),
97 conversation.getJid() == null ? null : conversation.getJid().toBareJid(),
98 null,
99 body,
100 System.currentTimeMillis(),
101 encryption,
102 status,
103 TYPE_TEXT,
104 false,
105 null,
106 null,
107 null,
108 null,
109 true,
110 null);
111 this.conversation = conversation;
112 }
113
114 private Message(final String uuid, final String conversationUUid, final Jid counterpart,
115 final Jid trueCounterpart, final String body, final long timeSent,
116 final int encryption, final int status, final int type, final boolean carbon,
117 final String remoteMsgId, final String relativeFilePath,
118 final String serverMsgId, final String fingerprint, final boolean read,
119 final String edited) {
120 this.uuid = uuid;
121 this.conversationUuid = conversationUUid;
122 this.counterpart = counterpart;
123 this.trueCounterpart = trueCounterpart;
124 this.body = body;
125 this.timeSent = timeSent;
126 this.encryption = encryption;
127 this.status = status;
128 this.type = type;
129 this.carbon = carbon;
130 this.remoteMsgId = remoteMsgId;
131 this.relativeFilePath = relativeFilePath;
132 this.serverMsgId = serverMsgId;
133 this.axolotlFingerprint = fingerprint;
134 this.read = read;
135 this.edited = edited;
136 }
137
138 public static Message fromCursor(Cursor cursor) {
139 Jid jid;
140 try {
141 String value = cursor.getString(cursor.getColumnIndex(COUNTERPART));
142 if (value != null) {
143 jid = Jid.fromString(value, true);
144 } else {
145 jid = null;
146 }
147 } catch (InvalidJidException e) {
148 jid = null;
149 }
150 Jid trueCounterpart;
151 try {
152 String value = cursor.getString(cursor.getColumnIndex(TRUE_COUNTERPART));
153 if (value != null) {
154 trueCounterpart = Jid.fromString(value, true);
155 } else {
156 trueCounterpart = null;
157 }
158 } catch (InvalidJidException e) {
159 trueCounterpart = null;
160 }
161 return new Message(cursor.getString(cursor.getColumnIndex(UUID)),
162 cursor.getString(cursor.getColumnIndex(CONVERSATION)),
163 jid,
164 trueCounterpart,
165 cursor.getString(cursor.getColumnIndex(BODY)),
166 cursor.getLong(cursor.getColumnIndex(TIME_SENT)),
167 cursor.getInt(cursor.getColumnIndex(ENCRYPTION)),
168 cursor.getInt(cursor.getColumnIndex(STATUS)),
169 cursor.getInt(cursor.getColumnIndex(TYPE)),
170 cursor.getInt(cursor.getColumnIndex(CARBON)) > 0,
171 cursor.getString(cursor.getColumnIndex(REMOTE_MSG_ID)),
172 cursor.getString(cursor.getColumnIndex(RELATIVE_FILE_PATH)),
173 cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID)),
174 cursor.getString(cursor.getColumnIndex(FINGERPRINT)),
175 cursor.getInt(cursor.getColumnIndex(READ)) > 0,
176 cursor.getString(cursor.getColumnIndex(EDITED)));
177 }
178
179 public static Message createStatusMessage(Conversation conversation, String body) {
180 final Message message = new Message();
181 message.setType(Message.TYPE_STATUS);
182 message.setConversation(conversation);
183 message.setBody(body);
184 return message;
185 }
186
187 public static Message createLoadMoreMessage(Conversation conversation) {
188 final Message message = new Message();
189 message.setType(Message.TYPE_STATUS);
190 message.setConversation(conversation);
191 message.setBody("LOAD_MORE");
192 return message;
193 }
194
195 @Override
196 public ContentValues getContentValues() {
197 ContentValues values = new ContentValues();
198 values.put(UUID, uuid);
199 values.put(CONVERSATION, conversationUuid);
200 if (counterpart == null) {
201 values.putNull(COUNTERPART);
202 } else {
203 values.put(COUNTERPART, counterpart.toString());
204 }
205 if (trueCounterpart == null) {
206 values.putNull(TRUE_COUNTERPART);
207 } else {
208 values.put(TRUE_COUNTERPART, trueCounterpart.toString());
209 }
210 values.put(BODY, body);
211 values.put(TIME_SENT, timeSent);
212 values.put(ENCRYPTION, encryption);
213 values.put(STATUS, status);
214 values.put(TYPE, type);
215 values.put(CARBON, carbon ? 1 : 0);
216 values.put(REMOTE_MSG_ID, remoteMsgId);
217 values.put(RELATIVE_FILE_PATH, relativeFilePath);
218 values.put(SERVER_MSG_ID, serverMsgId);
219 values.put(FINGERPRINT, axolotlFingerprint);
220 values.put(READ,read ? 1 : 0);
221 values.put(EDITED, edited);
222 return values;
223 }
224
225 public String getConversationUuid() {
226 return conversationUuid;
227 }
228
229 public Conversation getConversation() {
230 return this.conversation;
231 }
232
233 public void setConversation(Conversation conv) {
234 this.conversation = conv;
235 }
236
237 public Jid getCounterpart() {
238 return counterpart;
239 }
240
241 public void setCounterpart(final Jid counterpart) {
242 this.counterpart = counterpart;
243 }
244
245 public Contact getContact() {
246 if (this.conversation.getMode() == Conversation.MODE_SINGLE) {
247 return this.conversation.getContact();
248 } else {
249 if (this.trueCounterpart == null) {
250 return null;
251 } else {
252 return this.conversation.getAccount().getRoster()
253 .getContactFromRoster(this.trueCounterpart);
254 }
255 }
256 }
257
258 public String getBody() {
259 return body;
260 }
261
262 public void setBody(String body) {
263 this.body = body;
264 }
265
266 public long getTimeSent() {
267 return timeSent;
268 }
269
270 public int getEncryption() {
271 return encryption;
272 }
273
274 public void setEncryption(int encryption) {
275 this.encryption = encryption;
276 }
277
278 public int getStatus() {
279 return status;
280 }
281
282 public void setStatus(int status) {
283 this.status = status;
284 }
285
286 public String getRelativeFilePath() {
287 return this.relativeFilePath;
288 }
289
290 public void setRelativeFilePath(String path) {
291 this.relativeFilePath = path;
292 }
293
294 public String getRemoteMsgId() {
295 return this.remoteMsgId;
296 }
297
298 public void setRemoteMsgId(String id) {
299 this.remoteMsgId = id;
300 }
301
302 public String getServerMsgId() {
303 return this.serverMsgId;
304 }
305
306 public void setServerMsgId(String id) {
307 this.serverMsgId = id;
308 }
309
310 public boolean isRead() {
311 return this.read;
312 }
313
314 public void markRead() {
315 this.read = true;
316 }
317
318 public void markUnread() {
319 this.read = false;
320 }
321
322 public void setTime(long time) {
323 this.timeSent = time;
324 }
325
326 public String getEncryptedBody() {
327 return this.encryptedBody;
328 }
329
330 public void setEncryptedBody(String body) {
331 this.encryptedBody = body;
332 }
333
334 public int getType() {
335 return this.type;
336 }
337
338 public void setType(int type) {
339 this.type = type;
340 }
341
342 public boolean isCarbon() {
343 return carbon;
344 }
345
346 public void setCarbon(boolean carbon) {
347 this.carbon = carbon;
348 }
349
350 public void setEdited(String edited) {
351 this.edited = edited;
352 }
353
354 public boolean edited() {
355 return this.edited != null;
356 }
357
358 public void setTrueCounterpart(Jid trueCounterpart) {
359 this.trueCounterpart = trueCounterpart;
360 }
361
362 public Jid getTrueCounterpart() {
363 return this.trueCounterpart;
364 }
365
366 public Transferable getTransferable() {
367 return this.transferable;
368 }
369
370 public void setTransferable(Transferable transferable) {
371 this.transferable = transferable;
372 }
373
374 public boolean equals(Message message) {
375 if (this.serverMsgId != null && message.getServerMsgId() != null) {
376 return this.serverMsgId.equals(message.getServerMsgId());
377 } else if (this.body == null || this.counterpart == null) {
378 return false;
379 } else {
380 String body, otherBody;
381 if (this.hasFileOnRemoteHost()) {
382 body = getFileParams().url.toString();
383 otherBody = message.body == null ? null : message.body.trim();
384 } else {
385 body = this.body;
386 otherBody = message.body;
387 }
388 if (message.getRemoteMsgId() != null) {
389 return (message.getRemoteMsgId().equals(this.remoteMsgId) || message.getRemoteMsgId().equals(this.uuid))
390 && this.counterpart.equals(message.getCounterpart())
391 && (body.equals(otherBody)
392 ||(message.getEncryption() == Message.ENCRYPTION_PGP
393 && message.getRemoteMsgId().matches("[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"))) ;
394 } else {
395 return this.remoteMsgId == null
396 && this.counterpart.equals(message.getCounterpart())
397 && body.equals(otherBody)
398 && Math.abs(this.getTimeSent() - message.getTimeSent()) < Config.MESSAGE_MERGE_WINDOW * 1000;
399 }
400 }
401 }
402
403 public Message next() {
404 synchronized (this.conversation.messages) {
405 if (this.mNextMessage == null) {
406 int index = this.conversation.messages.indexOf(this);
407 if (index < 0 || index >= this.conversation.messages.size() - 1) {
408 this.mNextMessage = null;
409 } else {
410 this.mNextMessage = this.conversation.messages.get(index + 1);
411 }
412 }
413 return this.mNextMessage;
414 }
415 }
416
417 public Message prev() {
418 synchronized (this.conversation.messages) {
419 if (this.mPreviousMessage == null) {
420 int index = this.conversation.messages.indexOf(this);
421 if (index <= 0 || index > this.conversation.messages.size()) {
422 this.mPreviousMessage = null;
423 } else {
424 this.mPreviousMessage = this.conversation.messages.get(index - 1);
425 }
426 }
427 return this.mPreviousMessage;
428 }
429 }
430
431 public boolean mergeable(final Message message) {
432 return message != null &&
433 (message.getType() == Message.TYPE_TEXT &&
434 this.getTransferable() == null &&
435 message.getTransferable() == null &&
436 message.getEncryption() != Message.ENCRYPTION_PGP &&
437 this.getType() == message.getType() &&
438 //this.getStatus() == message.getStatus() &&
439 isStatusMergeable(this.getStatus(), message.getStatus()) &&
440 this.getEncryption() == message.getEncryption() &&
441 this.getCounterpart() != null &&
442 this.getCounterpart().equals(message.getCounterpart()) &&
443 this.edited() == message.edited() &&
444 (message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) &&
445 !GeoHelper.isGeoUri(message.getBody()) &&
446 !GeoHelper.isGeoUri(this.body) &&
447 message.treatAsDownloadable() == Decision.NEVER &&
448 this.treatAsDownloadable() == Decision.NEVER &&
449 !message.getBody().startsWith(ME_COMMAND) &&
450 !this.getBody().startsWith(ME_COMMAND) &&
451 !this.bodyIsHeart() &&
452 !message.bodyIsHeart() &&
453 this.isTrusted() == message.isTrusted()
454 );
455 }
456
457 private static boolean isStatusMergeable(int a, int b) {
458 return a == b || (
459 (a == Message.STATUS_SEND_RECEIVED && b == Message.STATUS_UNSEND)
460 || (a == Message.STATUS_SEND_RECEIVED && b == Message.STATUS_SEND)
461 || (a == Message.STATUS_UNSEND && b == Message.STATUS_SEND)
462 || (a == Message.STATUS_UNSEND && b == Message.STATUS_SEND_RECEIVED)
463 || (a == Message.STATUS_SEND && b == Message.STATUS_UNSEND)
464 || (a == Message.STATUS_SEND && b == Message.STATUS_SEND_RECEIVED)
465 );
466 }
467
468 public String getMergedBody() {
469 StringBuilder body = new StringBuilder(this.body.trim());
470 Message current = this;
471 while(current.mergeable(current.next())) {
472 current = current.next();
473 body.append(MERGE_SEPARATOR);
474 body.append(current.getBody().trim());
475 }
476 return body.toString();
477 }
478
479 public boolean hasMeCommand() {
480 return getMergedBody().startsWith(ME_COMMAND);
481 }
482
483 public int getMergedStatus() {
484 int status = this.status;
485 Message current = this;
486 while(current.mergeable(current.next())) {
487 current = current.next();
488 status = current.status;
489 }
490 return status;
491 }
492
493 public long getMergedTimeSent() {
494 long time = this.timeSent;
495 Message current = this;
496 while(current.mergeable(current.next())) {
497 current = current.next();
498 time = current.timeSent;
499 }
500 return time;
501 }
502
503 public boolean wasMergedIntoPrevious() {
504 Message prev = this.prev();
505 return prev != null && prev.mergeable(this);
506 }
507
508 public boolean trusted() {
509 Contact contact = this.getContact();
510 return (status > STATUS_RECEIVED || (contact != null && contact.trusted()));
511 }
512
513 public boolean fixCounterpart() {
514 Presences presences = conversation.getContact().getPresences();
515 if (counterpart != null && presences.has(counterpart.getResourcepart())) {
516 return true;
517 } else if (presences.size() >= 1) {
518 try {
519 counterpart = Jid.fromParts(conversation.getJid().getLocalpart(),
520 conversation.getJid().getDomainpart(),
521 presences.asStringArray()[0]);
522 return true;
523 } catch (InvalidJidException e) {
524 counterpart = null;
525 return false;
526 }
527 } else {
528 counterpart = null;
529 return false;
530 }
531 }
532
533 public void setUuid(String uuid) {
534 this.uuid = uuid;
535 }
536
537 public String getEditedId() {
538 return edited;
539 }
540
541 public enum Decision {
542 MUST,
543 SHOULD,
544 NEVER,
545 }
546
547 private static String extractRelevantExtension(URL url) {
548 String path = url.getPath();
549 return extractRelevantExtension(path);
550 }
551
552 private static String extractRelevantExtension(String path) {
553 if (path == null || path.isEmpty()) {
554 return null;
555 }
556
557 String filename = path.substring(path.lastIndexOf('/') + 1).toLowerCase();
558 int dotPosition = filename.lastIndexOf(".");
559
560 if (dotPosition != -1) {
561 String extension = filename.substring(dotPosition + 1);
562 // we want the real file extension, not the crypto one
563 if (Arrays.asList(Transferable.VALID_CRYPTO_EXTENSIONS).contains(extension)) {
564 return extractRelevantExtension(filename.substring(0,dotPosition));
565 } else {
566 return extension;
567 }
568 }
569 return null;
570 }
571
572 public String getMimeType() {
573 if (relativeFilePath != null) {
574 int start = relativeFilePath.lastIndexOf('.') + 1;
575 if (start < relativeFilePath.length()) {
576 return MimeUtils.guessMimeTypeFromExtension(relativeFilePath.substring(start));
577 } else {
578 return null;
579 }
580 } else {
581 try {
582 return MimeUtils.guessMimeTypeFromExtension(extractRelevantExtension(new URL(body.trim())));
583 } catch (MalformedURLException e) {
584 return null;
585 }
586 }
587 }
588
589 public Decision treatAsDownloadable() {
590 if (body.trim().contains(" ")) {
591 return Decision.NEVER;
592 }
593 try {
594 URL url = new URL(body);
595 if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) {
596 return Decision.NEVER;
597 }
598 String extension = extractRelevantExtension(url);
599 if (extension == null) {
600 return Decision.NEVER;
601 }
602 String ref = url.getRef();
603 boolean encrypted = ref != null && ref.matches("([A-Fa-f0-9]{2}){48}");
604
605 if (encrypted) {
606 if (MimeUtils.guessMimeTypeFromExtension(extension) != null) {
607 return Decision.MUST;
608 } else {
609 return Decision.NEVER;
610 }
611 } else if (Arrays.asList(Transferable.VALID_IMAGE_EXTENSIONS).contains(extension)
612 || Arrays.asList(Transferable.WELL_KNOWN_EXTENSIONS).contains(extension)) {
613 return Decision.SHOULD;
614 } else {
615 return Decision.NEVER;
616 }
617
618 } catch (MalformedURLException e) {
619 return Decision.NEVER;
620 }
621 }
622
623 public boolean bodyIsHeart() {
624 return body != null && UIHelper.HEARTS.contains(body.trim());
625 }
626
627 public FileParams getFileParams() {
628 FileParams params = getLegacyFileParams();
629 if (params != null) {
630 return params;
631 }
632 params = new FileParams();
633 if (this.transferable != null) {
634 params.size = this.transferable.getFileSize();
635 }
636 if (body == null) {
637 return params;
638 }
639 String parts[] = body.split("\\|");
640 switch (parts.length) {
641 case 1:
642 try {
643 params.size = Long.parseLong(parts[0]);
644 } catch (NumberFormatException e) {
645 try {
646 params.url = new URL(parts[0]);
647 } catch (MalformedURLException e1) {
648 params.url = null;
649 }
650 }
651 break;
652 case 2:
653 case 4:
654 try {
655 params.url = new URL(parts[0]);
656 } catch (MalformedURLException e1) {
657 params.url = null;
658 }
659 try {
660 params.size = Long.parseLong(parts[1]);
661 } catch (NumberFormatException e) {
662 params.size = 0;
663 }
664 try {
665 params.width = Integer.parseInt(parts[2]);
666 } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
667 params.width = 0;
668 }
669 try {
670 params.height = Integer.parseInt(parts[3]);
671 } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
672 params.height = 0;
673 }
674 break;
675 case 3:
676 try {
677 params.size = Long.parseLong(parts[0]);
678 } catch (NumberFormatException e) {
679 params.size = 0;
680 }
681 try {
682 params.width = Integer.parseInt(parts[1]);
683 } catch (NumberFormatException e) {
684 params.width = 0;
685 }
686 try {
687 params.height = Integer.parseInt(parts[2]);
688 } catch (NumberFormatException e) {
689 params.height = 0;
690 }
691 break;
692 }
693 return params;
694 }
695
696 public FileParams getLegacyFileParams() {
697 FileParams params = new FileParams();
698 if (body == null) {
699 return params;
700 }
701 String parts[] = body.split(",");
702 if (parts.length == 3) {
703 try {
704 params.size = Long.parseLong(parts[0]);
705 } catch (NumberFormatException e) {
706 return null;
707 }
708 try {
709 params.width = Integer.parseInt(parts[1]);
710 } catch (NumberFormatException e) {
711 return null;
712 }
713 try {
714 params.height = Integer.parseInt(parts[2]);
715 } catch (NumberFormatException e) {
716 return null;
717 }
718 return params;
719 } else {
720 return null;
721 }
722 }
723
724 public void untie() {
725 this.mNextMessage = null;
726 this.mPreviousMessage = null;
727 }
728
729 public boolean isFileOrImage() {
730 return type == TYPE_FILE || type == TYPE_IMAGE;
731 }
732
733 public boolean hasFileOnRemoteHost() {
734 return isFileOrImage() && getFileParams().url != null;
735 }
736
737 public boolean needsUploading() {
738 return isFileOrImage() && getFileParams().url == null;
739 }
740
741 public class FileParams {
742 public URL url;
743 public long size = 0;
744 public int width = 0;
745 public int height = 0;
746 }
747
748 public void setAxolotlFingerprint(String fingerprint) {
749 this.axolotlFingerprint = fingerprint;
750 }
751
752 public String getAxolotlFingerprint() {
753 return axolotlFingerprint;
754 }
755
756 public boolean isTrusted() {
757 XmppAxolotlSession.Trust t = conversation.getAccount().getAxolotlService().getFingerprintTrust(axolotlFingerprint);
758 return t != null && t.trusted();
759 }
760
761 private int getPreviousEncryption() {
762 for (Message iterator = this.prev(); iterator != null; iterator = iterator.prev()){
763 if( iterator.isCarbon() || iterator.getStatus() == STATUS_RECEIVED ) {
764 continue;
765 }
766 return iterator.getEncryption();
767 }
768 return ENCRYPTION_NONE;
769 }
770
771 private int getNextEncryption() {
772 for (Message iterator = this.next(); iterator != null; iterator = iterator.next()){
773 if( iterator.isCarbon() || iterator.getStatus() == STATUS_RECEIVED ) {
774 continue;
775 }
776 return iterator.getEncryption();
777 }
778 return conversation.getNextEncryption();
779 }
780
781 public boolean isValidInSession() {
782 int pastEncryption = getCleanedEncryption(this.getPreviousEncryption());
783 int futureEncryption = getCleanedEncryption(this.getNextEncryption());
784
785 boolean inUnencryptedSession = pastEncryption == ENCRYPTION_NONE
786 || futureEncryption == ENCRYPTION_NONE
787 || pastEncryption != futureEncryption;
788
789 return inUnencryptedSession || getCleanedEncryption(this.getEncryption()) == pastEncryption;
790 }
791
792 private static int getCleanedEncryption(int encryption) {
793 if (encryption == ENCRYPTION_DECRYPTED || encryption == ENCRYPTION_DECRYPTION_FAILED) {
794 return ENCRYPTION_PGP;
795 }
796 return encryption;
797 }
798}