diff options
Diffstat (limited to 'src/eu')
14 files changed, 363 insertions, 225 deletions
diff --git a/src/eu/siacs/conversations/entities/Contact.java b/src/eu/siacs/conversations/entities/Contact.java index 22e2661b..cff0dd73 100644 --- a/src/eu/siacs/conversations/entities/Contact.java +++ b/src/eu/siacs/conversations/entities/Contact.java @@ -3,12 +3,15 @@ package eu.siacs.conversations.entities; 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 { public static final String TABLENAME = "contacts"; @@ -36,8 +39,8 @@ public class Contact { protected boolean inRoster = true; - public Contact(String account, String systemName, - String serverName, String jid, int subscription, String photoUri, + public Contact(String account, String systemName, String serverName, + String jid, int subscription, String photoUri, String systemAccount, String keys) { this.accountUuid = account; this.systemName = systemName; @@ -247,6 +250,12 @@ public class Contact { return ((this.subscription & (1 << option)) != 0); } + public boolean showInRoster() { + return (this.getOption(Contact.Options.IN_ROSTER) && (!this + .getOption(Contact.Options.DIRTY_DELETE))) + || (this.getOption(Contact.Options.DIRTY_PUSH)); + } + public void parseSubscriptionFromElement(Element item) { String ask = item.getAttribute("ask"); String subscription = item.getAttribute("subscription"); @@ -261,13 +270,19 @@ public class Contact { } else if (subscription.equals("both")) { this.setOption(Contact.Options.TO); this.setOption(Contact.Options.FROM); + } else if (subscription.equals("none")) { + this.resetOption(Contact.Options.FROM); + this.resetOption(Contact.Options.TO); } } - if ((ask != null) && (ask.equals("subscribe"))) { - this.setOption(Contact.Options.ASKING); - } else { - this.resetOption(Contact.Options.ASKING); + // do NOT override asking if pending push request + if (!this.getOption(Contact.Options.DIRTY_PUSH)) { + if ((ask != null) && (ask.equals("subscribe"))) { + this.setOption(Contact.Options.ASKING); + } else { + this.resetOption(Contact.Options.ASKING); + } } } @@ -284,8 +299,10 @@ public class Contact { 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 static final int IN_ROSTER = 8; - public static final int PENDING_SUBSCRIPTION_REQUEST = 16; + public static final int PREEMPTIVE_GRANT = 3; + public static final int IN_ROSTER = 4; + public static final int PENDING_SUBSCRIPTION_REQUEST = 5; + public static final int DIRTY_PUSH = 6; + public static final int DIRTY_DELETE = 7; } } diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java index e61537da..37a230df 100644 --- a/src/eu/siacs/conversations/entities/Conversation.java +++ b/src/eu/siacs/conversations/entities/Conversation.java @@ -10,11 +10,11 @@ import net.java.otr4j.crypto.OtrCryptoException; import net.java.otr4j.session.SessionID; import net.java.otr4j.session.SessionImpl; import net.java.otr4j.session.SessionStatus; - import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.net.Uri; +import android.util.Log; public class Conversation extends AbstractEntity { @@ -240,6 +240,7 @@ public class Conversation extends AbstractEntity { public void endOtrIfNeeded() { if (this.otrSession != null) { if (this.otrSession.getSessionStatus() == SessionStatus.ENCRYPTED) { + Log.d("xmppService","ending otr session with "+getContactJid()); try { this.otrSession.endSession(); this.resetOtrSession(); @@ -251,20 +252,7 @@ public class Conversation extends AbstractEntity { } public boolean hasValidOtrSession() { - if (this.otrSession == null) { - return false; - } else { - String foreignPresence = this.otrSession.getSessionID().getUserID(); - if (getContact()==null) { - return true; - } else { - if (!getContact().getPresences().containsKey(foreignPresence)) { - this.resetOtrSession(); - return false; - } - return true; - } - } + return this.otrSession != null; } public String getOtrFingerprint() { diff --git a/src/eu/siacs/conversations/entities/Roster.java b/src/eu/siacs/conversations/entities/Roster.java index 7c18d80a..1b4bc954 100644 --- a/src/eu/siacs/conversations/entities/Roster.java +++ b/src/eu/siacs/conversations/entities/Roster.java @@ -31,12 +31,23 @@ public class Roster { } public void clearPresences() { - // TODO Auto-generated method stub - + for(Contact contact : getContacts()) { + contact.clearPresences(); + } } public void markAllAsNotInRoster() { - + for(Contact contact : getContacts()) { + contact.resetOption(Contact.Options.IN_ROSTER); + } + } + + public void clearSystemAccounts() { + for(Contact contact : getContacts()) { + contact.setPhotoUri(null); + contact.setSystemName(null); + contact.setSystemAccount(null); + } } public List<Contact> getContacts() { diff --git a/src/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/eu/siacs/conversations/persistance/DatabaseBackend.java index 771027f2..26d09378 100644 --- a/src/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -32,7 +32,6 @@ public class DatabaseBackend extends SQLiteOpenHelper { public DatabaseBackend(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); - Log.d("xmppService",CREATE_CONTATCS_STATEMENT); } @Override diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java index 7bddc55f..9d64c45f 100644 --- a/src/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/eu/siacs/conversations/persistance/FileBackend.java @@ -135,7 +135,12 @@ public class FileBackend { throw new ImageCopyException( R.string.error_security_exception_during_image_copy); } catch (OutOfMemoryError e) { - return copyImageToPrivateStorage(message, image, sampleSize++); + ++sampleSize; + if (sampleSize<=3) { + return copyImageToPrivateStorage(message, image, sampleSize); + } else { + throw new ImageCopyException(R.string.error_out_of_memory); + } } } diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 5abd2770..e31d28e0 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -36,6 +36,7 @@ import eu.siacs.conversations.utils.PhoneHelper; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.OnBindListener; +import eu.siacs.conversations.xmpp.OnContactStatusChanged; import eu.siacs.conversations.xmpp.OnIqPacketReceived; import eu.siacs.conversations.xmpp.OnMessagePacketReceived; import eu.siacs.conversations.xmpp.OnPresencePacketReceived; @@ -61,7 +62,6 @@ 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; @@ -82,7 +82,7 @@ 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); @@ -96,6 +96,16 @@ public class XmppConnectionService extends Service { private int convChangedListenerCount = 0; private OnAccountListChangedListener accountChangedListener = null; private OnTLSExceptionReceived tlsException = null; + private OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() { + + @Override + public void onContactStatusChanged(Contact contact) { + Conversation conversation = findActiveConversation(contact); + if (conversation!=null) { + conversation.endOtrIfNeeded(); + } + } + }; public void setOnTLSExceptionReceivedListener( OnTLSExceptionReceived listener) { @@ -110,7 +120,8 @@ public class XmppConnectionService extends Service { @Override public void onChange(boolean selfChange) { super.onChange(selfChange); - Intent intent = new Intent(getApplicationContext(), XmppConnectionService.class); + Intent intent = new Intent(getApplicationContext(), + XmppConnectionService.class); intent.setAction(ACTION_MERGE_PHONE_CONTACTS); startService(intent); } @@ -233,6 +244,7 @@ public class XmppConnectionService extends Service { sendUnsendMessages(conversations.get(i)); } } + syncDirtyContacts(account); scheduleWakeupCall(PING_MAX_INTERVAL, true); } else if (account.getStatus() == Account.STATUS_OFFLINE) { if (!account.isOptionSet(Account.OPTION_DISABLED)) { @@ -243,7 +255,8 @@ public class XmppConnectionService extends Service { } else if (account.getStatus() == Account.STATUS_REGISTRATION_SUCCESSFULL) { databaseBackend.updateAccount(account); reconnectAccount(account, true); - } else if (account.getStatus() != Account.STATUS_CONNECTING) { + } else if ((account.getStatus() != Account.STATUS_CONNECTING) + && (account.getStatus() != Account.STATUS_NO_INTERNET)) { int next = account.getXmppConnection().getTimeToNextAttempt(); Log.d(LOGTAG, account.getJid() + ": error connecting account. try again in " + next @@ -323,8 +336,7 @@ public class XmppConnectionService extends Service { msg, x.getContent())); } } - } else { - // Log.d(LOGTAG,"presence without resource "+packet.toString()); + onContactStatusChanged.onContactStatusChanged(contact); } } else if (type.equals("unavailable")) { if (fromParts.length != 2) { @@ -332,6 +344,7 @@ public class XmppConnectionService extends Service { } else { contact.removePresence(fromParts[1]); } + onContactStatusChanged.onContactStatusChanged(contact); } else if (type.equals("subscribe")) { Log.d(LOGTAG, "received subscribe packet from " + packet.getFrom()); @@ -488,9 +501,12 @@ public class XmppConnectionService extends Service { String name = item.getAttribute("name"); String subscription = item.getAttribute("subscription"); Contact contact = account.getRoster().getContact(jid); - contact.setServerName(name); + if (!contact.getOption(Contact.Options.DIRTY_PUSH)) { + contact.setServerName(name); + } if (subscription.equals("remove")) { contact.resetOption(Contact.Options.IN_ROSTER); + contact.resetOption(Contact.Options.DIRTY_DELETE); } else { contact.setOption(Contact.Options.IN_ROSTER); contact.parseSubscriptionFromElement(item); @@ -508,8 +524,14 @@ public class XmppConnectionService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { this.wakeLock.acquire(); - if ((intent!=null)&&(intent.getAction()!=null)&&(intent.getAction().equals(ACTION_MERGE_PHONE_CONTACTS))) { + if ((intent != null) + && (ACTION_MERGE_PHONE_CONTACTS.equals(intent.getAction()))) { mergePhoneContactsWithRoster(); + return START_STICKY; + } else if ((intent != null) + && (Intent.ACTION_SHUTDOWN.equals(intent.getAction()))) { + logoutAndSave(); + return START_NOT_STICKY; } ConnectivityManager cm = (ConnectivityManager) getApplicationContext() .getSystemService(Context.CONNECTIVITY_SERVICE); @@ -606,21 +628,27 @@ public class XmppConnectionService extends 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); + disconnect(account, false); } } - Log.d(LOGTAG,"good bye"); + Context context = getApplicationContext(); + AlarmManager alarmManager = (AlarmManager) context + .getSystemService(Context.ALARM_SERVICE); + Intent intent = new Intent(context, EventReceiver.class); + alarmManager.cancel(PendingIntent.getBroadcast(context, 0, intent, 0)); + Log.d(LOGTAG, "good bye"); + stopSelf(); } protected void scheduleWakeupCall(int seconds, boolean ping) { @@ -880,6 +908,9 @@ public class XmppConnectionService extends Service { new OnPhoneContactsLoadedListener() { @Override public void onPhoneContactsLoaded(List<Bundle> phoneContacts) { + for(Account account : accounts) { + account.getRoster().clearSystemAccounts(); + } for (Bundle phoneContact : phoneContacts) { for (Account account : accounts) { String jid = phoneContact.getString("jid"); @@ -927,6 +958,15 @@ public class XmppConnectionService extends Service { public List<Account> getAccounts() { return this.accounts; } + + public Conversation findActiveConversation(Contact contact) { + for (Conversation conversation : this.getConversations()) { + if (conversation.getContact() == contact) { + return conversation; + } + } + return null; + } public Conversation findOrCreateConversation(Account account, String jid, boolean muc) { @@ -1174,6 +1214,18 @@ public class XmppConnectionService extends Service { public void updateMessage(Message message) { databaseBackend.updateMessage(message); } + + protected void syncDirtyContacts(Account account) { + for(Contact contact : account.getRoster().getContacts()) { + if (contact.getOption(Contact.Options.DIRTY_PUSH)) { + pushContactToServer(contact); + } + if (contact.getOption(Contact.Options.DIRTY_DELETE)) { + Log.d(LOGTAG,"dirty delete"); + deleteContactOnServer(contact); + } + } + } public void createContact(Contact contact) { SharedPreferences sharedPref = getPreferences(); @@ -1183,29 +1235,41 @@ public class XmppConnectionService extends Service { contact.setOption(Contact.Options.ASKING); } pushContactToServer(contact); - if (autoGrant) { - requestPresenceUpdatesFrom(contact); + } + + public void pushContactToServer(Contact contact) { + contact.resetOption(Contact.Options.DIRTY_DELETE); + Account account = contact.getAccount(); + if (account.getStatus() == Account.STATUS_ONLINE) { + IqPacket iq = new IqPacket(IqPacket.TYPE_SET); + iq.query("jabber:iq:roster").addChild(contact.asElement()); + account.getXmppConnection().sendIqPacket(iq, null); + if (contact.getOption(Contact.Options.ASKING)) { + requestPresenceUpdatesFrom(contact); + } if (contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) { Log.d("xmppService", "contact had pending subscription"); sendPresenceUpdatesTo(contact); } + contact.resetOption(Contact.Options.DIRTY_PUSH); + } else { + contact.setOption(Contact.Options.DIRTY_PUSH); } } - - 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"); + contact.resetOption(Contact.Options.DIRTY_PUSH); Account account = contact.getAccount(); - account.getXmppConnection().sendIqPacket(iq, null); + if (account.getStatus() == Account.STATUS_ONLINE) { + 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.getXmppConnection().sendIqPacket(iq, null); + contact.resetOption(Contact.Options.DIRTY_DELETE); + } else { + contact.setOption(Contact.Options.DIRTY_DELETE); + } } public void requestPresenceUpdatesFrom(Contact contact) { @@ -1238,7 +1302,6 @@ public class XmppConnectionService extends Service { packet.setAttribute("to", contact.getJid()); packet.setAttribute("from", contact.getAccount().getJid()); contact.getAccount().getXmppConnection().sendPresencePacket(packet); - contact.resetOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST); } public void sendPresence(Account account) { @@ -1357,7 +1420,7 @@ public class XmppConnectionService extends Service { getConversations(), conversation, notify); } } - + public Account findAccountByJid(String accountJid) { for (Account account : this.accounts) { if (account.getJid().equals(accountJid)) { diff --git a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java index 72a0909a..83ae99d9 100644 --- a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -89,11 +89,10 @@ public class ContactDetailsActivity extends XmppActivity { @Override public void onClick(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setTitle("Add to phone book"); - builder.setMessage("Do you want to add " + contact.getJid() - + " to your phones contact list?"); - builder.setNegativeButton("Cancel", null); - builder.setPositiveButton("Add", addToPhonebook); + builder.setTitle(getString(R.string.action_add_phone_book)); + builder.setMessage(getString(R.string.add_phone_book_text, contact.getJid())); + builder.setNegativeButton(getString(R.string.cancel), null); + builder.setPositiveButton(getString(R.string.add), addToPhonebook); builder.create().show(); } }; @@ -125,17 +124,17 @@ public class ContactDetailsActivity extends XmppActivity { @Override public boolean onOptionsItemSelected(MenuItem menuItem) { AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setNegativeButton("Cancel", null); + builder.setNegativeButton(getString(R.string.cancel), null); switch (menuItem.getItemId()) { case android.R.id.home: finish(); break; case R.id.action_delete_contact: - builder.setTitle("Delete from roster") + builder.setTitle(getString(R.string.action_delete_contact)) .setMessage( getString(R.string.remove_contact_text, contact.getJid())) - .setPositiveButton("Delete", removeFromRoster).create() + .setPositiveButton(getString(R.string.delete), removeFromRoster).create() .show(); break; case R.id.action_edit_contact: @@ -146,7 +145,7 @@ public class ContactDetailsActivity extends XmppActivity { name = (EditText) view.findViewById(R.id.editText1); name.setText(contact.getDisplayName()); builder.setView(view).setTitle(contact.getJid()) - .setPositiveButton("Edit", editContactNameListener) + .setPositiveButton(getString(R.string.edit), editContactNameListener) .create().show(); } else { @@ -191,7 +190,8 @@ public class ContactDetailsActivity extends XmppActivity { @Override public void onClick(View v) { - Toast.makeText(getApplicationContext(), "Asked for presence updates",Toast.LENGTH_SHORT).show(); + Toast.makeText(getApplicationContext(), getString(R.string.asked_for_presence_updates), + Toast.LENGTH_SHORT).show(); xmppConnectionService.requestPresenceUpdatesFrom(contact); } @@ -205,31 +205,31 @@ public class ContactDetailsActivity extends XmppActivity { switch (contact.getMostAvailableStatus()) { case Presences.CHAT: - status.setText("free to chat"); + status.setText(R.string.contact_status_free_to_chat); status.setTextColor(0xFF83b600); break; case Presences.ONLINE: - status.setText("online"); + status.setText(R.string.contact_status_online); status.setTextColor(0xFF83b600); break; case Presences.AWAY: - status.setText("away"); + status.setText(R.string.contact_status_away); status.setTextColor(0xFFffa713); break; case Presences.XA: - status.setText("extended away"); + status.setText(R.string.contact_status_extended_away); status.setTextColor(0xFFffa713); break; case Presences.DND: - status.setText("do not disturb"); + status.setText(R.string.contact_status_do_not_disturb); status.setTextColor(0xFFe92727); break; case Presences.OFFLINE: - status.setText("offline"); + status.setText(R.string.contact_status_offline); status.setTextColor(0xFFe92727); break; default: - status.setText("offline"); + status.setText(R.string.contact_status_offline); status.setTextColor(0xFFe92727); break; } @@ -346,7 +346,7 @@ public class ContactDetailsActivity extends XmppActivity { } } if (updated) { - Toast.makeText(getApplicationContext(), "Subscription updated", Toast.LENGTH_SHORT).show(); + Toast.makeText(getApplicationContext(), getString(R.string.subscription_updated), Toast.LENGTH_SHORT).show(); } } diff --git a/src/eu/siacs/conversations/ui/ContactsActivity.java b/src/eu/siacs/conversations/ui/ContactsActivity.java index ca794b30..f4c8ef0b 100644 --- a/src/eu/siacs/conversations/ui/ContactsActivity.java +++ b/src/eu/siacs/conversations/ui/ContactsActivity.java @@ -186,7 +186,7 @@ public class ContactsActivity extends XmppActivity { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(getString(R.string.account_offline)); builder.setMessage(getString(R.string.cant_invite_while_offline)); - builder.setNegativeButton("OK", null); + builder.setNegativeButton(getString(R.string.ok), null); builder.setIconAttribute(android.R.attr.alertDialogIcon); builder.create().show(); return false; @@ -269,7 +269,7 @@ public class ContactsActivity extends XmppActivity { aggregatedContacts.clear(); for (Contact contact : rosterContacts) { - if (contact.match(searchString)&&(contact.getOption(Contact.Options.IN_ROSTER))) + if (contact.match(searchString)&&(contact.showInRoster())) aggregatedContacts.add(contact); } @@ -289,12 +289,12 @@ public class ContactsActivity extends XmppActivity { Contact newContact = new Contact(searchString); newContact.resetOption(Contact.Options.IN_ROSTER); aggregatedContacts.add(newContact); - contactsHeader.setText("Create new contact"); + contactsHeader.setText(getString(R.string.new_contact)); } else { - contactsHeader.setText("Contacts"); + contactsHeader.setText(getString(R.string.contacts)); } } else { - contactsHeader.setText("Contacts"); + contactsHeader.setText(getString(R.string.contacts)); } contactsAdapter.notifyDataSetChanged(); @@ -427,7 +427,7 @@ public class ContactsActivity extends XmppActivity { } AlertDialog.Builder accountChooser = new AlertDialog.Builder(this); - accountChooser.setTitle("Choose account"); + accountChooser.setTitle(getString(R.string.choose_account)); accountChooser.setItems(accountList, listener); return accountChooser.create(); } @@ -435,9 +435,9 @@ public class ContactsActivity extends XmppActivity { public void showIsMucDialogIfNeeded(final Contact clickedContact) { if (clickedContact.couldBeMuc()) { AlertDialog.Builder dialog = new AlertDialog.Builder(this); - dialog.setTitle("Multi User Conference"); - dialog.setMessage("Are you trying to join a conference?"); - dialog.setPositiveButton("Yes", new OnClickListener() { + dialog.setTitle(getString(R.string.multi_user_conference)); + dialog.setMessage(getString(R.string.trying_join_conference)); + dialog.setPositiveButton(getString(R.string.yes), new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { @@ -445,7 +445,7 @@ public class ContactsActivity extends XmppActivity { clickedContact.getAccount(), true); } }); - dialog.setNegativeButton("No", new OnClickListener() { + dialog.setNegativeButton(getString(R.string.no), new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java index bf83990a..bd98e979 100644 --- a/src/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/eu/siacs/conversations/ui/ConversationActivity.java @@ -474,7 +474,7 @@ public class ConversationActivity extends XmppActivity { break; case R.id.action_contact_details: Contact contact = this.getSelectedConversation().getContact(); - if (contact.getOption(Contact.Options.IN_ROSTER)) { + if (contact.showInRoster()) { Intent intent = new Intent(this, ContactDetailsActivity.class); intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT); intent.putExtra("account", this.getSelectedConversation().getAccount().getJid()); diff --git a/src/eu/siacs/conversations/ui/EditAccount.java b/src/eu/siacs/conversations/ui/EditAccount.java index 47930747..d1863f7e 100644 --- a/src/eu/siacs/conversations/ui/EditAccount.java +++ b/src/eu/siacs/conversations/ui/EditAccount.java @@ -82,8 +82,8 @@ public class EditAccount extends DialogFragment { }); builder.setView(view); - builder.setNeutralButton(R.string.cancel, null); - builder.setPositiveButton(R.string.save, null); + builder.setNeutralButton(getString(R.string.cancel), null); + builder.setPositiveButton(getString(R.string.save), null); return builder.create(); } diff --git a/src/eu/siacs/conversations/ui/OnRosterFetchedListener.java b/src/eu/siacs/conversations/ui/OnRosterFetchedListener.java deleted file mode 100644 index d69ce35b..00000000 --- a/src/eu/siacs/conversations/ui/OnRosterFetchedListener.java +++ /dev/null @@ -1,9 +0,0 @@ -package eu.siacs.conversations.ui; - -import java.util.List; - -import eu.siacs.conversations.entities.Contact; - -public interface OnRosterFetchedListener { - public void onRosterFetched(List<Contact> roster); -} diff --git a/src/eu/siacs/conversations/ui/ShareWithActivity.java b/src/eu/siacs/conversations/ui/ShareWithActivity.java index e2188c48..6dbb20c9 100644 --- a/src/eu/siacs/conversations/ui/ShareWithActivity.java +++ b/src/eu/siacs/conversations/ui/ShareWithActivity.java @@ -91,7 +91,7 @@ public class ShareWithActivity extends XmppActivity { List<Contact> contactsList = new ArrayList<Contact>(); for(Account account : xmppConnectionService.getAccounts()) { for(Contact contact : account.getRoster().getContacts()) { - if (!displayedContacts.contains(contact)&&(contact.getOption(Contact.Options.IN_ROSTER))) { + if (!displayedContacts.contains(contact)&&(contact.showInRoster())) { contactsList.add(contact); } } diff --git a/src/eu/siacs/conversations/xmpp/OnContactStatusChanged.java b/src/eu/siacs/conversations/xmpp/OnContactStatusChanged.java new file mode 100644 index 00000000..8597a753 --- /dev/null +++ b/src/eu/siacs/conversations/xmpp/OnContactStatusChanged.java @@ -0,0 +1,7 @@ +package eu.siacs.conversations.xmpp; + +import eu.siacs.conversations.entities.Contact; + +public interface OnContactStatusChanged { + public void onContactStatusChanged(Contact contact); +} diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 0ba9677a..a1aaf66a 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -77,15 +77,15 @@ public class XmppConnection implements Runnable { private String streamId = null; private int smVersion = 3; - + private int stanzasReceived = 0; private int stanzasSent = 0; - + public long lastPaketReceived = 0; public long lastPingSent = 0; public long lastConnect = 0; public long lastSessionStarted = 0; - + private int attempt = 0; private static final int PACKET_IQ = 0; @@ -103,13 +103,17 @@ public class XmppConnection implements Runnable { public XmppConnection(Account account, PowerManager pm) { this.account = account; - this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,account.getJid()); + this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + account.getJid()); tagWriter = new TagWriter(); } protected void changeStatus(int nextStatus) { if (account.getStatus() != nextStatus) { - if ((nextStatus == Account.STATUS_OFFLINE)&&(account.getStatus() != Account.STATUS_CONNECTING)&&(account.getStatus() != Account.STATUS_ONLINE)&&(account.getStatus() != Account.STATUS_DISABLED)) { + 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) { @@ -123,18 +127,19 @@ public class XmppConnection implements Runnable { } protected void connect() { - Log.d(LOGTAG,account.getJid()+ ": connecting"); + Log.d(LOGTAG, account.getJid() + ": connecting"); lastConnect = SystemClock.elapsedRealtime(); this.attempt++; try { - shouldAuthenticate = shouldBind = !account.isOptionSet(Account.OPTION_REGISTER); + shouldAuthenticate = shouldBind = !account + .isOptionSet(Account.OPTION_REGISTER); tagReader = new XmlReader(wakeLock); tagWriter = new TagWriter(); packetCallbacks.clear(); this.changeStatus(Account.STATUS_CONNECTING); Bundle namePort = DNSHelper.getSRVRecord(account.getServer()); if ("timeout".equals(namePort.getString("error"))) { - Log.d(LOGTAG,account.getJid()+": dns timeout"); + Log.d(LOGTAG, account.getJid() + ": dns timeout"); this.changeStatus(Account.STATUS_OFFLINE); return; } @@ -144,12 +149,12 @@ public class XmppConnection implements Runnable { if (srvRecordServer != null) { if (srvIpServer != null) { Log.d(LOGTAG, account.getJid() + ": using values from dns " - + srvRecordServer + "[" + srvIpServer + "]:" - + srvRecordPort); + + srvRecordServer + "[" + srvIpServer + "]:" + + srvRecordPort); socket = new Socket(srvIpServer, srvRecordPort); } else { Log.d(LOGTAG, account.getJid() + ": using values from dns " - + srvRecordServer + ":" + srvRecordPort); + + srvRecordServer + ":" + srvRecordPort); socket = new Socket(srvRecordServer, srvRecordPort); } } else { @@ -229,8 +234,7 @@ public class XmppConnection implements Runnable { } else if (nextTag.isStart("compressed")) { switchOverToZLib(nextTag); } else if (nextTag.isStart("success")) { - Log.d(LOGTAG, account.getJid() - + ": logged in"); + Log.d(LOGTAG, account.getJid() + ": logged in"); tagReader.readTag(); tagReader.reset(); sendStartStream(); @@ -242,17 +246,21 @@ public class XmppConnection implements Runnable { } else if (nextTag.isStart("challenge")) { String challange = tagReader.readElement(nextTag).getContent(); Element response = new Element("response"); - response.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl"); - response.setContent(CryptoHelper.saslDigestMd5(account, challange)); + response.setAttribute("xmlns", + "urn:ietf:params:xml:ns:xmpp-sasl"); + response.setContent(CryptoHelper.saslDigestMd5(account, + challange)); tagWriter.writeElement(response); } else if (nextTag.isStart("enabled")) { this.stanzasSent = 0; Element enabled = tagReader.readElement(nextTag); if ("true".equals(enabled.getAttribute("resume"))) { this.streamId = enabled.getAttribute("id"); - Log.d(LOGTAG,account.getJid()+": stream managment("+smVersion+") enabled (resumable)"); + Log.d(LOGTAG, account.getJid() + ": stream managment(" + + smVersion + ") enabled (resumable)"); } else { - Log.d(LOGTAG,account.getJid()+": stream managment("+smVersion+") enabled"); + Log.d(LOGTAG, account.getJid() + ": stream managment(" + + smVersion + ") enabled"); } this.lastSessionStarted = SystemClock.elapsedRealtime(); this.stanzasReceived = 0; @@ -260,26 +268,26 @@ public class XmppConnection implements Runnable { tagWriter.writeStanzaAsync(r); } else if (nextTag.isStart("resumed")) { lastPaketReceived = SystemClock.elapsedRealtime(); - Log.d(LOGTAG,account.getJid()+": session resumed"); + Log.d(LOGTAG, account.getJid() + ": session resumed"); tagReader.readElement(nextTag); sendPing(); changeStatus(Account.STATUS_ONLINE); } else if (nextTag.isStart("r")) { tagReader.readElement(nextTag); - AckPacket ack = new AckPacket(this.stanzasReceived,smVersion); - //Log.d(LOGTAG,ack.toString()); + AckPacket ack = new AckPacket(this.stanzasReceived, smVersion); + // Log.d(LOGTAG,ack.toString()); tagWriter.writeStanzaAsync(ack); } else if (nextTag.isStart("a")) { Element ack = tagReader.readElement(nextTag); lastPaketReceived = SystemClock.elapsedRealtime(); int serverSequence = Integer.parseInt(ack.getAttribute("h")); - if (serverSequence>this.stanzasSent) { + if (serverSequence > this.stanzasSent) { this.stanzasSent = serverSequence; } - //Log.d(LOGTAG,"server ack"+ack.toString()+" ("+this.stanzasSent+")"); + // Log.d(LOGTAG,"server ack"+ack.toString()+" ("+this.stanzasSent+")"); } else if (nextTag.isStart("failed")) { tagReader.readElement(nextTag); - Log.d(LOGTAG,account.getJid()+": resumption failed"); + Log.d(LOGTAG, account.getJid() + ": resumption failed"); streamId = null; if (account.getStatus() != Account.STATUS_ONLINE) { sendBindRequest(); @@ -322,16 +330,23 @@ public class XmppConnection implements Runnable { } element.setAttributes(currentTag.getAttributes()); Tag nextTag = tagReader.readTag(); + if (nextTag==null) { + throw new IOException("interrupted mid tag"); + } while (!nextTag.isEnd(element.getName())) { if (!nextTag.isNo()) { Element child = tagReader.readElement(nextTag); - if ((packetType == PACKET_IQ)&&("jingle".equals(child.getName()))) { + if ((packetType == PACKET_IQ) + && ("jingle".equals(child.getName()))) { element = new JinglePacket(); element.setAttributes(currentTag.getAttributes()); } element.addChild(child); } nextTag = tagReader.readTag(); + if (nextTag==null) { + throw new IOException("interrupted mid tag"); + } } ++stanzasReceived; lastPaketReceived = SystemClock.elapsedRealtime(); @@ -341,14 +356,15 @@ public class XmppConnection implements Runnable { private void processIq(Tag currentTag) throws XmlPullParserException, IOException { IqPacket packet = (IqPacket) processPacket(currentTag, PACKET_IQ); - + if (packet.getId() == null) { - return; //an iq packet without id is definitely invalid + return; // an iq packet without id is definitely invalid } - + if (packet instanceof JinglePacket) { - if (this.jingleListener !=null) { - this.jingleListener.onJinglePacketReceived(account, (JinglePacket) packet); + if (this.jingleListener != null) { + this.jingleListener.onJinglePacketReceived(account, + (JinglePacket) packet); } } else { if (packetCallbacks.containsKey(packet.getId())) { @@ -356,7 +372,7 @@ public class XmppConnection implements Runnable { ((OnIqPacketReceived) packetCallbacks.get(packet.getId())) .onIqPacketReceived(account, packet); } - + packetCallbacks.remove(packet.getId()); } else if (this.unregisteredIqListener != null) { this.unregisteredIqListener.onIqPacketReceived(account, packet); @@ -403,15 +419,18 @@ public class XmppConnection implements Runnable { tagWriter.writeElement(compress); } - private void switchOverToZLib(Tag currentTag) throws XmlPullParserException, - IOException, NoSuchAlgorithmException { + private void switchOverToZLib(Tag currentTag) + throws XmlPullParserException, IOException, + NoSuchAlgorithmException { tagReader.readTag(); // read tag close - tagWriter.setOutputStream(new ZLibOutputStream(tagWriter.getOutputStream())); - tagReader.setInputStream(new ZLibInputStream(tagReader.getInputStream())); + tagWriter.setOutputStream(new ZLibOutputStream(tagWriter + .getOutputStream())); + tagReader + .setInputStream(new ZLibInputStream(tagReader.getInputStream())); sendStartStream(); - Log.d(LOGTAG,account.getJid()+": compression enabled"); + Log.d(LOGTAG, account.getJid() + ": compression enabled"); processStream(tagReader.readTag()); } @@ -457,13 +476,15 @@ public class XmppConnection implements Runnable { if (e.getCause() instanceof CertPathValidatorException) { String sha; try { - MessageDigest sha1 = MessageDigest.getInstance("SHA1"); + MessageDigest sha1 = MessageDigest + .getInstance("SHA1"); sha1.update(chain[0].getEncoded()); sha = CryptoHelper.bytesToHex(sha1.digest()); if (!sha.equals(account.getSSLFingerprint())) { changeStatus(Account.STATUS_TLS_ERROR); - if (tlsListener!=null) { - tlsListener.onTLSExceptionReceived(sha,account); + if (tlsListener != null) { + tlsListener.onTLSExceptionReceived(sha, + account); } throw new CertificateException(); } @@ -486,12 +507,12 @@ public class XmppConnection implements Runnable { sc.init(null, wrappedTrustManagers, null); SSLSocketFactory factory = sc.getSocketFactory(); SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket, - socket.getInetAddress().getHostAddress(), socket.getPort(), - true); + socket.getInetAddress().getHostAddress(), socket.getPort(), + true); tagReader.setInputStream(sslSocket.getInputStream()); tagWriter.setOutputStream(sslSocket.getOutputStream()); sendStartStream(); - Log.d(LOGTAG,account.getJid()+": TLS connection established"); + Log.d(LOGTAG, account.getJid() + ": TLS connection established"); processStream(tagReader.readTag()); sslSocket.close(); } catch (NoSuchAlgorithmException e1) { @@ -512,7 +533,7 @@ public class XmppConnection implements Runnable { auth.setContent(saslString); tagWriter.writeElement(auth); } - + private void sendSaslAuthDigestMd5() throws IOException { Element auth = new Element("auth"); auth.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl"); @@ -528,21 +549,27 @@ public class XmppConnection implements Runnable { sendStartTLS(); } else if (compressionAvailable()) { sendCompressionZlib(); - } else if (this.streamFeatures.hasChild("register")&&(account.isOptionSet(Account.OPTION_REGISTER))) { - sendRegistryRequest(); - } else if (!this.streamFeatures.hasChild("register")&&(account.isOptionSet(Account.OPTION_REGISTER))) { + } else if (this.streamFeatures.hasChild("register") + && (account.isOptionSet(Account.OPTION_REGISTER))) { + sendRegistryRequest(); + } else if (!this.streamFeatures.hasChild("register") + && (account.isOptionSet(Account.OPTION_REGISTER))) { changeStatus(Account.STATUS_REGISTRATION_NOT_SUPPORTED); disconnect(true); } else if (this.streamFeatures.hasChild("mechanisms") && shouldAuthenticate) { - List<String> mechanisms = extractMechanisms( streamFeatures.findChild("mechanisms")); + List<String> mechanisms = extractMechanisms(streamFeatures + .findChild("mechanisms")); if (mechanisms.contains("PLAIN")) { sendSaslAuthPlain(); } else if (mechanisms.contains("DIGEST-MD5")) { sendSaslAuthDigestMd5(); } - } else if (this.streamFeatures.hasChild("sm","urn:xmpp:sm:"+smVersion) && streamId != null) { - ResumePacket resume = new ResumePacket(this.streamId,stanzasReceived,smVersion); + } else if (this.streamFeatures.hasChild("sm", "urn:xmpp:sm:" + + smVersion) + && streamId != null) { + ResumePacket resume = new ResumePacket(this.streamId, + stanzasReceived, smVersion); this.tagWriter.writeStanzaAsync(resume); } else if (this.streamFeatures.hasChild("bind") && shouldBind) { sendBindRequest(); @@ -550,13 +577,19 @@ public class XmppConnection implements Runnable { } private boolean compressionAvailable() { - if (!this.streamFeatures.hasChild("compression", "http://jabber.org/features/compress")) return false; - if (!ZLibOutputStream.SUPPORTED) return false; - if (!account.isOptionSet(Account.OPTION_USECOMPRESSION)) return false; + if (!this.streamFeatures.hasChild("compression", + "http://jabber.org/features/compress")) + return false; + if (!ZLibOutputStream.SUPPORTED) + return false; + if (!account.isOptionSet(Account.OPTION_USECOMPRESSION)) + return false; - Element compression = this.streamFeatures.findChild("compression", "http://jabber.org/features/compress"); + Element compression = this.streamFeatures.findChild("compression", + "http://jabber.org/features/compress"); for (Element child : compression.getChildren()) { - if (!"method".equals(child.getName())) continue; + if (!"method".equals(child.getName())) + continue; if ("zlib".equalsIgnoreCase(child.getContent())) { return true; @@ -566,8 +599,9 @@ public class XmppConnection implements Runnable { } private List<String> extractMechanisms(Element stream) { - ArrayList<String> mechanisms = new ArrayList<String>(stream.getChildren().size()); - for(Element child : stream.getChildren()) { + ArrayList<String> mechanisms = new ArrayList<String>(stream + .getChildren().size()); + for (Element child : stream.getChildren()) { mechanisms.add(child.getContent()); } return mechanisms; @@ -578,28 +612,35 @@ public class XmppConnection implements Runnable { register.query("jabber:iq:register"); register.setTo(account.getServer()); sendIqPacket(register, new OnIqPacketReceived() { - + @Override public void onIqPacketReceived(Account account, IqPacket packet) { Element instructions = packet.query().findChild("instructions"); - if (packet.query().hasChild("username")&&(packet.query().hasChild("password"))) { + if (packet.query().hasChild("username") + && (packet.query().hasChild("password"))) { IqPacket register = new IqPacket(IqPacket.TYPE_SET); - Element username = new Element("username").setContent(account.getUsername()); - Element password = new Element("password").setContent(account.getPassword()); + Element username = new Element("username") + .setContent(account.getUsername()); + Element password = new Element("password") + .setContent(account.getPassword()); register.query("jabber:iq:register").addChild(username); register.query().addChild(password); sendIqPacket(register, new OnIqPacketReceived() { - + @Override - public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType()==IqPacket.TYPE_RESULT) { - account.setOption(Account.OPTION_REGISTER, false); + public void onIqPacketReceived(Account account, + IqPacket packet) { + if (packet.getType() == IqPacket.TYPE_RESULT) { + account.setOption(Account.OPTION_REGISTER, + false); changeStatus(Account.STATUS_REGISTRATION_SUCCESSFULL); - } else if (packet.hasChild("error")&&(packet.findChild("error").hasChild("conflict"))){ + } else if (packet.hasChild("error") + && (packet.findChild("error") + .hasChild("conflict"))) { changeStatus(Account.STATUS_REGISTRATION_CONFLICT); } else { changeStatus(Account.STATUS_REGISTRATION_FAILED); - Log.d(LOGTAG,packet.toString()); + Log.d(LOGTAG, packet.toString()); } disconnect(true); } @@ -607,7 +648,9 @@ public class XmppConnection implements Runnable { } else { changeStatus(Account.STATUS_REGISTRATION_FAILED); disconnect(true); - Log.d(LOGTAG,account.getJid()+": could not register. instructions are"+instructions.getContent()); + Log.d(LOGTAG, account.getJid() + + ": could not register. instructions are" + + instructions.getContent()); } } }); @@ -615,35 +658,37 @@ public class XmppConnection implements Runnable { 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()); + iq.addChild("bind", "urn:ietf:params:xml:ns:xmpp-bind") + .addChild("resource").setContent(account.getResource()); this.sendUnboundIqPacket(iq, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { String resource = packet.findChild("bind").findChild("jid") .getContent().split("/")[1]; account.setResource(resource); - if (streamFeatures.hasChild("sm","urn:xmpp:sm:3")) { + if (streamFeatures.hasChild("sm", "urn:xmpp:sm:3")) { smVersion = 3; EnablePacket enable = new EnablePacket(smVersion); tagWriter.writeStanzaAsync(enable); - } else if (streamFeatures.hasChild("sm","urn:xmpp:sm:2")) { + } else if (streamFeatures.hasChild("sm", "urn:xmpp:sm:2")) { smVersion = 2; EnablePacket enable = new EnablePacket(smVersion); tagWriter.writeStanzaAsync(enable); } sendServiceDiscoveryInfo(account.getServer()); sendServiceDiscoveryItems(account.getServer()); - if (bindListener !=null) { + if (bindListener != null) { bindListener.onBind(account); } - + changeStatus(Account.STATUS_ONLINE); } }); if (this.streamFeatures.hasChild("session")) { - Log.d(LOGTAG,account.getJid()+": sending deprecated 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"); + startSession.addChild("session", + "urn:ietf:params:xml:ns:xmpp-session"); this.sendUnboundIqPacket(startSession, null); } } @@ -660,25 +705,24 @@ public class XmppConnection implements Runnable { List<String> features = new ArrayList<String>(); for (int i = 0; i < elements.size(); ++i) { if (elements.get(i).getName().equals("feature")) { - features.add(elements.get(i).getAttribute( - "var")); + features.add(elements.get(i).getAttribute("var")); } } disco.put(server, features); - + if (account.getServer().equals(server)) { enableAdvancedStreamFeatures(); } } }); } - + private void enableAdvancedStreamFeatures() { if (hasFeaturesCarbon()) { sendEnableCarbons(); } } - + private void sendServiceDiscoveryItems(final String server) { IqPacket iq = new IqPacket(IqPacket.TYPE_GET); iq.setTo(server); @@ -690,8 +734,7 @@ public class XmppConnection implements Runnable { List<Element> elements = packet.query().getChildren(); for (int i = 0; i < elements.size(); ++i) { if (elements.get(i).getName().equals("item")) { - String jid = elements.get(i).getAttribute( - "jid"); + String jid = elements.get(i).getAttribute("jid"); sendServiceDiscoveryInfo(jid); } } @@ -701,7 +744,7 @@ public class XmppConnection implements Runnable { private void sendEnableCarbons() { IqPacket iq = new IqPacket(IqPacket.TYPE_SET); - iq.addChild("enable","urn:xmpp:carbons:2"); + iq.addChild("enable", "urn:xmpp:carbons:2"); this.sendIqPacket(iq, new OnIqPacketReceived() { @Override @@ -737,16 +780,16 @@ public class XmppConnection implements Runnable { } public void sendIqPacket(IqPacket packet, OnIqPacketReceived callback) { - if (packet.getId()==null) { + if (packet.getId() == null) { String id = nextRandomId(); packet.setAttribute("id", id); } packet.setFrom(account.getFullJid()); this.sendPacket(packet, callback); } - + public void sendUnboundIqPacket(IqPacket packet, OnIqPacketReceived callback) { - if (packet.getId()==null) { + if (packet.getId() == null) { String id = nextRandomId(); packet.setAttribute("id", id); } @@ -770,26 +813,27 @@ public class XmppConnection implements Runnable { OnPresencePacketReceived callback) { this.sendPacket(packet, callback); } - - private synchronized void sendPacket(final AbstractStanza packet, PacketReceived callback) { + + private synchronized void sendPacket(final AbstractStanza packet, + PacketReceived callback) { // TODO dont increment stanza count if packet = request packet or ack; ++stanzasSent; tagWriter.writeStanzaAsync(packet); if (callback != null) { - if (packet.getId()==null) { + if (packet.getId() == null) { packet.setId(nextRandomId()); } packetCallbacks.put(packet.getId(), callback); } } - + public void sendPing() { if (streamFeatures.hasChild("sm")) { tagWriter.writeStanzaAsync(new RequestPacket(smVersion)); } else { IqPacket iq = new IqPacket(IqPacket.TYPE_GET); iq.setFrom(account.getFullJid()); - iq.addChild("ping","urn:xmpp:ping"); + iq.addChild("ping", "urn:xmpp:ping"); this.sendIqPacket(iq, null); } } @@ -808,82 +852,95 @@ public class XmppConnection implements Runnable { OnPresencePacketReceived listener) { this.presenceListener = listener; } - - public void setOnJinglePacketReceivedListener(OnJinglePacketReceived listener) { + + public void setOnJinglePacketReceivedListener( + OnJinglePacketReceived listener) { this.jingleListener = listener; } public void setOnStatusChangedListener(OnStatusChanged listener) { this.statusListener = listener; } - - public void setOnTLSExceptionReceivedListener(OnTLSExceptionReceived listener) { + + public void setOnTLSExceptionReceivedListener( + OnTLSExceptionReceived listener) { this.tlsListener = listener; } - + public void setOnBindListener(OnBindListener listener) { this.bindListener = listener; } public void disconnect(boolean force) { changeStatus(Account.STATUS_OFFLINE); - Log.d(LOGTAG,"disconnecting"); + Log.d(LOGTAG, "disconnecting"); try { - if (force) { + if (force) { socket.close(); return; - } - if (tagWriter.isActive()) { - tagWriter.finish(); - while(!tagWriter.finished()) { - //Log.d(LOGTAG,"not yet finished"); - Thread.sleep(100); } - tagWriter.writeTag(Tag.end("stream:stream")); - } + new Thread(new Runnable() { + + @Override + public void run() { + if (tagWriter.isActive()) { + tagWriter.finish(); + try { + while (!tagWriter.finished()) { + Log.d(LOGTAG, "not yet finished"); + Thread.sleep(100); + } + tagWriter.writeTag(Tag.end("stream:stream")); + } catch (IOException e) { + Log.d(LOGTAG, "io exception during disconnect"); + } catch (InterruptedException e) { + Log.d(LOGTAG, "interrupted"); + } + } + } + }); } catch (IOException e) { - Log.d(LOGTAG,"io exception during disconnect"); - } catch (InterruptedException e) { - Log.d(LOGTAG,"interupted while waiting for disconnect"); + Log.d(LOGTAG, "io exception during disconnect"); } } - + public boolean hasFeatureRosterManagment() { - if (this.streamFeatures==null) { + if (this.streamFeatures == null) { return false; } else { return this.streamFeatures.hasChild("ver"); } } - + public boolean hasFeatureStreamManagment() { - if (this.streamFeatures==null) { + if (this.streamFeatures == null) { return false; } else { return this.streamFeatures.hasChild("sm"); } } - + public boolean hasFeaturesCarbon() { return hasDiscoFeature(account.getServer(), "urn:xmpp:carbons:2"); } - + public boolean hasDiscoFeature(String server, String feature) { if (!disco.containsKey(server)) { return false; } return disco.get(server).contains(feature); } - + public String findDiscoItemByFeature(String feature) { - Iterator<Entry<String, List<String>>> it = this.disco.entrySet().iterator(); - while (it.hasNext()) { - Entry<String, List<String>> pairs = it.next(); - if (pairs.getValue().contains(feature)) { - return pairs.getKey(); - } - it.remove(); - } + Iterator<Entry<String, List<String>>> it = this.disco.entrySet() + .iterator(); + while (it.hasNext()) { + Entry<String, List<String>> pairs = it.next(); + if (pairs.getValue().contains(feature)) { + return pairs.getKey(); + } + it.remove(); + } return null; } @@ -894,7 +951,7 @@ public class XmppConnection implements Runnable { public int getReceivedStanzas() { return this.stanzasReceived; } - + public int getSentStanzas() { return this.stanzasSent; } @@ -902,13 +959,13 @@ public class XmppConnection implements Runnable { public String getMucServer() { return findDiscoItemByFeature("http://jabber.org/protocol/muc"); } - + public int getTimeToNextAttempt() { - int interval = (int) (25 * Math.pow(1.5,attempt)); + int interval = (int) (25 * Math.pow(1.5, attempt)); int secondsSinceLast = (int) ((SystemClock.elapsedRealtime() - this.lastConnect) / 1000); return interval - secondsSinceLast; } - + public int getAttempt() { return this.attempt; } |