show unknown otr fingerprint warining
This commit is contained in:
parent
42c4c1789a
commit
9c7cacdbdd
|
@ -42,24 +42,24 @@ public final class R {
|
||||||
public static final int section_header=0x7f02000d;
|
public static final int section_header=0x7f02000d;
|
||||||
}
|
}
|
||||||
public static final class id {
|
public static final class id {
|
||||||
public static final int account_confirm_password_desc=0x7f0a0019;
|
public static final int account_confirm_password_desc=0x7f0a001c;
|
||||||
public static final int account_delete=0x7f0a002d;
|
public static final int account_delete=0x7f0a0035;
|
||||||
public static final int account_disable=0x7f0a002e;
|
public static final int account_disable=0x7f0a0036;
|
||||||
public static final int account_enable=0x7f0a002f;
|
public static final int account_enable=0x7f0a0037;
|
||||||
public static final int account_jid=0x7f0a0000;
|
public static final int account_jid=0x7f0a0000;
|
||||||
public static final int account_list=0x7f0a0022;
|
public static final int account_list=0x7f0a0027;
|
||||||
public static final int account_password=0x7f0a0016;
|
public static final int account_password=0x7f0a0019;
|
||||||
public static final int account_password_confirm2=0x7f0a001a;
|
public static final int account_password_confirm2=0x7f0a001d;
|
||||||
public static final int account_status=0x7f0a0002;
|
public static final int account_status=0x7f0a0002;
|
||||||
public static final int account_usetls=0x7f0a0017;
|
public static final int account_usetls=0x7f0a001a;
|
||||||
public static final int action_accounts=0x7f0a002a;
|
public static final int action_accounts=0x7f0a002f;
|
||||||
public static final int action_add=0x7f0a0026;
|
public static final int action_add=0x7f0a002b;
|
||||||
public static final int action_add_account=0x7f0a002c;
|
public static final int action_add_account=0x7f0a0034;
|
||||||
public static final int action_archive=0x7f0a0029;
|
public static final int action_archive=0x7f0a002e;
|
||||||
public static final int action_details=0x7f0a0028;
|
public static final int action_details=0x7f0a002d;
|
||||||
public static final int action_refresh_contacts=0x7f0a0030;
|
public static final int action_refresh_contacts=0x7f0a0038;
|
||||||
public static final int action_security=0x7f0a0027;
|
public static final int action_security=0x7f0a002c;
|
||||||
public static final int action_settings=0x7f0a002b;
|
public static final int action_settings=0x7f0a0030;
|
||||||
public static final int contactList=0x7f0a0006;
|
public static final int contactList=0x7f0a0006;
|
||||||
public static final int contact_display_name=0x7f0a0008;
|
public static final int contact_display_name=0x7f0a0008;
|
||||||
public static final int contact_jid=0x7f0a0009;
|
public static final int contact_jid=0x7f0a0009;
|
||||||
|
@ -76,21 +76,29 @@ public final class R {
|
||||||
public static final int details_jidbox=0x7f0a000f;
|
public static final int details_jidbox=0x7f0a000f;
|
||||||
public static final int details_receive_presence=0x7f0a0014;
|
public static final int details_receive_presence=0x7f0a0014;
|
||||||
public static final int details_send_presence=0x7f0a0013;
|
public static final int details_send_presence=0x7f0a0013;
|
||||||
public static final int edit_account_register_new=0x7f0a0018;
|
public static final int edit_account_register_new=0x7f0a001b;
|
||||||
public static final int list=0x7f0a0020;
|
public static final int encryption_choice_none=0x7f0a0031;
|
||||||
public static final int message_body=0x7f0a0024;
|
public static final int encryption_choice_otr=0x7f0a0032;
|
||||||
public static final int message_photo=0x7f0a0023;
|
public static final int encryption_choice_pgp=0x7f0a0033;
|
||||||
public static final int message_time=0x7f0a0025;
|
public static final int list=0x7f0a0025;
|
||||||
public static final int messages_view=0x7f0a001e;
|
public static final int message_body=0x7f0a0029;
|
||||||
|
public static final int message_photo=0x7f0a0028;
|
||||||
|
public static final int message_time=0x7f0a002a;
|
||||||
|
public static final int messages_view=0x7f0a0021;
|
||||||
public static final int new_conversation_search=0x7f0a0004;
|
public static final int new_conversation_search=0x7f0a0004;
|
||||||
|
public static final int new_fingerprint=0x7f0a0022;
|
||||||
|
public static final int otr_fingerprint=0x7f0a0023;
|
||||||
public static final int progressBar1=0x7f0a0003;
|
public static final int progressBar1=0x7f0a0003;
|
||||||
public static final int selected_conversation=0x7f0a0021;
|
public static final int selected_conversation=0x7f0a0026;
|
||||||
public static final int slidingpanelayout=0x7f0a001f;
|
public static final int slidingpanelayout=0x7f0a0024;
|
||||||
public static final int textSendButton=0x7f0a001d;
|
public static final int textSendButton=0x7f0a0020;
|
||||||
public static final int textView1=0x7f0a0015;
|
public static final int textView1=0x7f0a0018;
|
||||||
public static final int textView2=0x7f0a0001;
|
public static final int textView2=0x7f0a0001;
|
||||||
public static final int textinput=0x7f0a001c;
|
public static final int textinput=0x7f0a001f;
|
||||||
public static final int textsend=0x7f0a001b;
|
public static final int textsend=0x7f0a001e;
|
||||||
|
public static final int verify_otr_fingerprint=0x7f0a0016;
|
||||||
|
public static final int verify_otr_jid=0x7f0a0015;
|
||||||
|
public static final int verify_otr_yourprint=0x7f0a0017;
|
||||||
}
|
}
|
||||||
public static final class layout {
|
public static final class layout {
|
||||||
public static final int account_row=0x7f030000;
|
public static final int account_row=0x7f030000;
|
||||||
|
@ -98,18 +106,20 @@ public final class R {
|
||||||
public static final int contact=0x7f030002;
|
public static final int contact=0x7f030002;
|
||||||
public static final int conversation_list_row=0x7f030003;
|
public static final int conversation_list_row=0x7f030003;
|
||||||
public static final int dialog_contact_details=0x7f030004;
|
public static final int dialog_contact_details=0x7f030004;
|
||||||
public static final int edit_account_dialog=0x7f030005;
|
public static final int dialog_verify_otr=0x7f030005;
|
||||||
public static final int fragment_conversation=0x7f030006;
|
public static final int edit_account_dialog=0x7f030006;
|
||||||
public static final int fragment_conversations_overview=0x7f030007;
|
public static final int fragment_conversation=0x7f030007;
|
||||||
public static final int manage_accounts=0x7f030008;
|
public static final int fragment_conversations_overview=0x7f030008;
|
||||||
public static final int message_recieved=0x7f030009;
|
public static final int manage_accounts=0x7f030009;
|
||||||
public static final int message_sent=0x7f03000a;
|
public static final int message_recieved=0x7f03000a;
|
||||||
|
public static final int message_sent=0x7f03000b;
|
||||||
}
|
}
|
||||||
public static final class menu {
|
public static final class menu {
|
||||||
public static final int conversations=0x7f090000;
|
public static final int conversations=0x7f090000;
|
||||||
public static final int manageaccounts=0x7f090001;
|
public static final int encryption_choices=0x7f090001;
|
||||||
public static final int manageaccounts_context=0x7f090002;
|
public static final int manageaccounts=0x7f090002;
|
||||||
public static final int newconversation=0x7f090003;
|
public static final int manageaccounts_context=0x7f090003;
|
||||||
|
public static final int newconversation=0x7f090004;
|
||||||
}
|
}
|
||||||
public static final class string {
|
public static final class string {
|
||||||
public static final int action_accounts=0x7f070003;
|
public static final int action_accounts=0x7f070003;
|
||||||
|
|
53
res/layout/dialog_verify_otr.xml
Normal file
53
res/layout/dialog_verify_otr.xml
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="8dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:text="Jabber ID"
|
||||||
|
android:textColor="#33B5E5"
|
||||||
|
android:textSize="20sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/verify_otr_jid"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:text="julia@jabber.example.com"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:text="OTR fingerprint"
|
||||||
|
android:textColor="#33B5E5"
|
||||||
|
android:textSize="20sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/verify_otr_fingerprint"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:text="2674D6A0 0B1421B1 BFC42AEC C56F3719 672437D8"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:text="Your fingerprint"
|
||||||
|
android:textColor="#33B5E5"
|
||||||
|
android:textSize="20sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/verify_otr_yourprint"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:text="2674D6A0 0B1421B1 BFC42AEC C56F3719 672437D8"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
</LinearLayout>
|
|
@ -53,5 +53,35 @@
|
||||||
android:transcriptMode="alwaysScroll"
|
android:transcriptMode="alwaysScroll"
|
||||||
android:listSelector="@android:color/transparent">
|
android:listSelector="@android:color/transparent">
|
||||||
</ListView>
|
</ListView>
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/new_fingerprint"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_alignTop="@+id/messages_view"
|
||||||
|
android:background="#cc0000"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Unknown OTR Fingerprint"
|
||||||
|
android:textColor="#eee"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:textSize="20sp"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/otr_fingerprint"
|
||||||
|
android:textColor="#eee"
|
||||||
|
android:text="2674D6A0 0B1421B1 BFC42AEC C56F3719 672437D8"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:textSize="14sp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
17
res/menu/encryption_choices.xml
Normal file
17
res/menu/encryption_choices.xml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
<group android:checkableBehavior="single">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/encryption_choice_none"
|
||||||
|
android:title="Plain text"
|
||||||
|
/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/encryption_choice_otr"
|
||||||
|
android:title="OTR"
|
||||||
|
/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/encryption_choice_pgp"
|
||||||
|
android:title="OpenPGP"/>
|
||||||
|
</group>
|
||||||
|
</menu>
|
|
@ -124,6 +124,10 @@ public class OtrEngine implements OtrEngineHost {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PublicKey getPublicKey() {
|
||||||
|
return this.keyPair.getPublic();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyPair getLocalKeyPair(SessionID arg0) throws OtrException {
|
public KeyPair getLocalKeyPair(SessionID arg0) throws OtrException {
|
||||||
if (this.keyPair==null) {
|
if (this.keyPair==null) {
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
package de.gultsch.chat.entities;
|
package de.gultsch.chat.entities;
|
||||||
|
|
||||||
|
import java.security.interfaces.DSAPublicKey;
|
||||||
|
|
||||||
|
import net.java.otr4j.crypto.OtrCryptoEngineImpl;
|
||||||
|
import net.java.otr4j.crypto.OtrCryptoException;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
@ -49,6 +54,8 @@ public class Account extends AbstractEntity{
|
||||||
transient OtrEngine otrEngine = null;
|
transient OtrEngine otrEngine = null;
|
||||||
transient XmppConnection xmppConnection = null;
|
transient XmppConnection xmppConnection = null;
|
||||||
|
|
||||||
|
private String otrFingerprint;
|
||||||
|
|
||||||
public Account() {
|
public Account() {
|
||||||
this.uuid = "0";
|
this.uuid = "0";
|
||||||
}
|
}
|
||||||
|
@ -177,4 +184,21 @@ public class Account extends AbstractEntity{
|
||||||
public String getFullJid() {
|
public String getFullJid() {
|
||||||
return this.getJid()+"/"+this.resource;
|
return this.getJid()+"/"+this.resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getOtrFingerprint() {
|
||||||
|
if (this.otrFingerprint == null) {
|
||||||
|
try {
|
||||||
|
DSAPublicKey pubkey = (DSAPublicKey) this.otrEngine.getPublicKey();
|
||||||
|
StringBuilder builder = new StringBuilder(new OtrCryptoEngineImpl().getFingerprint(pubkey));
|
||||||
|
builder.insert(8, " ");
|
||||||
|
builder.insert(17, " ");
|
||||||
|
builder.insert(26, " ");
|
||||||
|
builder.insert(35, " ");
|
||||||
|
this.otrFingerprint = builder.toString();
|
||||||
|
} catch (OtrCryptoException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.otrFingerprint;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
package de.gultsch.chat.entities;
|
package de.gultsch.chat.entities;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
@ -16,7 +22,7 @@ public class Contact extends AbstractEntity implements Serializable {
|
||||||
public static final String SUBSCRIPTION = "subscription";
|
public static final String SUBSCRIPTION = "subscription";
|
||||||
public static final String SYSTEMACCOUNT = "systemaccount";
|
public static final String SYSTEMACCOUNT = "systemaccount";
|
||||||
public static final String PHOTOURI = "photouri";
|
public static final String PHOTOURI = "photouri";
|
||||||
public static final String OPENPGPKEY = "pgpkey";
|
public static final String KEYS = "pgpkey";
|
||||||
public static final String PRESENCES = "presences";
|
public static final String PRESENCES = "presences";
|
||||||
public static final String ACCOUNT = "accountUuid";
|
public static final String ACCOUNT = "accountUuid";
|
||||||
|
|
||||||
|
@ -26,7 +32,7 @@ public class Contact extends AbstractEntity implements Serializable {
|
||||||
protected String subscription;
|
protected String subscription;
|
||||||
protected String systemAccount;
|
protected String systemAccount;
|
||||||
protected String photoUri;
|
protected String photoUri;
|
||||||
protected String openPGPKey;
|
protected JSONObject keys;
|
||||||
protected Presences presences = new Presences();
|
protected Presences presences = new Presences();
|
||||||
|
|
||||||
protected Account account;
|
protected Account account;
|
||||||
|
@ -45,7 +51,7 @@ public class Contact extends AbstractEntity implements Serializable {
|
||||||
|
|
||||||
public Contact(String uuid, String account, String displayName, String jid,
|
public Contact(String uuid, String account, String displayName, String jid,
|
||||||
String subscription, String photoUri, String systemAccount,
|
String subscription, String photoUri, String systemAccount,
|
||||||
String pgpKey,String presences) {
|
String keys, String presences) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.accountUuid = account;
|
this.accountUuid = account;
|
||||||
this.displayName = displayName;
|
this.displayName = displayName;
|
||||||
|
@ -53,7 +59,14 @@ public class Contact extends AbstractEntity implements Serializable {
|
||||||
this.subscription = subscription;
|
this.subscription = subscription;
|
||||||
this.photoUri = photoUri;
|
this.photoUri = photoUri;
|
||||||
this.systemAccount = systemAccount;
|
this.systemAccount = systemAccount;
|
||||||
this.openPGPKey = pgpKey;
|
if (keys == null) {
|
||||||
|
keys = "";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.keys = new JSONObject(keys);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
this.keys = new JSONObject();
|
||||||
|
}
|
||||||
this.presences = Presences.fromJsonString(presences);
|
this.presences = Presences.fromJsonString(presences);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +97,7 @@ public class Contact extends AbstractEntity implements Serializable {
|
||||||
values.put(SUBSCRIPTION, subscription);
|
values.put(SUBSCRIPTION, subscription);
|
||||||
values.put(SYSTEMACCOUNT, systemAccount);
|
values.put(SYSTEMACCOUNT, systemAccount);
|
||||||
values.put(PHOTOURI, photoUri);
|
values.put(PHOTOURI, photoUri);
|
||||||
values.put(OPENPGPKEY, openPGPKey);
|
values.put(KEYS, keys.toString());
|
||||||
values.put(PRESENCES, presences.toJsonString());
|
values.put(PRESENCES, presences.toJsonString());
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +110,7 @@ public class Contact extends AbstractEntity implements Serializable {
|
||||||
cursor.getString(cursor.getColumnIndex(SUBSCRIPTION)),
|
cursor.getString(cursor.getColumnIndex(SUBSCRIPTION)),
|
||||||
cursor.getString(cursor.getColumnIndex(PHOTOURI)),
|
cursor.getString(cursor.getColumnIndex(PHOTOURI)),
|
||||||
cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)),
|
cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)),
|
||||||
cursor.getString(cursor.getColumnIndex(OPENPGPKEY)),
|
cursor.getString(cursor.getColumnIndex(KEYS)),
|
||||||
cursor.getString(cursor.getColumnIndex(PRESENCES)));
|
cursor.getString(cursor.getColumnIndex(PRESENCES)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,4 +186,36 @@ public class Contact extends AbstractEntity implements Serializable {
|
||||||
public String getSystemAccount() {
|
public String getSystemAccount() {
|
||||||
return systemAccount;
|
return systemAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<String> getOtrFingerprints() {
|
||||||
|
Set<String> set = new HashSet<String>();
|
||||||
|
try {
|
||||||
|
if (this.keys.has("otr_fingerprints")) {
|
||||||
|
JSONArray fingerprints = this.keys.getJSONArray("otr_fingerprints");
|
||||||
|
for (int i = 0; i < fingerprints.length(); ++i) {
|
||||||
|
set.add(fingerprints.getString(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOtrFingerprint(String print) {
|
||||||
|
try {
|
||||||
|
JSONArray fingerprints;
|
||||||
|
if (!this.keys.has("otr_fingerprints")) {
|
||||||
|
fingerprints = new JSONArray();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fingerprints = this.keys.getJSONArray("otr_fingerprints");
|
||||||
|
}
|
||||||
|
fingerprints.put(print);
|
||||||
|
this.keys.put("otr_fingerprints", fingerprints);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package de.gultsch.chat.entities;
|
package de.gultsch.chat.entities;
|
||||||
|
|
||||||
|
import java.security.interfaces.DSAPublicKey;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -7,6 +8,8 @@ import de.gultsch.chat.crypto.OtrEngine;
|
||||||
import de.gultsch.chat.xmpp.XmppConnection;
|
import de.gultsch.chat.xmpp.XmppConnection;
|
||||||
|
|
||||||
import net.java.otr4j.OtrException;
|
import net.java.otr4j.OtrException;
|
||||||
|
import net.java.otr4j.crypto.OtrCryptoEngineImpl;
|
||||||
|
import net.java.otr4j.crypto.OtrCryptoException;
|
||||||
import net.java.otr4j.session.SessionID;
|
import net.java.otr4j.session.SessionID;
|
||||||
import net.java.otr4j.session.SessionImpl;
|
import net.java.otr4j.session.SessionImpl;
|
||||||
import net.java.otr4j.session.SessionStatus;
|
import net.java.otr4j.session.SessionStatus;
|
||||||
|
@ -51,7 +54,10 @@ public class Conversation extends AbstractEntity {
|
||||||
private transient Contact contact;
|
private transient Contact contact;
|
||||||
|
|
||||||
private transient SessionImpl otrSession;
|
private transient SessionImpl otrSession;
|
||||||
private transient String foreignOtrPresence;
|
|
||||||
|
private transient String otrFingerprint = null;
|
||||||
|
|
||||||
|
public int nextMessageEncryption = Message.ENCRYPTION_NONE;
|
||||||
|
|
||||||
public Conversation(String name, Account account,
|
public Conversation(String name, Account account,
|
||||||
String contactJid, int mode) {
|
String contactJid, int mode) {
|
||||||
|
@ -209,6 +215,11 @@ public class Conversation extends AbstractEntity {
|
||||||
Log.d("xmppService","starting otr session with "+presence);
|
Log.d("xmppService","starting otr session with "+presence);
|
||||||
SessionID sessionId = new SessionID(this.getContactJid(),presence,"xmpp");
|
SessionID sessionId = new SessionID(this.getContactJid(),presence,"xmpp");
|
||||||
this.otrSession = new SessionImpl(sessionId, getAccount().getOtrEngine(context));
|
this.otrSession = new SessionImpl(sessionId, getAccount().getOtrEngine(context));
|
||||||
|
try {
|
||||||
|
this.otrSession.startSession();
|
||||||
|
} catch (OtrException e) {
|
||||||
|
Log.d("xmppServic","couldnt start otr");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SessionImpl getOtrSession() {
|
public SessionImpl getOtrSession() {
|
||||||
|
@ -225,9 +236,36 @@ public class Conversation extends AbstractEntity {
|
||||||
this.otrSession.endSession();
|
this.otrSession.endSession();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.resetOtrSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasOtrSession() {
|
public boolean hasValidOtrSession() {
|
||||||
return (this.otrSession!=null);
|
if (this.otrSession == null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
String foreignPresence = this.otrSession.getSessionID().getUserID();
|
||||||
|
if (!getContact().getPresences().containsKey(foreignPresence)) {
|
||||||
|
this.resetOtrSession();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOtrFingerprint() {
|
||||||
|
if (this.otrFingerprint == null) {
|
||||||
|
try {
|
||||||
|
DSAPublicKey remotePubKey = (DSAPublicKey) getOtrSession().getRemotePublicKey();
|
||||||
|
StringBuilder builder = new StringBuilder(new OtrCryptoEngineImpl().getFingerprint(remotePubKey));
|
||||||
|
builder.insert(8, " ");
|
||||||
|
builder.insert(17, " ");
|
||||||
|
builder.insert(26, " ");
|
||||||
|
builder.insert(35, " ");
|
||||||
|
this.otrFingerprint = builder.toString();
|
||||||
|
} catch (OtrCryptoException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.otrFingerprint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,4 +132,8 @@ public class Message extends AbstractEntity {
|
||||||
this.timeSent = time;
|
this.timeSent = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setEncryption(int encryption) {
|
||||||
|
this.encryption = encryption;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
db.execSQL("create table " + Contact.TABLENAME + "(" + Contact.UUID
|
db.execSQL("create table " + Contact.TABLENAME + "(" + Contact.UUID
|
||||||
+ " TEXT PRIMARY KEY, " + Contact.ACCOUNT + " TEXT, "
|
+ " TEXT PRIMARY KEY, " + Contact.ACCOUNT + " TEXT, "
|
||||||
+ Contact.DISPLAYNAME + " TEXT," + Contact.JID + " TEXT,"
|
+ Contact.DISPLAYNAME + " TEXT," + Contact.JID + " TEXT,"
|
||||||
+ Contact.PRESENCES + " TEXT, " + Contact.OPENPGPKEY
|
+ Contact.PRESENCES + " TEXT, " + Contact.KEYS
|
||||||
+ " TEXT," + Contact.PHOTOURI + " TEXT," + Contact.SUBSCRIPTION
|
+ " TEXT," + Contact.PHOTOURI + " TEXT," + Contact.SUBSCRIPTION
|
||||||
+ " TEXT," + Contact.SYSTEMACCOUNT + " NUMBER, "
|
+ " TEXT," + Contact.SYSTEMACCOUNT + " NUMBER, "
|
||||||
+ "FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES "
|
+ "FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES "
|
||||||
|
@ -228,10 +228,6 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mergeMessageIntoConversation(Message message) {
|
|
||||||
// select counterpart,body,(timeSent/1000)-180 as min,(timeSent/1000)+180 as max from messages where min<1392035670 and max>1392035670;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Contact> getContacts(Account account) {
|
public List<Contact> getContacts(Account account) {
|
||||||
List<Contact> list = new ArrayList<Contact>();
|
List<Contact> list = new ArrayList<Contact>();
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
SQLiteDatabase db = this.getReadableDatabase();
|
||||||
|
|
|
@ -132,7 +132,7 @@ public class XmppConnectionService extends Service {
|
||||||
} else {
|
} else {
|
||||||
counterPart = fullJid;
|
counterPart = fullJid;
|
||||||
if ((runOtrCheck) && body.startsWith("?OTR")) {
|
if ((runOtrCheck) && body.startsWith("?OTR")) {
|
||||||
if (!conversation.hasOtrSession()) {
|
if (!conversation.hasValidOtrSession()) {
|
||||||
conversation.startOtrSession(
|
conversation.startOtrSession(
|
||||||
getApplicationContext(), fromParts[1]);
|
getApplicationContext(), fromParts[1]);
|
||||||
}
|
}
|
||||||
|
@ -162,6 +162,9 @@ public class XmppConnectionService extends Service {
|
||||||
if (convChangedListener!=null) {
|
if (convChangedListener!=null) {
|
||||||
convChangedListener.onConversationListChanged();
|
convChangedListener.onConversationListChanged();
|
||||||
}
|
}
|
||||||
|
} else if ((before != after) && (after == SessionStatus.FINISHED)) {
|
||||||
|
conversation.resetOtrSession();
|
||||||
|
Log.d(LOGTAG,"otr session stoped");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.d(LOGTAG, "error receiving otr. resetting");
|
Log.d(LOGTAG, "error receiving otr. resetting");
|
||||||
|
@ -327,60 +330,17 @@ public class XmppConnectionService extends Service {
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startOtrSession(Conversation conv) {
|
public void sendMessage(Account account, Message message, String presence) {
|
||||||
Set<String> presences = conv.getContact().getPresences()
|
|
||||||
.keySet();
|
|
||||||
if (presences.size() == 0) {
|
|
||||||
Log.d(LOGTAG, "counter part isnt online. cant use otr");
|
|
||||||
return;
|
|
||||||
} else if (presences.size() == 1) {
|
|
||||||
conv.startOtrSession(getApplicationContext(),
|
|
||||||
(String) presences.toArray()[0]);
|
|
||||||
try {
|
|
||||||
conv.getOtrSession().startSession();
|
|
||||||
} catch (OtrException e) {
|
|
||||||
Log.d(LOGTAG, "couldnt actually start");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String latestCounterpartPresence = null;
|
|
||||||
List<Message> messages = conv.getMessages();
|
|
||||||
for (int i = messages.size() - 1; i >= 0; --i) {
|
|
||||||
if (messages.get(i).getStatus() == Message.STATUS_RECIEVED) {
|
|
||||||
String[] parts = messages.get(i).getCounterpart()
|
|
||||||
.split("/");
|
|
||||||
if (parts.length == 2) {
|
|
||||||
latestCounterpartPresence = parts[1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (presences.contains(latestCounterpartPresence)) {
|
|
||||||
conv.startOtrSession(getApplicationContext(),
|
|
||||||
latestCounterpartPresence);
|
|
||||||
try {
|
|
||||||
conv.getOtrSession().startSession();
|
|
||||||
} catch (OtrException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
Log.d(LOGTAG, "couldnt actually start");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d(LOGTAG,
|
|
||||||
"could not decide where to send otr connection to");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendMessage(Account account, Message message) {
|
|
||||||
Conversation conv = message.getConversation();
|
Conversation conv = message.getConversation();
|
||||||
boolean saveInDb = false;
|
boolean saveInDb = false;
|
||||||
boolean addToConversation = false;
|
boolean addToConversation = false;
|
||||||
if (account.getStatus() == Account.STATUS_ONLINE) {
|
if (account.getStatus() == Account.STATUS_ONLINE) {
|
||||||
MessagePacket packet;
|
MessagePacket packet;
|
||||||
if (message.getEncryption() == Message.ENCRYPTION_OTR) {
|
if (message.getEncryption() == Message.ENCRYPTION_OTR) {
|
||||||
if (!conv.hasOtrSession()) {
|
if (!conv.hasValidOtrSession()) {
|
||||||
//starting otr session. messages will be send later
|
//starting otr session. messages will be send later
|
||||||
startOtrSession(conv);
|
conv.startOtrSession(getApplicationContext(), presence);
|
||||||
} else {
|
} else if (conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED){
|
||||||
//otr session aleary exists, creating message packet accordingly
|
//otr session aleary exists, creating message packet accordingly
|
||||||
packet = prepareMessagePacket(account, message,
|
packet = prepareMessagePacket(account, message,
|
||||||
conv.getOtrSession());
|
conv.getOtrSession());
|
||||||
|
@ -646,6 +606,7 @@ public class XmppConnectionService extends Service {
|
||||||
conversation.setMode(Conversation.MODE_SINGLE);
|
conversation.setMode(Conversation.MODE_SINGLE);
|
||||||
}
|
}
|
||||||
this.databaseBackend.updateConversation(conversation);
|
this.databaseBackend.updateConversation(conversation);
|
||||||
|
conversation.setContact(findContact(account, conversation.getContactJid()));
|
||||||
} else {
|
} else {
|
||||||
String conversationName;
|
String conversationName;
|
||||||
Contact contact = findContact(account, jid);
|
Contact contact = findContact(account, jid);
|
||||||
|
@ -766,9 +727,9 @@ public class XmppConnectionService extends Service {
|
||||||
x.setAttribute("xmlns", "http://jabber.org/protocol/muc");
|
x.setAttribute("xmlns", "http://jabber.org/protocol/muc");
|
||||||
if (conversation.getMessages().size() != 0) {
|
if (conversation.getMessages().size() != 0) {
|
||||||
Element history = new Element("history");
|
Element history = new Element("history");
|
||||||
history.setAttribute("seconds",
|
long lastMsgTime = conversation.getLatestMessage().getTimeSent();
|
||||||
(System.currentTimeMillis() - conversation
|
long diff = (System.currentTimeMillis() - lastMsgTime) / 1000;
|
||||||
.getLatestMessage().getTimeSent() / 1000) + "");
|
history.setAttribute("seconds",diff+"");
|
||||||
x.addChild(history);
|
x.addChild(history);
|
||||||
}
|
}
|
||||||
packet.addChild(x);
|
packet.addChild(x);
|
||||||
|
@ -806,4 +767,8 @@ public class XmppConnectionService extends Service {
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
return mBinder;
|
return mBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateContact(Contact contact) {
|
||||||
|
databaseBackend.updateContact(contact);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -32,6 +32,8 @@ import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
import android.widget.PopupMenu;
|
||||||
|
import android.widget.PopupMenu.OnMenuItemClickListener;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
@ -295,6 +297,56 @@ public class ConversationActivity extends XmppActivity {
|
||||||
} else {
|
} else {
|
||||||
Log.d("xmppService","contact was null - means not in roster");
|
Log.d("xmppService","contact was null - means not in roster");
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case R.id.action_security:
|
||||||
|
final Conversation selConv = getSelectedConversation();
|
||||||
|
View menuItemView = findViewById(R.id.action_security);
|
||||||
|
PopupMenu popup = new PopupMenu(this, menuItemView);
|
||||||
|
final ConversationFragment fragment = (ConversationFragment) getFragmentManager().findFragmentByTag("conversation");
|
||||||
|
if (fragment!=null) {
|
||||||
|
popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.encryption_choice_none:
|
||||||
|
selConv.nextMessageEncryption = Message.ENCRYPTION_NONE;
|
||||||
|
item.setChecked(true);
|
||||||
|
break;
|
||||||
|
case R.id.encryption_choice_otr:
|
||||||
|
selConv.nextMessageEncryption = Message.ENCRYPTION_OTR;
|
||||||
|
item.setChecked(true);
|
||||||
|
break;
|
||||||
|
case R.id.encryption_choice_pgp:
|
||||||
|
selConv.nextMessageEncryption = Message.ENCRYPTION_PGP;
|
||||||
|
item.setChecked(true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
selConv.nextMessageEncryption = Message.ENCRYPTION_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fragment.updateChatMsgHint();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
popup.inflate(R.menu.encryption_choices);
|
||||||
|
switch (selConv.nextMessageEncryption) {
|
||||||
|
case Message.ENCRYPTION_NONE:
|
||||||
|
popup.getMenu().findItem(R.id.encryption_choice_none).setChecked(true);
|
||||||
|
break;
|
||||||
|
case Message.ENCRYPTION_OTR:
|
||||||
|
popup.getMenu().findItem(R.id.encryption_choice_otr).setChecked(true);
|
||||||
|
break;
|
||||||
|
case Message.ENCRYPTION_PGP:
|
||||||
|
popup.getMenu().findItem(R.id.encryption_choice_pgp).setChecked(true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
popup.getMenu().findItem(R.id.encryption_choice_none).setChecked(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
popup.show();
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -344,13 +396,6 @@ public class ConversationActivity extends XmppActivity {
|
||||||
@Override
|
@Override
|
||||||
void onBackendConnected() {
|
void onBackendConnected() {
|
||||||
|
|
||||||
|
|
||||||
if (contactInserted) {
|
|
||||||
Log.d("xmppService","merge phone contacts with roster");
|
|
||||||
contactInserted = false;
|
|
||||||
xmppConnectionService.mergePhoneContactsWithRoster();
|
|
||||||
}
|
|
||||||
|
|
||||||
xmppConnectionService.setOnConversationListChangedListener(this.onConvChanged);
|
xmppConnectionService.setOnConversationListChangedListener(this.onConvChanged);
|
||||||
|
|
||||||
if (conversationList.size()==0) {
|
if (conversationList.size()==0) {
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
package de.gultsch.chat.ui;
|
package de.gultsch.chat.ui;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.java.otr4j.OtrException;
|
||||||
|
import net.java.otr4j.session.SessionStatus;
|
||||||
|
|
||||||
import de.gultsch.chat.R;
|
import de.gultsch.chat.R;
|
||||||
import de.gultsch.chat.entities.Contact;
|
import de.gultsch.chat.entities.Contact;
|
||||||
import de.gultsch.chat.entities.Conversation;
|
import de.gultsch.chat.entities.Conversation;
|
||||||
import de.gultsch.chat.entities.Message;
|
import de.gultsch.chat.entities.Message;
|
||||||
|
import de.gultsch.chat.services.XmppConnectionService;
|
||||||
import de.gultsch.chat.utils.PhoneHelper;
|
import de.gultsch.chat.utils.PhoneHelper;
|
||||||
import de.gultsch.chat.utils.UIHelper;
|
import de.gultsch.chat.utils.UIHelper;
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
|
import android.content.DialogInterface;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
@ -21,6 +29,7 @@ import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
@ -36,7 +45,80 @@ public class ConversationFragment extends Fragment {
|
||||||
protected Contact contact;
|
protected Contact contact;
|
||||||
|
|
||||||
private EditText chatMsg;
|
private EditText chatMsg;
|
||||||
private int nextMessageEncryption = Message.ENCRYPTION_NONE;
|
|
||||||
|
private OnClickListener sendMsgListener = new OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
ConversationActivity activity = (ConversationActivity) getActivity();
|
||||||
|
final XmppConnectionService xmppService = activity.xmppConnectionService;
|
||||||
|
if (chatMsg.getText().length() < 1)
|
||||||
|
return;
|
||||||
|
final Message message = new Message(conversation, chatMsg.getText()
|
||||||
|
.toString(), conversation.nextMessageEncryption);
|
||||||
|
if (conversation.nextMessageEncryption == Message.ENCRYPTION_OTR) {
|
||||||
|
if (conversation.hasValidOtrSession()) {
|
||||||
|
activity.xmppConnectionService.sendMessage(
|
||||||
|
conversation.getAccount(), message, null);
|
||||||
|
chatMsg.setText("");
|
||||||
|
} else {
|
||||||
|
Hashtable<String, Integer> presences = conversation
|
||||||
|
.getContact().getPresences();
|
||||||
|
if (presences.size() == 0) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(
|
||||||
|
getActivity());
|
||||||
|
builder.setTitle("Contact is offline");
|
||||||
|
builder.setIconAttribute(android.R.attr.alertDialogIcon);
|
||||||
|
builder.setMessage("Sending OTR encrypted messages to an offline contact is impossible.");
|
||||||
|
builder.setPositiveButton("Send plain text",
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog,
|
||||||
|
int which) {
|
||||||
|
conversation.nextMessageEncryption = Message.ENCRYPTION_NONE;
|
||||||
|
message.setEncryption(Message.ENCRYPTION_NONE);
|
||||||
|
xmppService.sendMessage(
|
||||||
|
conversation.getAccount(),
|
||||||
|
message, null);
|
||||||
|
chatMsg.setText("");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setNegativeButton("Cancel", null);
|
||||||
|
builder.create().show();
|
||||||
|
} else if (presences.size() == 1) {
|
||||||
|
xmppService.sendMessage(conversation.getAccount(),
|
||||||
|
message,
|
||||||
|
(String) presences.keySet().toArray()[0]);
|
||||||
|
chatMsg.setText("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
xmppService.sendMessage(conversation.getAccount(), message,
|
||||||
|
null);
|
||||||
|
chatMsg.setText("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void updateChatMsgHint() {
|
||||||
|
if (conversation.getMode() == Conversation.MODE_MULTI) {
|
||||||
|
chatMsg.setHint("Send message to conference");
|
||||||
|
} else {
|
||||||
|
switch (conversation.nextMessageEncryption) {
|
||||||
|
case Message.ENCRYPTION_NONE:
|
||||||
|
chatMsg.setHint("Send plain text message");
|
||||||
|
break;
|
||||||
|
case Message.ENCRYPTION_OTR:
|
||||||
|
chatMsg.setHint("Send OTR encrypted message");
|
||||||
|
break;
|
||||||
|
case Message.ENCRYPTION_PGP:
|
||||||
|
chatMsg.setHint("Send openPGP encryted messeage");
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(final LayoutInflater inflater,
|
public View onCreateView(final LayoutInflater inflater,
|
||||||
|
@ -47,36 +129,28 @@ public class ConversationFragment extends Fragment {
|
||||||
final View view = inflater.inflate(R.layout.fragment_conversation,
|
final View view = inflater.inflate(R.layout.fragment_conversation,
|
||||||
container, false);
|
container, false);
|
||||||
chatMsg = (EditText) view.findViewById(R.id.textinput);
|
chatMsg = (EditText) view.findViewById(R.id.textinput);
|
||||||
((ImageButton) view.findViewById(R.id.textSendButton))
|
ImageButton sendButton = (ImageButton) view
|
||||||
.setOnClickListener(new OnClickListener() {
|
.findViewById(R.id.textSendButton);
|
||||||
|
sendButton.setOnClickListener(this.sendMsgListener);
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
ConversationActivity activity = (ConversationActivity) getActivity();
|
|
||||||
if (chatMsg.getText().length() < 1)
|
|
||||||
return;
|
|
||||||
Message message = new Message(conversation, chatMsg
|
|
||||||
.getText().toString(), nextMessageEncryption);
|
|
||||||
activity.xmppConnectionService.sendMessage(conversation.getAccount(),message);
|
|
||||||
chatMsg.setText("");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
messagesView = (ListView) view.findViewById(R.id.messages_view);
|
messagesView = (ListView) view.findViewById(R.id.messages_view);
|
||||||
|
|
||||||
SharedPreferences sharedPref = PreferenceManager
|
SharedPreferences sharedPref = PreferenceManager
|
||||||
.getDefaultSharedPreferences(getActivity().getApplicationContext());
|
.getDefaultSharedPreferences(getActivity()
|
||||||
boolean showPhoneSelfContactPicture = sharedPref.getBoolean("show_phone_selfcontact_picture",true);
|
.getApplicationContext());
|
||||||
|
boolean showPhoneSelfContactPicture = sharedPref.getBoolean(
|
||||||
|
"show_phone_selfcontact_picture", true);
|
||||||
|
|
||||||
final Uri selfiUri;
|
final Uri selfiUri;
|
||||||
if (showPhoneSelfContactPicture) {
|
if (showPhoneSelfContactPicture) {
|
||||||
selfiUri = PhoneHelper.getSefliUri(getActivity());
|
selfiUri = PhoneHelper.getSefliUri(getActivity());
|
||||||
} else {
|
} else {
|
||||||
selfiUri = null;
|
selfiUri = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
messageListAdapter = new ArrayAdapter<Message>(this.getActivity()
|
messageListAdapter = new ArrayAdapter<Message>(this.getActivity()
|
||||||
.getApplicationContext(), R.layout.message_sent, this.messageList) {
|
.getApplicationContext(), R.layout.message_sent,
|
||||||
|
this.messageList) {
|
||||||
|
|
||||||
private static final int SENT = 0;
|
private static final int SENT = 0;
|
||||||
private static final int RECIEVED = 1;
|
private static final int RECIEVED = 1;
|
||||||
|
@ -111,32 +185,42 @@ public class ConversationFragment extends Fragment {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImageView imageView = (ImageView) view.findViewById(R.id.message_photo);
|
ImageView imageView = (ImageView) view
|
||||||
|
.findViewById(R.id.message_photo);
|
||||||
if (type == RECIEVED) {
|
if (type == RECIEVED) {
|
||||||
if(item.getConversation().getMode()==Conversation.MODE_SINGLE) {
|
if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
|
||||||
Uri uri = item.getConversation().getProfilePhotoUri();
|
Uri uri = item.getConversation().getProfilePhotoUri();
|
||||||
if (uri!=null) {
|
if (uri != null) {
|
||||||
imageView.setImageURI(uri);
|
imageView.setImageURI(uri);
|
||||||
} else {
|
} else {
|
||||||
imageView.setImageBitmap(UIHelper.getUnknownContactPicture(item.getConversation().getName(), 200));
|
imageView.setImageBitmap(UIHelper
|
||||||
|
.getUnknownContactPicture(item
|
||||||
|
.getConversation().getName(), 200));
|
||||||
}
|
}
|
||||||
} else if (item.getConversation().getMode()==Conversation.MODE_MULTI) {
|
} else if (item.getConversation().getMode() == Conversation.MODE_MULTI) {
|
||||||
if (item.getCounterpart()!=null) {
|
if (item.getCounterpart() != null) {
|
||||||
imageView.setImageBitmap(UIHelper.getUnknownContactPicture(item.getCounterpart(), 200));
|
imageView.setImageBitmap(UIHelper
|
||||||
|
.getUnknownContactPicture(
|
||||||
|
item.getCounterpart(), 200));
|
||||||
} else {
|
} else {
|
||||||
imageView.setImageBitmap(UIHelper.getUnknownContactPicture(item.getConversation().getName(), 200));
|
imageView.setImageBitmap(UIHelper
|
||||||
|
.getUnknownContactPicture(item
|
||||||
|
.getConversation().getName(), 200));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (selfiUri!=null) {
|
if (selfiUri != null) {
|
||||||
imageView.setImageURI(selfiUri);
|
imageView.setImageURI(selfiUri);
|
||||||
} else {
|
} else {
|
||||||
imageView.setImageBitmap(UIHelper.getUnknownContactPicture(conversation.getAccount().getJid(),200));
|
imageView.setImageBitmap(UIHelper
|
||||||
|
.getUnknownContactPicture(conversation
|
||||||
|
.getAccount().getJid(), 200));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextView messageBody = (TextView) view.findViewById(R.id.message_body);
|
TextView messageBody = (TextView) view
|
||||||
|
.findViewById(R.id.message_body);
|
||||||
String body = item.getBody();
|
String body = item.getBody();
|
||||||
if (body!=null) {
|
if (body != null) {
|
||||||
messageBody.setText(body.trim());
|
messageBody.setText(body.trim());
|
||||||
}
|
}
|
||||||
TextView time = (TextView) view.findViewById(R.id.message_time);
|
TextView time = (TextView) view.findViewById(R.id.message_time);
|
||||||
|
@ -144,13 +228,16 @@ public class ConversationFragment extends Fragment {
|
||||||
time.setTypeface(null, Typeface.ITALIC);
|
time.setTypeface(null, Typeface.ITALIC);
|
||||||
time.setText("sending\u2026");
|
time.setText("sending\u2026");
|
||||||
} else {
|
} else {
|
||||||
time.setTypeface(null,Typeface.NORMAL);
|
time.setTypeface(null, Typeface.NORMAL);
|
||||||
if ((item.getConversation().getMode()==Conversation.MODE_SINGLE)||(type != RECIEVED)) {
|
if ((item.getConversation().getMode() == Conversation.MODE_SINGLE)
|
||||||
|
|| (type != RECIEVED)) {
|
||||||
time.setText(UIHelper.readableTimeDifference(item
|
time.setText(UIHelper.readableTimeDifference(item
|
||||||
.getTimeSent()));
|
|
||||||
} else {
|
|
||||||
time.setText(item.getCounterpart()+" \u00B7 "+UIHelper.readableTimeDifference(item
|
|
||||||
.getTimeSent()));
|
.getTimeSent()));
|
||||||
|
} else {
|
||||||
|
time.setText(item.getCounterpart()
|
||||||
|
+ " \u00B7 "
|
||||||
|
+ UIHelper.readableTimeDifference(item
|
||||||
|
.getTimeSent()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return view;
|
return view;
|
||||||
|
@ -201,32 +288,50 @@ public class ConversationFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateMessages() {
|
public void updateMessages() {
|
||||||
|
ConversationActivity activity = (ConversationActivity) getActivity();
|
||||||
this.messageList.clear();
|
this.messageList.clear();
|
||||||
this.messageList.addAll(this.conversation.getMessages());
|
this.messageList.addAll(this.conversation.getMessages());
|
||||||
this.messageListAdapter.notifyDataSetChanged();
|
this.messageListAdapter.notifyDataSetChanged();
|
||||||
if (messageList.size()>=1) {
|
if (messageList.size() >= 1) {
|
||||||
nextMessageEncryption = this.conversation.getLatestMessage().getEncryption();
|
int latestEncryption = this.conversation.getLatestMessage()
|
||||||
|
.getEncryption();
|
||||||
|
conversation.nextMessageEncryption = latestEncryption;
|
||||||
|
makeFingerprintWarning(latestEncryption);
|
||||||
}
|
}
|
||||||
getActivity().invalidateOptionsMenu();
|
getActivity().invalidateOptionsMenu();
|
||||||
switch (nextMessageEncryption) {
|
updateChatMsgHint();
|
||||||
case Message.ENCRYPTION_NONE:
|
|
||||||
chatMsg.setHint("Send plain text message");
|
|
||||||
break;
|
|
||||||
case Message.ENCRYPTION_OTR:
|
|
||||||
chatMsg.setHint("Send OTR encrypted message");
|
|
||||||
break;
|
|
||||||
case Message.ENCRYPTION_PGP:
|
|
||||||
chatMsg.setHint("Send openPGP encryted messeage");
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
int size = this.messageList.size();
|
int size = this.messageList.size();
|
||||||
if (size >= 1)
|
if (size >= 1)
|
||||||
messagesView.setSelection(size - 1);
|
messagesView.setSelection(size - 1);
|
||||||
ConversationActivity activity = (ConversationActivity) getActivity();
|
|
||||||
if (!activity.shouldPaneBeOpen()) {
|
if (!activity.shouldPaneBeOpen()) {
|
||||||
conversation.markRead();
|
conversation.markRead();
|
||||||
activity.updateConversationList();
|
activity.updateConversationList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void makeFingerprintWarning(int latestEncryption) {
|
||||||
|
final LinearLayout fingerprintWarning = (LinearLayout) getView()
|
||||||
|
.findViewById(R.id.new_fingerprint);
|
||||||
|
Set<String> knownFingerprints = conversation.getContact()
|
||||||
|
.getOtrFingerprints();
|
||||||
|
if ((latestEncryption == Message.ENCRYPTION_OTR)
|
||||||
|
&& (conversation.hasValidOtrSession()
|
||||||
|
&& (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
|
||||||
|
.contains(conversation.getOtrFingerprint())))) {
|
||||||
|
fingerprintWarning.setVisibility(View.VISIBLE);
|
||||||
|
TextView fingerprint = (TextView) getView().findViewById(
|
||||||
|
R.id.otr_fingerprint);
|
||||||
|
fingerprint.setText(conversation.getOtrFingerprint());
|
||||||
|
fingerprintWarning.setOnClickListener(new OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
AlertDialog dialog = UIHelper.getVerifyFingerprintDialog((ConversationActivity) getActivity(),conversation,fingerprintWarning);
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fingerprintWarning.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,15 +7,19 @@ import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.gultsch.chat.R;
|
import de.gultsch.chat.R;
|
||||||
|
import de.gultsch.chat.entities.Account;
|
||||||
import de.gultsch.chat.entities.Contact;
|
import de.gultsch.chat.entities.Contact;
|
||||||
import de.gultsch.chat.entities.Conversation;
|
import de.gultsch.chat.entities.Conversation;
|
||||||
import de.gultsch.chat.entities.Message;
|
import de.gultsch.chat.entities.Message;
|
||||||
import de.gultsch.chat.ui.ConversationActivity;
|
import de.gultsch.chat.ui.ConversationActivity;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.DialogInterface.OnClickListener;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
@ -29,7 +33,11 @@ import android.provider.ContactsContract.Contacts;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.support.v4.app.TaskStackBuilder;
|
import android.support.v4.app.TaskStackBuilder;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
import android.widget.QuickContactBadge;
|
import android.widget.QuickContactBadge;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
public class UIHelper {
|
public class UIHelper {
|
||||||
public static String readableTimeDifference(long time) {
|
public static String readableTimeDifference(long time) {
|
||||||
|
@ -153,4 +161,33 @@ public class UIHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static AlertDialog getVerifyFingerprintDialog(final ConversationActivity activity,final Conversation conversation, final LinearLayout msg) {
|
||||||
|
final Contact contact = conversation.getContact();
|
||||||
|
final Account account = conversation.getAccount();
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
|
builder.setTitle("Verify fingerprint");
|
||||||
|
LayoutInflater inflater = activity.getLayoutInflater();
|
||||||
|
View view = inflater.inflate(R.layout.dialog_verify_otr, null);
|
||||||
|
TextView jid = (TextView) view.findViewById(R.id.verify_otr_jid);
|
||||||
|
TextView fingerprint = (TextView) view.findViewById(R.id.verify_otr_fingerprint);
|
||||||
|
TextView yourprint = (TextView) view.findViewById(R.id.verify_otr_yourprint);
|
||||||
|
|
||||||
|
jid.setText(contact.getJid());
|
||||||
|
fingerprint.setText(conversation.getOtrFingerprint());
|
||||||
|
yourprint.setText(account.getOtrFingerprint());
|
||||||
|
builder.setNegativeButton("Cancel", null);
|
||||||
|
builder.setPositiveButton("Verify", new OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
contact.addOtrFingerprint(conversation.getOtrFingerprint());
|
||||||
|
msg.setVisibility(View.GONE);
|
||||||
|
activity.xmppConnectionService.updateContact(contact);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setView(view);
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue