aboutsummaryrefslogtreecommitdiffstats
path: root/src/eu/siacs/conversations
diff options
context:
space:
mode:
Diffstat (limited to 'src/eu/siacs/conversations')
-rw-r--r--src/eu/siacs/conversations/crypto/PgpEngine.java78
-rw-r--r--src/eu/siacs/conversations/entities/Conversation.java5
-rw-r--r--src/eu/siacs/conversations/entities/MucOptions.java146
-rw-r--r--src/eu/siacs/conversations/services/XmppConnectionService.java93
-rw-r--r--src/eu/siacs/conversations/ui/ConversationActivity.java17
-rw-r--r--src/eu/siacs/conversations/ui/ConversationFragment.java41
-rw-r--r--src/eu/siacs/conversations/ui/DialogMucDetails.java100
-rw-r--r--src/eu/siacs/conversations/ui/XmppActivity.java15
-rw-r--r--src/eu/siacs/conversations/utils/MessageParser.java2
-rw-r--r--src/eu/siacs/conversations/xmpp/OnIqPacketReceived.java2
-rw-r--r--src/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java2
-rw-r--r--src/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java2
-rw-r--r--src/eu/siacs/conversations/xmpp/PacketReceived.java5
-rw-r--r--src/eu/siacs/conversations/xmpp/XmppConnection.java57
14 files changed, 479 insertions, 86 deletions
diff --git a/src/eu/siacs/conversations/crypto/PgpEngine.java b/src/eu/siacs/conversations/crypto/PgpEngine.java
index ba000c04..78384441 100644
--- a/src/eu/siacs/conversations/crypto/PgpEngine.java
+++ b/src/eu/siacs/conversations/crypto/PgpEngine.java
@@ -7,11 +7,9 @@ import java.io.InputStream;
import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.openintents.openpgp.util.OpenPgpApi;
-import org.openintents.openpgp.util.OpenPgpConstants;
import android.app.PendingIntent;
-import android.os.Bundle;
-import android.util.Log;
+import android.content.Intent;
public class PgpEngine {
private OpenPgpApi api;
@@ -22,34 +20,34 @@ public class PgpEngine {
public String decrypt(String message) throws UserInputRequiredException,
OpenPgpException {
+ Intent params = new Intent();
+ params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
InputStream is = new ByteArrayInputStream(message.getBytes());
ByteArrayOutputStream os = new ByteArrayOutputStream();
- Bundle result = api.decryptAndVerify(is, os);
- switch (result.getInt(OpenPgpConstants.RESULT_CODE)) {
- case OpenPgpConstants.RESULT_CODE_SUCCESS:
+ Intent result = api.executeApi(params, is, os);
+ switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
+ case OpenPgpApi.RESULT_CODE_SUCCESS:
return os.toString();
- case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED:
- throw new UserInputRequiredException(
- (PendingIntent) result
- .getParcelable(OpenPgpConstants.RESULT_INTENT));
- case OpenPgpConstants.RESULT_CODE_ERROR:
+ case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
+ throw new UserInputRequiredException((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
+ case OpenPgpApi.RESULT_CODE_ERROR:
throw new OpenPgpException(
- (OpenPgpError) result
- .getParcelable(OpenPgpConstants.RESULT_ERRORS));
+ (OpenPgpError) result.getParcelableExtra(OpenPgpApi.RESULT_ERRORS));
default:
return null;
}
}
public String encrypt(long keyId, String message) {
- Bundle params = new Bundle();
- params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
- long[] keyIds = { keyId };
- params.putLongArray(OpenPgpConstants.PARAMS_KEY_IDS, keyIds);
-
+ Long[] keys = {keyId};
+ Intent params = new Intent();
+ params.setAction(OpenPgpApi.ACTION_ENCRYPT);
+ params.putExtra(OpenPgpApi.EXTRA_KEY_IDS,keys);
+ params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
+
InputStream is = new ByteArrayInputStream(message.getBytes());
ByteArrayOutputStream os = new ByteArrayOutputStream();
- Bundle result = api.encrypt(params, is, os);
+ Intent result = api.executeApi(params, is, os);
StringBuilder encryptedMessageBody = new StringBuilder();
String[] lines = os.toString().split("\n");
for (int i = 3; i < lines.length - 1; ++i) {
@@ -74,47 +72,45 @@ public class PgpEngine {
pgpSig.append(signature.replace("\n", "").trim());
pgpSig.append('\n');
pgpSig.append("-----END PGP SIGNATURE-----");
- Bundle params = new Bundle();
- params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
+ Intent params = new Intent();
+ params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
+ params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
InputStream is = new ByteArrayInputStream(pgpSig.toString().getBytes());
ByteArrayOutputStream os = new ByteArrayOutputStream();
- Bundle result = api.decryptAndVerify(params, is, os);
- switch (result.getInt(OpenPgpConstants.RESULT_CODE)) {
- case OpenPgpConstants.RESULT_CODE_SUCCESS:
- OpenPgpSignatureResult sigResult = result
- .getParcelable(OpenPgpConstants.RESULT_SIGNATURE);
+ Intent result = api.executeApi(params, is, os);
+ switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
+ case OpenPgpApi.RESULT_CODE_SUCCESS:
+ OpenPgpSignatureResult sigResult
+ = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
return sigResult.getKeyId();
- case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED:
+ case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
break;
- case OpenPgpConstants.RESULT_CODE_ERROR:
+ case OpenPgpApi.RESULT_CODE_ERROR:
throw new OpenPgpException(
- (OpenPgpError) result
- .getParcelable(OpenPgpConstants.RESULT_ERRORS));
+ (OpenPgpError) result.getParcelableExtra(OpenPgpApi.RESULT_ERRORS));
}
return 0;
}
public String generateSignature(String status)
throws UserInputRequiredException {
- Bundle params = new Bundle();
- params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
+ Intent params = new Intent();
+ params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
+ params.setAction(OpenPgpApi.ACTION_SIGN);
InputStream is = new ByteArrayInputStream(status.getBytes());
ByteArrayOutputStream os = new ByteArrayOutputStream();
- Bundle result = api.sign(params, is, os);
+ Intent result = api.executeApi(params, is, os);
StringBuilder signatureBuilder = new StringBuilder();
- switch (result.getInt(OpenPgpConstants.RESULT_CODE)) {
- case OpenPgpConstants.RESULT_CODE_SUCCESS:
+ switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
+ case OpenPgpApi.RESULT_CODE_SUCCESS:
String[] lines = os.toString().split("\n");
for (int i = 7; i < lines.length - 1; ++i) {
signatureBuilder.append(lines[i].trim());
}
break;
- case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED:
- UserInputRequiredException exception = new UserInputRequiredException(
- (PendingIntent) result
- .getParcelable(OpenPgpConstants.RESULT_INTENT));
- throw exception;
- case OpenPgpConstants.RESULT_CODE_ERROR:
+ case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
+ throw new UserInputRequiredException((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
+ case OpenPgpApi.RESULT_CODE_ERROR:
break;
}
return signatureBuilder.toString();
diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java
index d1186a7d..1a4745f9 100644
--- a/src/eu/siacs/conversations/entities/Conversation.java
+++ b/src/eu/siacs/conversations/entities/Conversation.java
@@ -275,10 +275,15 @@ public class Conversation extends AbstractEntity {
if (this.mucOptions == null) {
this.mucOptions = new MucOptions();
}
+ this.mucOptions.setConversation(this);
return this.mucOptions ;
}
public void resetMucOptions() {
this.mucOptions = null;
}
+
+ public void setContactJid(String jid) {
+ this.contactJid = jid;
+ }
}
diff --git a/src/eu/siacs/conversations/entities/MucOptions.java b/src/eu/siacs/conversations/entities/MucOptions.java
index d5340ea8..b3b53e1d 100644
--- a/src/eu/siacs/conversations/entities/MucOptions.java
+++ b/src/eu/siacs/conversations/entities/MucOptions.java
@@ -1,9 +1,21 @@
package eu.siacs.conversations.entities;
+import java.util.ArrayList;
+import java.util.List;
+
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.PresencePacket;
import android.annotation.SuppressLint;
+import android.util.Log;
@SuppressLint("DefaultLocale")
public class MucOptions {
+ public static final int ERROR_NICK_IN_USE = 1;
+
+ public interface OnRenameListener {
+ public void onRename(boolean success);
+ }
+
public class User {
public static final int ROLE_MODERATOR = 3;
public static final int ROLE_NONE = 0;
@@ -17,6 +29,15 @@ public class MucOptions {
private int role;
private int affiliation;
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String user) {
+ this.name = user;
+ }
+
public int getRole() {
return this.role;
}
@@ -35,8 +56,127 @@ public class MucOptions {
public int getAffiliation() {
return this.affiliation;
}
- public void setAffiliation() {
-
+ public void setAffiliation(String affiliation) {
+ if (affiliation.equalsIgnoreCase("admin")) {
+ this.affiliation = AFFILIATION_ADMIN;
+ } else if (affiliation.equalsIgnoreCase("owner")) {
+ this.affiliation = AFFILIATION_OWNER;
+ } else if (affiliation.equalsIgnoreCase("member")) {
+ this.affiliation = AFFILIATION_MEMBER;
+ } else if (affiliation.equalsIgnoreCase("outcast")) {
+ this.affiliation = AFFILIATION_OUTCAST;
+ } else {
+ this.affiliation = AFFILIATION_NONE;
+ }
+ }
+ }
+ private ArrayList<User> users = new ArrayList<User>();
+ private Conversation conversation;
+ private boolean isOnline = false;
+ private int error = 0;
+ private OnRenameListener renameListener = null;
+
+
+ public void deleteUser(String name) {
+ for(int i = 0; i < users.size(); ++i) {
+ if (users.get(i).getName().equals(name)) {
+ users.remove(i);
+ return;
+ }
+ }
+ }
+
+ public void addUser(User user) {
+ for(int i = 0; i < users.size(); ++i) {
+ if (users.get(i).getName().equals(user.getName())) {
+ users.set(i, user);
+ return;
+ }
}
+ users.add(user);
+ }
+
+ public void processPacket(PresencePacket packet) {
+ Log.d("xmppService","process Packet for muc options: "+packet.toString());
+ String name = packet.getAttribute("from").split("/")[1];
+ String type = packet.getAttribute("type");
+ if (type==null) {
+ User user = new User();
+ Element item = packet.findChild("x").findChild("item");
+ user.setName(name);
+ user.setAffiliation(item.getAttribute("affiliation"));
+ user.setRole(item.getAttribute("role"));
+ user.setName(name);
+ addUser(user);
+ Log.d("xmppService","nick: "+getNick());
+ Log.d("xmppService","name: "+name);
+ if (name.equals(getNick())) {
+ this.isOnline = true;
+ this.error = 0;
+ }
+ } else if (type.equals("unavailable")) {
+ Log.d("xmppService","name: "+name);
+ if (name.equals(getNick())) {
+ Element item = packet.findChild("x").findChild("item");
+ Log.d("xmppService","nick equals name");
+ String nick = item.getAttribute("nick");
+ if (nick!=null) {
+ if (renameListener!=null) {
+ renameListener.onRename(true);
+ }
+ this.setNick(nick);
+ }
+ }
+ deleteUser(packet.getAttribute("from").split("/")[1]);
+ } else if (type.equals("error")) {
+ Element error = packet.findChild("error");
+ if (error.hasChild("conflict")) {
+ this.error = ERROR_NICK_IN_USE;
+ }
+ }
+ }
+
+ public List<User> getUsers() {
+ return this.users;
+ }
+
+ public String getNick() {
+ String[] split = conversation.getContactJid().split("/");
+ if (split.length == 2) {
+ return split[1];
+ } else {
+ return conversation.getAccount().getUsername();
+ }
+ }
+
+ public void setNick(String nick) {
+ String jid = conversation.getContactJid().split("/")[0]+"/"+nick;
+ conversation.setContactJid(jid);
+ }
+
+ public void setConversation(Conversation conversation) {
+ this.conversation = conversation;
+ }
+
+ public boolean online() {
+ return this.isOnline;
+ }
+
+ public int getError() {
+ return this.error;
+ }
+
+ public void setOnRenameListener(OnRenameListener listener) {
+ this.renameListener = listener;
+ }
+
+ public OnRenameListener getOnRenameListener() {
+ return this.renameListener;
+ }
+
+ public void setOffline() {
+ this.users.clear();
+ this.error = 0;
+ this.isOnline = false;
}
-}
+} \ No newline at end of file
diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java
index 218d5088..17537729 100644
--- a/src/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/eu/siacs/conversations/services/XmppConnectionService.java
@@ -20,12 +20,15 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.entities.MucOptions;
+import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.persistance.OnPhoneContactsMerged;
import eu.siacs.conversations.ui.OnAccountListChangedListener;
import eu.siacs.conversations.ui.OnConversationListChangedListener;
import eu.siacs.conversations.ui.OnRosterFetchedListener;
+import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.utils.MessageParser;
import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
import eu.siacs.conversations.utils.PhoneHelper;
@@ -53,6 +56,7 @@ import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.util.Log;
+import android.widget.Toast;
public class XmppConnectionService extends Service {
@@ -116,7 +120,7 @@ public class XmppConnectionService extends Service {
} else if (packet.getType() == MessagePacket.TYPE_ERROR) {
message = MessageParser.parseError(packet, account, service);
} else {
- Log.d(LOGTAG, "unparsed message " + packet.toString());
+ //Log.d(LOGTAG, "unparsed message " + packet.toString());
}
if (message == null) {
return;
@@ -188,8 +192,15 @@ public class XmppConnectionService extends Service {
@Override
public void onPresencePacketReceived(Account account,
PresencePacket packet) {
+ Log.d(LOGTAG, packet.toString());
if (packet.hasChild("x")&&(packet.findChild("x").getAttribute("xmlns").startsWith("http://jabber.org/protocol/muc"))) {
- Log.d(LOGTAG,"got muc presence "+packet.toString());
+ Conversation muc = findMuc(packet.getAttribute("from").split("/")[0]);
+ if (muc!=null) {
+ muc.getMucOptions().processPacket(packet);
+ if (convChangedListener!=null) {
+ convChangedListener.onConversationListChanged();
+ }
+ }
} else {
String[] fromParts = packet.getAttribute("from").split("/");
Contact contact = findContact(account, fromParts[0]);
@@ -290,6 +301,15 @@ public class XmppConnectionService extends Service {
}
+ protected Conversation findMuc(String name) {
+ for(Conversation conversation : this.conversations) {
+ if (conversation.getContactJid().split("/")[0].equals(name)) {
+ return conversation;
+ }
+ }
+ return null;
+ }
+
private void processRosterItems(Account account, Element elements) {
String version = elements.getAttribute("ver");
if (version != null) {
@@ -506,7 +526,7 @@ public class XmppConnectionService extends Service {
} else if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
packet.setType(MessagePacket.TYPE_GROUPCHAT);
packet.setBody(message.getBody());
- packet.setTo(message.getCounterpart());
+ packet.setTo(message.getCounterpart().split("/")[0]);
packet.setFrom(account.getJid());
}
return packet;
@@ -653,7 +673,7 @@ public class XmppConnectionService extends Service {
boolean muc) {
for (Conversation conv : this.getConversations()) {
if ((conv.getAccount().equals(account))
- && (conv.getContactJid().equals(jid))) {
+ && (conv.getContactJid().split("/")[0].equals(jid))) {
return conv;
}
}
@@ -799,10 +819,19 @@ public class XmppConnectionService extends Service {
}
public void joinMuc(Conversation conversation) {
- String muc = conversation.getContactJid();
+ String[] mucParts = conversation.getContactJid().split("/");
+ String muc;
+ String nick;
+ if (mucParts.length == 2) {
+ muc = mucParts[0];
+ nick = mucParts[1];
+ } else {
+ muc = mucParts[0];
+ nick = conversation.getAccount().getUsername();
+ }
PresencePacket packet = new PresencePacket();
packet.setAttribute("to", muc + "/"
- + conversation.getAccount().getUsername());
+ + nick);
Element x = new Element("x");
x.setAttribute("xmlns", "http://jabber.org/protocol/muc");
if (conversation.getMessages().size() != 0) {
@@ -816,9 +845,55 @@ public class XmppConnectionService extends Service {
conversation.getAccount().getXmppConnection()
.sendPresencePacket(packet);
}
+
+ public void renameInMuc(final Conversation conversation, final String nick, final XmppActivity activity) {
+ final MucOptions options = conversation.getMucOptions();
+ if (options.online()) {
+ options.setOnRenameListener(new OnRenameListener() {
+
+ @Override
+ public void onRename(final boolean success) {
+ activity.runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ if (success) {
+ databaseBackend.updateConversation(conversation);
+ Toast.makeText(activity, "Your nickname has been changed", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(activity, "Nickname already in use",Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }
+ });
+ PresencePacket packet = new PresencePacket();
+ packet.setAttribute("to", conversation.getContactJid().split("/")[0]+"/"+nick);
+ conversation.getAccount().getXmppConnection().sendPresencePacket(packet, new OnPresencePacketReceived() {
+
+ @Override
+ public void onPresencePacketReceived(Account account, PresencePacket packet) {
+ final boolean changed;
+ String type = packet.getAttribute("type");
+ changed = (!"error".equals(type));
+ if (!changed) {
+ options.getOnRenameListener().onRename(changed);
+ }
+ options.processPacket(packet);
+ }
+ });
+ } else {
+ String jid = conversation.getContactJid().split("/")[0]+"/"+nick;
+ conversation.setContactJid(jid);
+ databaseBackend.updateConversation(conversation);
+ if (conversation.getAccount().getStatus() == Account.STATUS_ONLINE) {
+ joinMuc(conversation);
+ }
+ }
+ }
public void leaveMuc(Conversation conversation) {
-
+ conversation.getMucOptions().setOffline();
}
public void disconnect(Account account) {
@@ -943,4 +1018,8 @@ public class XmppConnectionService extends Service {
sendPgpPresence(account, signature);
}
}
+
+ public void updateConversation(Conversation conversation) {
+ this.databaseBackend.updateConversation(conversation);
+ }
} \ No newline at end of file
diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java
index 7660b8fd..f826040b 100644
--- a/src/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/eu/siacs/conversations/ui/ConversationActivity.java
@@ -208,17 +208,7 @@ public class ConversationActivity extends XmppActivity {
getActionBar().setDisplayHomeAsUpEnabled(false);
getActionBar().setTitle(R.string.app_name);
invalidateOptionsMenu();
-
- InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
-
- View focus = getCurrentFocus();
-
- if (focus != null) {
-
- inputManager.hideSoftInputFromWindow(
- focus.getWindowToken(),
- InputMethodManager.HIDE_NOT_ALWAYS);
- }
+ hideKeyboard();
}
@Override
@@ -316,6 +306,11 @@ public class ConversationActivity extends XmppActivity {
builder.create().show();
}
break;
+ case R.id.action_muc_details:
+ DialogMucDetails mucDetails = new DialogMucDetails();
+ mucDetails.setConversation(getSelectedConversation());
+ mucDetails.show(getFragmentManager(), "details");
+ break;
case R.id.action_security:
final Conversation selConv = getSelectedConversation();
View menuItemView = findViewById(R.id.action_security);
diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java
index ff06fafc..a19cb18c 100644
--- a/src/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/eu/siacs/conversations/ui/ConversationFragment.java
@@ -13,9 +13,11 @@ import net.java.otr4j.session.SessionStatus;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.PgpEngine.OpenPgpException;
import eu.siacs.conversations.crypto.PgpEngine.UserInputRequiredException;
+import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.PhoneHelper;
import eu.siacs.conversations.utils.UIHelper;
@@ -95,6 +97,17 @@ public class ConversationFragment extends Fragment {
}
};
private LinearLayout pgpInfo;
+ private LinearLayout mucError;
+ private TextView mucErrorText;
+ private OnClickListener clickToMuc = new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ DialogMucDetails mucDetails = new DialogMucDetails();
+ mucDetails.setConversation(conversation);
+ mucDetails.show(getFragmentManager(), "details");
+ }
+ };
public void hidePgpPassphraseBox() {
pgpInfo.setVisibility(View.GONE);
@@ -138,6 +151,9 @@ public class ConversationFragment extends Fragment {
pgpInfo = (LinearLayout) view.findViewById(R.id.pgp_keyentry);
pgpInfo.setOnClickListener(clickToDecryptListener);
+ mucError = (LinearLayout) view.findViewById(R.id.muc_error);
+ mucError.setOnClickListener(clickToMuc );
+ mucErrorText = (TextView) view.findViewById(R.id.muc_error_msg);
messagesView = (ListView) view.findViewById(R.id.messages_view);
@@ -348,15 +364,26 @@ public class ConversationFragment extends Fragment {
this.messageList.clear();
this.messageList.addAll(this.conversation.getMessages());
this.messageListAdapter.notifyDataSetChanged();
- if (messageList.size() >= 1) {
- int latestEncryption = this.conversation.getLatestMessage()
- .getEncryption();
- if (latestEncryption== Message.ENCRYPTION_DECRYPTED) {
- conversation.nextMessageEncryption = Message.ENCRYPTION_PGP;
+ if (conversation.getMode() == Conversation.MODE_SINGLE) {
+ if (messageList.size() >= 1) {
+ int latestEncryption = this.conversation.getLatestMessage()
+ .getEncryption();
+ if (latestEncryption== Message.ENCRYPTION_DECRYPTED) {
+ conversation.nextMessageEncryption = Message.ENCRYPTION_PGP;
+ } else {
+ conversation.nextMessageEncryption = latestEncryption;
+ }
+ makeFingerprintWarning(latestEncryption);
+ }
+ } else {
+ if (conversation.getMucOptions().getError() != 0) {
+ mucError.setVisibility(View.VISIBLE);
+ if (conversation.getMucOptions().getError() == MucOptions.ERROR_NICK_IN_USE) {
+ mucErrorText.setText(getString(R.string.nick_in_use));
+ }
} else {
- conversation.nextMessageEncryption = latestEncryption;
+ mucError.setVisibility(View.GONE);
}
- makeFingerprintWarning(latestEncryption);
}
getActivity().invalidateOptionsMenu();
updateChatMsgHint();
diff --git a/src/eu/siacs/conversations/ui/DialogMucDetails.java b/src/eu/siacs/conversations/ui/DialogMucDetails.java
new file mode 100644
index 00000000..a752e88f
--- /dev/null
+++ b/src/eu/siacs/conversations/ui/DialogMucDetails.java
@@ -0,0 +1,100 @@
+package eu.siacs.conversations.ui;
+
+
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.MucOptions;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.TextView;
+
+public class DialogMucDetails extends DialogFragment {
+ private XmppActivity activity;
+ private Conversation conversation;
+ private EditText mYourNick;
+ private OnClickListener changeNickListener = new OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ MucOptions options = conversation.getMucOptions();
+ String nick = mYourNick.getText().toString();
+ if (!options.getNick().equals(nick)) {
+ activity.xmppConnectionService.renameInMuc(conversation,nick,activity);
+ }
+ }
+ };
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ this.activity = (XmppActivity) getActivity();
+ AlertDialog.Builder builder = new AlertDialog.Builder(this.activity);
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+ View view = inflater.inflate(R.layout.muc_options, null);
+ builder.setView(view);
+ builder.setTitle(getString(R.string.conference_details));
+ mYourNick = (EditText) view.findViewById(R.id.muc_your_nick);
+ TextView mTextModerators = (TextView) view.findViewById(R.id.muc_moderators);
+ TextView mTextParticipants = (TextView) view.findViewById(R.id.muc_participants);
+ TextView mTextVisiotors = (TextView) view.findViewById(R.id.muc_visitors);
+ TextView mTextModeratorsHead = (TextView) view.findViewById(R.id.muc_moderators_header);
+ TextView mTextParticipantsHead = (TextView) view.findViewById(R.id.muc_participants_header);
+ TextView mTextVisiotorsHead = (TextView) view.findViewById(R.id.muc_visitors_header);
+ StringBuilder mods = new StringBuilder();
+ StringBuilder participants = new StringBuilder();
+ StringBuilder visitors = new StringBuilder();
+ for(MucOptions.User user : conversation.getMucOptions().getUsers()) {
+ if (user.getRole() == MucOptions.User.ROLE_MODERATOR) {
+ if (mods.length()>=1) {
+ mods.append("\n, "+user.getName());
+ } else {
+ mods.append(user.getName());
+ }
+ } else if (user.getRole() == MucOptions.User.ROLE_PARTICIPANT) {
+ if (participants.length()>=1) {
+ participants.append("\n, "+user.getName());
+ } else {
+ participants.append(user.getName());
+ }
+ } else {
+ if (visitors.length()>=1) {
+ visitors.append("\n, "+user.getName());
+ } else {
+ visitors.append(user.getName());
+ }
+ }
+ }
+ if (mods.length()>0) {
+ mTextModerators.setText(mods.toString());
+ } else {
+ mTextModerators.setVisibility(View.GONE);
+ mTextModeratorsHead.setVisibility(View.GONE);
+ }
+ if (participants.length()>0) {
+ mTextParticipants.setText(participants.toString());
+ } else {
+ mTextParticipants.setVisibility(View.GONE);
+ mTextParticipantsHead.setVisibility(View.GONE);
+ }
+ if (visitors.length()>0) {
+ mTextVisiotors.setText(visitors.toString());
+ } else {
+ mTextVisiotors.setVisibility(View.GONE);
+ mTextVisiotorsHead.setVisibility(View.GONE);
+ }
+ mYourNick.setText(conversation.getMucOptions().getNick());
+ builder.setPositiveButton("Done", this.changeNickListener );
+ builder.setNegativeButton("Cancel", null);
+ return builder.create();
+ }
+
+ public void setConversation(Conversation conversation) {
+ this.conversation = conversation;
+ }
+}
diff --git a/src/eu/siacs/conversations/ui/XmppActivity.java b/src/eu/siacs/conversations/ui/XmppActivity.java
index 5114e640..569563c1 100644
--- a/src/eu/siacs/conversations/ui/XmppActivity.java
+++ b/src/eu/siacs/conversations/ui/XmppActivity.java
@@ -8,6 +8,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
public abstract class XmppActivity extends Activity {
public XmppConnectionService xmppConnectionService;
@@ -48,5 +50,18 @@ public abstract class XmppActivity extends Activity {
}
}
+ protected void hideKeyboard() {
+ InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ View focus = getCurrentFocus();
+
+ if (focus != null) {
+
+ inputManager.hideSoftInputFromWindow(
+ focus.getWindowToken(),
+ InputMethodManager.HIDE_NOT_ALWAYS);
+ }
+ }
+
abstract void onBackendConnected();
}
diff --git a/src/eu/siacs/conversations/utils/MessageParser.java b/src/eu/siacs/conversations/utils/MessageParser.java
index dc0cd35c..65186957 100644
--- a/src/eu/siacs/conversations/utils/MessageParser.java
+++ b/src/eu/siacs/conversations/utils/MessageParser.java
@@ -85,7 +85,7 @@ public class MessageParser {
return null;
}
String counterPart = fromParts[1];
- if (counterPart.equals(account.getUsername())) {
+ if (counterPart.equals(conversation.getMucOptions().getNick())) {
status = Message.STATUS_SEND;
} else {
status = Message.STATUS_RECIEVED;
diff --git a/src/eu/siacs/conversations/xmpp/OnIqPacketReceived.java b/src/eu/siacs/conversations/xmpp/OnIqPacketReceived.java
index 4e09282c..54909f88 100644
--- a/src/eu/siacs/conversations/xmpp/OnIqPacketReceived.java
+++ b/src/eu/siacs/conversations/xmpp/OnIqPacketReceived.java
@@ -2,6 +2,6 @@ package eu.siacs.conversations.xmpp;
import eu.siacs.conversations.entities.Account;
-public interface OnIqPacketReceived {
+public interface OnIqPacketReceived extends PacketReceived {
public void onIqPacketReceived(Account account, IqPacket packet);
}
diff --git a/src/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java b/src/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java
index 3d169300..6f0b387d 100644
--- a/src/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java
+++ b/src/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java
@@ -2,6 +2,6 @@ package eu.siacs.conversations.xmpp;
import eu.siacs.conversations.entities.Account;
-public interface OnMessagePacketReceived {
+public interface OnMessagePacketReceived extends PacketReceived {
public void onMessagePacketReceived(Account account, MessagePacket packet);
}
diff --git a/src/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java b/src/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java
index 058d8be9..55672fff 100644
--- a/src/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java
+++ b/src/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java
@@ -2,6 +2,6 @@ package eu.siacs.conversations.xmpp;
import eu.siacs.conversations.entities.Account;
-public interface OnPresencePacketReceived {
+public interface OnPresencePacketReceived extends PacketReceived {
public void onPresencePacketReceived(Account account, PresencePacket packet);
}
diff --git a/src/eu/siacs/conversations/xmpp/PacketReceived.java b/src/eu/siacs/conversations/xmpp/PacketReceived.java
new file mode 100644
index 00000000..d9f42459
--- /dev/null
+++ b/src/eu/siacs/conversations/xmpp/PacketReceived.java
@@ -0,0 +1,5 @@
+package eu.siacs.conversations.xmpp;
+
+abstract interface PacketReceived {
+
+}
diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java
index 4583c145..6e65e1ed 100644
--- a/src/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -53,7 +53,7 @@ public class XmppConnection implements Runnable {
private static final int PACKET_MESSAGE = 1;
private static final int PACKET_PRESENCE = 2;
- private Hashtable<String, OnIqPacketReceived> iqPacketCallbacks = new Hashtable<String, OnIqPacketReceived>();
+ private Hashtable<String, PacketReceived> packetCallbacks = new Hashtable<String, PacketReceived>();
private OnPresencePacketReceived presenceListener = null;
private OnIqPacketReceived unregisteredIqListener = null;
private OnMessagePacketReceived messageListener = null;
@@ -212,24 +212,33 @@ public class XmppConnection implements Runnable {
return element;
}
- private IqPacket processIq(Tag currentTag) throws XmlPullParserException,
+ private void processIq(Tag currentTag) throws XmlPullParserException,
IOException {
IqPacket packet = (IqPacket) processPacket(currentTag, PACKET_IQ);
- if (iqPacketCallbacks.containsKey(packet.getId())) {
- iqPacketCallbacks.get(packet.getId()).onIqPacketReceived(account,
- packet);
- iqPacketCallbacks.remove(packet.getId());
+ if (packetCallbacks.containsKey(packet.getId())) {
+ if (packetCallbacks.get(packet.getId()) instanceof OnIqPacketReceived) {
+ ((OnIqPacketReceived) packetCallbacks.get(packet.getId())).onIqPacketReceived(account,
+ packet);
+ }
+
+ packetCallbacks.remove(packet.getId());
} else if (this.unregisteredIqListener != null) {
this.unregisteredIqListener.onIqPacketReceived(account, packet);
}
- return packet;
}
private void processMessage(Tag currentTag) throws XmlPullParserException,
IOException {
MessagePacket packet = (MessagePacket) processPacket(currentTag,
PACKET_MESSAGE);
- if (this.messageListener != null) {
+ String id = packet.getAttribute("id");
+ if ((id!=null)&&(packetCallbacks.containsKey(id))) {
+ if (packetCallbacks.get(id) instanceof OnMessagePacketReceived) {
+ ((OnMessagePacketReceived) packetCallbacks.get(id)).onMessagePacketReceived(account,
+ packet);
+ }
+ packetCallbacks.remove(id);
+ } else if (this.messageListener != null) {
this.messageListener.onMessagePacketReceived(account, packet);
}
}
@@ -238,7 +247,14 @@ public class XmppConnection implements Runnable {
IOException {
PresencePacket packet = (PresencePacket) processPacket(currentTag,
PACKET_PRESENCE);
- if (this.presenceListener != null) {
+ String id = packet.getAttribute("id");
+ if ((id!=null)&&(packetCallbacks.containsKey(id))) {
+ if (packetCallbacks.get(id) instanceof OnPresencePacketReceived) {
+ ((OnPresencePacketReceived) packetCallbacks.get(id)).onPresencePacketReceived(account,
+ packet);
+ }
+ packetCallbacks.remove(id);
+ } else if (this.presenceListener != null) {
this.presenceListener.onPresencePacketReceived(account, packet);
}
}
@@ -405,19 +421,34 @@ public class XmppConnection implements Runnable {
packet.setAttribute("id", id);
tagWriter.writeElement(packet);
if (callback != null) {
- iqPacketCallbacks.put(id, callback);
+ packetCallbacks.put(id, callback);
}
- //Log.d(LOGTAG, account.getJid() + ": sending: " + packet.toString());
}
public void sendMessagePacket(MessagePacket packet) {
- Log.d(LOGTAG,"sending message packet "+packet.toString());
+ this.sendMessagePacket(packet, null);
+ }
+
+ public void sendMessagePacket(MessagePacket packet, OnMessagePacketReceived callback) {
+ String id = nextRandomId();
+ packet.setAttribute("id", id);
tagWriter.writeElement(packet);
+ if (callback != null) {
+ packetCallbacks.put(id, callback);
+ }
}
public void sendPresencePacket(PresencePacket packet) {
+ this.sendPresencePacket(packet, null);
+ }
+
+ public void sendPresencePacket(PresencePacket packet, OnPresencePacketReceived callback) {
+ String id = nextRandomId();
+ packet.setAttribute("id", id);
tagWriter.writeElement(packet);
- Log.d(LOGTAG, account.getJid() + ": sending: " + packet.toString());
+ if (callback != null) {
+ packetCallbacks.put(id, callback);
+ }
}
public void setOnMessagePacketReceivedListener(