aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml13
-rw-r--r--README.md2
-rw-r--r--res/values-es/strings.xml34
-rw-r--r--res/values-gl/arrays.xml22
-rw-r--r--res/values-gl/strings.xml173
-rw-r--r--res/values/strings.xml29
-rw-r--r--src/eu/siacs/conversations/entities/Contact.java35
-rw-r--r--src/eu/siacs/conversations/entities/Conversation.java18
-rw-r--r--src/eu/siacs/conversations/entities/Roster.java17
-rw-r--r--src/eu/siacs/conversations/persistance/DatabaseBackend.java1
-rw-r--r--src/eu/siacs/conversations/persistance/FileBackend.java7
-rw-r--r--src/eu/siacs/conversations/services/XmppConnectionService.java121
-rw-r--r--src/eu/siacs/conversations/ui/ContactDetailsActivity.java36
-rw-r--r--src/eu/siacs/conversations/ui/ContactsActivity.java20
-rw-r--r--src/eu/siacs/conversations/ui/ConversationActivity.java2
-rw-r--r--src/eu/siacs/conversations/ui/EditAccount.java4
-rw-r--r--src/eu/siacs/conversations/ui/OnRosterFetchedListener.java9
-rw-r--r--src/eu/siacs/conversations/ui/ShareWithActivity.java2
-rw-r--r--src/eu/siacs/conversations/xmpp/OnContactStatusChanged.java7
-rw-r--r--src/eu/siacs/conversations/xmpp/XmppConnection.java309
20 files changed, 625 insertions, 236 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 32e83085..62ea4035 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -32,13 +32,14 @@
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
+ <action android:name="android.intent.action.ACTION_SHUTDOWN" />
</intent-filter>
</receiver>
<activity
android:name="eu.siacs.conversations.ui.ConversationActivity"
android:configChanges="orientation|screenSize"
- android:label="Conversations"
+ android:label="@string/title_activity_conversations"
android:windowSoftInputMode="stateHidden" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -48,23 +49,23 @@
</activity>
<activity
android:name="eu.siacs.conversations.ui.SettingsActivity"
- android:label="Settings"
+ android:label="@string/title_activity_settings"
android:parentActivityName="eu.siacs.conversations.ui.ConversationActivity" >
</activity>
<activity
android:name="eu.siacs.conversations.ui.ManageAccountActivity"
- android:label="Manage Accounts"
+ android:label="@string/title_activity_manage_accounts"
android:configChanges="orientation|screenSize"
android:parentActivityName="eu.siacs.conversations.ui.ConversationActivity" >
</activity>
<activity
android:name="eu.siacs.conversations.ui.MucDetailsActivity"
- android:label="Conference Details"
+ android:label="@string/title_activity_conference_details"
android:windowSoftInputMode="stateHidden" >
</activity>
<activity
android:name="eu.siacs.conversations.ui.ContactDetailsActivity"
- android:label="Contact Details"
+ android:label="@string/title_activity_contact_details"
android:windowSoftInputMode="stateHidden" >
</activity>
<activity
@@ -84,7 +85,7 @@
</activity>
<activity
android:name="eu.siacs.conversations.ui.ShareWithActivity"
- android:label="Conversations"
+ android:label="@string/title_activity_conversations"
android:theme="@android:style/Theme.Holo.Light.DialogWhenLarge"
android:icon="@drawable/ic_launcher">
<intent-filter>
diff --git a/README.md b/README.md
index 93885688..ca423c00 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@ These XEPs are - as of now:
* [Sergio Cárdenas](https://github.com/kruks23) (Spanish)
* [Benoit Bouvarel](https://github.com/BenoitBouvarel) (French)
* [Daniel Gultsch](https://github.com/iNPUTmice) (German)
-
+* [Aitor Beriain](https://github.com/beriain) (Basque)
##FAQ
###General
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index c4330d5d..f0f05a67 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -13,7 +13,13 @@
<string name="action_add_account">Añadir cuenta</string>
<string name="action_edit_contact">Editar contacto</string>
<string name="action_delete_contact">Eliminar contacto de la lista</string>
+ <string name="action_add_phone_book">Añadir a contactos del teléfono</string>
<string name="title_activity_contacts">Contactos</string>
+ <string name="title_activity_manage_accounts">Gestionar Cuentas</string>
+ <string name="title_activity_settings">Ajustes</string>
+ <string name="title_activity_conference_details">Detalles de Conferencia</string>
+ <string name="title_activity_contact_details">Detalles de Contacto</string>
+ <string name="title_activity_conversations">Conversations</string>
<string name="just_now">ahora</string>
<string name="minutes_ago">min</string>
<string name="unread_conversations">conversaciones por leer</string>
@@ -26,7 +32,7 @@
<string name="participant">Participante</string>
<string name="visitor">Visitante</string>
<string name="enter_new_name">Introduce un nuevo nombre:</string>
- <string name="remove_contact_text">¿Quieres eliminar a %s de tu lista?. La conversación asociada a esta cuenta no se eliminará.</string>
+ <string name="remove_contact_text">¿Quieres eliminar a %s de tu lista? La conversación asociada a esta cuenta no se eliminará.</string>
<string name="untrusted_cert_hint">El servidor %s presenta un certificado no confiable, posiblemente auto firmado.</string>
<string name="account_info">Información del servidor</string>
<string name="register_account">Registrar nueva cuenta en servidor</string>
@@ -38,7 +44,19 @@
<string name="invite_contacts">Invitar contactos</string>
<string name="invite_contacts_to_existing">Invitar a conferencia existente</string>
<string name="new_conference">Crear nueva conferencia</string>
+ <string name="new_contact">Crear nuevo contacto</string>
+ <string name="contacts">Contactos</string>
+ <string name="choose_account">Seleccionar cuenta</string>
+ <string name="multi_user_conference">Conferencia multiusuario</string>
+ <string name="trying_join_conference">¿Estás intentando unirte a una conferencia?</string>
<string name="cancel">Cancelar</string>
+ <string name="add">Añadir</string>
+ <string name="edit">Editar</string>
+ <string name="delete">Eliminar</string>
+ <string name="save">Guardar</string>
+ <string name="yes">Sí</string>
+ <string name="no">No</string>
+ <string name="ok">Ok</string>
<string name="create_invite">Crear \u0026 Invitar</string>
<string name="new_conference_explained">¿Quieres crear una nueva conferencia con una dirección generada aleatoriamente e invitar a los contactos seleccionados a ella?</string>
<string name="no_open_mucs">No hay conferencias existentes</string>
@@ -126,16 +144,18 @@
<string name="accept">Aceptar</string>
<string name="error">Ha ocurrido un error</string>
<string name="pref_grant_presence_updates">Suscripción de presencia</string>
- <string name="pref_grant_presence_updates_summary">Por defecto otorgar y pedir suscripciones de presencia de los contactos que has creado</string>
+ <string name="pref_grant_presence_updates_summary">Por defecto solicitar y conceder suscripciones de presencia de los contactos que has creado</string>
<string name="subscriptions">Suscripciones</string>
+ <string name="subscription_updated">Suscripción actualizada</string>
<string name="your_account">Tu cuenta</string>
<string name="keys">Claves</string>
<string name="send_presence_updates">Enviar actualizaciones de presencia</string>
<string name="receive_presence_updates">Recibir actualizaciones de presencia</string>
<string name="ask_for_presence_updates">Solicitar actualizaciones de presencia</string>
+ <string name="asked_for_presence_updates">Solictida actualizaciones de presencia</string>
<string name="attach_choose_picture">Seleccionar imagen</string>
<string name="attach_take_picture">Hacer foto</string>
- <string name="preemptively_grant">Por defecto otorgar peticiones de suscripción</string>
+ <string name="preemptively_grant">Por defecto conceder solicitud de suscripción</string>
<string name="error_not_an_image_file">El archivo seleccionado no es una imagen</string>
<string name="error_compressing_image">Error convirtiendo el archivo de imagen</string>
<string name="error_file_not_found">Archivo no encontrado</string>
@@ -170,4 +190,12 @@
<string name="save">Guardar</string>
<string name="passwords_do_not_match">Las contraseñas no coinciden</string>
<string name="invalid_jid">El identificador no es un identificador de Jabber válido</string>
+ <string name="error_out_of_memory">Sin memoria. La imagen es demasiado grande</string>
+ <string name="add_phone_book_text">¿Te gustaría añadir a %s a tus contactos del teléfono?</string>
+ <string name="contact_status_online">Disponible</string>
+ <string name="contact_status_free_to_chat">Hablador</string>
+ <string name="contact_status_away">Ausente</string>
+ <string name="contact_status_extended_away">Ausencia ext.</string>
+ <string name="contact_status_do_not_disturb">No molestar</string>
+ <string name="contact_status_offline">Desconectado</string>
</resources> \ No newline at end of file
diff --git a/res/values-gl/arrays.xml b/res/values-gl/arrays.xml
new file mode 100644
index 00000000..318b9d5c
--- /dev/null
+++ b/res/values-gl/arrays.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <array name="resources">
+ <item>Móvil</item>
+ <item>Teléfono</item>
+ <item>Tablet</item>
+ <item>Conversations</item>
+ <item>Android</item>
+ </array>
+ <string-array name="filesizes">
+ <item>nunca</item>
+ <item>256 KB</item>
+ <item>512 KB</item>
+ <item>1 MB</item>
+ </string-array>
+ <string-array name="filesizes_values">
+ <item>0</item>
+ <item>262144</item>
+ <item>524288</item>
+ <item>1048576</item>
+ </string-array>
+</resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
new file mode 100644
index 00000000..fe1d4fd4
--- /dev/null
+++ b/res/values-gl/strings.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">Conversations</string>
+ <string name="action_settings">Axustes</string>
+ <string name="action_add">Nova conversa</string>
+ <string name="action_accounts">Xestionar contas</string>
+ <string name="action_refresh">Actualizar lista de contactos</string>
+ <string name="action_end_conversation">Terminar conversa</string>
+ <string name="action_contact_details">Detalles do contacto</string>
+ <string name="action_muc_details">Detalles da conferencia</string>
+ <string name="action_secure">Conversa segura</string>
+ <string name="action_add_account">Engadir conta</string>
+ <string name="action_edit_contact">Editar contacto</string>
+ <string name="action_delete_contact">Eliminar contacto da lista</string>
+ <string name="title_activity_contacts">Contactos</string>
+ <string name="just_now">agora</string>
+ <string name="minutes_ago">min</string>
+ <string name="unread_conversations">conversas sen ler</string>
+ <string name="sending">enviando&#8230;</string>
+ <string name="announce_pgp">Renovar anuncio PGP</string>
+ <string name="encrypted_message">Descifrando mensaxe. Agarda uns intres&#8230;</string>
+ <string name="conference_details">Detalles da conferencia</string>
+ <string name="nick_in_use">O apodo xa está en uso</string>
+ <string name="moderator">Moderador</string>
+ <string name="participant">Participante</string>
+ <string name="visitor">Visitante</string>
+ <string name="enter_new_name">Introduce un novo nome:</string>
+ <string name="remove_contact_text">¿Queres eliminar a %s da túa lista?. A conversa asociada a esta conta non se eliminará.</string>
+ <string name="untrusted_cert_hint">O servidor %s presenta un certificado non confiable, posiblemente auto firmado.</string>
+ <string name="account_info">Información do servidor</string>
+ <string name="register_account">Rexistrar nova conta no servidor</string>
+ <string name="share_with">Compartir con</string>
+ <string name="ask_again"><u>Pulsa para preguntar outra vez</u></string>
+ <string name="show_otr_key">Pegada dactilar OTR</string>
+ <string name="no_otr_fingerprint">Non hai pegadas dactilares OTR. Continúa e comeza unha conversación cifrada</string>
+ <string name="start_conversation">Comeza conversa</string>
+ <string name="invite_contacts">Invitar contactos</string>
+ <string name="invite_contacts_to_existing">Invitar a conferencia existente</string>
+ <string name="new_conference">Crear nova conferencia</string>
+ <string name="cancel">Cancelar</string>
+ <string name="create_invite">Crear \u0026 Invitar</string>
+ <string name="new_conference_explained">¿Queres crear unha nueva conferencia con unha dirección xerada aleatoriamente e invitar aos contactos seleccionados a ela?</string>
+ <string name="no_open_mucs">Non hai conferencias existentes</string>
+ <string name="invitation_sent">Invitación enviada</string>
+ <string name="account_offline">Conta desconectada</string>
+ <string name="cant_invite_while_offline">Debes estar conectado para invitar contactos á conferencia</string>
+ <string name="crash_report_title">Conversations deteuse.</string>
+ <string name="crash_report_message">Enviando volcados de pilas axudas ao desenrolo de Conversations\n<b>Aviso:</b> Isto empregará a túa conta XMPP para enviar o volcado de pila ao desenrolador.</string>
+ <string name="send_now">Enviar agora</string>
+ <string name="send_never">Non preguntar de novo</string>
+ <string name="problem_connecting_to_account">Erro na conexión á conta</string>
+ <string name="problem_connecting_to_accounts">Erro na conexión a múltiples contas</string>
+ <string name="touch_to_fix">Pulsa aquí para xestionar as túas contass</string>
+ <string name="attach_file">Adxuntar</string>
+ <string name="not_in_roster">O contacto non está na túa lista. ¿Queres engadilo?</string>
+ <string name="add_contact">Engadir contacto</string>
+ <string name="send_failed">Erro ao enviar</string>
+ <string name="send_rejected">rechazado</string>
+ <string name="receiving_image">Recibindo arquivo de imaxe. Agarda por favor&#8230;</string>
+ <string name="preparing_image">Preparando imaxe para enviar</string>
+ <string name="action_clear_history">Limpar historial</string>
+ <string name="clear_conversation_history">Limpar historial de conversa</string>
+ <string name="clear_histor_msg">¿Queres borrar todas as mensaxes desta conversa?\n\n<b>Ollo:</b> Isto non afectará ás mensaxes gardadas noutros dispositivos ou servidores.</string>
+ <string name="delete_messages">Borrar mensaxes</string>
+ <string name="also_end_conversation">Terminar esta conversa máis tarde</string>
+ <string name="choose_presence">Selecciona recurso del contacto</string>
+ <string name="send_message_to_conference">Enviar mensaxe a conferencia</string>
+ <string name="send_plain_text_message">Enviar mensaxe de texto</string>
+ <string name="send_otr_message">Enviar mensaxe cifrado con OTR</string>
+ <string name="send_pgp_message">Enviar mensaxe cifrado con openPGP</string>
+ <string name="your_nick_has_been_changed">Modificouse o teu apodo</string>
+ <string name="download_image">Descargar imaxe</string>
+ <string name="error_loading_image">Erro na carga da imaxen (Arquivo non atopado)</string>
+ <string name="image_offered_for_download"><i>Arquivo de imaxe ofrecido para descarga</i></string>
+ <string name="not_connected">Non conectado</string>
+ <string name="you_are_offline">Debes estar conectado para enviar %s pero a túa conta asociada a esta conversa está desconectada.</string>
+ <string name="you_are_offline_blank">Non podes executar esta acción estando desconectado</string>
+ <string name="files">arquivos</string>
+ <string name="otr_messages">Mensaxes cifrados con OTR</string>
+ <string name="manage_account">Xestionar conta</string>
+ <string name="contact_offline">O teu contacto está desconectado</string>
+ <string name="contact_offline_otr">É unha pena, pero non é posible enviar mensaxes encriptados con OTR a un contacto desconectado.\n¿Queres enviar a mensaxe sen cifrar?</string>
+ <string name="contact_offline_file">É unha pena, pero non se pode enviar arquivos a un contacto desconectado.</string>
+ <string name="send_unencrypted">Enviar sen cifrar</string>
+ <string name="decryption_failed">Fallou o descifrado. Quizábeis non teñas a clave privada apropiada.</string>
+ <string name="openkeychain_required">OpenKeychain</string>
+ <string name="openkeychain_required_long">Conversations emprega unha aplicación de terceiros chamada <b>OpenKeychain</b> para cifrar e descifrar mensaxes e xestionar as túas claves públicas.\n\nOpenKeychain está publicado baixo licencia GPLv3 e disponible en F-Droid e Google Play.\n\n<small>(Por favor, reinicie Conversations despois.)</small></string>
+ <string name="restart">Reiniciar</string>
+ <string name="install">Instalar</string>
+ <string name="offering">ofrecendo&#8230;</string>
+ <string name="no_pgp_key">Clave openPGP non atopada</string>
+ <string name="contact_has_no_pgp_key">Conversations non foi quen de cifrar as túas mensaxes porque o teu contactos non está anunciando a súa clave pública.\n\n<small>Por favor, pídelle ao teu contacto que configure openPGP.</small></string>
+ <string name="encrypted_message_received"><i>Mensaxe cifrado recibido. Pulsa para ver.</i></string>
+ <string name="encrypted_image_received"><i>Imaxe cifrada recibida. Pulsa para ver.</i></string>
+ <string name="image_file"><i>Imaxe recibida. Pulsa para ver</i></string>
+ <string name="otr_file_transfer">Cifrado con OTR non disponible</string>
+ <string name="otr_file_transfer_msg">É unha pena, pero o cifrado con OTR non está disponible para transferencia de arquivos. Podes selecionar cifrado con openPGP ou enviar os datos sen cifrar.</string>
+ <string name="use_pgp_encryption">Usa cifrado con openPGP</string>
+ <string name="pref_xmpp_resource">Recurso</string>
+ <string name="pref_xmpp_resource_summary">O nome que identifica o cliente que estás a empregar</string>
+ <string name="pref_accept_files">Aceptar arquivos</string>
+ <string name="pref_accept_files_summary">De forma automática aceptar arquivos menores de&#8230;</string>
+ <string name="pref_notification_settings">Axustes de notificación</string>
+ <string name="pref_notifications">Notificacións</string>
+ <string name="pref_notifications_summary">Notifica cuando chega unha nova mensaxe</string>
+ <string name="pref_vibrate">Tremer</string>
+ <string name="pref_vibrate_summary">Treme cando chega unha novo mensaxe</string>
+ <string name="pref_sound">Son</string>
+ <string name="pref_sound_summary">Reproduce un ton ca notificación</string>
+ <string name="pref_conference_notifications">Notificacións de conferencia</string>
+ <string name="pref_conference_notifications_summary">Siempre notifica cuando chega unha mensaxe de conferencia e non solo cuando chega unha mensaxe destacada</string>
+ <string name="pref_notification_grace_period">Notificacións Carbons</string>
+ <string name="pref_notification_grace_period_summary">Deshabilita as notificacións durante un corto periodo de tiempo despois de recibir a copia da mensaxe carbón</string>
+ <string name="pref_ui_options">Opcións de interfaz</string>
+ <string name="pref_use_phone_self_picture">Usar a foto do teléfono</string>
+ <string name="pref_use_phone_sefl_picture_summary">Poderías non ser capaz de distinguir que conta estase a utlizar nunha conversa</string>
+ <string name="pref_conference_name">Nome dea conferencia</string>
+ <string name="pref_conference_name_summary">Usa o nome da sala para identificar Conferencias</string>
+ <string name="pref_advanced_options">Opcións avanzadas</string>
+ <string name="pref_never_send_crash">Nunca enviar informe de erros</string>
+ <string name="pref_never_send_crash_summary">Enviando volcados de pilas axudas al desenrolo de Conversations</string>
+ <string name="openpgp_error">OpenKeychain reportou un erro</string>
+ <string name="error_decrypting_file">I/O Erro descifrando arquivo</string>
+ <string name="error_copying_image_file">Erro copiando arquivo de imaxe.</string>
+ <string name="accept">Aceptar</string>
+ <string name="error">Produciuse un erro</string>
+ <string name="pref_grant_presence_updates">Suscripción de presencia</string>
+ <string name="pref_grant_presence_updates_summary">Por defecto otorgar e pedir suscripcións de presencia dos contactos que creaches</string>
+ <string name="subscriptions">Suscripcións</string>
+ <string name="your_account">A túa conta</string>
+ <string name="keys">Chaves</string>
+ <string name="send_presence_updates">Enviar actualizacións de presencia</string>
+ <string name="receive_presence_updates">Recibir actualizacións de presencia</string>
+ <string name="ask_for_presence_updates">Solicitar actualizacións de presencia</string>
+ <string name="attach_choose_picture">Seleccionar imaxe</string>
+ <string name="attach_take_picture">Facer foto</string>
+ <string name="preemptively_grant">Por defecto otorgar peticiones de suscripción</string>
+ <string name="error_not_an_image_file">O arquivo seleccionado non é unha imaxe</string>
+ <string name="error_compressing_image">Erro convertindo o arquivo de imaxe</string>
+ <string name="error_file_not_found">Arquivo non atopado</string>
+ <string name="error_io_exception">Erro xeral de I/O. ¿Quedaches sen espazo no disco?</string>
+ <string name="error_security_exception_during_image_copy">A aplicación que usas para seleccionar imaxes non proporciona suficientes permisos para leer o arquivo.\n\n<small>Utiliza un explorador de arquivos diferente para seleccionar a imaxe</small></string>
+ <string name="account_status">Estado:</string>
+ <string name="account_status_unknown">Descoñecido</string>
+ <string name="account_status_disabled">Deshabilitado temporalmente</string>
+ <string name="account_status_online">Conectado</string>
+ <string name="account_status_connecting">Conectando\u2026</string>
+ <string name="account_status_offline">Desconectado</string>
+ <string name="account_status_unauthorized">Non autorizado</string>
+ <string name="account_status_not_found">Servidor non atopado</string>
+ <string name="account_status_no_internet">Sen conectividade</string>
+ <string name="account_status_requires_tls">O servidor require TLS</string>
+ <string name="account_status_error">Certificado non confiable</string>
+ <string name="account_status_regis_fail">Erro no rexistro</string>
+ <string name="account_status_regis_conflict">O identificador xa está en uso</string>
+ <string name="account_status_regis_success">Rexistro completado</string>
+ <string name="account_status_regis_not_sup">O servidor non soporta rexistros</string>
+ <string name="certif_no_trust">Non conectar</string>
+ <string name="certif_trust">Confiar no certificado</string>
+ <string name="encryption_choice_none">Texto plano</string>
+ <string name="encryption_choice_otr">OTR</string>
+ <string name="encryption_choice_pgp">openPGP</string>
+ <string name="mgmt_account_edit">Editar conta</string>
+ <string name="mgmt_account_delete">Eliminar conta</string>
+ <string name="mgmt_account_disable">Deshabilitar temporalmente</string>
+ <string name="mgmt_account_enable">Habilitar</string>
+ <string name="attach_record_voice">Grabar audio</string>
+ <string name="account_settings">Configuración de conta</string>
+ <string name="save">Gardar</string>
+ <string name="passwords_do_not_match">As contrasinais non coinciden</string>
+ <string name="invalid_jid">O identificador non é un identificador de Jabber válido</string>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9db67fdf..0512106e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -12,8 +12,14 @@
<string name="action_secure">Secure conversation</string>
<string name="action_add_account">Add account</string>
<string name="action_edit_contact">Edit name</string>
+ <string name="action_add_phone_book">Add to phone book</string>
<string name="action_delete_contact">Delete from roster</string>
<string name="title_activity_contacts">Contacts</string>
+ <string name="title_activity_manage_accounts">Manage Accounts</string>
+ <string name="title_activity_settings">Settings</string>
+ <string name="title_activity_conference_details">Conference Details</string>
+ <string name="title_activity_contact_details">Contact Details</string>
+ <string name="title_activity_conversations">Conversations</string>
<string name="just_now">just now</string>
<string name="minutes_ago">min ago</string>
<string name="unread_conversations">unread Conversations</string>
@@ -38,7 +44,19 @@
<string name="invite_contacts">Invite Contacts</string>
<string name="invite_contacts_to_existing">Invite to existing conference</string>
<string name="new_conference">Create new conference</string>
+ <string name="new_contact">Create new contact</string>
+ <string name="contacts">Contacts</string>
+ <string name="choose_account">Choose account</string>
+ <string name="multi_user_conference">Multi User Conference</string>
+ <string name="trying_join_conference">Are you trying to join a conference?</string>
<string name="cancel">Cancel</string>
+ <string name="add">Add</string>
+ <string name="edit">Edit</string>
+ <string name="delete">Delete</string>
+ <string name="save">Save</string>
+ <string name="yes">Yes</string>
+ <string name="no">No</string>
+ <string name="ok">Ok</string>
<string name="create_invite">Create \u0026 Invite</string>
<string name="new_conference_explained">Do you want to create a new conference with a randomly generated address and invite the selected contacts to it?</string>
<string name="no_open_mucs">No existing conferences</string>
@@ -128,11 +146,13 @@
<string name="pref_grant_presence_updates">Grant presence updates</string>
<string name="pref_grant_presence_updates_summary">Preemptively grant and ask for presence subscription for contacts you created</string>
<string name="subscriptions">Subscriptions</string>
+ <string name="subscription_updated">Subscription updated</string>
<string name="your_account">Your account</string>
<string name="keys">Keys</string>
<string name="send_presence_updates">Send presence updates</string>
<string name="receive_presence_updates">Receive presence updates</string>
<string name="ask_for_presence_updates">Ask for presence updates</string>
+ <string name="asked_for_presence_updates">Asked for presence updates</string>
<string name="attach_choose_picture">Choose picture</string>
<string name="attach_take_picture">Take picture</string>
<string name="preemptively_grant">Preemptively grant subscription request</string>
@@ -170,5 +190,12 @@
<string name="save">Save</string>
<string name="passwords_do_not_match">Passwords do not match</string>
<string name="invalid_jid">This is not a valid Jabber ID</string>
-
+ <string name="error_out_of_memory">Ouf of memory. Image is to large</string>
+ <string name="add_phone_book_text">Do you want to add %s to your phones contact list?</string>
+ <string name="contact_status_online">online</string>
+ <string name="contact_status_free_to_chat">free to chat</string>
+ <string name="contact_status_away">away</string>
+ <string name="contact_status_extended_away">extended away</string>
+ <string name="contact_status_do_not_disturb">do not disturb</string>
+ <string name="contact_status_offline">offline</string>
</resources> \ No newline at end of file
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;
}