Merge branch 'development'

This commit is contained in:
Daniel Gultsch 2014-03-21 22:16:39 +01:00
commit df9db8c8b6
12 changed files with 131 additions and 138 deletions

View file

@ -1,17 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<array name="conversation_encryption_type_entries"> <array name="resources">
<item>None</item> <item>Mobile</item>
<item>OpenPGP</item> <item>Phone</item>
<item>Off the record</item> <item>Tablet</item>
</array> <item>Conversations</item>
<array name="conversation_encryption_type_values"> <item>Android</item>
<item>none</item>
<item>pgp</item>
<item>otr</item>
</array>
<array name="manage_account_options">
<item>Delete</item>
<item>Disable</item>
</array> </array>
</resources> </resources>

View file

@ -1,20 +1,20 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory <PreferenceCategory
android:title="Security and Privacy Options"> android:title="General">
<ListPreference
android:key="default_conversation_encryption_type"
android:title="Default conversation encryption"
android:dialogTitle="Default conversation encryption"
android:entries="@array/conversation_encryption_type_entries"
android:entryValues="@array/conversation_encryption_type_values"
android:defaultValue="none"/>
<CheckBoxPreference <CheckBoxPreference
android:key="grant_new_contacts" android:key="grant_new_contacts"
android:title="Grant presence updates" android:title="Grant presence updates"
android:summary="Preemptivly grant and ask for presence subscription for contacts you created" android:summary="Preemptivly grant and ask for presence subscription for contacts you created"
android:defaultValue="true" android:defaultValue="true"
/> />
<ListPreference
android:key="resource"
android:title="XMPP Resource"
android:summary="The name this client identifies itself"
android:entries="@array/resources"
android:entryValues="@array/resources"
android:defaultValue="Mobile"/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory
android:title="Notification Settings"> android:title="Notification Settings">

View file

@ -158,11 +158,10 @@ public class OtrEngine implements OtrEngineHost {
packet.setFrom(account.getFullJid()); //sender packet.setFrom(account.getFullJid()); //sender
packet.setTo(session.getAccountID()+"/"+session.getUserID()); //reciepient packet.setTo(session.getAccountID()+"/"+session.getUserID()); //reciepient
packet.setBody(body); packet.setBody(body);
Element privateTag = new Element("private"); packet.addChild("private","urn:xmpp:carbons:2");
privateTag.setAttribute("xmlns","urn:xmpp:carbons:2"); packet.addChild("no-copy","urn:xmpp:hints");
packet.addChild(privateTag);
packet.setType(MessagePacket.TYPE_CHAT); packet.setType(MessagePacket.TYPE_CHAT);
Log.d(LOGTAG,packet.toString()); //Log.d(LOGTAG,packet.toString());
account.getXmppConnection().sendMessagePacket(packet); account.getXmppConnection().sendMessagePacket(packet);
} }

View file

@ -52,7 +52,7 @@ public class Account extends AbstractEntity{
protected String password; protected String password;
protected int options = 0; protected int options = 0;
protected String rosterVersion; protected String rosterVersion;
protected String resource; protected String resource = "mobile";
protected int status = -1; protected int status = -1;
protected JSONObject keys = new JSONObject(); protected JSONObject keys = new JSONObject();
@ -137,6 +137,10 @@ public class Account extends AbstractEntity{
this.resource = resource; this.resource = resource;
} }
public String getResource() {
return this.resource;
}
public String getJid() { public String getJid() {
return username+"@"+server; return username+"@"+server;
} }

View file

@ -219,7 +219,6 @@ public class Conversation extends AbstractEntity {
} }
public void startOtrSession(Context context, String presence) { public void startOtrSession(Context context, String presence) {
Log.d("xmppService", "starting otr session with " + presence);
SessionID sessionId = new SessionID(this.getContactJid(), presence, SessionID sessionId = new SessionID(this.getContactJid(), presence,
"xmpp"); "xmpp");
this.otrSession = new SessionImpl(sessionId, getAccount().getOtrEngine( this.otrSession = new SessionImpl(sessionId, getAccount().getOtrEngine(

View file

@ -7,6 +7,7 @@ import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Random; import java.util.Random;
import org.openintents.openpgp.util.OpenPgpApi; import org.openintents.openpgp.util.OpenPgpApi;
@ -203,6 +204,12 @@ public class XmppConnectionService extends Service {
accountChangedListener.onAccountListChangedListener(); accountChangedListener.onAccountListChangedListener();
} }
if (account.getStatus() == Account.STATUS_ONLINE) { if (account.getStatus() == Account.STATUS_ONLINE) {
List<Conversation> conversations = getConversations();
for (int i = 0; i < conversations.size(); ++i) {
if (conversations.get(i).getAccount() == account) {
sendUnsendMessages(conversations.get(i));
}
}
scheduleWakeupCall(PING_MAX_INTERVAL, true); scheduleWakeupCall(PING_MAX_INTERVAL, true);
} else if (account.getStatus() == Account.STATUS_OFFLINE) { } else if (account.getStatus() == Account.STATUS_OFFLINE) {
if (!account.isOptionSet(Account.OPTION_DISABLED)) { if (!account.isOptionSet(Account.OPTION_DISABLED)) {
@ -544,6 +551,9 @@ public class XmppConnectionService extends Service {
} }
public XmppConnection createConnection(Account account) { public XmppConnection createConnection(Account account) {
SharedPreferences sharedPref = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
account.setResource(sharedPref.getString("resource", "mobile").toLowerCase(Locale.getDefault()));
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
XmppConnection connection = new XmppConnection(account, pm); XmppConnection connection = new XmppConnection(account, pm);
connection.setOnMessagePacketReceivedListener(this.messageListener); connection.setOnMessagePacketReceivedListener(this.messageListener);
@ -574,12 +584,6 @@ public class XmppConnectionService extends Service {
updateRoster(account, null); updateRoster(account, null);
} }
connectMultiModeConversations(account); connectMultiModeConversations(account);
List<Conversation> conversations = getConversations();
for (int i = 0; i < conversations.size(); ++i) {
if (conversations.get(i).getAccount() == account) {
sendUnsendMessages(conversations.get(i));
}
}
if (convChangedListener != null) { if (convChangedListener != null) {
convChangedListener.onConversationListChanged(); convChangedListener.onConversationListChanged();
} }
@ -588,7 +592,7 @@ public class XmppConnectionService extends Service {
return connection; return connection;
} }
public void sendMessage(Message message, String presence) { synchronized public void sendMessage(Message message, String presence) {
Account account = message.getConversation().getAccount(); Account account = message.getConversation().getAccount();
Conversation conv = message.getConversation(); Conversation conv = message.getConversation();
boolean saveInDb = false; boolean saveInDb = false;
@ -619,11 +623,8 @@ public class XmppConnectionService extends Service {
.getFullJid()); .getFullJid());
packet.setTo(message.getCounterpart()); packet.setTo(message.getCounterpart());
packet.setBody("This is an XEP-0027 encryted message"); packet.setBody("This is an XEP-0027 encryted message");
Element x = new Element("x"); packet.addChild("x","jabber:x:encrypted").setContent(this.getPgpEngine().encrypt(keyId,
x.setAttribute("xmlns", "jabber:x:encrypted");
x.setContent(this.getPgpEngine().encrypt(keyId,
message.getBody())); message.getBody()));
packet.addChild(x);
account.getXmppConnection().sendMessagePacket(packet); account.getXmppConnection().sendMessagePacket(packet);
message.setStatus(Message.STATUS_SEND); message.setStatus(Message.STATUS_SEND);
message.setEncryption(Message.ENCRYPTION_DECRYPTED); message.setEncryption(Message.ENCRYPTION_DECRYPTED);
@ -661,7 +662,7 @@ public class XmppConnectionService extends Service {
private void sendUnsendMessages(Conversation conversation) { private void sendUnsendMessages(Conversation conversation) {
for (int i = 0; i < conversation.getMessages().size(); ++i) { for (int i = 0; i < conversation.getMessages().size(); ++i) {
if (conversation.getMessages().get(i).getStatus() == Message.STATUS_UNSEND) { if ((conversation.getMessages().get(i).getStatus() == Message.STATUS_UNSEND)&&(conversation.getMessages().get(i).getEncryption() == Message.ENCRYPTION_NONE)) {
Message message = conversation.getMessages().get(i); Message message = conversation.getMessages().get(i);
MessagePacket packet = prepareMessagePacket( MessagePacket packet = prepareMessagePacket(
conversation.getAccount(), message, null); conversation.getAccount(), message, null);
@ -694,9 +695,8 @@ public class XmppConnectionService extends Service {
+ ": could not encrypt message to " + ": could not encrypt message to "
+ message.getCounterpart()); + message.getCounterpart());
} }
Element privateMarker = new Element("private"); packet.addChild("private","urn:xmpp:carbons:2");
privateMarker.setAttribute("xmlns", "urn:xmpp:carbons:2"); packet.addChild("no-copy","urn:xmpp:hints");
packet.addChild(privateMarker);
packet.setTo(otrSession.getSessionID().getAccountID() + "/" packet.setTo(otrSession.getSessionID().getAccountID() + "/"
+ otrSession.getSessionID().getUserID()); + otrSession.getSessionID().getUserID());
packet.setFrom(account.getFullJid()); packet.setFrom(account.getFullJid());
@ -736,16 +736,13 @@ public class XmppConnectionService extends Service {
public void updateRoster(final Account account, public void updateRoster(final Account account,
final OnRosterFetchedListener listener) { final OnRosterFetchedListener listener) {
IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET); IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
Element query = new Element("query");
query.setAttribute("xmlns", "jabber:iq:roster");
if (!"".equals(account.getRosterVersion())) { if (!"".equals(account.getRosterVersion())) {
Log.d(LOGTAG, account.getJid() + ": fetching roster version " Log.d(LOGTAG, account.getJid() + ": fetching roster version "
+ account.getRosterVersion()); + account.getRosterVersion());
} else { } else {
Log.d(LOGTAG, account.getJid() + ": fetching roster"); Log.d(LOGTAG, account.getJid() + ": fetching roster");
} }
query.setAttribute("ver", account.getRosterVersion()); iqPacket.query("jabber:iq:roster").setAttribute("ver", account.getRosterVersion());
iqPacket.addChild(query);
account.getXmppConnection().sendIqPacket(iqPacket, account.getXmppConnection().sendIqPacket(iqPacket,
new OnIqPacketReceived() { new OnIqPacketReceived() {
@ -958,13 +955,8 @@ public class XmppConnectionService extends Service {
public void deleteContact(Contact contact) { public void deleteContact(Contact contact) {
IqPacket iq = new IqPacket(IqPacket.TYPE_SET); IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
Element query = new Element("query"); Element query = iq.query("jabber:iq:roster");
query.setAttribute("xmlns", "jabber:iq:roster"); query.addChild("item").setAttribute("jid", contact.getJid()).setAttribute("subscription", "remove");
Element item = new Element("item");
item.setAttribute("jid", contact.getJid());
item.setAttribute("subscription", "remove");
query.addChild(item);
iq.addChild(query);
contact.getAccount().getXmppConnection().sendIqPacket(iq, null); contact.getAccount().getXmppConnection().sendIqPacket(iq, null);
replaceContactInConversation(contact.getJid(), null); replaceContactInConversation(contact.getJid(), null);
databaseBackend.deleteContact(contact); databaseBackend.deleteContact(contact);
@ -1032,11 +1024,9 @@ public class XmppConnectionService extends Service {
Element x = new Element("x"); Element x = new Element("x");
x.setAttribute("xmlns", "http://jabber.org/protocol/muc"); x.setAttribute("xmlns", "http://jabber.org/protocol/muc");
if (conversation.getMessages().size() != 0) { if (conversation.getMessages().size() != 0) {
Element history = new Element("history");
long lastMsgTime = conversation.getLatestMessage().getTimeSent(); long lastMsgTime = conversation.getLatestMessage().getTimeSent();
long diff = (System.currentTimeMillis() - lastMsgTime) / 1000 - 1; long diff = (System.currentTimeMillis() - lastMsgTime) / 1000 - 1;
history.setAttribute("seconds", diff + ""); x.addChild("history").setAttribute("seconds", diff + "");
x.addChild(history);
} }
packet.addChild(x); packet.addChild(x);
conversation.getAccount().getXmppConnection() conversation.getAccount().getXmppConnection()

View file

@ -388,6 +388,7 @@ public class ConversationFragment extends Fragment {
public void updateMessages() { public void updateMessages() {
ConversationActivity activity = (ConversationActivity) getActivity(); ConversationActivity activity = (ConversationActivity) getActivity();
if (this.conversation != null) {
List<Message> encryptedMessages = new LinkedList<Message>(); List<Message> encryptedMessages = new LinkedList<Message>();
for (Message message : this.conversation.getMessages()) { for (Message message : this.conversation.getMessages()) {
if (message.getEncryption() == Message.ENCRYPTION_PGP) { if (message.getEncryption() == Message.ENCRYPTION_PGP) {
@ -436,6 +437,7 @@ public class ConversationFragment extends Fragment {
activity.updateConversationList(); activity.updateConversationList();
} }
} }
}
protected void makeFingerprintWarning(int latestEncryption) { protected void makeFingerprintWarning(int latestEncryption) {
final LinearLayout fingerprintWarning = (LinearLayout) getView() final LinearLayout fingerprintWarning = (LinearLayout) getView()

View file

@ -2,7 +2,6 @@ package eu.siacs.conversations.utils;
import java.util.List; import java.util.List;
import net.java.otr4j.OtrException;
import net.java.otr4j.session.Session; import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionStatus; import net.java.otr4j.session.SessionStatus;
import android.util.Log; import android.util.Log;
@ -31,13 +30,16 @@ public class MessageParser {
} }
public static Message parseOtrChat(MessagePacket packet, Account account, XmppConnectionService service) { public static Message parseOtrChat(MessagePacket packet, Account account, XmppConnectionService service) {
boolean justStarted = false;
boolean properlyAddressed = (packet.getTo().split("/").length == 2) || (account.countPresences() == 1); boolean properlyAddressed = (packet.getTo().split("/").length == 2) || (account.countPresences() == 1);
String[] fromParts = packet.getFrom().split("/"); String[] fromParts = packet.getFrom().split("/");
Conversation conversation = service.findOrCreateConversation(account, fromParts[0],false); Conversation conversation = service.findOrCreateConversation(account, fromParts[0],false);
String body = packet.getBody(); String body = packet.getBody();
if (!conversation.hasValidOtrSession()) { if (!conversation.hasValidOtrSession()) {
if (properlyAddressed) { 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]); conversation.startOtrSession(service.getApplicationContext(), fromParts[1]);
justStarted = true;
} else { } else {
Log.d("xmppService",account.getJid()+": ignoring otr session with "+fromParts[0]); Log.d("xmppService",account.getJid()+": ignoring otr session with "+fromParts[0]);
return null; return null;
@ -47,7 +49,9 @@ public class MessageParser {
if (!foreignPresence.equals(fromParts[1])) { if (!foreignPresence.equals(fromParts[1])) {
conversation.resetOtrSession(); conversation.resetOtrSession();
if (properlyAddressed) { if (properlyAddressed) {
Log.d("xmppService","replacing otr session with "+packet.getFrom());
conversation.startOtrSession(service.getApplicationContext(), fromParts[1]); conversation.startOtrSession(service.getApplicationContext(), fromParts[1]);
justStarted = true;
} else { } else {
return null; return null;
} }
@ -84,7 +88,9 @@ public class MessageParser {
Log.d(LOGTAG,"otr session stoped"); Log.d(LOGTAG,"otr session stoped");
} }
} catch (Exception e) { } catch (Exception e) {
if (!justStarted) {
conversation.resetOtrSession(); conversation.resetOtrSession();
}
return null; return null;
} }

View file

@ -305,6 +305,7 @@ public class UIHelper {
} }
public static Bitmap getSelfContactPicture(Account account, int size, boolean showPhoneSelfContactPicture, Activity activity) { public static Bitmap getSelfContactPicture(Account account, int size, boolean showPhoneSelfContactPicture, Activity activity) {
if (showPhoneSelfContactPicture) {
Uri selfiUri = PhoneHelper.getSefliUri(activity); Uri selfiUri = PhoneHelper.getSefliUri(activity);
if (selfiUri != null) { if (selfiUri != null) {
try { try {
@ -315,5 +316,8 @@ public class UIHelper {
} }
} }
return getUnknownContactPicture(account.getJid(), size); return getUnknownContactPicture(account.getJid(), size);
} else {
return getUnknownContactPicture(account.getJid(), size);
}
} }
} }

View file

@ -17,7 +17,22 @@ public class Element {
public Element addChild(Element child) { public Element addChild(Element child) {
this.content = null; this.content = null;
children.add(child); children.add(child);
return this; return child;
}
public Element addChild(String name) {
this.content = null;
Element child = new Element(name);
children.add(child);
return child;
}
public Element addChild(String name, String xmlns) {
this.content = null;
Element child = new Element(name);
child.setAttribute("xmlns", xmlns);
children.add(child);
return child;
} }
public Element setContent(String content) { public Element setContent(String content) {

View file

@ -461,11 +461,7 @@ public class XmppConnection implements Runnable {
if (this.streamFeatures.hasChild("session")) { if (this.streamFeatures.hasChild("session")) {
Log.d(LOGTAG,"sending session"); Log.d(LOGTAG,"sending session");
IqPacket startSession = new IqPacket(IqPacket.TYPE_SET); IqPacket startSession = new IqPacket(IqPacket.TYPE_SET);
Element session = new Element("session"); startSession.addChild("session","urn:ietf:params:xml:ns:xmpp-session"); //setContent("")
session.setAttribute("xmlns",
"urn:ietf:params:xml:ns:xmpp-session");
session.setContent("");
startSession.addChild(session);
this.sendIqPacket(startSession, null); this.sendIqPacket(startSession, null);
} }
} }
@ -484,7 +480,8 @@ public class XmppConnection implements Runnable {
IqPacket register = new IqPacket(IqPacket.TYPE_SET); IqPacket register = new IqPacket(IqPacket.TYPE_SET);
Element username = new Element("username").setContent(account.getUsername()); Element username = new Element("username").setContent(account.getUsername());
Element password = new Element("password").setContent(account.getPassword()); Element password = new Element("password").setContent(account.getPassword());
register.query("jabber:iq:register").addChild(username).addChild(password); register.query("jabber:iq:register").addChild(username);
register.query().addChild(password);
sendIqPacket(register, new OnIqPacketReceived() { sendIqPacket(register, new OnIqPacketReceived() {
@Override @Override
@ -516,13 +513,8 @@ public class XmppConnection implements Runnable {
if (account.getKeys().has("pgp_signature")) { if (account.getKeys().has("pgp_signature")) {
try { try {
String signature = account.getKeys().getString("pgp_signature"); String signature = account.getKeys().getString("pgp_signature");
Element status = new Element("status"); packet.addChild("status").setContent("online");
status.setContent("online"); packet.addChild("x","jabber:x:signed").setContent(signature);
packet.addChild(status);
Element x = new Element("x");
x.setAttribute("xmlns", "jabber:x:signed");
x.setContent(signature);
packet.addChild(x);
} catch (JSONException e) { } catch (JSONException e) {
// //
} }
@ -532,12 +524,7 @@ public class XmppConnection implements Runnable {
private void sendBindRequest() throws IOException { private void sendBindRequest() throws IOException {
IqPacket iq = new IqPacket(IqPacket.TYPE_SET); IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
Element bind = new Element("bind"); iq.addChild("bind", "urn:ietf:params:xml:ns:xmpp-bind").addChild("resource").setContent(account.getResource());
bind.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-bind");
Element resource = new Element("resource");
resource.setContent("Conversations");
bind.addChild(resource);
iq.addChild(bind);
this.sendIqPacket(iq, new OnIqPacketReceived() { this.sendIqPacket(iq, new OnIqPacketReceived() {
@Override @Override
public void onIqPacketReceived(Account account, IqPacket packet) { public void onIqPacketReceived(Account account, IqPacket packet) {
@ -601,9 +588,7 @@ public class XmppConnection implements Runnable {
private void sendEnableCarbons() { private void sendEnableCarbons() {
IqPacket iq = new IqPacket(IqPacket.TYPE_SET); IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
Element enable = new Element("enable"); iq.addChild("enable","urn:xmpp:carbons:2");
enable.setAttribute("xmlns", "urn:xmpp:carbons:2");
iq.addChild(enable);
this.sendIqPacket(iq, new OnIqPacketReceived() { this.sendIqPacket(iq, new OnIqPacketReceived() {
@Override @Override
@ -679,10 +664,8 @@ public class XmppConnection implements Runnable {
tagWriter.writeStanzaAsync(new RequestPacket()); tagWriter.writeStanzaAsync(new RequestPacket());
} else { } else {
IqPacket iq = new IqPacket(IqPacket.TYPE_GET); IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
Element ping = new Element("ping"); iq.setFrom(account.getFullJid());
iq.setAttribute("from",account.getFullJid()); iq.addChild("ping","urn:xmpp:ping");
ping.setAttribute("xmlns", "urn:xmpp:ping");
iq.addChild(ping);
this.sendIqPacket(iq, null); this.sendIqPacket(iq, null);
} }
} }

View file

@ -1,6 +1,5 @@
package eu.siacs.conversations.xmpp.stanzas; package eu.siacs.conversations.xmpp.stanzas;
import android.graphics.YuvImage;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
@ -39,8 +38,7 @@ public class IqPacket extends AbstractStanza {
public Element query() { public Element query() {
Element query = findChild("query"); Element query = findChild("query");
if (query==null) { if (query==null) {
query = new Element("query"); query = addChild("query");
addChild(query);
} }
return query; return query;
} }