aboutsummaryrefslogtreecommitdiffstats
path: root/src/eu
diff options
context:
space:
mode:
Diffstat (limited to 'src/eu')
-rw-r--r--src/eu/siacs/conversations/crypto/PgpEngine.java1
-rw-r--r--src/eu/siacs/conversations/entities/Account.java11
-rw-r--r--src/eu/siacs/conversations/entities/Contact.java139
-rw-r--r--src/eu/siacs/conversations/entities/Conversation.java38
-rw-r--r--src/eu/siacs/conversations/entities/Message.java1
-rw-r--r--src/eu/siacs/conversations/entities/Presences.java37
-rw-r--r--src/eu/siacs/conversations/entities/Roster.java63
-rw-r--r--src/eu/siacs/conversations/parser/MessageParser.java (renamed from src/eu/siacs/conversations/utils/MessageParser.java)52
-rw-r--r--src/eu/siacs/conversations/persistance/DatabaseBackend.java180
-rw-r--r--src/eu/siacs/conversations/persistance/FileBackend.java64
-rw-r--r--src/eu/siacs/conversations/services/ImageProvider.java103
-rw-r--r--src/eu/siacs/conversations/services/XmppConnectionService.java552
-rw-r--r--src/eu/siacs/conversations/ui/ContactDetailsActivity.java90
-rw-r--r--src/eu/siacs/conversations/ui/ContactsActivity.java63
-rw-r--r--src/eu/siacs/conversations/ui/ConversationActivity.java192
-rw-r--r--src/eu/siacs/conversations/ui/ConversationFragment.java161
-rw-r--r--src/eu/siacs/conversations/ui/EditAccount.java33
-rw-r--r--src/eu/siacs/conversations/ui/ManageAccountActivity.java32
-rw-r--r--src/eu/siacs/conversations/ui/ShareWithActivity.java22
-rw-r--r--src/eu/siacs/conversations/ui/XmppActivity.java4
-rw-r--r--src/eu/siacs/conversations/utils/OnPhoneContactsLoadedListener.java4
-rw-r--r--src/eu/siacs/conversations/utils/PhoneHelper.java23
-rw-r--r--src/eu/siacs/conversations/utils/UIHelper.java33
-rw-r--r--src/eu/siacs/conversations/utils/Validator.java2
-rw-r--r--src/eu/siacs/conversations/xml/XmlReader.java7
-rw-r--r--src/eu/siacs/conversations/xmpp/XmppConnection.java67
26 files changed, 910 insertions, 1064 deletions
diff --git a/src/eu/siacs/conversations/crypto/PgpEngine.java b/src/eu/siacs/conversations/crypto/PgpEngine.java
index 48750e24..0f2aeff4 100644
--- a/src/eu/siacs/conversations/crypto/PgpEngine.java
+++ b/src/eu/siacs/conversations/crypto/PgpEngine.java
@@ -221,7 +221,6 @@ public class PgpEngine {
return 0;
}
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
- Log.d("xmppService","openpgp user interaction requeried");
return 0;
case OpenPgpApi.RESULT_CODE_ERROR:
Log.d("xmppService","openpgp error: "+((OpenPgpError) result
diff --git a/src/eu/siacs/conversations/entities/Account.java b/src/eu/siacs/conversations/entities/Account.java
index 35870aaa..b9c87eac 100644
--- a/src/eu/siacs/conversations/entities/Account.java
+++ b/src/eu/siacs/conversations/entities/Account.java
@@ -65,6 +65,8 @@ public class Account extends AbstractEntity{
private String otrFingerprint;
+ private Roster roster = null;
+
public Account() {
this.uuid = "0";
}
@@ -135,7 +137,7 @@ public class Account extends AbstractEntity{
}
public boolean hasErrorStatus() {
- return getStatus() > STATUS_NO_INTERNET;
+ return getStatus() > STATUS_NO_INTERNET && (getXmppConnection().getAttempt() >= 2);
}
public void setResource(String resource) {
@@ -287,4 +289,11 @@ public class Account extends AbstractEntity{
return null;
}
}
+
+ public Roster getRoster() {
+ if (this.roster==null) {
+ this.roster = new Roster(this);
+ }
+ return this.roster;
+ }
}
diff --git a/src/eu/siacs/conversations/entities/Contact.java b/src/eu/siacs/conversations/entities/Contact.java
index 599aa8de..22e2661b 100644
--- a/src/eu/siacs/conversations/entities/Contact.java
+++ b/src/eu/siacs/conversations/entities/Contact.java
@@ -1,36 +1,30 @@
package eu.siacs.conversations.entities;
-import java.io.Serializable;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;
-
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-
import eu.siacs.conversations.xml.Element;
-
import android.content.ContentValues;
import android.database.Cursor;
-import android.util.Log;
-
-public class Contact extends AbstractEntity implements Serializable {
- private static final long serialVersionUID = -4570817093119419962L;
+public class Contact {
public static final String TABLENAME = "contacts";
- public static final String DISPLAYNAME = "name";
+ public static final String SYSTEMNAME = "systemname";
+ public static final String SERVERNAME = "servername";
public static final String JID = "jid";
- public static final String SUBSCRIPTION = "subscription";
+ public static final String OPTIONS = "options";
public static final String SYSTEMACCOUNT = "systemaccount";
public static final String PHOTOURI = "photouri";
public static final String KEYS = "pgpkey";
- public static final String PRESENCES = "presences";
public static final String ACCOUNT = "accountUuid";
protected String accountUuid;
- protected String displayName;
+ protected String systemName;
+ protected String serverName;
protected String jid;
protected int subscription = 0;
protected String systemAccount;
@@ -42,26 +36,12 @@ public class Contact extends AbstractEntity implements Serializable {
protected boolean inRoster = true;
- public Contact(Account account, String displayName, String jid,
- String photoUri) {
- if (account == null) {
- this.accountUuid = null;
- } else {
- this.accountUuid = account.getUuid();
- }
- this.account = account;
- this.displayName = displayName;
- this.jid = jid;
- this.photoUri = photoUri;
- this.uuid = java.util.UUID.randomUUID().toString();
- }
-
- public Contact(String uuid, String account, String displayName, String jid,
- int subscription, String photoUri, String systemAccount,
- String keys, String presences) {
- this.uuid = uuid;
+ public Contact(String account, String systemName,
+ String serverName, String jid, int subscription, String photoUri,
+ String systemAccount, String keys) {
this.accountUuid = account;
- this.displayName = displayName;
+ this.systemName = systemName;
+ this.serverName = serverName;
this.jid = jid;
this.subscription = subscription;
this.photoUri = photoUri;
@@ -74,11 +54,20 @@ public class Contact extends AbstractEntity implements Serializable {
} catch (JSONException e) {
this.keys = new JSONObject();
}
- this.presences = Presences.fromJsonString(presences);
+ }
+
+ public Contact(String jid) {
+ this.jid = jid;
}
public String getDisplayName() {
- return this.displayName;
+ if (this.systemName != null) {
+ return this.systemName;
+ } else if (this.serverName != null) {
+ return this.serverName;
+ } else {
+ return this.jid.split("@")[0];
+ }
}
public String getProfilePhoto() {
@@ -90,35 +79,32 @@ public class Contact extends AbstractEntity implements Serializable {
}
public boolean match(String needle) {
- return (jid.toLowerCase().contains(needle.toLowerCase()) || (displayName
+ return (jid.toLowerCase().contains(needle.toLowerCase()) || (getDisplayName()
.toLowerCase().contains(needle.toLowerCase())));
}
- @Override
public ContentValues getContentValues() {
ContentValues values = new ContentValues();
- values.put(UUID, uuid);
values.put(ACCOUNT, accountUuid);
- values.put(DISPLAYNAME, displayName);
+ values.put(SYSTEMNAME, systemName);
+ values.put(SERVERNAME, serverName);
values.put(JID, jid);
- values.put(SUBSCRIPTION, subscription);
+ values.put(OPTIONS, subscription);
values.put(SYSTEMACCOUNT, systemAccount);
values.put(PHOTOURI, photoUri);
values.put(KEYS, keys.toString());
- values.put(PRESENCES, presences.toJsonString());
return values;
}
public static Contact fromCursor(Cursor cursor) {
- return new Contact(cursor.getString(cursor.getColumnIndex(UUID)),
- cursor.getString(cursor.getColumnIndex(ACCOUNT)),
- cursor.getString(cursor.getColumnIndex(DISPLAYNAME)),
+ return new Contact(cursor.getString(cursor.getColumnIndex(ACCOUNT)),
+ cursor.getString(cursor.getColumnIndex(SYSTEMNAME)),
+ cursor.getString(cursor.getColumnIndex(SERVERNAME)),
cursor.getString(cursor.getColumnIndex(JID)),
- cursor.getInt(cursor.getColumnIndex(SUBSCRIPTION)),
+ cursor.getInt(cursor.getColumnIndex(OPTIONS)),
cursor.getString(cursor.getColumnIndex(PHOTOURI)),
cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)),
- cursor.getString(cursor.getColumnIndex(KEYS)),
- cursor.getString(cursor.getColumnIndex(PRESENCES)));
+ cursor.getString(cursor.getColumnIndex(KEYS)));
}
public int getSubscription() {
@@ -138,10 +124,6 @@ public class Contact extends AbstractEntity implements Serializable {
return this.account;
}
- public void setUuid(String uuid) {
- this.uuid = uuid;
- }
-
public boolean couldBeMuc() {
String[] split = this.getJid().split("@");
if (split.length != 2) {
@@ -154,8 +136,8 @@ public class Contact extends AbstractEntity implements Serializable {
return (domainParts[0].equals("conf")
|| domainParts[0].equals("conference")
|| domainParts[0].equals("muc")
- || domainParts[0].equals("sala")
- || domainParts[0].equals("salas"));
+ || domainParts[0].equals("sala") || domainParts[0]
+ .equals("salas"));
}
}
}
@@ -188,8 +170,12 @@ public class Contact extends AbstractEntity implements Serializable {
this.photoUri = uri;
}
- public void setDisplayName(String name) {
- this.displayName = name;
+ public void setServerName(String serverName) {
+ this.serverName = serverName;
+ }
+
+ public void setSystemName(String systemName) {
+ this.systemName = systemName;
}
public String getSystemAccount() {
@@ -249,15 +235,15 @@ public class Contact extends AbstractEntity implements Serializable {
}
}
- public void setSubscriptionOption(int option) {
+ public void setOption(int option) {
this.subscription |= 1 << option;
}
- public void resetSubscriptionOption(int option) {
+ public void resetOption(int option) {
this.subscription &= ~(1 << option);
}
- public boolean getSubscriptionOption(int option) {
+ public boolean getOption(int option) {
return ((this.subscription & (1 << option)) != 0);
}
@@ -267,40 +253,39 @@ public class Contact extends AbstractEntity implements Serializable {
if (subscription != null) {
if (subscription.equals("to")) {
- this.resetSubscriptionOption(Contact.Subscription.FROM);
- this.setSubscriptionOption(Contact.Subscription.TO);
+ this.resetOption(Contact.Options.FROM);
+ this.setOption(Contact.Options.TO);
} else if (subscription.equals("from")) {
- this.resetSubscriptionOption(Contact.Subscription.TO);
- this.setSubscriptionOption(Contact.Subscription.FROM);
+ this.resetOption(Contact.Options.TO);
+ this.setOption(Contact.Options.FROM);
} else if (subscription.equals("both")) {
- this.setSubscriptionOption(Contact.Subscription.TO);
- this.setSubscriptionOption(Contact.Subscription.FROM);
+ this.setOption(Contact.Options.TO);
+ this.setOption(Contact.Options.FROM);
}
}
if ((ask != null) && (ask.equals("subscribe"))) {
- this.setSubscriptionOption(Contact.Subscription.ASKING);
+ this.setOption(Contact.Options.ASKING);
} else {
- this.resetSubscriptionOption(Contact.Subscription.ASKING);
+ this.resetOption(Contact.Options.ASKING);
+ }
+ }
+
+ public Element asElement() {
+ Element item = new Element("item");
+ item.setAttribute("jid", this.jid);
+ if (this.serverName != null) {
+ item.setAttribute("name", this.serverName);
}
+ return item;
}
- public class Subscription {
+ public class Options {
public static final int TO = 0;
public static final int FROM = 1;
public static final int ASKING = 2;
public static final int PREEMPTIVE_GRANT = 4;
- }
-
- public void flagAsNotInRoster() {
- this.inRoster = false;
- }
-
- public boolean isInRoster() {
- return this.inRoster;
- }
-
- public String getAccountUuid() {
- return this.accountUuid;
+ public static final int IN_ROSTER = 8;
+ public static final int PENDING_SUBSCRIPTION_REQUEST = 16;
}
}
diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java
index 5674f84a..e61537da 100644
--- a/src/eu/siacs/conversations/entities/Conversation.java
+++ b/src/eu/siacs/conversations/entities/Conversation.java
@@ -49,7 +49,6 @@ public class Conversation extends AbstractEntity {
private transient List<Message> messages = null;
private transient Account account = null;
- private transient Contact contact;
private transient SessionImpl otrSession;
@@ -129,19 +128,13 @@ public class Conversation extends AbstractEntity {
public String getName(boolean useSubject) {
if ((getMode() == MODE_MULTI) && (getMucOptions().getSubject() != null) && useSubject) {
return getMucOptions().getSubject();
- } else if (this.contact != null) {
- return this.contact.getDisplayName();
} else {
- return this.name;
+ return this.getContact().getDisplayName();
}
}
public String getProfilePhotoString() {
- if (this.contact == null) {
- return null;
- } else {
- return this.contact.getProfilePhoto();
- }
+ return this.getContact().getProfilePhoto();
}
public String getAccountUuid() {
@@ -153,14 +146,7 @@ public class Conversation extends AbstractEntity {
}
public Contact getContact() {
- return this.contact;
- }
-
- public void setContact(Contact contact) {
- this.contact = contact;
- if (contact != null) {
- this.contactUuid = contact.getUuid();
- }
+ return this.account.getRoster().getContact(this.contactJid);
}
public void setAccount(Account account) {
@@ -269,11 +255,15 @@ public class Conversation extends AbstractEntity {
return false;
} else {
String foreignPresence = this.otrSession.getSessionID().getUserID();
- if (!getContact().getPresences().containsKey(foreignPresence)) {
- this.resetOtrSession();
- return false;
+ if (getContact()==null) {
+ return true;
+ } else {
+ if (!getContact().getPresences().containsKey(foreignPresence)) {
+ this.resetOtrSession();
+ return false;
+ }
+ return true;
}
- return true;
}
}
@@ -341,7 +331,11 @@ public class Conversation extends AbstractEntity {
}
public String getNextMessage() {
- return this.nextMessage;
+ if (this.nextMessage==null) {
+ return "";
+ } else {
+ return this.nextMessage;
+ }
}
public void setNextMessage(String message) {
diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java
index 33f7a8d4..950e349e 100644
--- a/src/eu/siacs/conversations/entities/Message.java
+++ b/src/eu/siacs/conversations/entities/Message.java
@@ -29,6 +29,7 @@ public class Message extends AbstractEntity {
public static final int TYPE_TEXT = 0;
public static final int TYPE_IMAGE = 1;
+ public static final int TYPE_AUDIO = 2;
public static String CONVERSATION = "conversationUuid";
public static String COUNTERPART = "counterpart";
diff --git a/src/eu/siacs/conversations/entities/Presences.java b/src/eu/siacs/conversations/entities/Presences.java
index acbaafca..fd8af573 100644
--- a/src/eu/siacs/conversations/entities/Presences.java
+++ b/src/eu/siacs/conversations/entities/Presences.java
@@ -4,10 +4,6 @@ import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map.Entry;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
import eu.siacs.conversations.xml.Element;
public class Presences {
@@ -47,39 +43,6 @@ public class Presences {
return status;
}
- public String toJsonString() {
- JSONArray json = new JSONArray();
- Iterator<Entry<String, Integer>> it = presences.entrySet().iterator();
-
- while (it.hasNext()) {
- Entry<String, Integer> entry = it.next();
- JSONObject jObj = new JSONObject();
- try {
- jObj.put("resource", entry.getKey());
- jObj.put("status", entry.getValue());
- } catch (JSONException e) {
-
- }
- json.put(jObj);
- }
- return json.toString();
- }
-
- public static Presences fromJsonString(String jsonString) {
- Presences presences = new Presences();
- try {
- JSONArray json = new JSONArray(jsonString);
- for (int i = 0; i < json.length(); ++i) {
- JSONObject jObj = json.getJSONObject(i);
- presences.updatePresence(jObj.getString("resource"),
- jObj.getInt("status"));
- }
- } catch (JSONException e1) {
-
- }
- return presences;
- }
-
public static int parseShow(Element show) {
if (show == null) {
return Presences.ONLINE;
diff --git a/src/eu/siacs/conversations/entities/Roster.java b/src/eu/siacs/conversations/entities/Roster.java
new file mode 100644
index 00000000..7c18d80a
--- /dev/null
+++ b/src/eu/siacs/conversations/entities/Roster.java
@@ -0,0 +1,63 @@
+package eu.siacs.conversations.entities;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class Roster {
+ Account account;
+ HashMap<String, Contact> contacts = new HashMap<String, Contact>();
+ private String version = null;
+
+ public Roster(Account account) {
+ this.account = account;
+ }
+
+ public boolean hasContact(String jid) {
+ String cleanJid = jid.split("/")[0];
+ return contacts.containsKey(cleanJid);
+ }
+
+ public Contact getContact(String jid) {
+ String cleanJid = jid.split("/")[0];
+ if (contacts.containsKey(cleanJid)) {
+ return contacts.get(cleanJid);
+ } else {
+ Contact contact = new Contact(cleanJid);
+ contact.setAccount(account);
+ contacts.put(cleanJid, contact);
+ return contact;
+ }
+ }
+
+ public void clearPresences() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void markAllAsNotInRoster() {
+
+ }
+
+ public List<Contact> getContacts() {
+ return new ArrayList<Contact>(this.contacts.values());
+ }
+
+ public void initContact(Contact contact) {
+ contact.setAccount(account);
+ contact.setOption(Contact.Options.IN_ROSTER);
+ contacts.put(contact.getJid(),contact);
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getVersion() {
+ return this.version;
+ }
+
+ public Account getAccount() {
+ return this.account;
+ }
+}
diff --git a/src/eu/siacs/conversations/utils/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java
index 52b18f66..3733767f 100644
--- a/src/eu/siacs/conversations/utils/MessageParser.java
+++ b/src/eu/siacs/conversations/parser/MessageParser.java
@@ -1,4 +1,4 @@
-package eu.siacs.conversations.utils;
+package eu.siacs.conversations.parser;
import java.util.List;
@@ -15,29 +15,34 @@ import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
public class MessageParser {
protected static final String LOGTAG = "xmppService";
+ private XmppConnectionService mXmppConnectionService;
- public static Message parsePlainTextChat(MessagePacket packet, Account account, XmppConnectionService service) {
+ public MessageParser(XmppConnectionService service) {
+ this.mXmppConnectionService = service;
+ }
+
+ public Message parsePlainTextChat(MessagePacket packet, Account account) {
String[] fromParts = packet.getFrom().split("/");
- Conversation conversation = service.findOrCreateConversation(account, fromParts[0],false);
+ Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, fromParts[0],false);
String body = packet.getBody();
return new Message(conversation, packet.getFrom(), body, Message.ENCRYPTION_NONE, Message.STATUS_RECIEVED);
}
- public static Message parsePgpChat(String pgpBody, MessagePacket packet, Account account, XmppConnectionService service) {
+ public Message parsePgpChat(String pgpBody, MessagePacket packet, Account account) {
String[] fromParts = packet.getFrom().split("/");
- Conversation conversation = service.findOrCreateConversation(account, fromParts[0],false);
+ Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, fromParts[0],false);
return new Message(conversation, packet.getFrom(), pgpBody, Message.ENCRYPTION_PGP, Message.STATUS_RECIEVED);
}
- public static Message parseOtrChat(MessagePacket packet, Account account, XmppConnectionService service) {
+ public Message parseOtrChat(MessagePacket packet, Account account) {
boolean properlyAddressed = (packet.getTo().split("/").length == 2) || (account.countPresences() == 1);
String[] fromParts = packet.getFrom().split("/");
- Conversation conversation = service.findOrCreateConversation(account, fromParts[0],false);
+ Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, fromParts[0],false);
String body = packet.getBody();
if (!conversation.hasValidOtrSession()) {
if (properlyAddressed) {
Log.d("xmppService","starting new otr session with "+packet.getFrom()+" because no valid otr session has been found");
- conversation.startOtrSession(service.getApplicationContext(), fromParts[1],false);
+ conversation.startOtrSession(mXmppConnectionService.getApplicationContext(), fromParts[1],false);
} else {
Log.d("xmppService",account.getJid()+": ignoring otr session with "+fromParts[0]);
return null;
@@ -48,7 +53,7 @@ public class MessageParser {
conversation.resetOtrSession();
if (properlyAddressed) {
Log.d("xmppService","replacing otr session with "+packet.getFrom());
- conversation.startOtrSession(service.getApplicationContext(), fromParts[1],false);
+ conversation.startOtrSession(mXmppConnectionService.getApplicationContext(), fromParts[1],false);
} else {
return null;
}
@@ -69,15 +74,15 @@ public class MessageParser {
Message msg = messages.get(i);
if ((msg.getStatus() == Message.STATUS_UNSEND)
&& (msg.getEncryption() == Message.ENCRYPTION_OTR)) {
- MessagePacket outPacket = service.prepareMessagePacket(
+ MessagePacket outPacket = mXmppConnectionService.prepareMessagePacket(
account, msg, otrSession);
msg.setStatus(Message.STATUS_SEND);
- service.databaseBackend.updateMessage(msg);
+ mXmppConnectionService.databaseBackend.updateMessage(msg);
account.getXmppConnection()
.sendMessagePacket(outPacket);
}
}
- service.updateUi(conversation, false);
+ mXmppConnectionService.updateUi(conversation, false);
} else if ((before != after) && (after == SessionStatus.FINISHED)) {
conversation.resetOtrSession();
Log.d(LOGTAG,"otr session stoped");
@@ -93,13 +98,13 @@ public class MessageParser {
}
}
- public static Message parseGroupchat(MessagePacket packet, Account account, XmppConnectionService service) {
+ public Message parseGroupchat(MessagePacket packet, Account account) {
int status;
String[] fromParts = packet.getFrom().split("/");
- Conversation conversation = service.findOrCreateConversation(account, fromParts[0],true);
+ Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, fromParts[0],true);
if (packet.hasChild("subject")) {
conversation.getMucOptions().setSubject(packet.findChild("subject").getContent());
- service.updateUi(conversation, false);
+ mXmppConnectionService.updateUi(conversation, false);
return null;
}
if ((fromParts.length == 1)) {
@@ -107,15 +112,18 @@ public class MessageParser {
}
String counterPart = fromParts[1];
if (counterPart.equals(conversation.getMucOptions().getNick())) {
- status = Message.STATUS_SEND;
+ if (mXmppConnectionService.markMessage(conversation, packet.getId(), Message.STATUS_SEND)) {
+ return null;
+ } else {
+ status = Message.STATUS_SEND;
+ }
} else {
status = Message.STATUS_RECIEVED;
}
return new Message(conversation, counterPart, packet.getBody(), Message.ENCRYPTION_NONE, status);
}
- public static Message parseCarbonMessage(MessagePacket packet,
- Account account, XmppConnectionService service) {
+ public Message parseCarbonMessage(MessagePacket packet,Account account) {
int status;
String fullJid;
Element forwarded;
@@ -142,16 +150,16 @@ public class MessageParser {
fullJid = message.getAttribute("to");
}
String[] parts = fullJid.split("/");
- Conversation conversation = service.findOrCreateConversation(account, parts[0],false);
+ Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, parts[0],false);
return new Message(conversation,fullJid, message.findChild("body").getContent(), Message.ENCRYPTION_NONE,status);
}
- public static void parseError(MessagePacket packet, Account account, XmppConnectionService service) {
+ public void parseError(MessagePacket packet, Account account) {
String[] fromParts = packet.getFrom().split("/");
- service.markMessage(account, fromParts[0], packet.getId(), Message.STATUS_SEND_FAILED);
+ mXmppConnectionService.markMessage(account, fromParts[0], packet.getId(), Message.STATUS_SEND_FAILED);
}
- public static String getPgpBody(MessagePacket packet) {
+ public String getPgpBody(MessagePacket packet) {
for(Element child : packet.getChildren()) {
if (child.getName().equals("x")&&child.getAttribute("xmlns").equals("jabber:x:encrypted")) {
return child.getContent();
diff --git a/src/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/eu/siacs/conversations/persistance/DatabaseBackend.java
index 5a34dac6..771027f2 100644
--- a/src/eu/siacs/conversations/persistance/DatabaseBackend.java
+++ b/src/eu/siacs/conversations/persistance/DatabaseBackend.java
@@ -2,20 +2,17 @@ package eu.siacs.conversations.persistance;
import java.util.ArrayList;
import java.util.List;
-import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.entities.Presences;
-import android.content.ContentValues;
+import eu.siacs.conversations.entities.Roster;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
-import android.os.Bundle;
import android.util.Log;
public class DatabaseBackend extends SQLiteOpenHelper {
@@ -23,10 +20,19 @@ public class DatabaseBackend extends SQLiteOpenHelper {
private static DatabaseBackend instance = null;
private static final String DATABASE_NAME = "history";
- private static final int DATABASE_VERSION = 3;
+ private static final int DATABASE_VERSION = 5;
+
+ private static String CREATE_CONTATCS_STATEMENT = "create table "
+ + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " + Contact.SERVERNAME + " TEXT, "
+ + Contact.SYSTEMNAME + " TEXT," + Contact.JID + " TEXT,"
+ + Contact.KEYS + " TEXT," + Contact.PHOTOURI + " TEXT,"
+ + Contact.OPTIONS + " NUMBER," + Contact.SYSTEMACCOUNT
+ + " NUMBER, " + "FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES "
+ + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE, UNIQUE("+Contact.ACCOUNT+", "+Contact.JID+") ON CONFLICT REPLACE);";
public DatabaseBackend(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ Log.d("xmppService",CREATE_CONTATCS_STATEMENT);
}
@Override
@@ -36,7 +42,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ " TEXT PRIMARY KEY," + Account.USERNAME + " TEXT,"
+ Account.SERVER + " TEXT," + Account.PASSWORD + " TEXT,"
+ Account.ROSTERVERSION + " TEXT," + Account.OPTIONS
- + " NUMBER, "+Account.KEYS+" TEXT)");
+ + " NUMBER, " + Account.KEYS + " TEXT)");
db.execSQL("create table " + Conversation.TABLENAME + " ("
+ Conversation.UUID + " TEXT PRIMARY KEY, " + Conversation.NAME
+ " TEXT, " + Conversation.CONTACT + " TEXT, "
@@ -50,31 +56,28 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ " TEXT PRIMARY KEY, " + Message.CONVERSATION + " TEXT, "
+ Message.TIME_SENT + " NUMBER, " + Message.COUNTERPART
+ " TEXT, " + Message.BODY + " TEXT, " + Message.ENCRYPTION
- + " NUMBER, " + Message.STATUS + " NUMBER," +Message.TYPE +" NUMBER, FOREIGN KEY("
- + Message.CONVERSATION + ") REFERENCES "
- + Conversation.TABLENAME + "(" + Conversation.UUID
- + ") ON DELETE CASCADE);");
- db.execSQL("create table " + Contact.TABLENAME + "(" + Contact.UUID
- + " TEXT PRIMARY KEY, " + Contact.ACCOUNT + " TEXT, "
- + Contact.DISPLAYNAME + " TEXT," + Contact.JID + " TEXT,"
- + Contact.PRESENCES + " TEXT, " + Contact.KEYS
- + " TEXT," + Contact.PHOTOURI + " TEXT," + Contact.SUBSCRIPTION
- + " NUMBER," + Contact.SYSTEMACCOUNT + " NUMBER, "
- + "FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES "
- + Account.TABLENAME + "(" + Account.UUID
- + ") ON DELETE CASCADE);");
+ + " NUMBER, " + Message.STATUS + " NUMBER," + Message.TYPE
+ + " NUMBER, FOREIGN KEY(" + Message.CONVERSATION
+ + ") REFERENCES " + Conversation.TABLENAME + "("
+ + Conversation.UUID + ") ON DELETE CASCADE);");
+
+ db.execSQL(CREATE_CONTATCS_STATEMENT);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2 && newVersion >= 2) {
- // enable compression by default.
- db.execSQL("update " + Account.TABLENAME
- + " set " + Account.OPTIONS + " = " + Account.OPTIONS + " | 8");
+ db.execSQL("update " + Account.TABLENAME + " set "
+ + Account.OPTIONS + " = " + Account.OPTIONS + " | 8");
}
if (oldVersion < 3 && newVersion >= 3) {
- //add field type to message
- db.execSQL("ALTER TABLE "+Message.TABLENAME+" ADD COLUMN "+Message.TYPE+" NUMBER");;
+ db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN "
+ + Message.TYPE + " NUMBER");
+ }
+ if (oldVersion < 5 && newVersion >= 5) {
+ db.execSQL("DROP TABLE "+Contact.TABLENAME);
+ db.execSQL(CREATE_CONTATCS_STATEMENT);
+ db.execSQL("UPDATE "+Account.TABLENAME+ " SET "+Account.ROSTERVERSION+" = NULL");
}
}
@@ -99,7 +102,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
SQLiteDatabase db = this.getWritableDatabase();
db.insert(Account.TABLENAME, null, account.getContentValues());
}
-
+
public void createContact(Contact contact) {
SQLiteDatabase db = this.getWritableDatabase();
db.insert(Contact.TABLENAME, null, contact.getContentValues());
@@ -145,10 +148,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
public Conversation findConversation(Account account, String contactJid) {
SQLiteDatabase db = this.getReadableDatabase();
- String[] selectionArgs = { account.getUuid(), contactJid+"%" };
+ String[] selectionArgs = { account.getUuid(), contactJid + "%" };
Cursor cursor = db.query(Conversation.TABLENAME, null,
- Conversation.ACCOUNT + "=? AND " + Conversation.CONTACTJID + " like ?",
- selectionArgs, null, null, null);
+ Conversation.ACCOUNT + "=? AND " + Conversation.CONTACTJID
+ + " like ?", selectionArgs, null, null, null);
if (cursor.getCount() == 0)
return null;
cursor.moveToFirst();
@@ -200,87 +203,32 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.update(Message.TABLENAME, message.getContentValues(), Message.UUID
+ "=?", args);
}
-
- public void updateContact(Contact contact, boolean updatePresences) {
- SQLiteDatabase db = this.getWritableDatabase();
- String[] args = { contact.getUuid() };
- ContentValues values = contact.getContentValues();
- if (!updatePresences) {
- values.remove(Contact.PRESENCES);
- } else {
- values.remove(Contact.DISPLAYNAME);
- values.remove(Contact.PHOTOURI);
- values.remove(Contact.SYSTEMACCOUNT);
- }
- db.update(Contact.TABLENAME, contact.getContentValues(), Contact.UUID
- + "=?", args);
- }
-
- public void clearPresences(Account account) {
- SQLiteDatabase db = this.getWritableDatabase();
- String[] args = { account.getUuid() };
- ContentValues values = new ContentValues();
- values.put(Contact.PRESENCES,"[]");
- db.update(Contact.TABLENAME, values, Contact.ACCOUNT
- + "=?", args);
- }
-
- public void mergeContacts(List<Contact> contacts) {
- SQLiteDatabase db = this.getWritableDatabase();
- for (int i = 0; i < contacts.size(); i++) {
- Contact contact = contacts.get(i);
- String[] columns = {Contact.UUID, Contact.PRESENCES};
- String[] args = {contact.getAccount().getUuid(), contact.getJid()};
- Cursor cursor = db.query(Contact.TABLENAME, columns,Contact.ACCOUNT+"=? AND "+Contact.JID+"=?", args, null, null, null);
- if (cursor.getCount()>=1) {
- cursor.moveToFirst();
- contact.setUuid(cursor.getString(0));
- updateContact(contact,false);
- } else {
- contact.setUuid(UUID.randomUUID().toString());
- createContact(contact);
- }
- }
- }
- public List<Contact> getContactsByAccount(Account account) {
- List<Contact> list = new ArrayList<Contact>();
+ public void readRoster(Roster roster) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor;
- if (account==null) {
- cursor = db.query(Contact.TABLENAME, null, null, null, null,
- null, null);
- } else {
- String args[] = {account.getUuid()};
- cursor = db.query(Contact.TABLENAME, null, Contact.ACCOUNT+"=?", args, null,
- null, null);
- }
+ String args[] = { roster.getAccount().getUuid() };
+ cursor = db.query(Contact.TABLENAME, null, Contact.ACCOUNT + "=?",
+ args, null, null, null);
while (cursor.moveToNext()) {
- list.add(Contact.fromCursor(cursor));
+ roster.initContact(Contact.fromCursor(cursor));
}
- return list;
}
- public List<Contact> getContacts(String where) {
- List<Contact> list = new ArrayList<Contact>();
- SQLiteDatabase db = this.getReadableDatabase();
- Cursor cursor = db.query(Contact.TABLENAME, null, where, null, null, null, null);
- while (cursor.moveToNext()) {
- list.add(Contact.fromCursor(cursor));
+ public void writeRoster(Roster roster) {
+ Account account = roster.getAccount();
+ SQLiteDatabase db = this.getWritableDatabase();
+ for(Contact contact : roster.getContacts()) {
+ if (contact.getOption(Contact.Options.IN_ROSTER)) {
+ db.insert(Contact.TABLENAME, null, contact.getContentValues());
+ } else {
+ String where = Contact.ACCOUNT + "=? AND "+Contact.JID+"=?";
+ String[] whereArgs = {account.getUuid(), contact.getJid()};
+ db.delete(Contact.TABLENAME, where, whereArgs);
+ }
}
- return list;
- }
-
- public Contact findContact(Account account, String jid) {
- SQLiteDatabase db = this.getReadableDatabase();
- String[] selectionArgs = { account.getUuid(), jid };
- Cursor cursor = db.query(Contact.TABLENAME, null,
- Contact.ACCOUNT + "=? AND " + Contact.JID + "=?",
- selectionArgs, null, null, null);
- if (cursor.getCount() == 0)
- return null;
- cursor.moveToFirst();
- return Contact.fromCursor(cursor);
+ account.setRosterVersion(roster.getVersion());
+ updateAccount(account);
}
public void deleteMessage(Message message) {
@@ -288,34 +236,18 @@ public class DatabaseBackend extends SQLiteOpenHelper {
String[] args = { message.getUuid() };
db.delete(Message.TABLENAME, Message.UUID + "=?", args);
}
-
+
public void deleteMessagesInConversation(Conversation conversation) {
SQLiteDatabase db = this.getWritableDatabase();
String[] args = { conversation.getUuid() };
db.delete(Message.TABLENAME, Message.CONVERSATION + "=?", args);
}
- public void deleteContact(Contact contact) {
- SQLiteDatabase db = this.getWritableDatabase();
- String[] args = { contact.getUuid() };
- db.delete(Contact.TABLENAME, Contact.UUID + "=?", args);
- }
-
- public Contact getContact(String uuid) {
- SQLiteDatabase db = this.getWritableDatabase();
- String[] args = { uuid };
- Cursor cursor = db.query(Contact.TABLENAME, null, Contact.UUID + "=?", args, null, null, null);
- if (cursor.getCount() == 0) {
- return null;
- }
- cursor.moveToFirst();
- return Contact.fromCursor(cursor);
- }
-
public Conversation findConversationByUuid(String conversationUuid) {
SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = { conversationUuid };
- Cursor cursor = db.query(Conversation.TABLENAME, null, Conversation.UUID + "=?", selectionArgs, null, null, null);
+ Cursor cursor = db.query(Conversation.TABLENAME, null,
+ Conversation.UUID + "=?", selectionArgs, null, null, null);
if (cursor.getCount() == 0) {
return null;
}
@@ -326,18 +258,20 @@ public class DatabaseBackend extends SQLiteOpenHelper {
public Message findMessageByUuid(String messageUuid) {
SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = { messageUuid };
- Cursor cursor = db.query(Message.TABLENAME, null, Message.UUID + "=?", selectionArgs, null, null, null);
+ Cursor cursor = db.query(Message.TABLENAME, null, Message.UUID + "=?",
+ selectionArgs, null, null, null);
if (cursor.getCount() == 0) {
return null;
}
cursor.moveToFirst();
return Message.fromCursor(cursor);
}
-
+
public Account findAccountByUuid(String accountUuid) {
SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = { accountUuid };
- Cursor cursor = db.query(Account.TABLENAME, null, Account.UUID + "=?", selectionArgs, null, null, null);
+ Cursor cursor = db.query(Account.TABLENAME, null, Account.UUID + "=?",
+ selectionArgs, null, null, null);
if (cursor.getCount() == 0) {
return null;
}
diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java
index becb1ee3..3a580048 100644
--- a/src/eu/siacs/conversations/persistance/FileBackend.java
+++ b/src/eu/siacs/conversations/persistance/FileBackend.java
@@ -1,12 +1,12 @@
package eu.siacs.conversations.persistance;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.lang.ref.WeakReference;
import android.content.Context;
import android.graphics.Bitmap;
@@ -14,14 +14,9 @@ import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Log;
import android.util.LruCache;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xmpp.jingle.JingleFile;
public class FileBackend {
@@ -43,11 +38,11 @@ public class FileBackend {
};
}
-
+
public LruCache<String, Bitmap> getThumbnailCache() {
return thumbnailCache;
}
-
+
public JingleFile getJingleFile(Message message) {
return getJingleFile(message, true);
}
@@ -58,7 +53,7 @@ public class FileBackend {
String path = prefix + "/" + conversation.getAccount().getJid() + "/"
+ conversation.getContactJid();
String filename;
- if ((decrypted)||(message.getEncryption() == Message.ENCRYPTION_NONE)) {
+ if ((decrypted) || (message.getEncryption() == Message.ENCRYPTION_NONE)) {
filename = message.getUuid() + ".webp";
} else {
filename = message.getUuid() + ".webp.pgp";
@@ -87,36 +82,48 @@ public class FileBackend {
}
}
- public JingleFile copyImageToPrivateStorage(Message message, Uri image) {
+ public JingleFile copyImageToPrivateStorage(Message message, Uri image)
+ throws ImageCopyException {
try {
- Log.d("xmppService","copying file: "+image.toString()+ " to internal storage");
- InputStream is = context.getContentResolver()
- .openInputStream(image);
+ InputStream is;
+ if (image != null) {
+ is = context.getContentResolver().openInputStream(image);
+ } else {
+ is = new FileInputStream(getIncomingFile());
+ }
JingleFile file = getJingleFile(message);
file.getParentFile().mkdirs();
file.createNewFile();
OutputStream os = new FileOutputStream(file);
Bitmap originalBitmap = BitmapFactory.decodeStream(is);
+ if (originalBitmap == null) {
+ os.close();
+ throw new ImageCopyException(R.string.error_not_an_image_file);
+ }
is.close();
+ if (image == null) {
+ getIncomingFile().delete();
+ }
Bitmap scalledBitmap = resize(originalBitmap, IMAGE_SIZE);
boolean success = scalledBitmap.compress(
Bitmap.CompressFormat.WEBP, 75, os);
if (!success) {
- return null;
+ throw new ImageCopyException(R.string.error_compressing_image);
}
os.flush();
os.close();
long size = file.getSize();
int width = scalledBitmap.getWidth();
int height = scalledBitmap.getHeight();
- message.setBody(""+size+","+width+","+height);
+ message.setBody("" + size + "," + width + "," + height);
return file;
} catch (FileNotFoundException e) {
- return null;
+ throw new ImageCopyException(R.string.error_file_not_found);
} catch (IOException e) {
- return null;
+ throw new ImageCopyException(R.string.error_io_exception);
} catch (SecurityException e) {
- return null;
+ throw new ImageCopyException(
+ R.string.error_security_exception_during_image_copy);
}
}
@@ -128,7 +135,7 @@ public class FileBackend {
public Bitmap getThumbnail(Message message, int size, boolean cacheOnly)
throws FileNotFoundException {
Bitmap thumbnail = thumbnailCache.get(message.getUuid());
- if ((thumbnail == null)&&(!cacheOnly)) {
+ if ((thumbnail == null) && (!cacheOnly)) {
Bitmap fullsize = BitmapFactory.decodeFile(getJingleFile(message)
.getAbsolutePath());
if (fullsize == null) {
@@ -160,4 +167,21 @@ public class FileBackend {
}
f.delete();
}
+
+ public File getIncomingFile() {
+ return new File(context.getFilesDir().getAbsolutePath() + "/incoming");
+ }
+
+ public class ImageCopyException extends Exception {
+ private static final long serialVersionUID = -1010013599132881427L;
+ private int resId;
+
+ public ImageCopyException(int resId) {
+ this.resId = resId;
+ }
+
+ public int getResId() {
+ return resId;
+ }
+ }
}
diff --git a/src/eu/siacs/conversations/services/ImageProvider.java b/src/eu/siacs/conversations/services/ImageProvider.java
index c1bae661..798a4e25 100644
--- a/src/eu/siacs/conversations/services/ImageProvider.java
+++ b/src/eu/siacs/conversations/services/ImageProvider.java
@@ -2,13 +2,13 @@ package eu.siacs.conversations.services;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.IOException;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.persistance.FileBackend;
-
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
@@ -21,46 +21,60 @@ public class ImageProvider extends ContentProvider {
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
- DatabaseBackend databaseBackend = DatabaseBackend
- .getInstance(getContext());
+ ParcelFileDescriptor pfd;
FileBackend fileBackend = new FileBackend(getContext());
- String uuids = uri.getPath();
- Log.d("xmppService", "uuids = " + uuids);
- if (uuids == null) {
- throw new FileNotFoundException();
- }
- String[] uuidsSplited = uuids.split("/");
- if (uuidsSplited.length != 3) {
+ if ("r".equals(mode)) {
+ DatabaseBackend databaseBackend = DatabaseBackend
+ .getInstance(getContext());
+ String uuids = uri.getPath();
+ Log.d("xmppService", "uuids = " + uuids+" mode="+mode);
+ if (uuids == null) {
+ throw new FileNotFoundException();
+ }
+ String[] uuidsSplited = uuids.split("/");
+ if (uuidsSplited.length != 3) {
+ throw new FileNotFoundException();
+ }
+ String conversationUuid = uuidsSplited[1];
+ String messageUuid = uuidsSplited[2];
+
+ Conversation conversation = databaseBackend
+ .findConversationByUuid(conversationUuid);
+ if (conversation == null) {
+ throw new FileNotFoundException("conversation " + conversationUuid
+ + " could not be found");
+ }
+ Message message = databaseBackend.findMessageByUuid(messageUuid);
+ if (message == null) {
+ throw new FileNotFoundException("message " + messageUuid
+ + " could not be found");
+ }
+
+ Account account = databaseBackend.findAccountByUuid(conversation
+ .getAccountUuid());
+ if (account == null) {
+ throw new FileNotFoundException("account "
+ + conversation.getAccountUuid() + " cound not be found");
+ }
+ message.setConversation(conversation);
+ conversation.setAccount(account);
+
+ File file = fileBackend.getJingleFile(message);
+ pfd = ParcelFileDescriptor.open(file,
+ ParcelFileDescriptor.MODE_READ_ONLY);
+ return pfd;
+ } else if ("w".equals(mode)){
+ File file = fileBackend.getIncomingFile();
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ throw new FileNotFoundException();
+ }
+ pfd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);
+ return pfd;
+ } else {
throw new FileNotFoundException();
}
- String conversationUuid = uuidsSplited[1];
- String messageUuid = uuidsSplited[2];
-
- Conversation conversation = databaseBackend
- .findConversationByUuid(conversationUuid);
- if (conversation == null) {
- throw new FileNotFoundException("conversation " + conversationUuid
- + " could not be found");
- }
- Message message = databaseBackend.findMessageByUuid(messageUuid);
- if (message == null) {
- throw new FileNotFoundException("message " + messageUuid
- + " could not be found");
- }
-
- Account account = databaseBackend.findAccountByUuid(conversation
- .getAccountUuid());
- if (account == null) {
- throw new FileNotFoundException("account "
- + conversation.getAccountUuid() + " cound not be found");
- }
- message.setConversation(conversation);
- conversation.setAccount(account);
-
- File file = fileBackend.getJingleFile(message);
- ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file,
- ParcelFileDescriptor.MODE_READ_ONLY);
- return pfd;
}
@Override
@@ -93,5 +107,16 @@ public class ImageProvider extends ContentProvider {
public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
return 0;
}
+
+ public static Uri getContentUri(Message message) {
+ return Uri
+ .parse("content://eu.siacs.conversations.images/"
+ + message.getConversationUuid()
+ + "/"
+ + message.getUuid());
+ }
-}
+ public static Uri getIncomingContentUri() {
+ return Uri.parse("content://eu.siacs.conversations.images/incoming");
+ }
+} \ No newline at end of file
diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java
index d2742997..9ea7f2b1 100644
--- a/src/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/eu/siacs/conversations/services/XmppConnectionService.java
@@ -10,14 +10,12 @@ import java.util.List;
import java.util.Locale;
import java.util.Random;
-import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpServiceConnection;
import net.java.otr4j.OtrException;
import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionStatus;
-import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
@@ -26,15 +24,13 @@ import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
import eu.siacs.conversations.entities.Presences;
+import eu.siacs.conversations.parser.MessageParser;
import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.persistance.FileBackend;
-import eu.siacs.conversations.persistance.OnPhoneContactsMerged;
import eu.siacs.conversations.ui.OnAccountListChangedListener;
import eu.siacs.conversations.ui.OnConversationListChangedListener;
-import eu.siacs.conversations.ui.OnRosterFetchedListener;
import eu.siacs.conversations.ui.UiCallback;
import eu.siacs.conversations.utils.ExceptionHelper;
-import eu.siacs.conversations.utils.MessageParser;
import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
import eu.siacs.conversations.utils.PhoneHelper;
import eu.siacs.conversations.utils.UIHelper;
@@ -47,7 +43,6 @@ import eu.siacs.conversations.xmpp.OnStatusChanged;
import eu.siacs.conversations.xmpp.OnTLSExceptionReceived;
import eu.siacs.conversations.xmpp.XmppConnection;
import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
-import eu.siacs.conversations.xmpp.jingle.JingleFile;
import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived;
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
@@ -60,13 +55,13 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.ContentObserver;
-import android.database.DatabaseUtils;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.Looper;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
@@ -87,6 +82,10 @@ public class XmppConnectionService extends Service {
private static final int PING_TIMEOUT = 5;
private static final int CONNECT_TIMEOUT = 60;
private static final long CARBON_GRACE_PERIOD = 60000L;
+
+ private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
+
+ private MessageParser mMessageParser = new MessageParser(this);
private List<Account> accounts;
private List<Conversation> conversations = null;
@@ -111,13 +110,12 @@ public class XmppConnectionService extends Service {
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
- Log.d(LOGTAG, "contact list has changed");
- mergePhoneContactsWithRoster(null);
+ Intent intent = new Intent(getApplicationContext(), XmppConnectionService.class);
+ intent.setAction(ACTION_MERGE_PHONE_CONTACTS);
+ startService(intent);
}
};
- private XmppConnectionService service = this;
-
private final IBinder mBinder = new XmppConnectionBinder();
private OnMessagePacketReceived messageListener = new OnMessagePacketReceived() {
@@ -132,26 +130,25 @@ public class XmppConnectionService extends Service {
}
if ((packet.getType() == MessagePacket.TYPE_CHAT)) {
- String pgpBody = MessageParser.getPgpBody(packet);
+ String pgpBody = mMessageParser.getPgpBody(packet);
if (pgpBody != null) {
- message = MessageParser.parsePgpChat(pgpBody, packet,
- account, service);
+ message = mMessageParser.parsePgpChat(pgpBody, packet,
+ account);
message.markUnread();
} else if ((packet.getBody() != null)
&& (packet.getBody().startsWith("?OTR"))) {
- message = MessageParser.parseOtrChat(packet, account,
- service);
+ message = mMessageParser.parseOtrChat(packet, account);
if (message != null) {
message.markUnread();
}
} else if (packet.hasChild("body")) {
- message = MessageParser.parsePlainTextChat(packet, account,
- service);
+ message = mMessageParser
+ .parsePlainTextChat(packet, account);
message.markUnread();
} else if (packet.hasChild("received")
|| (packet.hasChild("sent"))) {
- message = MessageParser.parseCarbonMessage(packet, account,
- service);
+ message = mMessageParser
+ .parseCarbonMessage(packet, account);
if (message != null) {
if (message.getStatus() == Message.STATUS_SEND) {
lastCarbonMessageReceived = SystemClock
@@ -165,8 +162,7 @@ public class XmppConnectionService extends Service {
}
} else if (packet.getType() == MessagePacket.TYPE_GROUPCHAT) {
- message = MessageParser
- .parseGroupchat(packet, account, service);
+ message = mMessageParser.parseGroupchat(packet, account);
if (message != null) {
if (message.getStatus() == Message.STATUS_RECIEVED) {
message.markUnread();
@@ -176,7 +172,7 @@ public class XmppConnectionService extends Service {
}
}
} else if (packet.getType() == MessagePacket.TYPE_ERROR) {
- MessageParser.parseError(packet, account, service);
+ mMessageParser.parseError(packet, account);
return;
} else if (packet.getType() == MessagePacket.TYPE_NORMAL) {
if (packet.hasChild("x")) {
@@ -247,10 +243,17 @@ public class XmppConnectionService extends Service {
} else if (account.getStatus() == Account.STATUS_REGISTRATION_SUCCESSFULL) {
databaseBackend.updateAccount(account);
reconnectAccount(account, true);
- } else {
- UIHelper.showErrorNotification(getApplicationContext(),
- getAccounts());
+ } else if (account.getStatus() != Account.STATUS_CONNECTING) {
+ int next = account.getXmppConnection().getTimeToNextAttempt();
+ Log.d(LOGTAG, account.getJid()
+ + ": error connecting account. try again in " + next
+ + "s for the "
+ + (account.getXmppConnection().getAttempt() + 1)
+ + " time");
+ scheduleWakeupCall(next, false);
}
+ UIHelper.showErrorNotification(getApplicationContext(),
+ getAccounts());
}
};
@@ -298,17 +301,8 @@ public class XmppConnectionService extends Service {
}
} else {
- Contact contact = findContact(account, fromParts[0]);
- if (contact == null) {
- if ("subscribe".equals(type)) {
- account.getXmppConnection().addPendingSubscription(
- fromParts[0]);
- } else {
- // Log.d(LOGTAG,packet.getFrom()+
- // " could not be found");
- }
- return;
- }
+ Contact contact = account.getRoster().getContact(
+ packet.getFrom());
if (type == null) {
if (fromParts.length == 2) {
contact.updatePresence(fromParts[1], Presences
@@ -325,13 +319,10 @@ public class XmppConnectionService extends Service {
} else {
msg = "";
}
- contact.setPgpKeyId(pgp.fetchKeyId(account,msg,x.getContent()));
- Log.d("xmppService",account.getJid()+": fetched key id for "+contact.getJid()+" was:"+contact.getPgpKeyId());
+ contact.setPgpKeyId(pgp.fetchKeyId(account,
+ msg, x.getContent()));
}
}
- replaceContactInConversation(account,
- contact.getJid(), contact);
- databaseBackend.updateContact(contact, true);
} else {
// Log.d(LOGTAG,"presence without resource "+packet.toString());
}
@@ -341,30 +332,20 @@ public class XmppConnectionService extends Service {
} else {
contact.removePresence(fromParts[1]);
}
- replaceContactInConversation(account, contact.getJid(),
- contact);
- databaseBackend.updateContact(contact, true);
} else if (type.equals("subscribe")) {
Log.d(LOGTAG, "received subscribe packet from "
+ packet.getFrom());
- if (contact
- .getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) {
+ if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) {
Log.d(LOGTAG, "preemptive grant; granting");
sendPresenceUpdatesTo(contact);
- contact.setSubscriptionOption(Contact.Subscription.FROM);
- contact.resetSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
- replaceContactInConversation(account,
- contact.getJid(), contact);
- databaseBackend.updateContact(contact, false);
- if ((contact
- .getSubscriptionOption(Contact.Subscription.ASKING))
- && (!contact
- .getSubscriptionOption(Contact.Subscription.TO))) {
+ contact.setOption(Contact.Options.FROM);
+ contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
+ if ((contact.getOption(Contact.Options.ASKING))
+ && (!contact.getOption(Contact.Options.TO))) {
requestPresenceUpdatesFrom(contact);
}
} else {
- account.getXmppConnection().addPendingSubscription(
- fromParts[0]);
+ contact.setOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST);
}
} else {
// Log.d(LOGTAG, packet.toString());
@@ -378,14 +359,13 @@ public class XmppConnectionService extends Service {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
- if (packet.hasChild("query","jabber:iq:roster")) {
+ if (packet.hasChild("query", "jabber:iq:roster")) {
String from = packet.getFrom();
- if ((from==null)||(from.equals(account.getJid()))) {
+ if ((from == null) || (from.equals(account.getJid()))) {
Element query = packet.findChild("query");
processRosterItems(account, query);
- mergePhoneContactsWithRoster(null);
} else {
- Log.d(LOGTAG,"unauthorized roster push from: "+from);
+ Log.d(LOGTAG, "unauthorized roster push from: " + from);
}
} else if (packet
.hasChild("open", "http://jabber.org/protocol/ibb")
@@ -393,20 +373,30 @@ public class XmppConnectionService extends Service {
.hasChild("data", "http://jabber.org/protocol/ibb")) {
XmppConnectionService.this.mJingleConnectionManager
.deliverIbbPacket(account, packet);
- } else if (packet.hasChild("query","http://jabber.org/protocol/disco#info")) {
- IqPacket iqResponse = packet.generateRespone(IqPacket.TYPE_RESULT);
- Element query = iqResponse.addChild("query", "http://jabber.org/protocol/disco#info");
- query.addChild("feature").setAttribute("var", "urn:xmpp:jingle:1");
- query.addChild("feature").setAttribute("var", "urn:xmpp:jingle:apps:file-transfer:3");
- query.addChild("feature").setAttribute("var", "urn:xmpp:jingle:transports:s5b:1");
- query.addChild("feature").setAttribute("var", "urn:xmpp:jingle:transports:ibb:1");
+ } else if (packet.hasChild("query",
+ "http://jabber.org/protocol/disco#info")) {
+ IqPacket iqResponse = packet
+ .generateRespone(IqPacket.TYPE_RESULT);
+ Element query = iqResponse.addChild("query",
+ "http://jabber.org/protocol/disco#info");
+ query.addChild("feature").setAttribute("var",
+ "urn:xmpp:jingle:1");
+ query.addChild("feature").setAttribute("var",
+ "urn:xmpp:jingle:apps:file-transfer:3");
+ query.addChild("feature").setAttribute("var",
+ "urn:xmpp:jingle:transports:s5b:1");
+ query.addChild("feature").setAttribute("var",
+ "urn:xmpp:jingle:transports:ibb:1");
account.getXmppConnection().sendIqPacket(iqResponse, null);
} else {
- if ((packet.getType() == IqPacket.TYPE_GET)||(packet.getType() == IqPacket.TYPE_SET)) {
- IqPacket response = packet.generateRespone(IqPacket.TYPE_ERROR);
+ if ((packet.getType() == IqPacket.TYPE_GET)
+ || (packet.getType() == IqPacket.TYPE_SET)) {
+ IqPacket response = packet
+ .generateRespone(IqPacket.TYPE_ERROR);
Element error = response.addChild("error");
- error.setAttribute("type","cancel");
- error.addChild("feature-not-implemented","urn:ietf:params:xml:ns:xmpp-stanzas");
+ error.setAttribute("type", "cancel");
+ error.addChild("feature-not-implemented",
+ "urn:ietf:params:xml:ns:xmpp-stanzas");
account.getXmppConnection().sendIqPacket(response, null);
}
}
@@ -433,7 +423,7 @@ public class XmppConnectionService extends Service {
if (this.mPgpEngine == null) {
this.mPgpEngine = new PgpEngine(new OpenPgpApi(
getApplicationContext(),
- pgpServiceConnection.getService()),this);
+ pgpServiceConnection.getService()), this);
}
return mPgpEngine;
} else {
@@ -446,10 +436,12 @@ public class XmppConnectionService extends Service {
return this.fileBackend;
}
- public Message attachImageToConversation(final Conversation conversation, final Uri uri, final UiCallback callback) {
+ public Message attachImageToConversation(final Conversation conversation,
+ final Uri uri, final UiCallback callback) {
final Message message;
if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
- message = new Message(conversation, "",Message.ENCRYPTION_DECRYPTED);
+ message = new Message(conversation, "",
+ Message.ENCRYPTION_DECRYPTED);
} else {
message = new Message(conversation, "", Message.ENCRYPTION_NONE);
}
@@ -460,21 +452,21 @@ public class XmppConnectionService extends Service {
@Override
public void run() {
- JingleFile file = getFileBackend().copyImageToPrivateStorage(message, uri);
- if (file==null) {
- callback.error(R.string.error_copying_image_file);
- } else {
+ try {
+ getFileBackend().copyImageToPrivateStorage(message, uri);
if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
getPgpEngine().encrypt(message, callback);
} else {
callback.success();
}
+ } catch (FileBackend.ImageCopyException e) {
+ callback.error(e.getResId());
}
}
}).start();
return message;
}
-
+
protected Conversation findMuc(String name, Account account) {
for (Conversation conversation : this.conversations) {
if (conversation.getContactJid().split("/")[0].equals(name)
@@ -488,51 +480,25 @@ public class XmppConnectionService extends Service {
private void processRosterItems(Account account, Element elements) {
String version = elements.getAttribute("ver");
if (version != null) {
- account.setRosterVersion(version);
- databaseBackend.updateAccount(account);
+ account.getRoster().setVersion(version);
}
for (Element item : elements.getChildren()) {
if (item.getName().equals("item")) {
String jid = item.getAttribute("jid");
+ String name = item.getAttribute("name");
String subscription = item.getAttribute("subscription");
- Contact contact = databaseBackend.findContact(account, jid);
- if (contact == null) {
- if (!subscription.equals("remove")) {
- String name = item.getAttribute("name");
- if (name == null) {
- name = jid.split("@")[0];
- }
- contact = new Contact(account, name, jid, null);
- contact.parseSubscriptionFromElement(item);
- databaseBackend.createContact(contact);
- }
+ Contact contact = account.getRoster().getContact(jid);
+ contact.setServerName(name);
+ if (subscription.equals("remove")) {
+ contact.resetOption(Contact.Options.IN_ROSTER);
} else {
- if (subscription.equals("remove")) {
- databaseBackend.deleteContact(contact);
- replaceContactInConversation(account, contact.getJid(),
- null);
- } else {
- contact.parseSubscriptionFromElement(item);
- databaseBackend.updateContact(contact, false);
- replaceContactInConversation(account, contact.getJid(),
- contact);
- }
+ contact.setOption(Contact.Options.IN_ROSTER);
+ contact.parseSubscriptionFromElement(item);
}
}
}
}
- private void replaceContactInConversation(Account account, String jid,
- Contact contact) {
- List<Conversation> conversations = getConversations();
- for (Conversation c : conversations) {
- if (c.getContactJid().equals(jid) && (c.getAccount() == account)) {
- c.setContact(contact);
- break;
- }
- }
- }
-
public class XmppConnectionBinder extends Binder {
public XmppConnectionService getService() {
return XmppConnectionService.this;
@@ -542,7 +508,9 @@ public class XmppConnectionService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.wakeLock.acquire();
- // Log.d(LOGTAG,"calling start service. caller was:"+intent.getAction());
+ if ((intent.getAction()!=null)&&(intent.getAction().equals(ACTION_MERGE_PHONE_CONTACTS))) {
+ mergePhoneContactsWithRoster();
+ }
ConnectivityManager cm = (ConnectivityManager) getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
@@ -563,8 +531,6 @@ public class XmppConnectionService extends Service {
statusListener.onStatusChanged(account);
}
}
-
- // TODO 3 remaining cases
if (account.getStatus() == Account.STATUS_ONLINE) {
long lastReceived = account.getXmppConnection().lastPaketReceived;
long lastSent = account.getXmppConnection().lastPingSent;
@@ -592,15 +558,9 @@ public class XmppConnectionService extends Service {
+ ": time out during connect reconnecting");
reconnectAccount(account, true);
} else {
- Log.d(LOGTAG,
- "seconds since last connect:"
- + ((SystemClock.elapsedRealtime() - account
- .getXmppConnection().lastConnect) / 1000));
- Log.d(LOGTAG,
- account.getJid() + ": status="
- + account.getStatus());
- // TODO notify user of ssl cert problem or auth problem
- // or what ever
+ if (account.getXmppConnection().getTimeToNextAttempt() <= 0) {
+ reconnectAccount(account, true);
+ }
}
// in any case. reschedule wakup call
this.scheduleWakeupCall(PING_MAX_INTERVAL, true);
@@ -624,6 +584,10 @@ public class XmppConnectionService extends Service {
this.fileBackend = new FileBackend(getApplicationContext());
this.accounts = databaseBackend.getAccounts();
+ for (Account account : this.accounts) {
+ this.databaseBackend.readRoster(account.getRoster());
+ }
+ this.mergePhoneContactsWithRoster();
this.getConversations();
getContentResolver().registerContentObserver(
@@ -639,13 +603,24 @@ public class XmppConnectionService extends Service {
@Override
public void onDestroy() {
- Log.d(LOGTAG,"stopping service");
super.onDestroy();
+ this.logoutAndSave();
+ }
+
+ @Override
+ public void onTaskRemoved(Intent rootIntent) {
+ super.onTaskRemoved(rootIntent);
+ this.logoutAndSave();
+ }
+
+ private void logoutAndSave() {
for (Account account : accounts) {
+ databaseBackend.writeRoster(account.getRoster());
if (account.getXmppConnection() != null) {
disconnect(account, true);
}
}
+ Log.d(LOGTAG,"good bye");
}
protected void scheduleWakeupCall(int seconds, boolean ping) {
@@ -663,7 +638,6 @@ public class XmppConnectionService extends Service {
this.pingIntent, 0);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
timeToWake, pendingPingIntent);
- // Log.d(LOGTAG,"schedule ping in "+seconds+" seconds");
} else {
long scheduledTime = this.pingIntent.getLongExtra("time", 0);
if (scheduledTime < SystemClock.elapsedRealtime()
@@ -674,7 +648,6 @@ public class XmppConnectionService extends Service {
context, 0, this.pingIntent, 0);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
timeToWake, pendingPingIntent);
- // Log.d(LOGTAG,"reschedule old ping to ping in "+seconds+" seconds");
}
}
} else {
@@ -715,12 +688,11 @@ public class XmppConnectionService extends Service {
connection.setOnBindListener(new OnBindListener() {
@Override
- public void onBind(Account account) {
- databaseBackend.clearPresences(account);
+ public void onBind(final Account account) {
+ account.getRoster().clearPresences();
account.clearPresences(); // self presences
- if (account.getXmppConnection().hasFeatureRosterManagment()) {
- updateRoster(account, null);
- }
+ fetchRosterFromServer(account);
+ sendPresence(account);
connectMultiModeConversations(account);
if (convChangedListener != null) {
convChangedListener.onConversationListChanged();
@@ -758,11 +730,7 @@ public class XmppConnectionService extends Service {
addToConversation = true;
} else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
message.getConversation().endOtrIfNeeded();
- packet = new MessagePacket();
- packet.setType(MessagePacket.TYPE_CHAT);
- packet.setFrom(message.getConversation().getAccount()
- .getFullJid());
- packet.setTo(message.getCounterpart());
+ packet = prepareMessagePacket(account, message, null);
packet.setBody("This is an XEP-0027 encryted message");
packet.addChild("x", "jabber:x:encrypted").setContent(
message.getEncryptedBody());
@@ -776,17 +744,26 @@ public class XmppConnectionService extends Service {
// don't encrypt
if (message.getConversation().getMode() == Conversation.MODE_SINGLE) {
message.setStatus(Message.STATUS_SEND);
- saveInDb = true;
- addToConversation = true;
}
packet = prepareMessagePacket(account, message, null);
send = true;
+ saveInDb = true;
+ addToConversation = true;
}
}
} else {
- // account is offline
- saveInDb = true;
- addToConversation = true;
+ if (message.getEncryption() == Message.ENCRYPTION_PGP) {
+ String pgpBody = message.getEncryptedBody();
+ String decryptedBody = message.getBody();
+ message.setBody(pgpBody);
+ databaseBackend.createMessage(message);
+ message.setEncryption(Message.ENCRYPTION_DECRYPTED);
+ message.setBody(decryptedBody);
+ addToConversation = true;
+ } else {
+ saveInDb = true;
+ addToConversation = true;
+ }
}
if (saveInDb) {
@@ -806,25 +783,38 @@ public class XmppConnectionService extends Service {
private void sendUnsendMessages(Conversation conversation) {
for (int i = 0; i < conversation.getMessages().size(); ++i) {
- if ((conversation.getMessages().get(i).getStatus() == Message.STATUS_UNSEND)
- && (conversation.getMessages().get(i).getEncryption() == Message.ENCRYPTION_NONE)) {
- Message message = conversation.getMessages().get(i);
- MessagePacket packet = prepareMessagePacket(
- conversation.getAccount(), message, null);
- conversation.getAccount().getXmppConnection()
- .sendMessagePacket(packet);
- message.setStatus(Message.STATUS_SEND);
- if (conversation.getMode() == Conversation.MODE_SINGLE) {
- databaseBackend.updateMessage(message);
- } else {
- databaseBackend.deleteMessage(message);
- conversation.getMessages().remove(i);
- i--;
- }
+ if (conversation.getMessages().get(i).getStatus() == Message.STATUS_UNSEND) {
+ resendMessage(conversation.getMessages().get(i));
}
}
}
+ private void resendMessage(Message message) {
+ Account account = message.getConversation().getAccount();
+ MessagePacket packet = null;
+ if (message.getEncryption() == Message.ENCRYPTION_NONE) {
+ packet = prepareMessagePacket(account, message, null);
+ } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
+ packet = prepareMessagePacket(account, message, null);
+ packet.setBody("This is an XEP-0027 encryted message");
+ if (message.getEncryptedBody() == null) {
+ markMessage(message, Message.STATUS_SEND_FAILED);
+ return;
+ }
+ packet.addChild("x", "jabber:x:encrypted").setContent(
+ message.getEncryptedBody());
+ } else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
+ packet = prepareMessagePacket(account, message, null);
+ packet.setBody("This is an XEP-0027 encryted message");
+ packet.addChild("x", "jabber:x:encrypted").setContent(
+ message.getBody());
+ }
+ if (packet != null) {
+ account.getXmppConnection().sendMessagePacket(packet);
+ markMessage(message, Message.STATUS_SEND);
+ }
+ }
+
public MessagePacket prepareMessagePacket(Account account, Message message,
Session otrSession) {
MessagePacket packet = new MessagePacket();
@@ -860,27 +850,7 @@ public class XmppConnectionService extends Service {
return packet;
}
- private void getRoster(Account account,
- final OnRosterFetchedListener listener) {
- List<Contact> contacts = databaseBackend.getContactsByAccount(account);
- for (int i = 0; i < contacts.size(); ++i) {
- contacts.get(i).setAccount(account);
- }
- if (listener != null) {
- listener.onRosterFetched(contacts);
- }
- }
-
- public List<Contact> getRoster(Account account) {
- List<Contact> contacts = databaseBackend.getContactsByAccount(account);
- for (int i = 0; i < contacts.size(); ++i) {
- contacts.get(i).setAccount(account);
- }
- return contacts;
- }
-
- public void updateRoster(final Account account,
- final OnRosterFetchedListener listener) {
+ public void fetchRosterFromServer(Account account) {
IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
if (!"".equals(account.getRosterVersion())) {
Log.d(LOGTAG, account.getJid() + ": fetching roster version "
@@ -898,62 +868,23 @@ public class XmppConnectionService extends Service {
IqPacket packet) {
Element roster = packet.findChild("query");
if (roster != null) {
- Log.d(LOGTAG, account.getJid()
- + ": processing roster");
+ account.getRoster().markAllAsNotInRoster();
processRosterItems(account, roster);
- StringBuilder mWhere = new StringBuilder();
- mWhere.append("jid NOT IN(");
- List<Element> items = roster.getChildren();
- for (int i = 0; i < items.size(); ++i) {
- mWhere.append(DatabaseUtils
- .sqlEscapeString(items.get(i)
- .getAttribute("jid")));
- if (i != items.size() - 1) {
- mWhere.append(",");
- }
- }
- mWhere.append(") and accountUuid = \"");
- mWhere.append(account.getUuid());
- mWhere.append("\"");
- List<Contact> contactsToDelete = databaseBackend
- .getContacts(mWhere.toString());
- for (Contact contact : contactsToDelete) {
- databaseBackend.deleteContact(contact);
- replaceContactInConversation(account,
- contact.getJid(), null);
- }
-
- } else {
- Log.d(LOGTAG, account.getJid()
- + ": empty roster returend");
}
- mergePhoneContactsWithRoster(new OnPhoneContactsMerged() {
-
- @Override
- public void phoneContactsMerged() {
- if (listener != null) {
- getRoster(account, listener);
- }
- }
- });
}
});
}
- public void mergePhoneContactsWithRoster(
- final OnPhoneContactsMerged listener) {
+ private void mergePhoneContactsWithRoster() {
PhoneHelper.loadPhoneContacts(getApplicationContext(),
new OnPhoneContactsLoadedListener() {
@Override
- public void onPhoneContactsLoaded(
- Hashtable<String, Bundle> phoneContacts) {
- List<Contact> contacts = databaseBackend
- .getContactsByAccount(null);
- for (int i = 0; i < contacts.size(); ++i) {
- Contact contact = contacts.get(i);
- if (phoneContacts.containsKey(contact.getJid())) {
- Bundle phoneContact = phoneContacts.get(contact
- .getJid());
+ public void onPhoneContactsLoaded(List<Bundle> phoneContacts) {
+ for (Bundle phoneContact : phoneContacts) {
+ for (Account account : accounts) {
+ String jid = phoneContact.getString("jid");
+ Contact contact = account.getRoster()
+ .getContact(jid);
String systemAccount = phoneContact
.getInt("phoneid")
+ "#"
@@ -961,28 +892,10 @@ public class XmppConnectionService extends Service {
contact.setSystemAccount(systemAccount);
contact.setPhotoUri(phoneContact
.getString("photouri"));
- contact.setDisplayName(phoneContact
+ contact.setSystemName(phoneContact
.getString("displayname"));
- databaseBackend.updateContact(contact, false);
- replaceContactInConversation(
- contact.getAccount(), contact.getJid(),
- contact);
- } else {
- if ((contact.getSystemAccount() != null)
- || (contact.getProfilePhoto() != null)) {
- contact.setSystemAccount(null);
- contact.setPhotoUri(null);
- databaseBackend.updateContact(contact,
- false);
- replaceContactInConversation(
- contact.getAccount(),
- contact.getJid(), contact);
- }
}
}
- if (listener != null) {
- listener.phoneContactsMerged();
- }
}
});
}
@@ -998,7 +911,6 @@ public class XmppConnectionService extends Service {
for (Conversation conv : this.conversations) {
Account account = accountLookupTable.get(conv.getAccountUuid());
conv.setAccount(account);
- conv.setContact(findContact(account, conv.getContactJid()));
conv.setMessages(databaseBackend.getMessages(conv, 50));
}
}
@@ -1016,14 +928,6 @@ public class XmppConnectionService extends Service {
return this.accounts;
}
- public Contact findContact(Account account, String jid) {
- Contact contact = databaseBackend.findContact(account, jid);
- if (contact != null) {
- contact.setAccount(account);
- }
- return contact;
- }
-
public Conversation findOrCreateConversation(Account account, String jid,
boolean muc) {
for (Conversation conv : this.getConversations()) {
@@ -1045,11 +949,9 @@ public class XmppConnectionService extends Service {
conversation.setMessages(databaseBackend.getMessages(conversation,
50));
this.databaseBackend.updateConversation(conversation);
- conversation.setContact(findContact(account,
- conversation.getContactJid()));
} else {
String conversationName;
- Contact contact = findContact(account, jid);
+ Contact contact = account.getRoster().getContact(jid);
if (contact != null) {
conversationName = contact.getDisplayName();
} else {
@@ -1062,7 +964,6 @@ public class XmppConnectionService extends Service {
conversation = new Conversation(conversationName, account, jid,
Conversation.MODE_SINGLE);
}
- conversation.setContact(contact);
this.databaseBackend.createConversation(conversation);
}
this.conversations.add(conversation);
@@ -1110,23 +1011,14 @@ public class XmppConnectionService extends Service {
accountChangedListener.onAccountListChangedListener();
}
- public void deleteContact(Contact contact) {
- IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
- Element query = iq.query("jabber:iq:roster");
- query.addChild("item").setAttribute("jid", contact.getJid())
- .setAttribute("subscription", "remove");
- contact.getAccount().getXmppConnection().sendIqPacket(iq, null);
- replaceContactInConversation(contact.getAccount(), contact.getJid(),
- null);
- databaseBackend.deleteContact(contact);
- }
-
public void updateAccount(Account account) {
this.statusListener.onStatusChanged(account);
databaseBackend.updateAccount(account);
reconnectAccount(account, false);
- if (accountChangedListener != null)
+ if (accountChangedListener != null) {
accountChangedListener.onAccountListChangedListener();
+ }
+ UIHelper.showErrorNotification(getApplicationContext(), getAccounts());
}
public void deleteAccount(Account account) {
@@ -1135,8 +1027,10 @@ public class XmppConnectionService extends Service {
}
databaseBackend.deleteAccount(account);
this.accounts.remove(account);
- if (accountChangedListener != null)
+ if (accountChangedListener != null) {
accountChangedListener.onAccountListChangedListener();
+ }
+ UIHelper.showErrorNotification(getApplicationContext(), getAccounts());
}
public void setOnConversationListChangedListener(
@@ -1214,8 +1108,8 @@ public class XmppConnectionService extends Service {
renameListener.onRename(success);
}
if (success) {
- String jid = conversation.getContactJid().split("/")[0] + "/"
- + nick;
+ String jid = conversation.getContactJid().split("/")[0]
+ + "/" + nick;
conversation.setContactJid(jid);
databaseBackend.updateConversation(conversation);
}
@@ -1277,12 +1171,6 @@ public class XmppConnectionService extends Service {
return mBinder;
}
- public void updateContact(Contact contact) {
- databaseBackend.updateContact(contact, false);
- replaceContactInConversation(contact.getAccount(), contact.getJid(),
- contact);
- }
-
public void updateMessage(Message message) {
databaseBackend.updateMessage(message);
}
@@ -1291,30 +1179,33 @@ public class XmppConnectionService extends Service {
SharedPreferences sharedPref = getPreferences();
boolean autoGrant = sharedPref.getBoolean("grant_new_contacts", true);
if (autoGrant) {
- contact.setSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
- contact.setSubscriptionOption(Contact.Subscription.ASKING);
+ contact.setOption(Contact.Options.PREEMPTIVE_GRANT);
+ contact.setOption(Contact.Options.ASKING);
}
- databaseBackend.createContact(contact);
- IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
- Element query = new Element("query");
- query.setAttribute("xmlns", "jabber:iq:roster");
- Element item = new Element("item");
- item.setAttribute("jid", contact.getJid());
- item.setAttribute("name", contact.getJid());
- query.addChild(item);
- iq.addChild(query);
- Account account = contact.getAccount();
- account.getXmppConnection().sendIqPacket(iq, null);
+ pushContactToServer(contact);
if (autoGrant) {
requestPresenceUpdatesFrom(contact);
- if (account.getXmppConnection().hasPendingSubscription(
- contact.getJid())) {
+ if (contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
Log.d("xmppService", "contact had pending subscription");
sendPresenceUpdatesTo(contact);
}
}
- replaceContactInConversation(contact.getAccount(), contact.getJid(),
- contact);
+ }
+
+ public void pushContactToServer(Contact contact) {
+ IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
+ iq.query("jabber:iq:roster").addChild(contact.asElement());
+ Account account = contact.getAccount();
+ account.getXmppConnection().sendIqPacket(iq, null);
+ }
+
+ public void deleteContactOnServer(Contact contact) {
+ IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
+ Element item = iq.query("jabber:iq:roster").addChild("item");
+ item.setAttribute("jid", contact.getJid());
+ item.setAttribute("subscription", "remove");
+ Account account = contact.getAccount();
+ account.getXmppConnection().sendIqPacket(iq, null);
}
public void requestPresenceUpdatesFrom(Contact contact) {
@@ -1355,18 +1246,17 @@ public class XmppConnectionService extends Service {
packet.setAttribute("from", contact.getAccount().getJid());
Log.d(LOGTAG, packet.toString());
contact.getAccount().getXmppConnection().sendPresencePacket(packet);
+ contact.resetOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST);
}
- public void sendPgpPresence(Account account, String signature) {
+ public void sendPresence(Account account) {
PresencePacket packet = new PresencePacket();
packet.setAttribute("from", account.getFullJid());
- Element status = new Element("status");
- status.setContent("online");
- packet.addChild(status);
- Element x = new Element("x");
- x.setAttribute("xmlns", "jabber:x:signed");
- x.setContent(signature);
- packet.addChild(x);
+ String sig = account.getPgpSignature();
+ if (sig != null) {
+ packet.addChild("status").setContent("online");
+ packet.addChild("x", "jabber:x:signed").setContent(sig);
+ }
account.getXmppConnection().sendPresencePacket(packet);
}
@@ -1374,23 +1264,10 @@ public class XmppConnectionService extends Service {
this.databaseBackend.updateConversation(conversation);
}
- public Contact findContact(String uuid) {
- Contact contact = this.databaseBackend.getContact(uuid);
- if (contact != null) {
- for (Account account : getAccounts()) {
- if (contact.getAccountUuid().equals(account.getUuid())) {
- contact.setAccount(account);
- }
- }
- }
- return contact;
- }
-
public void removeOnTLSExceptionReceivedListener() {
this.tlsException = null;
}
- // TODO dont let thread sleep but schedule wake up
public void reconnectAccount(final Account account, final boolean force) {
new Thread(new Runnable() {
@@ -1447,21 +1324,24 @@ public class XmppConnectionService extends Service {
public boolean markMessage(Account account, String recipient, String uuid,
int status) {
- boolean marked = false;
for (Conversation conversation : getConversations()) {
if (conversation.getContactJid().equals(recipient)
&& conversation.getAccount().equals(account)) {
- for (Message message : conversation.getMessages()) {
- if (message.getUuid().equals(uuid)) {
- markMessage(message, status);
- marked = true;
- break;
- }
- }
- break;
+ return markMessage(conversation, uuid, status);
+ }
+ }
+ return false;
+ }
+
+ public boolean markMessage(Conversation conversation, String uuid,
+ int status) {
+ for (Message message : conversation.getMessages()) {
+ if (message.getUuid().equals(uuid)) {
+ markMessage(message, status);
+ return true;
}
}
- return marked;
+ return false;
}
public void markMessage(Message message, int status) {
@@ -1476,12 +1356,22 @@ public class XmppConnectionService extends Service {
return PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
}
-
+
public void updateUi(Conversation conversation, boolean notify) {
if (convChangedListener != null) {
convChangedListener.onConversationListChanged();
} else {
- UIHelper.updateNotification(getApplicationContext(), getConversations(), conversation, notify);
+ UIHelper.updateNotification(getApplicationContext(),
+ getConversations(), conversation, notify);
}
}
+
+ public Account findAccountByJid(String accountJid) {
+ for (Account account : this.accounts) {
+ if (account.getJid().equals(accountJid)) {
+ return account;
+ }
+ }
+ return null;
+ }
}
diff --git a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java
index 06179bc6..72a0909a 100644
--- a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java
+++ b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java
@@ -1,8 +1,6 @@
package eu.siacs.conversations.ui;
-import java.math.BigInteger;
import java.util.Iterator;
-import java.util.Locale;
import org.openintents.openpgp.util.OpenPgpUtils;
@@ -17,7 +15,6 @@ import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Intents;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -31,6 +28,7 @@ import android.widget.TextView;
import android.widget.Toast;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.PgpEngine;
+import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.utils.UIHelper;
@@ -40,12 +38,14 @@ public class ContactDetailsActivity extends XmppActivity {
protected ContactDetailsActivity activity = this;
- private String uuid;
private Contact contact;
-
+
+ private String accountJid;
+ private String contactJid;
+
private EditText name;
- private TextView contactJid;
- private TextView accountJid;
+ private TextView contactJidTv;
+ private TextView accountJidTv;
private TextView status;
private TextView askAgain;
private CheckBox send;
@@ -56,7 +56,7 @@ public class ContactDetailsActivity extends XmppActivity {
@Override
public void onClick(DialogInterface dialog, int which) {
- activity.xmppConnectionService.deleteContact(contact);
+ activity.xmppConnectionService.deleteContactOnServer(contact);
activity.finish();
}
};
@@ -65,8 +65,8 @@ public class ContactDetailsActivity extends XmppActivity {
@Override
public void onClick(DialogInterface dialog, int which) {
- contact.setDisplayName(name.getText().toString());
- activity.xmppConnectionService.updateContact(contact);
+ contact.setServerName(name.getText().toString());
+ activity.xmppConnectionService.pushContactToServer(contact);
populateView();
}
};
@@ -104,12 +104,13 @@ public class ContactDetailsActivity extends XmppActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) {
- this.uuid = getIntent().getExtras().getString("uuid");
+ this.accountJid = getIntent().getExtras().getString("account");
+ this.contactJid = getIntent().getExtras().getString("contact");
}
setContentView(R.layout.activity_contact_details);
- contactJid = (TextView) findViewById(R.id.details_contactjid);
- accountJid = (TextView) findViewById(R.id.details_account);
+ contactJidTv = (TextView) findViewById(R.id.details_contactjid);
+ accountJidTv = (TextView) findViewById(R.id.details_account);
status = (TextView) findViewById(R.id.details_contactstatus);
send = (CheckBox) findViewById(R.id.details_send_presence);
receive = (CheckBox) findViewById(R.id.details_receive_presence);
@@ -170,18 +171,18 @@ public class ContactDetailsActivity extends XmppActivity {
private void populateView() {
setTitle(contact.getDisplayName());
- if (contact.getSubscriptionOption(Contact.Subscription.FROM)) {
+ if (contact.getOption(Contact.Options.FROM)) {
send.setChecked(true);
} else {
send.setText(R.string.preemptively_grant);
if (contact
- .getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) {
+ .getOption(Contact.Options.PREEMPTIVE_GRANT)) {
send.setChecked(true);
} else {
send.setChecked(false);
}
}
- if (contact.getSubscriptionOption(Contact.Subscription.TO)) {
+ if (contact.getOption(Contact.Options.TO)) {
receive.setChecked(true);
} else {
receive.setText(R.string.ask_for_presence_updates);
@@ -195,7 +196,7 @@ public class ContactDetailsActivity extends XmppActivity {
}
});
- if (contact.getSubscriptionOption(Contact.Subscription.ASKING)) {
+ if (contact.getOption(Contact.Options.ASKING)) {
receive.setChecked(true);
} else {
receive.setChecked(false);
@@ -233,11 +234,11 @@ public class ContactDetailsActivity extends XmppActivity {
break;
}
if (contact.getPresences().size() > 1) {
- contactJid.setText(contact.getJid()+" ("+contact.getPresences().size()+")");
+ contactJidTv.setText(contact.getJid()+" ("+contact.getPresences().size()+")");
} else {
- contactJid.setText(contact.getJid());
+ contactJidTv.setText(contact.getJid());
}
- accountJid.setText(contact.getAccount().getJid());
+ accountJidTv.setText(contact.getAccount().getJid());
UIHelper.prepareContactBadge(this, badge, contact, getApplicationContext());
@@ -286,65 +287,66 @@ public class ContactDetailsActivity extends XmppActivity {
@Override
public void onBackendConnected() {
- if (uuid != null) {
- this.contact = xmppConnectionService.findContact(uuid);
- if (this.contact != null) {
- populateView();
+ if ((accountJid != null)&&(contactJid != null)) {
+ Account account = xmppConnectionService.findAccountByJid(accountJid);
+ if (account==null) {
+ return;
}
+ this.contact = account.getRoster().getContact(contactJid);
+ populateView();
}
}
@Override
protected void onStop() {
super.onStop();
- boolean needsUpdating = false;
- if (contact.getSubscriptionOption(Contact.Subscription.FROM)) {
+ boolean updated = false;
+ if (contact.getOption(Contact.Options.FROM)) {
if (!send.isChecked()) {
- contact.resetSubscriptionOption(Contact.Subscription.FROM);
- contact.resetSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
+ contact.resetOption(Contact.Options.FROM);
+ contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
activity.xmppConnectionService.stopPresenceUpdatesTo(contact);
- needsUpdating = true;
+ updated = true;
}
} else {
if (contact
- .getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) {
+ .getOption(Contact.Options.PREEMPTIVE_GRANT)) {
if (!send.isChecked()) {
- contact.resetSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
- needsUpdating = true;
+ contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
+ updated = true;
}
} else {
if (send.isChecked()) {
- contact.setSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
- needsUpdating = true;
+ contact.setOption(Contact.Options.PREEMPTIVE_GRANT);
+ updated = true;
}
}
}
- if (contact.getSubscriptionOption(Contact.Subscription.TO)) {
+ if (contact.getOption(Contact.Options.TO)) {
if (!receive.isChecked()) {
- contact.resetSubscriptionOption(Contact.Subscription.TO);
+ contact.resetOption(Contact.Options.TO);
activity.xmppConnectionService.stopPresenceUpdatesFrom(contact);
- needsUpdating = true;
+ updated = true;
}
} else {
- if (contact.getSubscriptionOption(Contact.Subscription.ASKING)) {
+ if (contact.getOption(Contact.Options.ASKING)) {
if (!receive.isChecked()) {
- contact.resetSubscriptionOption(Contact.Subscription.ASKING);
+ contact.resetOption(Contact.Options.ASKING);
activity.xmppConnectionService
.stopPresenceUpdatesFrom(contact);
- needsUpdating = true;
+ updated = true;
}
} else {
if (receive.isChecked()) {
- contact.setSubscriptionOption(Contact.Subscription.ASKING);
+ contact.setOption(Contact.Options.ASKING);
activity.xmppConnectionService
.requestPresenceUpdatesFrom(contact);
- needsUpdating = true;
+ updated = true;
}
}
}
- if (needsUpdating) {
+ if (updated) {
Toast.makeText(getApplicationContext(), "Subscription updated", Toast.LENGTH_SHORT).show();
- activity.xmppConnectionService.updateContact(contact);
}
}
diff --git a/src/eu/siacs/conversations/ui/ContactsActivity.java b/src/eu/siacs/conversations/ui/ContactsActivity.java
index e403450a..d703b172 100644
--- a/src/eu/siacs/conversations/ui/ContactsActivity.java
+++ b/src/eu/siacs/conversations/ui/ContactsActivity.java
@@ -18,7 +18,6 @@ import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.TextWatcher;
-import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.LayoutInflater;
@@ -34,13 +33,11 @@ import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
-import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.ImageView;
import android.widget.Toast;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
-import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
@@ -130,8 +127,10 @@ public class ContactsActivity extends XmppActivity {
Intent intent = new Intent(getApplicationContext(),
ContactDetailsActivity.class);
intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
- intent.putExtra("uuid", selectedContacts.get(0).getUuid());
+ intent.putExtra("account", selectedContacts.get(0).getAccount().getJid());
+ intent.putExtra("contact",selectedContacts.get(0).getJid());
startActivity(intent);
+ finish();
break;
case R.id.action_invite:
invite();
@@ -270,7 +269,7 @@ public class ContactsActivity extends XmppActivity {
aggregatedContacts.clear();
for (Contact contact : rosterContacts) {
- if (contact.match(searchString))
+ if (contact.match(searchString)&&(contact.getOption(Contact.Options.IN_ROSTER)))
aggregatedContacts.add(contact);
}
@@ -287,9 +286,8 @@ public class ContactsActivity extends XmppActivity {
if (aggregatedContacts.size() == 0) {
if (Validator.isValidJid(searchString)) {
- String name = searchString.split("@")[0];
- Contact newContact = new Contact(null, name, searchString, null);
- newContact.flagAsNotInRoster();
+ Contact newContact = new Contact(searchString);
+ newContact.resetOption(Contact.Options.IN_ROSTER);
aggregatedContacts.add(newContact);
contactsHeader.setText("Create new contact");
} else {
@@ -463,7 +461,7 @@ public class ContactsActivity extends XmppActivity {
}
public void startConversation(Contact contact, Account account, boolean muc) {
- if (!contact.isInRoster()&&(!muc)) {
+ if (!contact.getOption(Contact.Options.IN_ROSTER)&&(!muc)) {
xmppConnectionService.createContact(contact);
}
Conversation conversation = xmppConnectionService
@@ -515,9 +513,10 @@ public class ContactsActivity extends XmppActivity {
getActionBar().setHomeButtonEnabled(false);
}
this.rosterContacts.clear();
- for (int i = 0; i < accounts.size(); ++i) {
- rosterContacts.addAll(xmppConnectionService.getRoster(accounts
- .get(i)));
+ for(Account account : accounts) {
+ if (account.getStatus() != Account.STATUS_DISABLED) {
+ rosterContacts.addAll(account.getRoster().getContacts());
+ }
}
updateAggregatedContacts();
}
@@ -532,52 +531,12 @@ public class ContactsActivity extends XmppActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case R.id.action_refresh_contacts:
- refreshContacts();
- break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
- private void refreshContacts() {
- final ProgressBar progress = (ProgressBar) findViewById(R.id.progressBar1);
- final EditText searchBar = (EditText) findViewById(R.id.new_conversation_search);
- final TextView contactsHeader = (TextView) findViewById(R.id.contacts_header);
- final ListView contactList = (ListView) findViewById(R.id.contactList);
- searchBar.setVisibility(View.GONE);
- contactsHeader.setVisibility(View.GONE);
- contactList.setVisibility(View.GONE);
- progress.setVisibility(View.VISIBLE);
- this.accounts = xmppConnectionService.getAccounts();
- this.rosterContacts.clear();
- for (int i = 0; i < accounts.size(); ++i) {
- if (accounts.get(i).getStatus() == Account.STATUS_ONLINE) {
- xmppConnectionService.updateRoster(accounts.get(i),
- new OnRosterFetchedListener() {
-
- @Override
- public void onRosterFetched(
- final List<Contact> roster) {
- runOnUiThread(new Runnable() {
-
- @Override
- public void run() {
- rosterContacts.addAll(roster);
- progress.setVisibility(View.GONE);
- searchBar.setVisibility(View.VISIBLE);
- contactList.setVisibility(View.VISIBLE);
- contactList.setVisibility(View.VISIBLE);
- updateAggregatedContacts();
- }
- });
- }
- });
- }
- }
- }
-
@Override
public void onActionModeStarted(ActionMode mode) {
super.onActionModeStarted(mode);
diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java
index 88728245..f1995935 100644
--- a/src/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/eu/siacs/conversations/ui/ConversationActivity.java
@@ -6,19 +6,19 @@ import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
-import org.openintents.openpgp.OpenPgpError;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.services.ImageProvider;
import eu.siacs.conversations.utils.ExceptionHelper;
import eu.siacs.conversations.utils.UIHelper;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
+import android.provider.MediaStore;
import android.app.AlertDialog;
import android.app.FragmentTransaction;
import android.app.PendingIntent;
@@ -65,9 +65,14 @@ public class ConversationActivity extends XmppActivity {
public static final int REQUEST_SEND_MESSAGE = 0x75441;
public static final int REQUEST_DECRYPT_PGP = 0x76783;
private static final int REQUEST_ATTACH_FILE_DIALOG = 0x48502;
+ private static final int REQUEST_IMAGE_CAPTURE = 0x33788;
+ private static final int REQUEST_RECORD_AUDIO = 0x46189;
private static final int REQUEST_SEND_PGP_IMAGE = 0x53883;
- private static final int REQUEST_ATTACH_FILE = 0x73824;
public static final int REQUEST_ENCRYPT_MESSAGE = 0x378018;
+
+ private static final int ATTACHMENT_CHOICE_CHOOSE_IMAGE = 0x92734;
+ private static final int ATTACHMENT_CHOICE_TAKE_PHOTO = 0x84123;
+ private static final int ATTACHMENT_CHOICE_RECORD_VOICE = 0x75291;
protected SlidingPaneLayout spl;
@@ -120,6 +125,10 @@ public class ConversationActivity extends XmppActivity {
public Conversation getSelectedConversation() {
return this.selectedConversation;
}
+
+ public void setSelectedConversation(Conversation conversation) {
+ this.selectedConversation = conversation;
+ }
public ListView getConversationListView() {
return this.listView;
@@ -214,7 +223,7 @@ public class ConversationActivity extends XmppActivity {
}
((TextView) view.findViewById(R.id.conversation_lastupdate))
- .setText(UIHelper.readableTimeDifference(conv
+ .setText(UIHelper.readableTimeDifference(getContext(), conv
.getLatestMessage().getTimeSent()));
ImageView profilePicture = (ImageView) view
@@ -235,8 +244,8 @@ public class ConversationActivity extends XmppActivity {
public void onItemClick(AdapterView<?> arg0, View clickedView,
int position, long arg3) {
paneShouldBeOpen = false;
- if (selectedConversation != conversationList.get(position)) {
- selectedConversation = conversationList.get(position);
+ if (getSelectedConversation() != conversationList.get(position)) {
+ setSelectedConversation(conversationList.get(position));
swapConversationFragment(); // .onBackendConnected(conversationList.get(position));
} else {
spl.closePane();
@@ -327,28 +336,40 @@ public class ConversationActivity extends XmppActivity {
return true;
}
- private void attachFileDialog() {
+ private void selectPresenceToAttachFile(final int attachmentChoice) {
selectPresence(getSelectedConversation(), new OnPresenceSelected() {
@Override
public void onPresenceSelected(boolean success, String presence) {
if (success) {
- Intent attachFileIntent = new Intent();
- attachFileIntent.setType("image/*");
- attachFileIntent.setAction(Intent.ACTION_GET_CONTENT);
- Intent chooser = Intent.createChooser(attachFileIntent, getString(R.string.attach_file));
- startActivityForResult(chooser, REQUEST_ATTACH_FILE_DIALOG);
+ if (attachmentChoice==ATTACHMENT_CHOICE_TAKE_PHOTO) {
+ Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, ImageProvider.getIncomingContentUri());
+ if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
+ startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
+ }
+ } else if (attachmentChoice==ATTACHMENT_CHOICE_CHOOSE_IMAGE) {
+ Intent attachFileIntent = new Intent();
+ attachFileIntent.setType("image/*");
+ attachFileIntent.setAction(Intent.ACTION_GET_CONTENT);
+ Intent chooser = Intent.createChooser(attachFileIntent, getString(R.string.attach_file));
+ startActivityForResult(chooser, REQUEST_ATTACH_FILE_DIALOG);
+ } else if (attachmentChoice==ATTACHMENT_CHOICE_RECORD_VOICE) {
+ Intent intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
+ startActivityForResult(intent, REQUEST_RECORD_AUDIO);
+ }
}
}
@Override
public void onSendPlainTextInstead() {
+ // TODO Auto-generated method stub
}
},"file");
}
- private void attachFile() {
+ private void attachFile(final int attachmentChoice) {
final Conversation conversation = getSelectedConversation();
if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
if (hasPgp()) {
@@ -357,18 +378,17 @@ public class ConversationActivity extends XmppActivity {
@Override
public void userInputRequried(PendingIntent pi) {
- ConversationActivity.this.runIntent(pi, REQUEST_ATTACH_FILE);
+ ConversationActivity.this.runIntent(pi, attachmentChoice);
}
@Override
public void success() {
- attachFileDialog();
+ selectPresenceToAttachFile(attachmentChoice);
}
@Override
public void error(int error) {
- // TODO Auto-generated method stub
-
+ displayErrorDialog(error);
}
});
} else {
@@ -380,14 +400,14 @@ public class ConversationActivity extends XmppActivity {
@Override
public void onClick(DialogInterface dialog, int which) {
conversation.setNextEncryption(Message.ENCRYPTION_NONE);
- attachFileDialog();
+ selectPresenceToAttachFile(attachmentChoice);
}
});
}
}
}
} else if (getSelectedConversation().getNextEncryption() == Message.ENCRYPTION_NONE) {
- attachFileDialog();
+ selectPresenceToAttachFile(attachmentChoice);
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.otr_file_transfer));
@@ -399,7 +419,7 @@ public class ConversationActivity extends XmppActivity {
@Override
public void onClick(DialogInterface dialog, int which) {
conversation.setNextEncryption(Message.ENCRYPTION_NONE);
- attachFile();
+ attachFile(attachmentChoice);
}
});
} else {
@@ -408,7 +428,7 @@ public class ConversationActivity extends XmppActivity {
@Override
public void onClick(DialogInterface dialog, int which) {
conversation.setNextEncryption(Message.ENCRYPTION_PGP);
- attachFile();
+ attachFile(attachmentChoice);
}
});
}
@@ -423,7 +443,28 @@ public class ConversationActivity extends XmppActivity {
spl.openPane();
break;
case R.id.action_attach_file:
- attachFile();
+ View menuAttachFile = findViewById(R.id.action_attach_file);
+ PopupMenu attachFilePopup = new PopupMenu(this, menuAttachFile);
+ attachFilePopup.inflate(R.menu.attachment_choices);
+ attachFilePopup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
+
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.attach_choose_picture:
+ attachFile(ATTACHMENT_CHOICE_CHOOSE_IMAGE);
+ break;
+ case R.id.attach_take_picture:
+ attachFile(ATTACHMENT_CHOICE_TAKE_PHOTO);
+ break;
+ case R.id.attach_record_voice:
+ attachFile(ATTACHMENT_CHOICE_RECORD_VOICE);
+ break;
+ }
+ return false;
+ }
+ });
+ attachFilePopup.show();
break;
case R.id.action_add:
startActivity(new Intent(this, ContactsActivity.class));
@@ -433,10 +474,11 @@ public class ConversationActivity extends XmppActivity {
break;
case R.id.action_contact_details:
Contact contact = this.getSelectedConversation().getContact();
- if (contact != null) {
+ if (contact.getOption(Contact.Options.IN_ROSTER)) {
Intent intent = new Intent(this, ContactDetailsActivity.class);
intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
- intent.putExtra("uuid", contact.getUuid());
+ intent.putExtra("account", this.getSelectedConversation().getAccount().getJid());
+ intent.putExtra("contact",contact.getJid());
startActivity(intent);
} else {
showAddToRosterDialog(getSelectedConversation());
@@ -452,7 +494,7 @@ public class ConversationActivity extends XmppActivity {
Intent inviteIntent = new Intent(getApplicationContext(),
ContactsActivity.class);
inviteIntent.setAction("invite");
- inviteIntent.putExtra("uuid", selectedConversation.getUuid());
+ inviteIntent.putExtra("uuid", getSelectedConversation().getUuid());
startActivity(inviteIntent);
break;
case R.id.action_security:
@@ -531,9 +573,9 @@ public class ConversationActivity extends XmppActivity {
spl.openPane();
xmppConnectionService.archiveConversation(conversation);
if (conversationList.size() > 0) {
- selectedConversation = conversationList.get(0);
+ setSelectedConversation(conversationList.get(0));
} else {
- selectedConversation = null;
+ setSelectedConversation(null);
}
}
@@ -619,7 +661,7 @@ public class ConversationActivity extends XmppActivity {
for (int i = 0; i < conversationList.size(); ++i) {
if (conversationList.get(i).getUuid().equals(convToView)) {
- selectedConversation = conversationList.get(i);
+ setSelectedConversation(conversationList.get(i));
}
}
paneShouldBeOpen = false;
@@ -642,7 +684,7 @@ public class ConversationActivity extends XmppActivity {
if (selectedFragment != null) {
selectedFragment.onBackendConnected();
} else {
- selectedConversation = conversationList.get(0);
+ setSelectedConversation(conversationList.get(0));
swapConversationFragment();
}
ExceptionHelper.checkForCrash(this, this.xmppConnectionService);
@@ -668,67 +710,68 @@ public class ConversationActivity extends XmppActivity {
selectedFragment.hidePgpPassphraseBox();
}
} else if (requestCode == REQUEST_ATTACH_FILE_DIALOG) {
- prepareImageToast = Toast.makeText(getApplicationContext(), getText(R.string.preparing_image), Toast.LENGTH_LONG);
- final Conversation conversation = getSelectedConversation();
- if (conversation.getNextEncryption() == Message.ENCRYPTION_NONE) {
- prepareImageToast.show();
- this.pendingMessage = xmppConnectionService.attachImageToConversation(conversation, data.getData(),new UiCallback() {
-
- @Override
- public void userInputRequried(PendingIntent pi) {
-
- }
-
- @Override
- public void success() {
- sendPendingImageMessage();
- }
-
- @Override
- public void error(int error) {
- pendingMessage = null;
- displayErrorDialog(error);
- }
- });
- } else if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
- prepareImageToast.show();
- attachPgpFile(conversation,data.getData());
- } else {
- Log.d(LOGTAG,"unknown next message encryption: "+conversation.getNextEncryption());
- }
+ attachImageToConversation(getSelectedConversation(),data.getData());
} else if (requestCode == REQUEST_SEND_PGP_IMAGE) {
- } else if (requestCode == REQUEST_ATTACH_FILE) {
- attachFile();
+ } else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_IMAGE) {
+ attachFile(ATTACHMENT_CHOICE_CHOOSE_IMAGE);
+ } else if (requestCode == ATTACHMENT_CHOICE_TAKE_PHOTO) {
+ attachFile(ATTACHMENT_CHOICE_TAKE_PHOTO);
} else if (requestCode == REQUEST_ANNOUNCE_PGP) {
announcePgp(getSelectedConversation().getAccount(),getSelectedConversation());
} else if (requestCode == REQUEST_ENCRYPT_MESSAGE) {
encryptTextMessage();
+ } else if (requestCode == REQUEST_IMAGE_CAPTURE) {
+ attachImageToConversation(getSelectedConversation(), null);
+ } else if (requestCode == REQUEST_RECORD_AUDIO) {
+ Log.d("xmppService",data.getData().toString());
+ attachAudioToConversation(getSelectedConversation(),data.getData());
} else {
Log.d(LOGTAG,"unknown result code:"+requestCode);
}
}
}
- private void attachPgpFile(Conversation conversation, Uri uri) {
- pendingMessage = xmppConnectionService.attachImageToConversation(conversation, uri, new UiCallback() {
-
- @Override
- public void userInputRequried(PendingIntent pi) {
- ConversationActivity.this.runIntent(pi, ConversationActivity.REQUEST_SEND_PGP_IMAGE);
- }
+ private void attachAudioToConversation(Conversation conversation, Uri uri) {
+
+ }
+
+ private void attachImageToConversation(Conversation conversation, Uri uri) {
+ prepareImageToast = Toast.makeText(getApplicationContext(), getText(R.string.preparing_image), Toast.LENGTH_LONG);
+ prepareImageToast.show();
+ pendingMessage = xmppConnectionService.attachImageToConversation(conversation, uri, new UiCallback() {
- @Override
- public void success() {
- sendPendingImageMessage();
- }
+ @Override
+ public void userInputRequried(PendingIntent pi) {
+ hidePrepareImageToast();
+ ConversationActivity.this.runIntent(pi, ConversationActivity.REQUEST_SEND_PGP_IMAGE);
+ }
+
+ @Override
+ public void success() {
+ sendPendingImageMessage();
+ hidePrepareImageToast();
+ }
+
+ @Override
+ public void error(int error) {
+ hidePrepareImageToast();
+ pendingMessage = null;
+ displayErrorDialog(error);
+ }
+ });
+ }
+
+ private void hidePrepareImageToast() {
+ if (prepareImageToast!=null) {
+ runOnUiThread(new Runnable() {
@Override
- public void error(int error) {
- pendingMessage = null;
- displayErrorDialog(error);
+ public void run() {
+ prepareImageToast.cancel();
}
});
+ }
}
private void sendPendingImageMessage() {
@@ -832,8 +875,7 @@ public class ConversationActivity extends XmppActivity {
public void onClick(DialogInterface dialog, int which) {
String jid = conversation.getContactJid();
Account account = getSelectedConversation().getAccount();
- String name = jid.split("@")[0];
- Contact contact = new Contact(account, name, jid, null);
+ Contact contact = account.getRoster().getContact(jid);
xmppConnectionService.createContact(contact);
}
});
diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java
index 91a39ecc..41837d8f 100644
--- a/src/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/eu/siacs/conversations/ui/ConversationFragment.java
@@ -5,17 +5,15 @@ import java.util.HashMap;
import java.util.List;
import java.util.Set;
-import org.openintents.openpgp.OpenPgpError;
-
import net.java.otr4j.session.SessionStatus;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.PgpEngine;
-import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
+import eu.siacs.conversations.services.ImageProvider;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.jingle.JingleConnection;
@@ -30,7 +28,6 @@ import android.content.SharedPreferences;
import android.content.IntentSender.SendIntentException;
import android.graphics.Bitmap;
import android.graphics.Typeface;
-import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Editable;
@@ -236,7 +233,7 @@ public class ConversationFragment extends Fragment {
viewHolder.indicator.setVisibility(View.VISIBLE);
}
- String formatedTime = UIHelper.readableTimeDifference(message
+ String formatedTime = UIHelper.readableTimeDifference(getContext(), message
.getTimeSent());
if (message.getStatus() <= Message.STATUS_RECIEVED) {
if ((filesize != null) && (info != null)) {
@@ -266,7 +263,9 @@ public class ConversationFragment extends Fragment {
}
private void displayInfoMessage(ViewHolder viewHolder, int r) {
- viewHolder.download_button.setVisibility(View.GONE);
+ if (viewHolder.download_button != null) {
+ viewHolder.download_button.setVisibility(View.GONE);
+ }
viewHolder.image.setVisibility(View.GONE);
viewHolder.messageBody.setVisibility(View.VISIBLE);
viewHolder.messageBody.setText(getString(r));
@@ -329,15 +328,9 @@ public class ConversationFragment extends Fragment {
@Override
public void onClick(View v) {
- Uri uri = Uri
- .parse("content://eu.siacs.conversations.images/"
- + message.getConversationUuid()
- + "/"
- + message.getUuid());
- Log.d("xmppService",
- "staring intent with uri:" + uri.toString());
Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(uri, "image/*");
+ intent.setDataAndType(
+ ImageProvider.getContentUri(message), "image/*");
startActivity(intent);
}
});
@@ -399,20 +392,17 @@ public class ConversationFragment extends Fragment {
if (type == RECIEVED) {
if (item.getConversation().getMode() == Conversation.MODE_MULTI) {
- if (item.getCounterpart() != null) {
- viewHolder.contact_picture
- .setImageBitmap(mBitmapCache.get(item
- .getCounterpart(), null,
- getActivity()
- .getApplicationContext()));
- } else {
- viewHolder.contact_picture
- .setImageBitmap(mBitmapCache.get(
- item.getConversation().getName(
- useSubject), null,
- getActivity()
- .getApplicationContext()));
- }
+ viewHolder.contact_picture.setImageBitmap(mBitmapCache
+ .get(item.getCounterpart(), null, getActivity()
+ .getApplicationContext()));
+ viewHolder.contact_picture
+ .setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ highlightInConference(item.getCounterpart());
+ }
+ });
}
}
@@ -468,6 +458,22 @@ public class ConversationFragment extends Fragment {
return view;
}
+ protected void highlightInConference(String nick) {
+ if (chatMsg.getText().toString().isEmpty()) {
+ chatMsg.setText(nick+": ");
+ } else {
+ String oldString = chatMsg.getText().toString();
+ if (oldString.endsWith(" ")) {
+ chatMsg.setText(oldString+nick+" ");
+ } else {
+ chatMsg.setText(oldString+" "+nick+" ");
+ }
+ }
+ int position = chatMsg.length();
+ Editable etext = chatMsg.getText();
+ Selection.setSelection(etext, position);
+ }
+
protected Bitmap findSelfPicture() {
SharedPreferences sharedPref = PreferenceManager
.getDefaultSharedPreferences(getActivity()
@@ -494,7 +500,7 @@ public class ConversationFragment extends Fragment {
@Override
public void onStop() {
super.onStop();
- if (this.conversation!=null) {
+ if (this.conversation != null) {
this.conversation.setNextMessage(chatMsg.getText().toString());
}
}
@@ -585,14 +591,15 @@ public class ConversationFragment extends Fragment {
}
public void updateMessages() {
- if (getView()==null) {
+ if (getView() == null) {
return;
}
ConversationActivity activity = (ConversationActivity) getActivity();
if (this.conversation != null) {
for (Message message : this.conversation.getMessages()) {
if ((message.getEncryption() == Message.ENCRYPTION_PGP)
- && (message.getStatus() == Message.STATUS_RECIEVED)) {
+ && ((message.getStatus() == Message.STATUS_RECIEVED) || (message
+ .getStatus() == Message.STATUS_SEND))) {
decryptMessage(message);
break;
}
@@ -632,31 +639,26 @@ public class ConversationFragment extends Fragment {
protected void makeFingerprintWarning(int latestEncryption) {
final LinearLayout fingerprintWarning = (LinearLayout) getView()
.findViewById(R.id.new_fingerprint);
- if (conversation.getContact() != null) {
- 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() {
+ 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);
- }
+ @Override
+ public void onClick(View v) {
+ AlertDialog dialog = UIHelper.getVerifyFingerprintDialog(
+ (ConversationActivity) getActivity(), conversation,
+ fingerprintWarning);
+ dialog.show();
+ }
+ });
} else {
fingerprintWarning.setVisibility(View.GONE);
}
@@ -675,35 +677,31 @@ public class ConversationFragment extends Fragment {
final Contact contact = message.getConversation().getContact();
if (activity.hasPgp()) {
if (contact.getPgpKeyId() != 0) {
- xmppService.getPgpEngine().hasKey(contact,
- new UiCallback() {
-
- @Override
- public void userInputRequried(PendingIntent pi) {
- activity.runIntent(
- pi,
- ConversationActivity.REQUEST_ENCRYPT_MESSAGE);
- }
+ xmppService.getPgpEngine().hasKey(contact, new UiCallback() {
- @Override
- public void success() {
- activity.encryptTextMessage();
- }
+ @Override
+ public void userInputRequried(PendingIntent pi) {
+ activity.runIntent(pi,
+ ConversationActivity.REQUEST_ENCRYPT_MESSAGE);
+ }
- @Override
- public void error(int error) {
-
- }
- });
+ @Override
+ public void success() {
+ activity.encryptTextMessage();
+ }
+
+ @Override
+ public void error(int error) {
+
+ }
+ });
} else {
showNoPGPKeyDialog(new DialogInterface.OnClickListener() {
@Override
- public void onClick(DialogInterface dialog,
- int which) {
- conversation
- .setNextEncryption(Message.ENCRYPTION_NONE);
+ public void onClick(DialogInterface dialog, int which) {
+ conversation.setNextEncryption(Message.ENCRYPTION_NONE);
message.setEncryption(Message.ENCRYPTION_NONE);
xmppService.sendMessage(message, null);
chatMsg.setText("");
@@ -712,15 +710,15 @@ public class ConversationFragment extends Fragment {
}
}
}
-
+
public void showNoPGPKeyDialog(DialogInterface.OnClickListener listener) {
- AlertDialog.Builder builder = new AlertDialog.Builder(
- getActivity());
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(getString(R.string.no_pgp_key));
builder.setIconAttribute(android.R.attr.alertDialogIcon);
builder.setMessage(getText(R.string.contact_has_no_pgp_key));
builder.setNegativeButton(getString(R.string.cancel), null);
- builder.setPositiveButton(getString(R.string.send_unencrypted),listener);
+ builder.setPositiveButton(getString(R.string.send_unencrypted),
+ listener);
builder.create().show();
}
@@ -766,7 +764,6 @@ public class ConversationFragment extends Fragment {
private class BitmapCache {
private HashMap<String, Bitmap> bitmaps = new HashMap<String, Bitmap>();
- private Bitmap error = null;
public Bitmap get(String name, Contact contact, Context context) {
if (bitmaps.containsKey(name)) {
diff --git a/src/eu/siacs/conversations/ui/EditAccount.java b/src/eu/siacs/conversations/ui/EditAccount.java
index 8b1c0fa6..47930747 100644
--- a/src/eu/siacs/conversations/ui/EditAccount.java
+++ b/src/eu/siacs/conversations/ui/EditAccount.java
@@ -51,27 +51,19 @@ public class EditAccount extends DialogFragment {
final CheckBox registerAccount = (CheckBox) view
.findViewById(R.id.edit_account_register_new);
- final String okButtonDesc;
-
if (account != null) {
jidText.setText(account.getJid());
password.setText(account.getPassword());
- Log.d("xmppService","mein debugger. account != null");
if (account.isOptionSet(Account.OPTION_REGISTER)) {
registerAccount.setChecked(true);
- builder.setTitle(getString(R.string.register_account));
- okButtonDesc = "Register";
passwordConfirm.setVisibility(View.VISIBLE);
passwordConfirm.setText(account.getPassword());
} else {
registerAccount.setVisibility(View.GONE);
- builder.setTitle("Edit account");
- okButtonDesc = "Edit";
}
- } else {
- builder.setTitle("Add account");
- okButtonDesc = "Add";
}
+ builder.setTitle(R.string.account_settings);
+
registerAccount
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@@ -79,26 +71,19 @@ public class EditAccount extends DialogFragment {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
- AlertDialog d = (AlertDialog) getDialog();
- Button positiveButton = (Button) d
- .getButton(Dialog.BUTTON_POSITIVE);
if (isChecked) {
- d.setTitle(getString(R.string.register_account));
- positiveButton.setText("Register");
passwordConfirm.setVisibility(View.VISIBLE);
confirmPwDesc.setVisibility(View.VISIBLE);
} else {
- d.setTitle("Add account");
passwordConfirm.setVisibility(View.GONE);
- positiveButton.setText("Add");
confirmPwDesc.setVisibility(View.GONE);
}
}
});
builder.setView(view);
- builder.setNeutralButton("Cancel", null);
- builder.setPositiveButton(okButtonDesc, null);
+ builder.setNeutralButton(R.string.cancel, null);
+ builder.setPositiveButton(R.string.save, null);
return builder.create();
}
@@ -114,7 +99,9 @@ public class EditAccount extends DialogFragment {
String jid = jidEdit.getText().toString();
EditText passwordEdit = (EditText) d
.findViewById(R.id.account_password);
+ EditText passwordConfirmEdit = (EditText) d.findViewById(R.id.account_password_confirm2);
String password = passwordEdit.getText().toString();
+ String passwordConfirm = passwordConfirmEdit.getText().toString();
CheckBox register = (CheckBox) d.findViewById(R.id.edit_account_register_new);
String username;
String server;
@@ -123,9 +110,15 @@ public class EditAccount extends DialogFragment {
username = parts[0];
server = parts[1];
} else {
- jidEdit.setError("Invalid Jabber ID");
+ jidEdit.setError(getString(R.string.invalid_jid));
return;
}
+ if (register.isChecked()) {
+ if (!passwordConfirm.equals(password)) {
+ passwordConfirmEdit.setError(getString(R.string.passwords_do_not_match));
+ return;
+ }
+ }
if (account != null) {
account.setPassword(password);
account.setUsername(username);
diff --git a/src/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/eu/siacs/conversations/ui/ManageAccountActivity.java
index 0b7dac58..ba570364 100644
--- a/src/eu/siacs/conversations/ui/ManageAccountActivity.java
+++ b/src/eu/siacs/conversations/ui/ManageAccountActivity.java
@@ -73,7 +73,7 @@ public class ManageAccountActivity extends XmppActivity {
@Override
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle("Untrusted Certificate");
+ builder.setTitle(getString(R.string.account_status_error));
builder.setIconAttribute(android.R.attr.alertDialogIcon);
View view = (View) getLayoutInflater().inflate(R.layout.cert_warning, null);
TextView sha = (TextView) view.findViewById(R.id.sha);
@@ -91,8 +91,8 @@ public class ManageAccountActivity extends XmppActivity {
hint.setText(getString(R.string.untrusted_cert_hint,account.getServer()));
sha.setText(humanReadableSha.toString());
builder.setView(view);
- builder.setNegativeButton("Don't connect", null);
- builder.setPositiveButton("Trust certificate", new OnClickListener() {
+ builder.setNegativeButton(getString(R.string.certif_no_trust), null);
+ builder.setPositiveButton(getString(R.string.certif_trust), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
@@ -130,55 +130,55 @@ public class ManageAccountActivity extends XmppActivity {
.findViewById(R.id.account_status);
switch (account.getStatus()) {
case Account.STATUS_DISABLED:
- statusView.setText("temporarily disabled");
+ statusView.setText(getString(R.string.account_status_disabled));
statusView.setTextColor(0xFF1da9da);
break;
case Account.STATUS_ONLINE:
- statusView.setText("online");
+ statusView.setText(getString(R.string.account_status_online));
statusView.setTextColor(0xFF83b600);
break;
case Account.STATUS_CONNECTING:
- statusView.setText("connecting\u2026");
+ statusView.setText(getString(R.string.account_status_connecting));
statusView.setTextColor(0xFF1da9da);
break;
case Account.STATUS_OFFLINE:
- statusView.setText("offline");
+ statusView.setText(getString(R.string.account_status_offline));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_UNAUTHORIZED:
- statusView.setText("unauthorized");
+ statusView.setText(getString(R.string.account_status_unauthorized));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_SERVER_NOT_FOUND:
- statusView.setText("server not found");
+ statusView.setText(getString(R.string.account_status_not_found));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_NO_INTERNET:
- statusView.setText("no internet");
+ statusView.setText(getString(R.string.account_status_no_internet));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_SERVER_REQUIRES_TLS:
- statusView.setText("server requires TLS");
+ statusView.setText(getString(R.string.account_status_requires_tls));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_TLS_ERROR:
- statusView.setText("untrusted cerficate");
+ statusView.setText(getString(R.string.account_status_error));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_REGISTRATION_FAILED:
- statusView.setText("registration failed");
+ statusView.setText(getString(R.string.account_status_regis_fail));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_REGISTRATION_CONFLICT:
- statusView.setText("username already in use");
+ statusView.setText(getString(R.string.account_status_regis_conflict));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_REGISTRATION_SUCCESSFULL:
- statusView.setText("registration completed");
+ statusView.setText(getString(R.string.account_status_regis_success));
statusView.setTextColor(0xFF83b600);
break;
case Account.STATUS_REGISTRATION_NOT_SUPPORTED:
- statusView.setText("server does not support registration");
+ statusView.setText(getString(R.string.account_status_regis_not_sup));
statusView.setTextColor(0xFFe92727);
break;
default:
diff --git a/src/eu/siacs/conversations/ui/ShareWithActivity.java b/src/eu/siacs/conversations/ui/ShareWithActivity.java
index 1bc9fc46..e4abfd2d 100644
--- a/src/eu/siacs/conversations/ui/ShareWithActivity.java
+++ b/src/eu/siacs/conversations/ui/ShareWithActivity.java
@@ -17,7 +17,6 @@ import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.preference.PreferenceManager;
-import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
@@ -29,15 +28,6 @@ public class ShareWithActivity extends XmppActivity {
private LinearLayout conversations;
private LinearLayout contacts;
- private OnClickListener click = new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
-
- }
- };
-
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -71,7 +61,7 @@ public class ShareWithActivity extends XmppActivity {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
boolean useSubject = preferences.getBoolean("use_subject_in_muc", true);
- Set<String> displayedContacts = new HashSet<String>();
+ Set<Contact> displayedContacts = new HashSet<Contact>();
conversations.removeAllViews();
List<Conversation> convList = xmppConnectionService.getConversations();
Collections.sort(convList, new Comparator<Conversation>() {
@@ -95,15 +85,13 @@ public class ShareWithActivity extends XmppActivity {
}
});
conversations.addView(view);
- if (conversation.getContact() != null) {
- displayedContacts.add(conversation.getContact().getUuid());
- }
+ displayedContacts.add(conversation.getContact());
}
contacts.removeAllViews();
- final List<Contact> contactsList = new ArrayList<Contact>();
+ List<Contact> contactsList = new ArrayList<Contact>();
for(Account account : xmppConnectionService.getAccounts()) {
- for(final Contact contact : xmppConnectionService.getRoster(account)) {
- if (!displayedContacts.contains(contact.getUuid())) {
+ for(Contact contact : account.getRoster().getContacts()) {
+ if (!displayedContacts.contains(contact)&&(contact.getOption(Contact.Options.IN_ROSTER))) {
contactsList.add(contact);
}
}
diff --git a/src/eu/siacs/conversations/ui/XmppActivity.java b/src/eu/siacs/conversations/ui/XmppActivity.java
index dc894ad5..02900ac8 100644
--- a/src/eu/siacs/conversations/ui/XmppActivity.java
+++ b/src/eu/siacs/conversations/ui/XmppActivity.java
@@ -1,7 +1,5 @@
package eu.siacs.conversations.ui;
-import java.nio.channels.AlreadyConnectedException;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
@@ -177,7 +175,7 @@ public abstract class XmppActivity extends Activity {
@Override
public void success() {
xmppConnectionService.databaseBackend.updateAccount(account);
- xmppConnectionService.sendPgpPresence(account, account.getPgpSignature());
+ xmppConnectionService.sendPresence(account);
if (conversation!=null) {
conversation.setNextEncryption(Message.ENCRYPTION_PGP);
}
diff --git a/src/eu/siacs/conversations/utils/OnPhoneContactsLoadedListener.java b/src/eu/siacs/conversations/utils/OnPhoneContactsLoadedListener.java
index fa8cea04..9a689768 100644
--- a/src/eu/siacs/conversations/utils/OnPhoneContactsLoadedListener.java
+++ b/src/eu/siacs/conversations/utils/OnPhoneContactsLoadedListener.java
@@ -1,9 +1,9 @@
package eu.siacs.conversations.utils;
-import java.util.Hashtable;
+import java.util.List;
import android.os.Bundle;
public interface OnPhoneContactsLoadedListener {
- public void onPhoneContactsLoaded(Hashtable<String, Bundle> phoneContacts);
+ public void onPhoneContactsLoaded(List<Bundle> phoneContacts);
}
diff --git a/src/eu/siacs/conversations/utils/PhoneHelper.java b/src/eu/siacs/conversations/utils/PhoneHelper.java
index 6355e378..773312bb 100644
--- a/src/eu/siacs/conversations/utils/PhoneHelper.java
+++ b/src/eu/siacs/conversations/utils/PhoneHelper.java
@@ -1,8 +1,8 @@
package eu.siacs.conversations.utils;
-import java.util.Hashtable;
+import java.util.ArrayList;
+import java.util.List;
-import android.app.Activity;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Loader;
@@ -10,21 +10,15 @@ import android.content.Loader.OnLoadCompleteListener;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Looper;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Profile;
-import android.provider.MediaStore;
public class PhoneHelper {
public static void loadPhoneContacts(Context context,
final OnPhoneContactsLoadedListener listener) {
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
- final Looper mLooper = Looper.myLooper();
- final Hashtable<String, Bundle> phoneContacts = new Hashtable<String, Bundle>();
-
+ final List<Bundle> phoneContacts = new ArrayList<Bundle>();
+
final String[] PROJECTION = new String[] { ContactsContract.Data._ID,
ContactsContract.Data.DISPLAY_NAME,
ContactsContract.Data.PHOTO_THUMBNAIL_URI,
@@ -58,15 +52,14 @@ public class PhoneHelper {
.getColumnIndex(ContactsContract.Data.PHOTO_THUMBNAIL_URI)));
contact.putString("lookup", cursor.getString(cursor
.getColumnIndex(ContactsContract.Data.LOOKUP_KEY)));
- phoneContacts.put(
- cursor.getString(cursor
- .getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)),
- contact);
+
+ contact.putString("jid",cursor.getString(cursor
+ .getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)));
+ phoneContacts.add(contact);
}
if (listener != null) {
listener.onPhoneContactsLoaded(phoneContacts);
}
- mLooper.quit();
}
});
mCursorLoader.startLoading();
diff --git a/src/eu/siacs/conversations/utils/UIHelper.java b/src/eu/siacs/conversations/utils/UIHelper.java
index 8baa3c25..d626d421 100644
--- a/src/eu/siacs/conversations/utils/UIHelper.java
+++ b/src/eu/siacs/conversations/utils/UIHelper.java
@@ -12,7 +12,6 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.MucOptions.User;
import eu.siacs.conversations.ui.ConversationActivity;
import eu.siacs.conversations.ui.ManageAccountActivity;
@@ -27,7 +26,6 @@ import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
@@ -38,11 +36,9 @@ import android.net.Uri;
import android.preference.PreferenceManager;
import android.provider.ContactsContract.Contacts;
import android.support.v4.app.NotificationCompat;
-import android.support.v4.app.NotificationCompat.InboxStyle;
import android.support.v4.app.TaskStackBuilder;
import android.text.Html;
import android.util.DisplayMetrics;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
@@ -54,16 +50,16 @@ public class UIHelper {
private static final int FG_COLOR = 0xFFE5E5E5;
private static final int TRANSPARENT = 0x00000000;
- public static String readableTimeDifference(long time) {
+ public static String readableTimeDifference(Context context, long time) {
if (time == 0) {
- return "just now";
+ return context.getString(R.string.just_now);
}
Date date = new Date(time);
long difference = (System.currentTimeMillis() - time) / 1000;
if (difference < 60) {
- return "just now";
+ return context.getString(R.string.just_now);
} else if (difference < 60 * 10) {
- return difference / 60 + " min ago";
+ return difference / 60 + " " + context.getString(R.string.minutes_ago);
} else if (difference < 60 * 60 * 24) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm",Locale.US);
return sdf.format(date);
@@ -234,11 +230,7 @@ public class UIHelper {
}
return bitmap;
}
-
- private static Bitmap getUnknownContactPicture(String[] names, int size) {
- return getUnknownContactPicture(names, size, UIHelper.BG_COLOR, UIHelper.FG_COLOR);
- }
-
+
private static Bitmap getMucContactPicture(Conversation conversation, int size, int bgColor, int fgColor) {
List<User> members = conversation.getMucOptions().getUsers();
if (members.size() == 0) {
@@ -255,13 +247,8 @@ public class UIHelper {
public static Bitmap getContactPicture(Conversation conversation, int dpSize, Context context, boolean notification) {
if(conversation.getMode() == Conversation.MODE_SINGLE) {
- if (conversation.getContact() != null){
return getContactPicture(conversation.getContact(), dpSize,
context, notification);
- } else {
- return getContactPicture(conversation.getName(false), dpSize,
- context, notification);
- }
} else{
int fgColor = UIHelper.FG_COLOR,
bgColor = (notification) ?
@@ -273,10 +260,6 @@ public class UIHelper {
}
public static Bitmap getContactPicture(Contact contact, int dpSize, Context context, boolean notification) {
- int fgColor = UIHelper.FG_COLOR,
- bgColor = (notification) ?
- UIHelper.BG_COLOR : UIHelper.TRANSPARENT;
-
String uri = contact.getProfilePhoto();
if (uri==null) {
return getContactPicture(contact.getDisplayName(), dpSize,
@@ -412,7 +395,7 @@ public class UIHelper {
.bigText(bigText.toString()));
} else {
NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle();
- style.setBigContentTitle(unread.size() + " unread Conversations");
+ style.setBigContentTitle(unread.size() + " " + context.getString(R.string.unread_conversations));
StringBuilder names = new StringBuilder();
for (int i = 0; i < unread.size(); ++i) {
targetUuid = unread.get(i).getUuid();
@@ -424,7 +407,7 @@ public class UIHelper {
style.addLine(Html.fromHtml("<b>" + unread.get(i).getName(useSubject)
+ "</b> " + unread.get(i).getLatestMessage().getReadableBody(context)));
}
- mBuilder.setContentTitle(unread.size() + " unread Conversations");
+ mBuilder.setContentTitle(unread.size() + " " + context.getString(R.string.unread_conversations));
mBuilder.setContentText(names.toString());
mBuilder.setStyle(style);
}
@@ -518,7 +501,7 @@ public class UIHelper {
public void onClick(DialogInterface dialog, int which) {
contact.addOtrFingerprint(conversation.getOtrFingerprint());
msg.setVisibility(View.GONE);
- activity.xmppConnectionService.updateContact(contact);
+ //activity.xmppConnectionService.updateContact(contact);
}
});
builder.setView(view);
diff --git a/src/eu/siacs/conversations/utils/Validator.java b/src/eu/siacs/conversations/utils/Validator.java
index fce953ae..51d8b25c 100644
--- a/src/eu/siacs/conversations/utils/Validator.java
+++ b/src/eu/siacs/conversations/utils/Validator.java
@@ -5,7 +5,7 @@ import java.util.regex.Pattern;
public class Validator {
public static final Pattern VALID_JID =
- Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE);
+ Pattern.compile("\\b^[A-Z0-9._%+-]+@([A-Z0-9.-]+\\.)?\\d{1,3}[.]\\d{1,3}[.]\\d{1,3}[.]\\d{1,3}\\b$|^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE);
public static boolean isValidJid(String jid) {
Matcher matcher = VALID_JID.matcher(jid);
diff --git a/src/eu/siacs/conversations/xml/XmlReader.java b/src/eu/siacs/conversations/xml/XmlReader.java
index 0a82a5d8..b4b1647e 100644
--- a/src/eu/siacs/conversations/xml/XmlReader.java
+++ b/src/eu/siacs/conversations/xml/XmlReader.java
@@ -85,10 +85,8 @@ public class XmlReader {
public Element readElement(Tag currentTag) throws XmlPullParserException, IOException {
Element element = new Element(currentTag.getName());
- //Log.d(LOGTAG,"trying to read element "+element.getName());
element.setAttributes(currentTag.getAttributes());
Tag nextTag = this.readTag();
- //Log.d(LOGTAG,"next Tag is: "+nextTag.toString());
if(nextTag.isNo()) {
element.setContent(nextTag.getName());
nextTag = this.readTag();
@@ -96,15 +94,16 @@ public class XmlReader {
if (nextTag == null) {
throw new IOException("unterupted mid tag");
}
- //Log.d(LOGTAG,"reading till the end of "+element.getName());
while(!nextTag.isEnd(element.getName())) {
if (!nextTag.isNo()) {
Element child = this.readElement(nextTag);
element.addChild(child);
}
nextTag = this.readTag();
+ if (nextTag == null) {
+ throw new IOException("unterupted mid tag");
+ }
}
- //Log.d(LOGTAG,"return with element"+element);
return element;
}
}
diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java
index adb27ec8..0ba9677a 100644
--- a/src/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -21,7 +21,6 @@ import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Map.Entry;
import javax.net.ssl.SSLContext;
@@ -31,7 +30,6 @@ import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
-import org.json.JSONException;
import org.xmlpull.v1.XmlPullParserException;
import android.os.Bundle;
@@ -76,9 +74,7 @@ public class XmppConnection implements Runnable {
private boolean shouldAuthenticate = true;
private Element streamFeatures;
private HashMap<String, List<String>> disco = new HashMap<String, List<String>>();
-
- private HashSet<String> pendingSubscriptions = new HashSet<String>();
-
+
private String streamId = null;
private int smVersion = 3;
@@ -89,6 +85,8 @@ public class XmppConnection implements Runnable {
public long lastPingSent = 0;
public long lastConnect = 0;
public long lastSessionStarted = 0;
+
+ private int attempt = 0;
private static final int PACKET_IQ = 0;
private static final int PACKET_MESSAGE = 1;
@@ -111,9 +109,12 @@ public class XmppConnection implements Runnable {
protected void changeStatus(int nextStatus) {
if (account.getStatus() != nextStatus) {
- if ((nextStatus == Account.STATUS_OFFLINE)&&(account.getStatus() != Account.STATUS_CONNECTING)&&(account.getStatus() != Account.STATUS_ONLINE)) {
+ if ((nextStatus == Account.STATUS_OFFLINE)&&(account.getStatus() != Account.STATUS_CONNECTING)&&(account.getStatus() != Account.STATUS_ONLINE)&&(account.getStatus() != Account.STATUS_DISABLED)) {
return;
}
+ if (nextStatus == Account.STATUS_ONLINE) {
+ this.attempt = 0;
+ }
account.setStatus(nextStatus);
if (statusListener != null) {
statusListener.onStatusChanged(account);
@@ -124,6 +125,7 @@ public class XmppConnection implements Runnable {
protected void connect() {
Log.d(LOGTAG,account.getJid()+ ": connecting");
lastConnect = SystemClock.elapsedRealtime();
+ this.attempt++;
try {
shouldAuthenticate = shouldBind = !account.isOptionSet(Account.OPTION_REGISTER);
tagReader = new XmlReader(wakeLock);
@@ -257,10 +259,11 @@ public class XmppConnection implements Runnable {
RequestPacket r = new RequestPacket(smVersion);
tagWriter.writeStanzaAsync(r);
} else if (nextTag.isStart("resumed")) {
+ lastPaketReceived = SystemClock.elapsedRealtime();
+ Log.d(LOGTAG,account.getJid()+": session resumed");
tagReader.readElement(nextTag);
sendPing();
changeStatus(Account.STATUS_ONLINE);
- Log.d(LOGTAG,account.getJid()+": session resumed");
} else if (nextTag.isStart("r")) {
tagReader.readElement(nextTag);
AckPacket ack = new AckPacket(this.stanzasReceived,smVersion);
@@ -543,12 +546,6 @@ public class XmppConnection implements Runnable {
this.tagWriter.writeStanzaAsync(resume);
} else if (this.streamFeatures.hasChild("bind") && shouldBind) {
sendBindRequest();
- if (this.streamFeatures.hasChild("session")) {
- Log.d(LOGTAG,account.getJid()+": sending deprecated session");
- IqPacket startSession = new IqPacket(IqPacket.TYPE_SET);
- startSession.addChild("session","urn:ietf:params:xml:ns:xmpp-session"); //setContent("")
- this.sendIqPacket(startSession, null);
- }
}
}
@@ -616,25 +613,10 @@ public class XmppConnection implements Runnable {
});
}
- private void sendInitialPresence() {
- PresencePacket packet = new PresencePacket();
- packet.setAttribute("from", account.getFullJid());
- if (account.getKeys().has("pgp_signature")) {
- try {
- String signature = account.getKeys().getString("pgp_signature");
- packet.addChild("status").setContent("online");
- packet.addChild("x","jabber:x:signed").setContent(signature);
- } catch (JSONException e) {
- //
- }
- }
- this.sendPresencePacket(packet);
- }
-
private void sendBindRequest() throws IOException {
IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
iq.addChild("bind", "urn:ietf:params:xml:ns:xmpp-bind").addChild("resource").setContent(account.getResource());
- this.sendIqPacket(iq, new OnIqPacketReceived() {
+ this.sendUnboundIqPacket(iq, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
String resource = packet.findChild("bind").findChild("jid")
@@ -649,15 +631,21 @@ public class XmppConnection implements Runnable {
EnablePacket enable = new EnablePacket(smVersion);
tagWriter.writeStanzaAsync(enable);
}
- sendInitialPresence();
sendServiceDiscoveryInfo(account.getServer());
sendServiceDiscoveryItems(account.getServer());
if (bindListener !=null) {
bindListener.onBind(account);
}
+
changeStatus(Account.STATUS_ONLINE);
}
});
+ if (this.streamFeatures.hasChild("session")) {
+ Log.d(LOGTAG,account.getJid()+": sending deprecated session");
+ IqPacket startSession = new IqPacket(IqPacket.TYPE_SET);
+ startSession.addChild("session","urn:ietf:params:xml:ns:xmpp-session");
+ this.sendUnboundIqPacket(startSession, null);
+ }
}
private void sendServiceDiscoveryInfo(final String server) {
@@ -756,6 +744,14 @@ public class XmppConnection implements Runnable {
packet.setFrom(account.getFullJid());
this.sendPacket(packet, callback);
}
+
+ public void sendUnboundIqPacket(IqPacket packet, OnIqPacketReceived callback) {
+ if (packet.getId()==null) {
+ String id = nextRandomId();
+ packet.setAttribute("id", id);
+ }
+ this.sendPacket(packet, callback);
+ }
public void sendMessagePacket(MessagePacket packet) {
this.sendPacket(packet, null);
@@ -907,12 +903,13 @@ public class XmppConnection implements Runnable {
return findDiscoItemByFeature("http://jabber.org/protocol/muc");
}
- public boolean hasPendingSubscription(String jid) {
- return this.pendingSubscriptions.contains(jid);
+ public int getTimeToNextAttempt() {
+ int interval = (int) (25 * Math.pow(1.5,attempt));
+ int secondsSinceLast = (int) ((SystemClock.elapsedRealtime() - this.lastConnect) / 1000);
+ return interval - secondsSinceLast;
}
- public void addPendingSubscription(String jid) {
- Log.d(LOGTAG,"adding "+jid+" to pending subscriptions");
- this.pendingSubscriptions.add(jid);
+ public int getAttempt() {
+ return this.attempt;
}
}