mirror of
https://github.com/moparisthebest/Conversations
synced 2024-11-24 17:52:17 -05:00
commit
a94663aaa4
@ -50,9 +50,11 @@ run your own XMPP server for you and your friends. These XEP's are:
|
||||
* XEP-0313: Message Archive Management synchronize message history with the
|
||||
server. Catch up with messages that were sent while Conversations was
|
||||
offline.
|
||||
* XEP-0352: Client State Indication let the server know whether or not
|
||||
* XEP-0352: Client State Indication lets the server know whether or not
|
||||
Conversations is in the background. Allows the server to save bandwidth by
|
||||
withholding unimportant packages.
|
||||
* XEP-0191: Blocking command lets you blacklist spammers or block contacts
|
||||
without removing them from your roster.
|
||||
|
||||
## Team
|
||||
|
||||
|
@ -16,3 +16,4 @@
|
||||
* XEP-0313: Message Archive Management
|
||||
* XEP-0333: Chat Markers
|
||||
* XEP-0352: Client State Indication
|
||||
* XEP-0191: Blocking command
|
||||
|
@ -76,6 +76,9 @@
|
||||
<activity
|
||||
android:name=".ui.ChooseContactActivity"
|
||||
android:label="@string/title_activity_choose_contact" />
|
||||
<activity
|
||||
android:name=".ui.BlocklistActivity"
|
||||
android:label="@string/title_activity_block_list" />
|
||||
<activity
|
||||
android:name=".ui.ManageAccountActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
|
@ -11,8 +11,10 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.security.interfaces.DSAPublicKey;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
@ -56,7 +58,7 @@ public class Account extends AbstractEntity {
|
||||
SECURITY_ERROR(true),
|
||||
INCOMPATIBLE_SERVER(true);
|
||||
|
||||
private boolean isError;
|
||||
private final boolean isError;
|
||||
|
||||
public boolean isError() {
|
||||
return this.isError;
|
||||
@ -120,6 +122,7 @@ public class Account extends AbstractEntity {
|
||||
private String otrFingerprint;
|
||||
private final Roster roster = new Roster(this);
|
||||
private List<Bookmark> bookmarks = new CopyOnWriteArrayList<>();
|
||||
private final Collection<Jid> blocklist = new CopyOnWriteArraySet<>();
|
||||
|
||||
public Account() {
|
||||
this.uuid = "0";
|
||||
@ -279,7 +282,7 @@ public class Account extends AbstractEntity {
|
||||
return values;
|
||||
}
|
||||
|
||||
public void initOtrEngine(XmppConnectionService context) {
|
||||
public void initOtrEngine(final XmppConnectionService context) {
|
||||
this.otrEngine = new OtrEngine(context, this);
|
||||
}
|
||||
|
||||
@ -291,7 +294,7 @@ public class Account extends AbstractEntity {
|
||||
return this.xmppConnection;
|
||||
}
|
||||
|
||||
public void setXmppConnection(XmppConnection connection) {
|
||||
public void setXmppConnection(final XmppConnection connection) {
|
||||
this.xmppConnection = connection;
|
||||
}
|
||||
|
||||
@ -323,7 +326,7 @@ public class Account extends AbstractEntity {
|
||||
}
|
||||
}
|
||||
|
||||
public void setRosterVersion(String version) {
|
||||
public void setRosterVersion(final String version) {
|
||||
this.rosterVersion = version;
|
||||
}
|
||||
|
||||
@ -351,7 +354,7 @@ public class Account extends AbstractEntity {
|
||||
return this.bookmarks;
|
||||
}
|
||||
|
||||
public void setBookmarks(List<Bookmark> bookmarks) {
|
||||
public void setBookmarks(final List<Bookmark> bookmarks) {
|
||||
this.bookmarks = bookmarks;
|
||||
}
|
||||
|
||||
@ -399,4 +402,21 @@ public class Account extends AbstractEntity {
|
||||
return "xmpp:" + this.getJid().toBareJid().toString();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBlocked(final ListItem contact) {
|
||||
final Jid jid = contact.getJid();
|
||||
return jid != null && (blocklist.contains(jid.toBareJid()) || blocklist.contains(jid.toDomainJid()));
|
||||
}
|
||||
|
||||
public boolean isBlocked(final Jid jid) {
|
||||
return jid != null && blocklist.contains(jid.toBareJid());
|
||||
}
|
||||
|
||||
public Collection<Jid> getBlocklist() {
|
||||
return this.blocklist;
|
||||
}
|
||||
|
||||
public void clearBlocklist() {
|
||||
getBlocklist().clear();
|
||||
}
|
||||
}
|
||||
|
11
src/main/java/eu/siacs/conversations/entities/Blockable.java
Normal file
11
src/main/java/eu/siacs/conversations/entities/Blockable.java
Normal file
@ -0,0 +1,11 @@
|
||||
package eu.siacs.conversations.entities;
|
||||
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
|
||||
public interface Blockable {
|
||||
public boolean isBlocked();
|
||||
public boolean isDomainBlocked();
|
||||
public Jid getBlockedJid();
|
||||
public Jid getJid();
|
||||
public Account getAccount();
|
||||
}
|
@ -6,7 +6,6 @@ import java.util.Locale;
|
||||
|
||||
import eu.siacs.conversations.utils.UIHelper;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
|
||||
public class Bookmark extends Element implements ListItem {
|
||||
|
@ -16,7 +16,7 @@ import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
|
||||
public class Contact implements ListItem {
|
||||
public class Contact implements ListItem, Blockable {
|
||||
public static final String TABLENAME = "contacts";
|
||||
|
||||
public static final String SYSTEMNAME = "systemname";
|
||||
@ -122,11 +122,10 @@ public class Contact implements ListItem {
|
||||
|
||||
@Override
|
||||
public List<Tag> getTags() {
|
||||
ArrayList<Tag> tags = new ArrayList<Tag>();
|
||||
for (String group : getGroups()) {
|
||||
final ArrayList<Tag> tags = new ArrayList<>();
|
||||
for (final String group : getGroups()) {
|
||||
tags.add(new Tag(group, UIHelper.getColorForName(group)));
|
||||
}
|
||||
int status = getMostAvailableStatus();
|
||||
switch (getMostAvailableStatus()) {
|
||||
case Presences.CHAT:
|
||||
case Presences.ONLINE:
|
||||
@ -142,6 +141,9 @@ public class Contact implements ListItem {
|
||||
tags.add(new Tag("dnd", 0xffe51c23));
|
||||
break;
|
||||
}
|
||||
if (isBlocked()) {
|
||||
tags.add(new Tag("blocked", 0xff2e2f3b));
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
@ -176,7 +178,7 @@ public class Contact implements ListItem {
|
||||
}
|
||||
|
||||
public ContentValues getContentValues() {
|
||||
ContentValues values = new ContentValues();
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(ACCOUNT, accountUuid);
|
||||
values.put(SYSTEMNAME, systemName);
|
||||
values.put(SERVERNAME, serverName);
|
||||
@ -213,11 +215,11 @@ public class Contact implements ListItem {
|
||||
this.presences = pres;
|
||||
}
|
||||
|
||||
public void updatePresence(String resource, int status) {
|
||||
public void updatePresence(final String resource, final int status) {
|
||||
this.presences.updatePresence(resource, status);
|
||||
}
|
||||
|
||||
public void removePresence(String resource) {
|
||||
public void removePresence(final String resource) {
|
||||
this.presences.removePresence(resource);
|
||||
}
|
||||
|
||||
@ -457,22 +459,40 @@ public class Contact implements ListItem {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlocked() {
|
||||
return getAccount().isBlocked(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDomainBlocked() {
|
||||
return getAccount().isBlocked(this.getJid().toDomainJid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jid getBlockedJid() {
|
||||
if (isDomainBlocked()) {
|
||||
return getJid().toDomainJid();
|
||||
} else {
|
||||
return getJid();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Lastseen {
|
||||
public long time;
|
||||
public String presence;
|
||||
|
||||
public Lastseen() {
|
||||
time = 0;
|
||||
presence = null;
|
||||
this(null, 0);
|
||||
}
|
||||
|
||||
public Lastseen(final String presence, final long time) {
|
||||
this.time = time;
|
||||
this.presence = presence;
|
||||
this.time = time;
|
||||
}
|
||||
}
|
||||
|
||||
public class Options {
|
||||
public final class Options {
|
||||
public static final int TO = 0;
|
||||
public static final int FROM = 1;
|
||||
public static final int ASKING = 2;
|
||||
|
@ -3,7 +3,6 @@ package eu.siacs.conversations.entities;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
import net.java.otr4j.OtrException;
|
||||
import net.java.otr4j.crypto.OtrCryptoEngineImpl;
|
||||
@ -25,7 +24,7 @@ import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
|
||||
public class Conversation extends AbstractEntity {
|
||||
public class Conversation extends AbstractEntity implements Blockable {
|
||||
public static final String TABLENAME = "conversations";
|
||||
|
||||
public static final int STATUS_AVAILABLE = 0;
|
||||
@ -174,13 +173,29 @@ public class Conversation extends AbstractEntity {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void populateWithMessages(List<Message> messages) {
|
||||
public void populateWithMessages(final List<Message> messages) {
|
||||
synchronized (this.messages) {
|
||||
messages.clear();
|
||||
messages.addAll(this.messages);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlocked() {
|
||||
return getContact().isBlocked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDomainBlocked() {
|
||||
return getContact().isDomainBlocked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jid getBlockedJid() {
|
||||
return getContact().getBlockedJid();
|
||||
}
|
||||
|
||||
|
||||
public interface OnMessageFound {
|
||||
public void onMessageFound(final Message message);
|
||||
}
|
||||
@ -267,7 +282,7 @@ public class Conversation extends AbstractEntity {
|
||||
if (generatedName != null) {
|
||||
return generatedName;
|
||||
} else {
|
||||
return getContactJid().getLocalpart();
|
||||
return getJid().getLocalpart();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -287,11 +302,12 @@ public class Conversation extends AbstractEntity {
|
||||
return this.account.getRoster().getContact(this.contactJid);
|
||||
}
|
||||
|
||||
public void setAccount(Account account) {
|
||||
public void setAccount(final Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public Jid getContactJid() {
|
||||
@Override
|
||||
public Jid getJid() {
|
||||
return this.contactJid;
|
||||
}
|
||||
|
||||
@ -352,7 +368,7 @@ public class Conversation extends AbstractEntity {
|
||||
if (this.otrSession != null) {
|
||||
return this.otrSession;
|
||||
} else {
|
||||
final SessionID sessionId = new SessionID(this.getContactJid().toBareJid().toString(),
|
||||
final SessionID sessionId = new SessionID(this.getJid().toBareJid().toString(),
|
||||
presence,
|
||||
"xmpp");
|
||||
this.otrSession = new SessionImpl(sessionId, getAccount().getOtrEngine());
|
||||
|
@ -12,10 +12,10 @@ public interface ListItem extends Comparable<ListItem> {
|
||||
public List<Tag> getTags();
|
||||
|
||||
public final class Tag {
|
||||
private String name;
|
||||
private int color;
|
||||
private final String name;
|
||||
private final int color;
|
||||
|
||||
public Tag(String name, int color) {
|
||||
public Tag(final String name, final int color) {
|
||||
this.name = name;
|
||||
this.color = color;
|
||||
}
|
||||
@ -28,4 +28,6 @@ public interface ListItem extends Comparable<ListItem> {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean match(final String needle);
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public class Message extends AbstractEntity {
|
||||
public Message(Conversation conversation, String body, int encryption, int status) {
|
||||
this(java.util.UUID.randomUUID().toString(),
|
||||
conversation.getUuid(),
|
||||
conversation.getContactJid() == null ? null : conversation.getContactJid().toBareJid(),
|
||||
conversation.getJid() == null ? null : conversation.getJid().toBareJid(),
|
||||
null,
|
||||
body,
|
||||
System.currentTimeMillis(),
|
||||
|
@ -179,7 +179,7 @@ public class MucOptions {
|
||||
user.setAffiliation(item.getAttribute("affiliation"));
|
||||
user.setRole(item.getAttribute("role"));
|
||||
user.setJid(item.getAttributeAsJid("jid"));
|
||||
if (codes.contains(STATUS_CODE_SELF_PRESENCE) || packet.getFrom().equals(this.conversation.getContactJid())) {
|
||||
if (codes.contains(STATUS_CODE_SELF_PRESENCE) || packet.getFrom().equals(this.conversation.getJid())) {
|
||||
this.isOnline = true;
|
||||
this.error = ERROR_NO_ERROR;
|
||||
self = user;
|
||||
@ -211,7 +211,7 @@ public class MucOptions {
|
||||
}
|
||||
} else if (type.equals("unavailable")) {
|
||||
if (codes.contains(STATUS_CODE_SELF_PRESENCE) ||
|
||||
packet.getFrom().equals(this.conversation.getContactJid())) {
|
||||
packet.getFrom().equals(this.conversation.getJid())) {
|
||||
if (codes.contains(STATUS_CODE_CHANGED_NICK)) {
|
||||
this.mNickChangingInProgress = true;
|
||||
} else if (codes.contains(STATUS_CODE_KICKED)) {
|
||||
@ -282,8 +282,8 @@ public class MucOptions {
|
||||
&& conversation.getBookmark().getNick() != null
|
||||
&& !conversation.getBookmark().getNick().isEmpty()) {
|
||||
return conversation.getBookmark().getNick();
|
||||
} else if (!conversation.getContactJid().isBareJid()) {
|
||||
return conversation.getContactJid().getResourcepart();
|
||||
} else if (!conversation.getJid().isBareJid()) {
|
||||
return conversation.getJid().getResourcepart();
|
||||
} else {
|
||||
return account.getUsername();
|
||||
}
|
||||
@ -389,7 +389,7 @@ public class MucOptions {
|
||||
|
||||
public Jid createJoinJid(String nick) {
|
||||
try {
|
||||
return Jid.fromString(this.conversation.getContactJid().toBareJid().toString() + "/"+nick);
|
||||
return Jid.fromString(this.conversation.getJid().toBareJid().toString() + "/"+nick);
|
||||
} catch (final InvalidJidException e) {
|
||||
return null;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
|
||||
public class Roster {
|
||||
Account account;
|
||||
final Account account;
|
||||
final ConcurrentHashMap<String, Contact> contacts = new ConcurrentHashMap<>();
|
||||
private String version = null;
|
||||
|
||||
@ -19,7 +19,7 @@ public class Roster {
|
||||
if (jid == null) {
|
||||
return null;
|
||||
}
|
||||
Contact contact = contacts.get(jid.toBareJid().toString());
|
||||
final Contact contact = contacts.get(jid.toBareJid().toString());
|
||||
if (contact != null && contact.showInRoster()) {
|
||||
return contact;
|
||||
} else {
|
||||
@ -32,7 +32,7 @@ public class Roster {
|
||||
if (contacts.containsKey(bareJid.toString())) {
|
||||
return contacts.get(bareJid.toString());
|
||||
} else {
|
||||
Contact contact = new Contact(bareJid);
|
||||
final Contact contact = new Contact(bareJid);
|
||||
contact.setAccount(account);
|
||||
contacts.put(bareJid.toString(), contact);
|
||||
return contact;
|
||||
@ -46,13 +46,13 @@ public class Roster {
|
||||
}
|
||||
|
||||
public void markAllAsNotInRoster() {
|
||||
for (Contact contact : getContacts()) {
|
||||
for (final Contact contact : getContacts()) {
|
||||
contact.resetOption(Contact.Options.IN_ROSTER);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearSystemAccounts() {
|
||||
for (Contact contact : getContacts()) {
|
||||
for (final Contact contact : getContacts()) {
|
||||
contact.setPhotoUri(null);
|
||||
contact.setSystemName(null);
|
||||
contact.setSystemAccount(null);
|
||||
|
@ -1,14 +1,12 @@
|
||||
package eu.siacs.conversations.generator;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.services.MessageArchiveService;
|
||||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
import eu.siacs.conversations.utils.Xmlns;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.forms.Data;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
@ -17,44 +15,44 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||
|
||||
public class IqGenerator extends AbstractGenerator {
|
||||
|
||||
public IqGenerator(XmppConnectionService service) {
|
||||
public IqGenerator(final XmppConnectionService service) {
|
||||
super(service);
|
||||
}
|
||||
|
||||
public IqPacket discoResponse(IqPacket request) {
|
||||
IqPacket packet = new IqPacket(IqPacket.TYPE_RESULT);
|
||||
public IqPacket discoResponse(final IqPacket request) {
|
||||
final IqPacket packet = new IqPacket(IqPacket.TYPE_RESULT);
|
||||
packet.setId(request.getId());
|
||||
packet.setTo(request.getFrom());
|
||||
Element query = packet.addChild("query",
|
||||
final Element query = packet.addChild("query",
|
||||
"http://jabber.org/protocol/disco#info");
|
||||
query.setAttribute("node", request.query().getAttribute("node"));
|
||||
Element identity = query.addChild("identity");
|
||||
final Element identity = query.addChild("identity");
|
||||
identity.setAttribute("category", "client");
|
||||
identity.setAttribute("type", this.IDENTITY_TYPE);
|
||||
identity.setAttribute("name", IDENTITY_NAME);
|
||||
List<String> features = Arrays.asList(FEATURES);
|
||||
final List<String> features = Arrays.asList(FEATURES);
|
||||
Collections.sort(features);
|
||||
for (String feature : features) {
|
||||
for (final String feature : features) {
|
||||
query.addChild("feature").setAttribute("var", feature);
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
protected IqPacket publish(String node, Element item) {
|
||||
IqPacket packet = new IqPacket(IqPacket.TYPE_SET);
|
||||
Element pubsub = packet.addChild("pubsub",
|
||||
protected IqPacket publish(final String node, final Element item) {
|
||||
final IqPacket packet = new IqPacket(IqPacket.TYPE_SET);
|
||||
final Element pubsub = packet.addChild("pubsub",
|
||||
"http://jabber.org/protocol/pubsub");
|
||||
Element publish = pubsub.addChild("publish");
|
||||
final Element publish = pubsub.addChild("publish");
|
||||
publish.setAttribute("node", node);
|
||||
publish.addChild(item);
|
||||
return packet;
|
||||
}
|
||||
|
||||
protected IqPacket retrieve(String node, Element item) {
|
||||
IqPacket packet = new IqPacket(IqPacket.TYPE_GET);
|
||||
Element pubsub = packet.addChild("pubsub",
|
||||
final IqPacket packet = new IqPacket(IqPacket.TYPE_GET);
|
||||
final Element pubsub = packet.addChild("pubsub",
|
||||
"http://jabber.org/protocol/pubsub");
|
||||
Element items = pubsub.addChild("items");
|
||||
final Element items = pubsub.addChild("items");
|
||||
items.setAttribute("node", node);
|
||||
if (item != null) {
|
||||
items.addChild(item);
|
||||
@ -63,19 +61,19 @@ public class IqGenerator extends AbstractGenerator {
|
||||
}
|
||||
|
||||
public IqPacket publishAvatar(Avatar avatar) {
|
||||
Element item = new Element("item");
|
||||
final Element item = new Element("item");
|
||||
item.setAttribute("id", avatar.sha1sum);
|
||||
Element data = item.addChild("data", "urn:xmpp:avatar:data");
|
||||
final Element data = item.addChild("data", "urn:xmpp:avatar:data");
|
||||
data.setContent(avatar.image);
|
||||
return publish("urn:xmpp:avatar:data", item);
|
||||
}
|
||||
|
||||
public IqPacket publishAvatarMetadata(Avatar avatar) {
|
||||
Element item = new Element("item");
|
||||
public IqPacket publishAvatarMetadata(final Avatar avatar) {
|
||||
final Element item = new Element("item");
|
||||
item.setAttribute("id", avatar.sha1sum);
|
||||
Element metadata = item
|
||||
final Element metadata = item
|
||||
.addChild("metadata", "urn:xmpp:avatar:metadata");
|
||||
Element info = metadata.addChild("info");
|
||||
final Element info = metadata.addChild("info");
|
||||
info.setAttribute("bytes", avatar.size);
|
||||
info.setAttribute("id", avatar.sha1sum);
|
||||
info.setAttribute("height", avatar.height);
|
||||
@ -84,10 +82,10 @@ public class IqGenerator extends AbstractGenerator {
|
||||
return publish("urn:xmpp:avatar:metadata", item);
|
||||
}
|
||||
|
||||
public IqPacket retrieveAvatar(Avatar avatar) {
|
||||
Element item = new Element("item");
|
||||
public IqPacket retrieveAvatar(final Avatar avatar) {
|
||||
final Element item = new Element("item");
|
||||
item.setAttribute("id", avatar.sha1sum);
|
||||
IqPacket packet = retrieve("urn:xmpp:avatar:data", item);
|
||||
final IqPacket packet = retrieve("urn:xmpp:avatar:data", item);
|
||||
packet.setTo(avatar.owner);
|
||||
return packet;
|
||||
}
|
||||
@ -100,11 +98,11 @@ public class IqGenerator extends AbstractGenerator {
|
||||
return packet;
|
||||
}
|
||||
|
||||
public IqPacket queryMessageArchiveManagement(MessageArchiveService.Query mam) {
|
||||
public IqPacket queryMessageArchiveManagement(final MessageArchiveService.Query mam) {
|
||||
final IqPacket packet = new IqPacket(IqPacket.TYPE_SET);
|
||||
Element query = packet.query("urn:xmpp:mam:0");
|
||||
final Element query = packet.query("urn:xmpp:mam:0");
|
||||
query.setAttribute("queryid",mam.getQueryId());
|
||||
Data data = new Data();
|
||||
final Data data = new Data();
|
||||
data.setFormType("urn:xmpp:mam:0");
|
||||
if (mam.getWith()!=null) {
|
||||
data.put("with", mam.getWith().toString());
|
||||
@ -119,4 +117,25 @@ public class IqGenerator extends AbstractGenerator {
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
public IqPacket generateGetBlockList() {
|
||||
final IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
|
||||
iq.addChild("blocklist", Xmlns.BLOCKING);
|
||||
|
||||
return iq;
|
||||
}
|
||||
|
||||
public IqPacket generateSetBlockRequest(final Jid jid) {
|
||||
final IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
|
||||
final Element block = iq.addChild("block", Xmlns.BLOCKING);
|
||||
block.addChild("item").setAttribute("jid", jid.toBareJid().toString());
|
||||
return iq;
|
||||
}
|
||||
|
||||
public IqPacket generateSetUnblockRequest(final Jid jid) {
|
||||
final IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
|
||||
final Element block = iq.addChild("unblock", Xmlns.BLOCKING);
|
||||
block.addChild("item").setAttribute("jid", jid.toBareJid().toString());
|
||||
return iq;
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ public class MessageGenerator extends AbstractGenerator {
|
||||
String subject) {
|
||||
MessagePacket packet = new MessagePacket();
|
||||
packet.setType(MessagePacket.TYPE_GROUPCHAT);
|
||||
packet.setTo(conversation.getContactJid().toBareJid());
|
||||
packet.setTo(conversation.getJid().toBareJid());
|
||||
Element subjectChild = new Element("subject");
|
||||
subjectChild.setContent(subject);
|
||||
packet.addChild(subjectChild);
|
||||
@ -149,13 +149,13 @@ public class MessageGenerator extends AbstractGenerator {
|
||||
packet.setTo(contact);
|
||||
packet.setFrom(conversation.getAccount().getJid());
|
||||
Element x = packet.addChild("x", "jabber:x:conference");
|
||||
x.setAttribute("jid", conversation.getContactJid().toBareJid().toString());
|
||||
x.setAttribute("jid", conversation.getJid().toBareJid().toString());
|
||||
return packet;
|
||||
}
|
||||
|
||||
public MessagePacket invite(Conversation conversation, Jid contact) {
|
||||
MessagePacket packet = new MessagePacket();
|
||||
packet.setTo(conversation.getContactJid().toBareJid());
|
||||
packet.setTo(conversation.getJid().toBareJid());
|
||||
packet.setFrom(conversation.getAccount().getJid());
|
||||
Element x = new Element("x");
|
||||
x.setAttribute("xmlns", "http://jabber.org/protocol/muc#user");
|
||||
|
@ -53,10 +53,10 @@ public abstract class AbstractParser {
|
||||
|
||||
protected void updateLastseen(final Element packet, final Account account,
|
||||
final boolean presenceOverwrite) {
|
||||
Jid from = packet.getAttributeAsJid("from");
|
||||
String presence = from == null || from.isBareJid() ? "" : from.getResourcepart();
|
||||
Contact contact = account.getRoster().getContact(from);
|
||||
long timestamp = getTimestamp(packet);
|
||||
final Jid from = packet.getAttributeAsJid("from");
|
||||
final String presence = from == null || from.isBareJid() ? "" : from.getResourcepart();
|
||||
final Contact contact = account.getRoster().getContact(from);
|
||||
final long timestamp = getTimestamp(packet);
|
||||
if (timestamp >= contact.lastseen.time) {
|
||||
contact.lastseen.time = timestamp;
|
||||
if (!presence.isEmpty() && presenceOverwrite) {
|
||||
|
@ -2,36 +2,40 @@ package eu.siacs.conversations.parser;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Contact;
|
||||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
import eu.siacs.conversations.utils.Xmlns;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||
|
||||
public class IqParser extends AbstractParser implements OnIqPacketReceived {
|
||||
|
||||
public IqParser(XmppConnectionService service) {
|
||||
public IqParser(final XmppConnectionService service) {
|
||||
super(service);
|
||||
}
|
||||
|
||||
public void rosterItems(Account account, Element query) {
|
||||
String version = query.getAttribute("ver");
|
||||
public void rosterItems(final Account account, final Element query) {
|
||||
final String version = query.getAttribute("ver");
|
||||
if (version != null) {
|
||||
account.getRoster().setVersion(version);
|
||||
}
|
||||
for (Element item : query.getChildren()) {
|
||||
for (final Element item : query.getChildren()) {
|
||||
if (item.getName().equals("item")) {
|
||||
final Jid jid = item.getAttributeAsJid("jid");
|
||||
if (jid == null) {
|
||||
continue;
|
||||
}
|
||||
String name = item.getAttribute("name");
|
||||
String subscription = item.getAttribute("subscription");
|
||||
Contact contact = account.getRoster().getContact(jid);
|
||||
final String name = item.getAttribute("name");
|
||||
final String subscription = item.getAttribute("subscription");
|
||||
final Contact contact = account.getRoster().getContact(jid);
|
||||
if (!contact.getOption(Contact.Options.DIRTY_PUSH)) {
|
||||
contact.setServerName(name);
|
||||
contact.parseGroupsFromElement(item);
|
||||
@ -54,13 +58,13 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
|
||||
mXmppConnectionService.updateRosterUi();
|
||||
}
|
||||
|
||||
public String avatarData(IqPacket packet) {
|
||||
Element pubsub = packet.findChild("pubsub",
|
||||
public String avatarData(final IqPacket packet) {
|
||||
final Element pubsub = packet.findChild("pubsub",
|
||||
"http://jabber.org/protocol/pubsub");
|
||||
if (pubsub == null) {
|
||||
return null;
|
||||
}
|
||||
Element items = pubsub.findChild("items");
|
||||
final Element items = pubsub.findChild("items");
|
||||
if (items == null) {
|
||||
return null;
|
||||
}
|
||||
@ -68,13 +72,76 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||
public void onIqPacketReceived(final Account account, final IqPacket packet) {
|
||||
if (packet.hasChild("query", "jabber:iq:roster")) {
|
||||
final Jid from = packet.getFrom();
|
||||
if ((from == null) || (from.equals(account.getJid().toBareJid()))) {
|
||||
Element query = packet.findChild("query");
|
||||
final Element query = packet.findChild("query");
|
||||
this.rosterItems(account, query);
|
||||
}
|
||||
} else if (packet.hasChild("block", Xmlns.BLOCKING) || packet.hasChild("blocklist", Xmlns.BLOCKING)) {
|
||||
// Only accept block list changes from the server.
|
||||
// The server should probably prevent other people from faking a blocklist push,
|
||||
// but just in case let's prevent it client side as well.
|
||||
final Jid from = packet.getFrom();
|
||||
if (from == null || from.equals(account.getServer()) || from.equals(account.getJid().toBareJid())) {
|
||||
Log.d(Config.LOGTAG, "Received blocklist update from server");
|
||||
final Element blocklist = packet.findChild("blocklist", Xmlns.BLOCKING);
|
||||
final Element block = packet.findChild("block", Xmlns.BLOCKING);
|
||||
final Collection<Element> items = blocklist != null ? blocklist.getChildren() :
|
||||
(block != null ? block.getChildren() : null);
|
||||
// If this is a response to a blocklist query, clear the block list and replace with the new one.
|
||||
// Otherwise, just update the existing blocklist.
|
||||
if (packet.getType() == IqPacket.TYPE_RESULT) {
|
||||
account.clearBlocklist();
|
||||
}
|
||||
if (items != null) {
|
||||
final Collection<Jid> jids = new ArrayList<>(items.size());
|
||||
// Create a collection of Jids from the packet
|
||||
for (final Element item : items) {
|
||||
if (item.getName().equals("item")) {
|
||||
final Jid jid = item.getAttributeAsJid("jid");
|
||||
if (jid != null) {
|
||||
jids.add(jid);
|
||||
}
|
||||
}
|
||||
}
|
||||
account.getBlocklist().addAll(jids);
|
||||
}
|
||||
// Update the UI
|
||||
mXmppConnectionService.updateBlocklistUi(OnUpdateBlocklist.Status.BLOCKED);
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, "Received blocklist update from invalid jid: " + from.toString());
|
||||
}
|
||||
} else if (packet.hasChild("unblock", Xmlns.BLOCKING)) {
|
||||
final Jid from = packet.getFrom();
|
||||
if ((from == null || from.equals(account.getServer()) || from.equals(account.getJid().toBareJid())) &&
|
||||
packet.getType() == IqPacket.TYPE_SET) {
|
||||
Log.d(Config.LOGTAG, "Received unblock update from server");
|
||||
final Collection<Element> items = packet.getChildren().get(0).getChildren();
|
||||
if (items.size() == 0) {
|
||||
// No children to unblock == unblock all
|
||||
account.getBlocklist().clear();
|
||||
} else {
|
||||
final Collection<Jid> jids = new ArrayList<>(items.size());
|
||||
for (final Element item : items) {
|
||||
if (item.getName().equals("item")) {
|
||||
final Jid jid = item.getAttributeAsJid("jid");
|
||||
if (jid != null) {
|
||||
jids.add(jid);
|
||||
}
|
||||
}
|
||||
}
|
||||
account.getBlocklist().removeAll(jids);
|
||||
mXmppConnectionService.updateBlocklistUi(OnUpdateBlocklist.Status.UNBLOCKED);
|
||||
}
|
||||
} else {
|
||||
if (packet.getType() == IqPacket.TYPE_SET) {
|
||||
Log.d(Config.LOGTAG, "Received unblock update from invalid jid " + from.toString());
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, "Received unblock update with invalid type " + packet.getType());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (packet.getFrom() == null) {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": received iq with invalid from "+packet.toString());
|
||||
@ -84,17 +151,17 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
|
||||
mXmppConnectionService.getJingleConnectionManager()
|
||||
.deliverIbbPacket(account, packet);
|
||||
} else if (packet.hasChild("query", "http://jabber.org/protocol/disco#info")) {
|
||||
IqPacket response = mXmppConnectionService.getIqGenerator()
|
||||
final IqPacket response = mXmppConnectionService.getIqGenerator()
|
||||
.discoResponse(packet);
|
||||
account.getXmppConnection().sendIqPacket(response, null);
|
||||
} else if (packet.hasChild("ping", "urn:xmpp:ping")) {
|
||||
IqPacket response = packet.generateRespone(IqPacket.TYPE_RESULT);
|
||||
final IqPacket response = packet.generateRespone(IqPacket.TYPE_RESULT);
|
||||
mXmppConnectionService.sendIqPacket(account, response, null);
|
||||
} else {
|
||||
if ((packet.getType() == IqPacket.TYPE_GET)
|
||||
|| (packet.getType() == IqPacket.TYPE_SET)) {
|
||||
IqPacket response = packet.generateRespone(IqPacket.TYPE_ERROR);
|
||||
Element error = response.addChild("error");
|
||||
final IqPacket response = packet.generateRespone(IqPacket.TYPE_ERROR);
|
||||
final Element error = response.addChild("error");
|
||||
error.setAttribute("type", "cancel");
|
||||
error.addChild("feature-not-implemented",
|
||||
"urn:ietf:params:xml:ns:xmpp-stanzas");
|
||||
|
@ -228,9 +228,9 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||
return conversation;
|
||||
}
|
||||
|
||||
public void updateConversation(Conversation conversation) {
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
String[] args = { conversation.getUuid() };
|
||||
public void updateConversation(final Conversation conversation) {
|
||||
final SQLiteDatabase db = this.getWritableDatabase();
|
||||
final String[] args = { conversation.getUuid() };
|
||||
db.update(Conversation.TABLENAME, conversation.getContentValues(),
|
||||
Conversation.UUID + "=?", args);
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
||||
public Query(Conversation conversation, long start, long end) {
|
||||
this(conversation.getAccount(), start, end);
|
||||
this.conversation = conversation;
|
||||
this.with = conversation.getContactJid().toBareJid();
|
||||
this.with = conversation.getJid().toBareJid();
|
||||
}
|
||||
|
||||
public Query(Conversation conversation, long start, long end, PagingOrder order) {
|
||||
|
@ -35,11 +35,13 @@ import org.openintents.openpgp.util.OpenPgpServiceConnection;
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import de.duenndns.ssl.MemorizingTrustManager;
|
||||
@ -47,11 +49,11 @@ import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.PgpEngine;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Blockable;
|
||||
import eu.siacs.conversations.entities.Bookmark;
|
||||
import eu.siacs.conversations.entities.Contact;
|
||||
import eu.siacs.conversations.entities.Conversation;
|
||||
import eu.siacs.conversations.entities.Downloadable;
|
||||
import eu.siacs.conversations.entities.DownloadableFile;
|
||||
import eu.siacs.conversations.entities.DownloadablePlaceholder;
|
||||
import eu.siacs.conversations.entities.Message;
|
||||
import eu.siacs.conversations.entities.MucOptions;
|
||||
@ -77,7 +79,11 @@ import eu.siacs.conversations.xmpp.OnBindListener;
|
||||
import eu.siacs.conversations.xmpp.OnContactStatusChanged;
|
||||
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||
import eu.siacs.conversations.xmpp.OnMessageAcknowledged;
|
||||
import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
|
||||
import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
|
||||
import eu.siacs.conversations.xmpp.OnStatusChanged;
|
||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||
import eu.siacs.conversations.xmpp.PacketReceived;
|
||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||
import eu.siacs.conversations.xmpp.forms.Data;
|
||||
import eu.siacs.conversations.xmpp.forms.Field;
|
||||
@ -93,9 +99,10 @@ import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
||||
|
||||
public class XmppConnectionService extends Service implements OnPhoneContactsLoadedListener {
|
||||
|
||||
public static String ACTION_CLEAR_NOTIFICATION = "clear_notification";
|
||||
private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
|
||||
public static String ACTION_DISABLE_FOREGROUND = "disable_foreground";
|
||||
public static final String ACTION_CLEAR_NOTIFICATION = "clear_notification";
|
||||
private static final String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
|
||||
public static final String ACTION_DISABLE_FOREGROUND = "disable_foreground";
|
||||
|
||||
private ContentObserver contactObserver = new ContentObserver(null) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
@ -129,13 +136,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
private MemorizingTrustManager mMemorizingTrustManager;
|
||||
private NotificationService mNotificationService = new NotificationService(
|
||||
this);
|
||||
private MessageParser mMessageParser = new MessageParser(this);
|
||||
private PresenceParser mPresenceParser = new PresenceParser(this);
|
||||
private OnMessagePacketReceived mMessageParser = new MessageParser(this);
|
||||
private OnPresencePacketReceived mPresenceParser = new PresenceParser(this);
|
||||
private IqParser mIqParser = new IqParser(this);
|
||||
private MessageGenerator mMessageGenerator = new MessageGenerator(this);
|
||||
private PresenceGenerator mPresenceGenerator = new PresenceGenerator(this);
|
||||
private List<Account> accounts;
|
||||
private final CopyOnWriteArrayList<Conversation> conversations = new CopyOnWriteArrayList<Conversation>();
|
||||
private final List<Conversation> conversations = new CopyOnWriteArrayList<>();
|
||||
private JingleConnectionManager mJingleConnectionManager = new JingleConnectionManager(
|
||||
this);
|
||||
private HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager(
|
||||
@ -208,6 +215,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
|
||||
private int accountChangedListenerCount = 0;
|
||||
private OnRosterUpdate mOnRosterUpdate = null;
|
||||
private OnUpdateBlocklist mOnUpdateBlocklist = null;
|
||||
private int updateBlocklistListenerCount = 0;
|
||||
private int rosterChangedListenerCount = 0;
|
||||
private OnMucRosterUpdate mOnMucRosterUpdate = null;
|
||||
private int mucRosterChangedListenerCount = 0;
|
||||
@ -354,13 +363,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
DownloadableFile file = getFileBackend().copyImageToPrivateStorage(message, uri);
|
||||
getFileBackend().copyImageToPrivateStorage(message, uri);
|
||||
if (conversation.getNextEncryption(forceEncryption()) == Message.ENCRYPTION_PGP) {
|
||||
getPgpEngine().encrypt(message, callback);
|
||||
} else {
|
||||
callback.success(message);
|
||||
}
|
||||
} catch (FileBackend.FileCopyException e) {
|
||||
} catch (final FileBackend.FileCopyException e) {
|
||||
callback.error(e.getResId(), message);
|
||||
}
|
||||
}
|
||||
@ -573,11 +582,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
|
||||
}
|
||||
|
||||
public XmppConnection createConnection(Account account) {
|
||||
SharedPreferences sharedPref = getPreferences();
|
||||
public XmppConnection createConnection(final Account account) {
|
||||
final SharedPreferences sharedPref = getPreferences();
|
||||
account.setResource(sharedPref.getString("resource", "mobile")
|
||||
.toLowerCase(Locale.getDefault()));
|
||||
XmppConnection connection = new XmppConnection(account, this);
|
||||
final XmppConnection connection = new XmppConnection(account, this);
|
||||
connection.setOnMessagePacketReceivedListener(this.mMessageParser);
|
||||
connection.setOnStatusChangedListener(this.statusListener);
|
||||
connection.setOnPresencePacketReceivedListener(this.mPresenceParser);
|
||||
@ -589,10 +598,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void sendMessage(Message message) {
|
||||
Account account = message.getConversation().getAccount();
|
||||
public void sendMessage(final Message message) {
|
||||
final Account account = message.getConversation().getAccount();
|
||||
account.deactivateGracePeriod();
|
||||
Conversation conv = message.getConversation();
|
||||
final Conversation conv = message.getConversation();
|
||||
MessagePacket packet = null;
|
||||
boolean saveInDb = true;
|
||||
boolean send = false;
|
||||
@ -694,7 +703,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
updateConversationUi();
|
||||
}
|
||||
|
||||
private void sendUnsentMessages(Conversation conversation) {
|
||||
private void sendUnsentMessages(final Conversation conversation) {
|
||||
conversation.findWaitingMessages(new Conversation.OnMessageFound() {
|
||||
|
||||
@Override
|
||||
@ -704,7 +713,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
});
|
||||
}
|
||||
|
||||
private void resendMessage(Message message) {
|
||||
private void resendMessage(final Message message) {
|
||||
Account account = message.getConversation().getAccount();
|
||||
MessagePacket packet = null;
|
||||
if (message.getEncryption() == Message.ENCRYPTION_OTR) {
|
||||
@ -731,7 +740,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
} else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) {
|
||||
mJingleConnectionManager.createNewConnection(message);
|
||||
}
|
||||
} catch (InvalidJidException e) {
|
||||
} catch (final InvalidJidException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -774,8 +783,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
}
|
||||
}
|
||||
|
||||
public void fetchRosterFromServer(Account account) {
|
||||
IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
|
||||
public void fetchRosterFromServer(final Account account) {
|
||||
final IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
|
||||
if (!"".equals(account.getRosterVersion())) {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid()
|
||||
+ ": fetching roster version " + account.getRosterVersion());
|
||||
@ -789,8 +798,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(final Account account,
|
||||
IqPacket packet) {
|
||||
Element query = packet.findChild("query");
|
||||
final IqPacket packet) {
|
||||
final Element query = packet.findChild("query");
|
||||
if (query != null) {
|
||||
account.getRoster().markAllAsNotInRoster();
|
||||
mIqParser.rosterItems(account, query);
|
||||
@ -799,22 +808,22 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
});
|
||||
}
|
||||
|
||||
public void fetchBookmarks(Account account) {
|
||||
IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
|
||||
Element query = iqPacket.query("jabber:iq:private");
|
||||
public void fetchBookmarks(final Account account) {
|
||||
final IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
|
||||
final Element query = iqPacket.query("jabber:iq:private");
|
||||
query.addChild("storage", "storage:bookmarks");
|
||||
OnIqPacketReceived callback = new OnIqPacketReceived() {
|
||||
final PacketReceived callback = new OnIqPacketReceived() {
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||
Element query = packet.query();
|
||||
List<Bookmark> bookmarks = new CopyOnWriteArrayList<>();
|
||||
Element storage = query.findChild("storage",
|
||||
public void onIqPacketReceived(final Account account, final IqPacket packet) {
|
||||
final Element query = packet.query();
|
||||
final List<Bookmark> bookmarks = new CopyOnWriteArrayList<>();
|
||||
final Element storage = query.findChild("storage",
|
||||
"storage:bookmarks");
|
||||
if (storage != null) {
|
||||
for (Element item : storage.getChildren()) {
|
||||
for (final Element item : storage.getChildren()) {
|
||||
if (item.getName().equals("conference")) {
|
||||
Bookmark bookmark = Bookmark.parse(item, account);
|
||||
final Bookmark bookmark = Bookmark.parse(item, account);
|
||||
bookmarks.add(bookmark);
|
||||
Conversation conversation = find(bookmark);
|
||||
if (conversation != null) {
|
||||
@ -832,7 +841,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
}
|
||||
};
|
||||
sendIqPacket(account, iqPacket, callback);
|
||||
|
||||
}
|
||||
|
||||
public void pushBookmarks(Account account) {
|
||||
@ -885,7 +893,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
|
||||
private void initConversations() {
|
||||
synchronized (this.conversations) {
|
||||
Hashtable<String, Account> accountLookupTable = new Hashtable<>();
|
||||
final Map<String, Account> accountLookupTable = new Hashtable<>();
|
||||
for (Account account : this.accounts) {
|
||||
accountLookupTable.put(account.getUuid(), account);
|
||||
}
|
||||
@ -992,8 +1000,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
return this.accounts;
|
||||
}
|
||||
|
||||
public Conversation find(List<Conversation> haystack, Contact contact) {
|
||||
for (Conversation conversation : haystack) {
|
||||
public Conversation find(final Iterable<Conversation> haystack, final Contact contact) {
|
||||
for (final Conversation conversation : haystack) {
|
||||
if (conversation.getContact() == contact) {
|
||||
return conversation;
|
||||
}
|
||||
@ -1001,15 +1009,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
return null;
|
||||
}
|
||||
|
||||
public Conversation find(final List<Conversation> haystack,
|
||||
final Account account,
|
||||
final Jid jid) {
|
||||
public Conversation find(final Iterable<Conversation> haystack, final Account account, final Jid jid) {
|
||||
if (jid == null ) {
|
||||
return null;
|
||||
}
|
||||
for (Conversation conversation : haystack) {
|
||||
for (final Conversation conversation : haystack) {
|
||||
if ((account == null || conversation.getAccount() == account)
|
||||
&& (conversation.getContactJid().toBareJid().equals(jid.toBareJid()))) {
|
||||
&& (conversation.getJid().toBareJid().equals(jid.toBareJid()))) {
|
||||
return conversation;
|
||||
}
|
||||
}
|
||||
@ -1177,7 +1183,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnRosterUpdateListener(OnRosterUpdate listener) {
|
||||
public void setOnRosterUpdateListener(final OnRosterUpdate listener) {
|
||||
synchronized (this) {
|
||||
if (checkListeners()) {
|
||||
switchToForeground();
|
||||
@ -1202,6 +1208,31 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnUpdateBlocklistListener(final OnUpdateBlocklist listener) {
|
||||
synchronized (this) {
|
||||
if (checkListeners()) {
|
||||
switchToForeground();
|
||||
}
|
||||
this.mOnUpdateBlocklist = listener;
|
||||
if (this.updateBlocklistListenerCount < 2) {
|
||||
this.updateBlocklistListenerCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeOnUpdateBlocklistListener() {
|
||||
synchronized (this) {
|
||||
this.updateBlocklistListenerCount--;
|
||||
if (this.updateBlocklistListenerCount <= 0) {
|
||||
this.updateBlocklistListenerCount = 0;
|
||||
this.mOnUpdateBlocklist = null;
|
||||
if (checkListeners()) {
|
||||
switchToBackground();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnMucRosterUpdateListener(OnMucRosterUpdate listener) {
|
||||
synchronized (this) {
|
||||
if (checkListeners()) {
|
||||
@ -1293,7 +1324,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
packet.addChild("x", "jabber:x:signed").setContent(sig);
|
||||
}
|
||||
sendPresencePacket(account, packet);
|
||||
if (!joinJid.equals(conversation.getContactJid())) {
|
||||
if (!joinJid.equals(conversation.getJid())) {
|
||||
conversation.setContactJid(joinJid);
|
||||
databaseBackend.updateConversation(conversation);
|
||||
}
|
||||
@ -1369,14 +1400,14 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
account.pendingConferenceLeaves.remove(conversation);
|
||||
if (account.getStatus() == Account.State.ONLINE) {
|
||||
PresencePacket packet = new PresencePacket();
|
||||
packet.setTo(conversation.getContactJid());
|
||||
packet.setTo(conversation.getJid());
|
||||
packet.setFrom(conversation.getAccount().getJid());
|
||||
packet.setAttribute("type", "unavailable");
|
||||
sendPresencePacket(conversation.getAccount(), packet);
|
||||
conversation.getMucOptions().setOffline();
|
||||
conversation.deregisterWithBookmark();
|
||||
Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid()
|
||||
+ ": leaving muc " + conversation.getContactJid());
|
||||
+ ": leaving muc " + conversation.getJid());
|
||||
} else {
|
||||
account.pendingConferenceLeaves.add(conversation);
|
||||
}
|
||||
@ -1401,7 +1432,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
return null;
|
||||
}
|
||||
|
||||
public void createAdhocConference(final Account account, final List<Jid> jids, final UiCallback<Conversation> callback) {
|
||||
public void createAdhocConference(final Account account, final Iterable<Jid> jids, final UiCallback<Conversation> callback) {
|
||||
Log.d(Config.LOGTAG,account.getJid().toBareJid().toString()+": creating adhoc conference with "+ jids.toString());
|
||||
if (account.getStatus() == Account.State.ONLINE) {
|
||||
try {
|
||||
@ -1454,7 +1485,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
|
||||
public void pushConferenceConfiguration(final Conversation conversation,final Bundle options, final OnConferenceOptionsPushed callback) {
|
||||
IqPacket request = new IqPacket(IqPacket.TYPE_GET);
|
||||
request.setTo(conversation.getContactJid().toBareJid());
|
||||
request.setTo(conversation.getJid().toBareJid());
|
||||
request.query("http://jabber.org/protocol/muc#owner");
|
||||
sendIqPacket(conversation.getAccount(),request,new OnIqPacketReceived() {
|
||||
@Override
|
||||
@ -1468,7 +1499,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
}
|
||||
data.submit();
|
||||
IqPacket set = new IqPacket(IqPacket.TYPE_SET);
|
||||
set.setTo(conversation.getContactJid().toBareJid());
|
||||
set.setTo(conversation.getJid().toBareJid());
|
||||
set.query("http://jabber.org/protocol/muc#owner").addChild(data);
|
||||
sendIqPacket(account, set, new OnIqPacketReceived() {
|
||||
@Override
|
||||
@ -1506,7 +1537,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
if (conversation.endOtrIfNeeded()) {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid()
|
||||
+ ": ended otr session with "
|
||||
+ conversation.getContactJid());
|
||||
+ conversation.getJid());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1552,7 +1583,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
final Session otrSession = conversation.getOtrSession();
|
||||
Log.d(Config.LOGTAG,
|
||||
account.getJid().toBareJid() + " otr session established with "
|
||||
+ conversation.getContactJid() + "/"
|
||||
+ conversation.getJid() + "/"
|
||||
+ otrSession.getSessionID().getUserID());
|
||||
conversation.findUnsentMessagesWithOtrEncryption(new Conversation.OnMessageFound() {
|
||||
|
||||
@ -1848,7 +1879,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
return false;
|
||||
} else {
|
||||
for (Conversation conversation : getConversations()) {
|
||||
if (conversation.getContactJid().equals(recipient)
|
||||
if (conversation.getJid().equals(recipient)
|
||||
&& conversation.getAccount().equals(account)) {
|
||||
return markMessage(conversation, uuid, status);
|
||||
}
|
||||
@ -1922,6 +1953,12 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
}
|
||||
}
|
||||
|
||||
public void updateBlocklistUi(final OnUpdateBlocklist.Status status) {
|
||||
if (mOnUpdateBlocklist != null) {
|
||||
mOnUpdateBlocklist.OnUpdateBlocklist(status);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateMucRosterUi() {
|
||||
if (mOnMucRosterUpdate != null) {
|
||||
mOnMucRosterUpdate.onMucRosterUpdate();
|
||||
@ -2034,9 +2071,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
}
|
||||
}
|
||||
|
||||
public void sendIqPacket(Account account, IqPacket packet,
|
||||
OnIqPacketReceived callback) {
|
||||
XmppConnection connection = account.getXmppConnection();
|
||||
public void sendIqPacket(final Account account, final IqPacket packet, final PacketReceived callback) {
|
||||
final XmppConnection connection = account.getXmppConnection();
|
||||
if (connection != null) {
|
||||
connection.sendIqPacket(packet, callback);
|
||||
}
|
||||
@ -2054,6 +2090,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
return this.mIqGenerator;
|
||||
}
|
||||
|
||||
public IqParser getIqParser() { return this.mIqParser; }
|
||||
|
||||
public JingleConnectionManager getJingleConnectionManager() {
|
||||
return this.mJingleConnectionManager;
|
||||
}
|
||||
@ -2083,8 +2121,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
return this.mHttpConnectionManager;
|
||||
}
|
||||
|
||||
public void resendFailedMessages(Message message) {
|
||||
List<Message> messages = new ArrayList<>();
|
||||
public void resendFailedMessages(final Message message) {
|
||||
final Collection<Message> messages = new ArrayList<>();
|
||||
Message current = message;
|
||||
while (current.getStatus() == Message.STATUS_SEND_FAILED) {
|
||||
messages.add(current);
|
||||
@ -2094,7 +2132,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (Message msg : messages) {
|
||||
for (final Message msg : messages) {
|
||||
markMessage(msg, Message.STATUS_WAITING);
|
||||
this.resendMessage(msg);
|
||||
}
|
||||
@ -2136,4 +2174,35 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||
return XmppConnectionService.this;
|
||||
}
|
||||
}
|
||||
|
||||
public void sendBlockRequest(final Blockable blockable) {
|
||||
if (blockable != null && blockable.getBlockedJid() != null) {
|
||||
final Jid jid = blockable.getBlockedJid();
|
||||
this.sendIqPacket(blockable.getAccount(), getIqGenerator().generateSetBlockRequest(jid), new OnIqPacketReceived() {
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(final Account account, final IqPacket packet) {
|
||||
if (packet.getType() == IqPacket.TYPE_RESULT) {
|
||||
account.getBlocklist().add(jid);
|
||||
updateBlocklistUi(OnUpdateBlocklist.Status.BLOCKED);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void sendUnblockRequest(final Blockable blockable) {
|
||||
if (blockable != null && blockable.getJid() != null) {
|
||||
final Jid jid = blockable.getBlockedJid();
|
||||
this.sendIqPacket(blockable.getAccount(), getIqGenerator().generateSetUnblockRequest(jid), new OnIqPacketReceived() {
|
||||
@Override
|
||||
public void onIqPacketReceived(final Account account, final IqPacket packet) {
|
||||
if (packet.getType() == IqPacket.TYPE_RESULT) {
|
||||
account.getBlocklist().remove(jid);
|
||||
updateBlocklistUi(OnUpdateBlocklist.Status.UNBLOCKED);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,124 @@
|
||||
package eu.siacs.conversations.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.entities.ListItem;
|
||||
import eu.siacs.conversations.ui.adapter.ListItemAdapter;
|
||||
|
||||
public abstract class AbstractSearchableListItemActivity extends XmppActivity {
|
||||
private ListView mListView;
|
||||
private final List<ListItem> listItems = new ArrayList<>();
|
||||
private ArrayAdapter<ListItem> mListItemsAdapter;
|
||||
|
||||
private EditText mSearchEditText;
|
||||
|
||||
private final MenuItem.OnActionExpandListener mOnActionExpandListener = new MenuItem.OnActionExpandListener() {
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemActionExpand(final MenuItem item) {
|
||||
mSearchEditText.post(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mSearchEditText.requestFocus();
|
||||
final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.showSoftInput(mSearchEditText,
|
||||
InputMethodManager.SHOW_IMPLICIT);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemActionCollapse(final MenuItem item) {
|
||||
final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(),
|
||||
InputMethodManager.HIDE_IMPLICIT_ONLY);
|
||||
mSearchEditText.setText("");
|
||||
filterContacts();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private final TextWatcher mSearchTextWatcher = new TextWatcher() {
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(final Editable editable) {
|
||||
filterContacts(editable.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(final CharSequence s, final int start, final int count,
|
||||
final int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(final CharSequence s, final int start, final int before,
|
||||
final int count) {
|
||||
}
|
||||
};
|
||||
|
||||
public ListView getListView() {
|
||||
return mListView;
|
||||
}
|
||||
|
||||
public List<ListItem> getListItems() {
|
||||
return listItems;
|
||||
}
|
||||
|
||||
public EditText getSearchEditText() {
|
||||
return mSearchEditText;
|
||||
}
|
||||
|
||||
public ArrayAdapter<ListItem> getListItemAdapter() {
|
||||
return mListItemsAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_choose_contact);
|
||||
mListView = (ListView) findViewById(R.id.choose_contact_list);
|
||||
mListView.setFastScrollEnabled(true);
|
||||
mListItemsAdapter = new ListItemAdapter(this, listItems);
|
||||
mListView.setAdapter(mListItemsAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.choose_contact, menu);
|
||||
final MenuItem menuSearchView = menu.findItem(R.id.action_search);
|
||||
final View mSearchView = menuSearchView.getActionView();
|
||||
mSearchEditText = (EditText) mSearchView
|
||||
.findViewById(R.id.search_field);
|
||||
mSearchEditText.addTextChangedListener(mSearchTextWatcher);
|
||||
menuSearchView.setOnActionExpandListener(mOnActionExpandListener);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void filterContacts() {
|
||||
filterContacts(null);
|
||||
}
|
||||
|
||||
protected abstract void filterContacts(final String needle);
|
||||
|
||||
@Override
|
||||
void onBackendConnected() {
|
||||
filterContacts();
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package eu.siacs.conversations.ui;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.entities.Blockable;
|
||||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
|
||||
public final class BlockContactDialog {
|
||||
public static void show(final Context context,
|
||||
final XmppConnectionService xmppConnectionService,
|
||||
final Blockable blockable) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
final boolean isBlocked = blockable.isBlocked();
|
||||
builder.setNegativeButton(R.string.cancel, null);
|
||||
|
||||
if (blockable.getJid().isDomainJid() || blockable.getAccount().isBlocked(blockable.getJid().toDomainJid())) {
|
||||
builder.setTitle(isBlocked ? R.string.action_unblock_domain : R.string.action_block_domain);
|
||||
builder.setMessage(context.getResources().getString(isBlocked ? R.string.unblock_domain_text : R.string.block_domain_text,
|
||||
blockable.getJid().toDomainJid()));
|
||||
} else {
|
||||
builder.setTitle(isBlocked ? R.string.action_unblock_contact : R.string.action_block_contact);
|
||||
builder.setMessage(context.getResources().getString(isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text,
|
||||
blockable.getJid().toBareJid()));
|
||||
}
|
||||
builder.setPositiveButton(isBlocked ? R.string.unblock : R.string.block, new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
if (isBlocked) {
|
||||
xmppConnectionService.sendUnblockRequest(blockable);
|
||||
} else {
|
||||
xmppConnectionService.sendBlockRequest(blockable);
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package eu.siacs.conversations.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Contact;
|
||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
|
||||
public class BlocklistActivity extends AbstractSearchableListItemActivity implements OnUpdateBlocklist {
|
||||
|
||||
private Account account = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClick(final AdapterView<?> parent,
|
||||
final View view,
|
||||
final int position,
|
||||
final long id) {
|
||||
BlockContactDialog.show(parent.getContext(), xmppConnectionService,(Contact) getListItems().get(position));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackendConnected() {
|
||||
for (final Account account : xmppConnectionService.getAccounts()) {
|
||||
if (account.getJid().toString().equals(getIntent().getStringExtra("account"))) {
|
||||
this.account = account;
|
||||
break;
|
||||
}
|
||||
}
|
||||
filterContacts();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void filterContacts(final String needle) {
|
||||
getListItems().clear();
|
||||
if (account != null) {
|
||||
for (final Jid jid : account.getBlocklist()) {
|
||||
final Contact contact = account.getRoster().getContact(jid);
|
||||
if (contact.match(needle) && contact.isBlocked()) {
|
||||
getListItems().add(contact);
|
||||
}
|
||||
}
|
||||
Collections.sort(getListItems());
|
||||
}
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getListItemAdapter().notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnUpdateBlocklist(final OnUpdateBlocklist.Status status) {
|
||||
final Editable editable = getSearchEditText().getText();
|
||||
if (editable != null) {
|
||||
filterContacts(editable.toString());
|
||||
} else {
|
||||
filterContacts();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,101 +1,33 @@
|
||||
package eu.siacs.conversations.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
import eu.siacs.conversations.R;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Contact;
|
||||
import eu.siacs.conversations.entities.ListItem;
|
||||
import eu.siacs.conversations.ui.adapter.ListItemAdapter;
|
||||
|
||||
public class ChooseContactActivity extends XmppActivity {
|
||||
|
||||
private ListView mListView;
|
||||
private ArrayList<ListItem> contacts = new ArrayList<>();
|
||||
private ArrayAdapter<ListItem> mContactsAdapter;
|
||||
|
||||
private EditText mSearchEditText;
|
||||
|
||||
private TextWatcher mSearchTextWatcher = new TextWatcher() {
|
||||
|
||||
public class ChooseContactActivity extends AbstractSearchableListItemActivity {
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
filterContacts(editable.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count,
|
||||
int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before,
|
||||
int count) {
|
||||
}
|
||||
};
|
||||
|
||||
private MenuItem.OnActionExpandListener mOnActionExpandListener = new MenuItem.OnActionExpandListener() {
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemActionExpand(MenuItem item) {
|
||||
mSearchEditText.post(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mSearchEditText.requestFocus();
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.showSoftInput(mSearchEditText,
|
||||
InputMethodManager.SHOW_IMPLICIT);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemActionCollapse(MenuItem item) {
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(),
|
||||
InputMethodManager.HIDE_IMPLICIT_ONLY);
|
||||
mSearchEditText.setText("");
|
||||
filterContacts(null);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_choose_contact);
|
||||
mListView = (ListView) findViewById(R.id.choose_contact_list);
|
||||
mListView.setFastScrollEnabled(true);
|
||||
mContactsAdapter = new ListItemAdapter(this, contacts);
|
||||
mListView.setAdapter(mContactsAdapter);
|
||||
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> arg0, View arg1,
|
||||
int position, long arg3) {
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(),
|
||||
public void onItemClick(final AdapterView<?> parent, final View view,
|
||||
final int position, final long id) {
|
||||
final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(getSearchEditText().getWindowToken(),
|
||||
InputMethodManager.HIDE_IMPLICIT_ONLY);
|
||||
Intent request = getIntent();
|
||||
Intent data = new Intent();
|
||||
ListItem mListItem = contacts.get(position);
|
||||
final Intent request = getIntent();
|
||||
final Intent data = new Intent();
|
||||
final ListItem mListItem = getListItems().get(position);
|
||||
data.putExtra("contact", mListItem.getJid().toString());
|
||||
String account = request.getStringExtra("account");
|
||||
if (account == null && mListItem instanceof Contact) {
|
||||
@ -108,38 +40,21 @@ public class ChooseContactActivity extends XmppActivity {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.choose_contact, menu);
|
||||
MenuItem menuSearchView = menu.findItem(R.id.action_search);
|
||||
View mSearchView = menuSearchView.getActionView();
|
||||
mSearchEditText = (EditText) mSearchView
|
||||
.findViewById(R.id.search_field);
|
||||
mSearchEditText.addTextChangedListener(mSearchTextWatcher);
|
||||
menuSearchView.setOnActionExpandListener(mOnActionExpandListener);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void onBackendConnected() {
|
||||
filterContacts(null);
|
||||
}
|
||||
|
||||
protected void filterContacts(String needle) {
|
||||
this.contacts.clear();
|
||||
for (Account account : xmppConnectionService.getAccounts()) {
|
||||
protected void filterContacts(final String needle) {
|
||||
getListItems().clear();
|
||||
for (final Account account : xmppConnectionService.getAccounts()) {
|
||||
if (account.getStatus() != Account.State.DISABLED) {
|
||||
for (Contact contact : account.getRoster().getContacts()) {
|
||||
for (final Contact contact : account.getRoster().getContacts()) {
|
||||
if (contact.showInRoster() && contact.match(needle)) {
|
||||
this.contacts.add(contact);
|
||||
getListItems().add(contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(this.contacts);
|
||||
mContactsAdapter.notifyDataSetChanged();
|
||||
Collections.sort(getListItems());
|
||||
getListItemAdapter().notifyDataSetChanged();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
|
||||
@Override
|
||||
protected String getShareableUri() {
|
||||
if (mConversation != null) {
|
||||
return "xmpp:" + mConversation.getContactJid().toBareJid().toString() + "?join";
|
||||
return "xmpp:" + mConversation.getJid().toBareJid().toString() + "?join";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
@ -202,7 +202,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
|
||||
MenuItem menuItemSaveBookmark = menu.findItem(R.id.action_save_as_bookmark);
|
||||
MenuItem menuItemDeleteBookmark = menu.findItem(R.id.action_delete_bookmark);
|
||||
Account account = mConversation.getAccount();
|
||||
if (account.hasBookmarkFor(mConversation.getContactJid().toBareJid())) {
|
||||
if (account.hasBookmarkFor(mConversation.getJid().toBareJid())) {
|
||||
menuItemSaveBookmark.setVisible(false);
|
||||
menuItemDeleteBookmark.setVisible(true);
|
||||
} else {
|
||||
@ -263,9 +263,9 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
|
||||
|
||||
protected void saveAsBookmark() {
|
||||
Account account = mConversation.getAccount();
|
||||
Bookmark bookmark = new Bookmark(account, mConversation.getContactJid().toBareJid());
|
||||
if (!mConversation.getContactJid().isBareJid()) {
|
||||
bookmark.setNick(mConversation.getContactJid().getResourcepart());
|
||||
Bookmark bookmark = new Bookmark(account, mConversation.getJid().toBareJid());
|
||||
if (!mConversation.getJid().isBareJid()) {
|
||||
bookmark.setNick(mConversation.getJid().getResourcepart());
|
||||
}
|
||||
bookmark.setAutojoin(true);
|
||||
account.getBookmarks().add(bookmark);
|
||||
@ -301,7 +301,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
|
||||
mYourPhoto.setImageBitmap(avatarService().get(
|
||||
mConversation.getAccount(), getPixel(48)));
|
||||
setTitle(mConversation.getName());
|
||||
mFullJid.setText(mConversation.getContactJid().toBareJid().toString());
|
||||
mFullJid.setText(mConversation.getJid().toBareJid().toString());
|
||||
mYourNick.setText(mConversation.getMucOptions().getActualNick());
|
||||
mRoleAffiliaton = (TextView) findViewById(R.id.muc_role);
|
||||
if (mConversation.getMucOptions().online()) {
|
||||
|
@ -38,10 +38,11 @@ import eu.siacs.conversations.entities.ListItem;
|
||||
import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
|
||||
import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
|
||||
import eu.siacs.conversations.utils.UIHelper;
|
||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
|
||||
public class ContactDetailsActivity extends XmppActivity implements OnAccountUpdate, OnRosterUpdate {
|
||||
public class ContactDetailsActivity extends XmppActivity implements OnAccountUpdate, OnRosterUpdate, OnUpdateBlocklist {
|
||||
public static final String ACTION_VIEW_CONTACT = "view_contact";
|
||||
|
||||
private Contact contact;
|
||||
@ -166,7 +167,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) {
|
||||
try {
|
||||
@ -188,15 +189,17 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
|
||||
badge = (QuickContactBadge) findViewById(R.id.details_contact_badge);
|
||||
keys = (LinearLayout) findViewById(R.id.details_contact_keys);
|
||||
tags = (LinearLayout) findViewById(R.id.tags);
|
||||
if (getActionBar() != null) {
|
||||
getActionBar().setHomeButtonEnabled(true);
|
||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
this.showDynamicTags = preferences.getBoolean("show_dynamic_tags",false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
||||
public boolean onOptionsItemSelected(final MenuItem menuItem) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setNegativeButton(getString(R.string.cancel), null);
|
||||
switch (menuItem.getItemId()) {
|
||||
@ -363,8 +366,8 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
|
||||
} else {
|
||||
tags.setVisibility(View.VISIBLE);
|
||||
tags.removeAllViewsInLayout();
|
||||
for(ListItem.Tag tag : tagList) {
|
||||
TextView tv = (TextView) inflater.inflate(R.layout.list_item_tag,tags,false);
|
||||
for(final ListItem.Tag tag : tagList) {
|
||||
final TextView tv = (TextView) inflater.inflate(R.layout.list_item_tag,tags,false);
|
||||
tv.setText(tag.getName());
|
||||
tv.setBackgroundColor(tag.getColor());
|
||||
tags.addView(tv);
|
||||
@ -414,4 +417,15 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
|
||||
populateView();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnUpdateBlocklist(final Status status) {
|
||||
runOnUiThread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
populateView();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import android.os.SystemClock;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.v4.widget.SlidingPaneLayout;
|
||||
import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
@ -32,6 +31,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.entities.Blockable;
|
||||
import eu.siacs.conversations.entities.Contact;
|
||||
import eu.siacs.conversations.entities.Conversation;
|
||||
import eu.siacs.conversations.entities.Message;
|
||||
@ -40,9 +40,10 @@ import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdat
|
||||
import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
|
||||
import eu.siacs.conversations.ui.adapter.ConversationAdapter;
|
||||
import eu.siacs.conversations.utils.ExceptionHelper;
|
||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||
|
||||
public class ConversationActivity extends XmppActivity implements
|
||||
OnAccountUpdate, OnConversationUpdate, OnRosterUpdate {
|
||||
public class ConversationActivity extends XmppActivity
|
||||
implements OnAccountUpdate, OnConversationUpdate, OnRosterUpdate, OnUpdateBlocklist {
|
||||
|
||||
public static final String VIEW_CONVERSATION = "viewConversation";
|
||||
public static final String CONVERSATION = "conversationUuid";
|
||||
@ -244,7 +245,7 @@ public class ConversationActivity extends XmppActivity implements
|
||||
if (conversation.getMode() == Conversation.MODE_SINGLE || useSubjectToIdentifyConference()) {
|
||||
ab.setTitle(conversation.getName());
|
||||
} else {
|
||||
ab.setTitle(conversation.getContactJid().toBareJid().toString());
|
||||
ab.setTitle(conversation.getJid().toBareJid().toString());
|
||||
}
|
||||
} else {
|
||||
ab.setDisplayHomeAsUpEnabled(false);
|
||||
@ -269,17 +270,18 @@ public class ConversationActivity extends XmppActivity implements
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.conversations, menu);
|
||||
MenuItem menuSecure = menu.findItem(R.id.action_security);
|
||||
MenuItem menuArchive = menu.findItem(R.id.action_archive);
|
||||
MenuItem menuMucDetails = menu.findItem(R.id.action_muc_details);
|
||||
MenuItem menuContactDetails = menu
|
||||
.findItem(R.id.action_contact_details);
|
||||
MenuItem menuAttach = menu.findItem(R.id.action_attach_file);
|
||||
MenuItem menuClearHistory = menu.findItem(R.id.action_clear_history);
|
||||
MenuItem menuAdd = menu.findItem(R.id.action_add);
|
||||
MenuItem menuInviteContact = menu.findItem(R.id.action_invite);
|
||||
MenuItem menuMute = menu.findItem(R.id.action_mute);
|
||||
MenuItem menuUnmute = menu.findItem(R.id.action_unmute);
|
||||
final MenuItem menuSecure = menu.findItem(R.id.action_security);
|
||||
final MenuItem menuArchive = menu.findItem(R.id.action_archive);
|
||||
final MenuItem menuMucDetails = menu.findItem(R.id.action_muc_details);
|
||||
final MenuItem menuContactDetails = menu.findItem(R.id.action_contact_details);
|
||||
final MenuItem menuAttach = menu.findItem(R.id.action_attach_file);
|
||||
final MenuItem menuClearHistory = menu.findItem(R.id.action_clear_history);
|
||||
final MenuItem menuAdd = menu.findItem(R.id.action_add);
|
||||
final MenuItem menuInviteContact = menu.findItem(R.id.action_invite);
|
||||
final MenuItem menuMute = menu.findItem(R.id.action_mute);
|
||||
final MenuItem menuUnmute = menu.findItem(R.id.action_unmute);
|
||||
final MenuItem menuBlock = menu.findItem(R.id.action_block);
|
||||
final MenuItem menuUnblock = menu.findItem(R.id.action_unblock);
|
||||
|
||||
if (isConversationsOverviewVisable()
|
||||
&& isConversationsOverviewHideable()) {
|
||||
@ -292,6 +294,8 @@ public class ConversationActivity extends XmppActivity implements
|
||||
menuClearHistory.setVisible(false);
|
||||
menuMute.setVisible(false);
|
||||
menuUnmute.setVisible(false);
|
||||
menuBlock.setVisible(false);
|
||||
menuUnblock.setVisible(false);
|
||||
} else {
|
||||
menuAdd.setVisible(!isConversationsOverviewHideable());
|
||||
if (this.getSelectedConversation() != null) {
|
||||
@ -302,9 +306,20 @@ public class ConversationActivity extends XmppActivity implements
|
||||
if (this.getSelectedConversation().getMode() == Conversation.MODE_MULTI) {
|
||||
menuContactDetails.setVisible(false);
|
||||
menuAttach.setVisible(false);
|
||||
menuBlock.setVisible(false);
|
||||
menuUnblock.setVisible(false);
|
||||
} else {
|
||||
menuMucDetails.setVisible(false);
|
||||
menuInviteContact.setTitle(R.string.conference_with);
|
||||
if (this.getSelectedConversation().isBlocked()) {
|
||||
menuBlock.setVisible(false);
|
||||
} else {
|
||||
menuUnblock.setVisible(false);
|
||||
}
|
||||
if (!this.getSelectedConversation().getAccount().getXmppConnection().getFeatures().blocking()) {
|
||||
menuBlock.setVisible(false);
|
||||
menuUnblock.setVisible(false);
|
||||
}
|
||||
}
|
||||
if (this.getSelectedConversation().isMuted()) {
|
||||
menuMute.setVisible(false);
|
||||
@ -410,7 +425,7 @@ public class ConversationActivity extends XmppActivity implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
showConversationsOverview();
|
||||
return true;
|
||||
@ -455,6 +470,12 @@ public class ConversationActivity extends XmppActivity implements
|
||||
case R.id.action_unmute:
|
||||
unmuteConversation(getSelectedConversation());
|
||||
break;
|
||||
case R.id.action_block:
|
||||
BlockContactDialog.show(this, xmppConnectionService, getSelectedConversation());
|
||||
break;
|
||||
case R.id.action_unblock:
|
||||
BlockContactDialog.show(this, xmppConnectionService, getSelectedConversation());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -619,8 +640,8 @@ public class ConversationActivity extends XmppActivity implements
|
||||
new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
long till;
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
final long till;
|
||||
if (durations[which] == -1) {
|
||||
till = Long.MAX_VALUE;
|
||||
} else {
|
||||
@ -983,4 +1004,23 @@ public class ConversationActivity extends XmppActivity implements
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnUpdateBlocklist(Status status) {
|
||||
invalidateOptionsMenu();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ConversationActivity.this.mConversationFragment.updateMessages();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void unblockConversation(final Blockable conversation) {
|
||||
xmppConnectionService.sendUnblockRequest(conversation);
|
||||
}
|
||||
|
||||
public void blockConversation(final Blockable conversation) {
|
||||
xmppConnectionService.sendBlockRequest(conversation);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.IntentSender.SendIntentException;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.Gravity;
|
||||
@ -39,7 +38,6 @@ import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.PgpEngine;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
@ -583,12 +581,30 @@ public class ConversationFragment extends Fragment {
|
||||
final ConversationActivity activity = (ConversationActivity) getActivity();
|
||||
if (this.conversation != null) {
|
||||
final Contact contact = this.conversation.getContact();
|
||||
if (this.conversation.isMuted()) {
|
||||
if (this.conversation.isBlocked()) {
|
||||
showSnackbar(R.string.contact_blocked, R.string.unblock,
|
||||
new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
v.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
v.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
if (conversation.isDomainBlocked()) {
|
||||
BlockContactDialog.show(getActivity(), ((ConversationActivity) getActivity()).xmppConnectionService, conversation);
|
||||
} else {
|
||||
((ConversationActivity) getActivity()).unblockConversation(conversation);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (this.conversation.isMuted()) {
|
||||
showSnackbar(R.string.notifications_disabled, R.string.enable,
|
||||
new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
public void onClick(final View v) {
|
||||
activity.unmuteConversation(conversation);
|
||||
}
|
||||
});
|
||||
@ -787,12 +803,13 @@ public class ConversationFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
protected void showSnackbar(int message, int action,
|
||||
OnClickListener clickListener) {
|
||||
protected void showSnackbar(final int message, final int action,
|
||||
final OnClickListener clickListener) {
|
||||
snackbar.setVisibility(View.VISIBLE);
|
||||
snackbar.setOnClickListener(null);
|
||||
snackbarMessage.setText(message);
|
||||
snackbarMessage.setOnClickListener(null);
|
||||
snackbarAction.setVisibility(View.VISIBLE);
|
||||
snackbarAction.setText(action);
|
||||
snackbarAction.setOnClickListener(clickListener);
|
||||
}
|
||||
|
@ -319,12 +319,16 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
getMenuInflater().inflate(R.menu.editaccount, menu);
|
||||
MenuItem showQrCode = menu.findItem(R.id.action_show_qr_code);
|
||||
final MenuItem showQrCode = menu.findItem(R.id.action_show_qr_code);
|
||||
final MenuItem showBlocklist = menu.findItem(R.id.action_show_block_list);
|
||||
if (mAccount == null) {
|
||||
showQrCode.setVisible(false);
|
||||
showBlocklist.setVisible(false);
|
||||
} else if (!mAccount.getXmppConnection().getFeatures().blocking()) {
|
||||
showBlocklist.setVisible(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -340,25 +344,31 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
|
||||
}
|
||||
if (this.jidToEdit != null) {
|
||||
this.mRegisterNew.setVisibility(View.GONE);
|
||||
if (getActionBar() != null) {
|
||||
getActionBar().setTitle(getString(R.string.account_details));
|
||||
}
|
||||
} else {
|
||||
this.mAvatar.setVisibility(View.GONE);
|
||||
if (getActionBar() != null) {
|
||||
getActionBar().setTitle(R.string.action_add_account);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBackendConnected() {
|
||||
KnownHostsAdapter mKnownHostsAdapter = new KnownHostsAdapter(this,
|
||||
final KnownHostsAdapter mKnownHostsAdapter = new KnownHostsAdapter(this,
|
||||
android.R.layout.simple_list_item_1,
|
||||
xmppConnectionService.getKnownHosts());
|
||||
if (this.jidToEdit != null) {
|
||||
this.mAccount = xmppConnectionService.findAccountByJid(jidToEdit);
|
||||
updateAccountInformation();
|
||||
} else if (this.xmppConnectionService.getAccounts().size() == 0) {
|
||||
if (getActionBar() != null) {
|
||||
getActionBar().setDisplayHomeAsUpEnabled(false);
|
||||
getActionBar().setDisplayShowHomeEnabled(false);
|
||||
}
|
||||
this.mCancelButton.setEnabled(false);
|
||||
this.mCancelButton.setTextColor(getSecondaryTextColor());
|
||||
}
|
||||
@ -366,6 +376,18 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
|
||||
updateSaveButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_show_block_list:
|
||||
final Intent intent = new Intent(this, BlocklistActivity.class);
|
||||
intent.putExtra("account", mAccount.getJid().toString());
|
||||
startActivity(intent);
|
||||
break;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void updateAccountInformation() {
|
||||
this.mAccountJid.setText(this.mAccount.getJid().toBareJid().toString());
|
||||
this.mPassword.setText(this.mAccount.getPassword());
|
||||
@ -387,7 +409,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
|
||||
this.mSessionEst.setText(UIHelper.readableTimeDifferenceFull(
|
||||
getApplicationContext(), this.mAccount.getXmppConnection()
|
||||
.getLastSessionEstablished()));
|
||||
Features features = this.mAccount.getXmppConnection().getFeatures();
|
||||
final Features features = this.mAccount.getXmppConnection().getFeatures();
|
||||
if (features.carbons()) {
|
||||
this.mServerInfoCarbons.setText(R.string.server_info_available);
|
||||
} else {
|
||||
|
@ -117,10 +117,10 @@ public class ShareWithActivity extends XmppActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_add:
|
||||
Intent intent = new Intent(getApplicationContext(),
|
||||
final Intent intent = new Intent(getApplicationContext(),
|
||||
ChooseContactActivity.class);
|
||||
startActivityForResult(intent, REQUEST_START_NEW_CONVERSATION);
|
||||
return true;
|
||||
|
@ -53,19 +53,21 @@ import java.util.List;
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Blockable;
|
||||
import eu.siacs.conversations.entities.Bookmark;
|
||||
import eu.siacs.conversations.entities.Contact;
|
||||
import eu.siacs.conversations.entities.Conversation;
|
||||
import eu.siacs.conversations.entities.ListItem;
|
||||
import eu.siacs.conversations.utils.XmppUri;
|
||||
import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
|
||||
import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
|
||||
import eu.siacs.conversations.ui.adapter.ListItemAdapter;
|
||||
import eu.siacs.conversations.utils.Validator;
|
||||
import eu.siacs.conversations.utils.XmppUri;
|
||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
|
||||
public class StartConversationActivity extends XmppActivity implements OnRosterUpdate {
|
||||
public class StartConversationActivity extends XmppActivity implements OnRosterUpdate, OnUpdateBlocklist {
|
||||
|
||||
public int conference_context_id;
|
||||
public int contact_context_id;
|
||||
@ -133,7 +135,9 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||
private ViewPager.SimpleOnPageChangeListener mOnPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
if (getActionBar() != null) {
|
||||
getActionBar().setSelectedNavigationItem(position);
|
||||
}
|
||||
onTabChanged();
|
||||
}
|
||||
};
|
||||
@ -270,10 +274,15 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||
switchToContactDetails(contact);
|
||||
}
|
||||
|
||||
protected void toggleContactBlock() {
|
||||
final int position = contact_context_id;
|
||||
BlockContactDialog.show(this, xmppConnectionService, (Contact)contacts.get(position));
|
||||
}
|
||||
|
||||
protected void deleteContact() {
|
||||
int position = contact_context_id;
|
||||
final int position = contact_context_id;
|
||||
final Contact contact = (Contact) contacts.get(position);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setNegativeButton(R.string.cancel, null);
|
||||
builder.setTitle(R.string.action_delete_contact);
|
||||
builder.setMessage(getString(R.string.remove_contact_text,
|
||||
@ -287,7 +296,6 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
|
||||
}
|
||||
|
||||
protected void deleteConference() {
|
||||
@ -685,16 +693,29 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnUpdateBlocklist(final Status status) {
|
||||
runOnUiThread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (mSearchEditText != null) {
|
||||
filter(mSearchEditText.getText().toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static class MyListFragment extends ListFragment {
|
||||
private AdapterView.OnItemClickListener mOnItemClickListener;
|
||||
private int mResContextMenu;
|
||||
|
||||
public void setContextMenu(int res) {
|
||||
public void setContextMenu(final int res) {
|
||||
this.mResContextMenu = res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
public void onListItemClick(final ListView l, final View v, final int position, final long id) {
|
||||
if (mOnItemClickListener != null) {
|
||||
mOnItemClickListener.onItemClick(l, v, position, id);
|
||||
}
|
||||
@ -705,28 +726,38 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
public void onViewCreated(final View view, final Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
registerForContextMenu(getListView());
|
||||
getListView().setFastScrollEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenuInfo menuInfo) {
|
||||
public void onCreateContextMenu(final ContextMenu menu, final View v,
|
||||
final ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
StartConversationActivity activity = (StartConversationActivity) getActivity();
|
||||
final StartConversationActivity activity = (StartConversationActivity) getActivity();
|
||||
activity.getMenuInflater().inflate(mResContextMenu, menu);
|
||||
AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo;
|
||||
final AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo;
|
||||
if (mResContextMenu == R.menu.conference_context) {
|
||||
activity.conference_context_id = acmi.position;
|
||||
} else {
|
||||
activity.contact_context_id = acmi.position;
|
||||
final Blockable contact = (Contact) activity.contacts.get(acmi.position);
|
||||
|
||||
final MenuItem blockUnblockItem = menu.findItem(R.id.context_contact_block_unblock);
|
||||
if (blockUnblockItem != null) {
|
||||
if (contact.isBlocked()) {
|
||||
blockUnblockItem.setTitle(R.string.unblock_contact);
|
||||
} else {
|
||||
blockUnblockItem.setTitle(R.string.block_contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
public boolean onContextItemSelected(final MenuItem item) {
|
||||
StartConversationActivity activity = (StartConversationActivity) getActivity();
|
||||
switch (item.getItemId()) {
|
||||
case R.id.context_start_conversation:
|
||||
@ -735,6 +766,9 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||
case R.id.context_contact_details:
|
||||
activity.openDetailsForContact();
|
||||
break;
|
||||
case R.id.context_contact_block_unblock:
|
||||
activity.toggleContactBlock();
|
||||
break;
|
||||
case R.id.context_delete_contact:
|
||||
activity.deleteContact();
|
||||
break;
|
||||
@ -750,11 +784,11 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||
|
||||
private class Invite extends XmppUri {
|
||||
|
||||
public Invite(Uri uri) {
|
||||
public Invite(final Uri uri) {
|
||||
super(uri);
|
||||
}
|
||||
|
||||
public Invite(String uri) {
|
||||
public Invite(final String uri) {
|
||||
super(uri);
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ import eu.siacs.conversations.services.AvatarService;
|
||||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder;
|
||||
import eu.siacs.conversations.utils.ExceptionHelper;
|
||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
|
||||
@ -245,6 +246,9 @@ public abstract class XmppActivity extends Activity {
|
||||
if (this instanceof XmppConnectionService.OnMucRosterUpdate) {
|
||||
this.xmppConnectionService.setOnMucRosterUpdateListener((XmppConnectionService.OnMucRosterUpdate) this);
|
||||
}
|
||||
if (this instanceof OnUpdateBlocklist) {
|
||||
this.xmppConnectionService.setOnUpdateBlocklistListener((OnUpdateBlocklist) this);
|
||||
}
|
||||
}
|
||||
|
||||
protected void unregisterListeners() {
|
||||
@ -260,9 +264,13 @@ public abstract class XmppActivity extends Activity {
|
||||
if (this instanceof XmppConnectionService.OnMucRosterUpdate) {
|
||||
this.xmppConnectionService.removeOnMucRosterUpdateListener();
|
||||
}
|
||||
if (this instanceof OnUpdateBlocklist) {
|
||||
this.xmppConnectionService.removeOnUpdateBlocklistListener();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_settings:
|
||||
startActivity(new Intent(this, SettingsActivity.class));
|
||||
@ -420,7 +428,7 @@ public abstract class XmppActivity extends Activity {
|
||||
}
|
||||
|
||||
protected void showAddToRosterDialog(final Conversation conversation) {
|
||||
final Jid jid = conversation.getContactJid();
|
||||
final Jid jid = conversation.getJid();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(jid.toString());
|
||||
builder.setMessage(getString(R.string.not_in_roster));
|
||||
@ -430,7 +438,7 @@ public abstract class XmppActivity extends Activity {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
final Jid jid = conversation.getContactJid();
|
||||
final Jid jid = conversation.getJid();
|
||||
Account account = conversation.getAccount();
|
||||
Contact contact = account.getRoster().getContact(jid);
|
||||
xmppConnectionService.createContact(contact);
|
||||
@ -613,7 +621,7 @@ public abstract class XmppActivity extends Activity {
|
||||
xmppConnectionService.invite(conversation, jid);
|
||||
} else {
|
||||
List<Jid> jids = new ArrayList<Jid>();
|
||||
jids.add(conversation.getContactJid().toBareJid());
|
||||
jids.add(conversation.getJid().toBareJid());
|
||||
jids.add(jid);
|
||||
xmppConnectionService.createAdhocConference(conversation.getAccount(), jids, adhocCallback);
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ public class ConversationAdapter extends ArrayAdapter<Conversation> {
|
||||
|| activity.useSubjectToIdentifyConference()) {
|
||||
convName.setText(conversation.getName());
|
||||
} else {
|
||||
convName.setText(conversation.getContactJid().toBareJid().toString());
|
||||
convName.setText(conversation.getJid().toBareJid().toString());
|
||||
}
|
||||
TextView mLastMessage = (TextView) view
|
||||
.findViewById(R.id.conversation_lastmsg);
|
||||
|
5
src/main/java/eu/siacs/conversations/utils/Xmlns.java
Normal file
5
src/main/java/eu/siacs/conversations/utils/Xmlns.java
Normal file
@ -0,0 +1,5 @@
|
||||
package eu.siacs.conversations.utils;
|
||||
|
||||
public final class Xmlns {
|
||||
public static final String BLOCKING = "urn:xmpp:blocking";
|
||||
}
|
@ -5,7 +5,6 @@ import android.net.Uri;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
import eu.siacs.conversations.utils.CryptoHelper;
|
||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
|
||||
|
@ -67,11 +67,11 @@ public class Element {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasChild(String name) {
|
||||
public boolean hasChild(final String name) {
|
||||
return findChild(name) != null;
|
||||
}
|
||||
|
||||
public boolean hasChild(String name, String xmlns) {
|
||||
public boolean hasChild(final String name, final String xmlns) {
|
||||
return findChild(name, xmlns) != null;
|
||||
}
|
||||
|
||||
|
@ -3,5 +3,5 @@ package eu.siacs.conversations.xmpp;
|
||||
import eu.siacs.conversations.entities.Contact;
|
||||
|
||||
public interface OnContactStatusChanged {
|
||||
public void onContactStatusChanged(Contact contact, boolean online);
|
||||
public void onContactStatusChanged(final Contact contact, final boolean online);
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
package eu.siacs.conversations.xmpp;
|
||||
|
||||
public interface OnUpdateBlocklist {
|
||||
// Use an enum instead of a boolean to make sure we don't run into the boolean trap
|
||||
// (`onUpdateBlocklist(true)' doesn't read well, and could be confusing).
|
||||
public static enum Status {
|
||||
BLOCKED,
|
||||
UNBLOCKED
|
||||
}
|
||||
|
||||
@SuppressWarnings("MethodNameSameAsClassName")
|
||||
public void OnUpdateBlocklist(final Status status);
|
||||
}
|
@ -30,10 +30,12 @@ import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
@ -48,8 +50,10 @@ import eu.siacs.conversations.crypto.sasl.Plain;
|
||||
import eu.siacs.conversations.crypto.sasl.SaslMechanism;
|
||||
import eu.siacs.conversations.crypto.sasl.ScramSha1;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.generator.IqGenerator;
|
||||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
import eu.siacs.conversations.utils.DNSHelper;
|
||||
import eu.siacs.conversations.utils.Xmlns;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xml.Tag;
|
||||
import eu.siacs.conversations.xml.TagWriter;
|
||||
@ -76,19 +80,19 @@ public class XmppConnection implements Runnable {
|
||||
private static final int PACKET_PRESENCE = 2;
|
||||
private final Context applicationContext;
|
||||
protected Account account;
|
||||
private WakeLock wakeLock;
|
||||
private final WakeLock wakeLock;
|
||||
private Socket socket;
|
||||
private XmlReader tagReader;
|
||||
private TagWriter tagWriter;
|
||||
private Features features = new Features(this);
|
||||
private final Features features = new Features(this);
|
||||
private boolean shouldBind = true;
|
||||
private boolean shouldAuthenticate = true;
|
||||
private Element streamFeatures;
|
||||
private HashMap<String, List<String>> disco = new HashMap<>();
|
||||
private final HashMap<String, List<String>> disco = new HashMap<>();
|
||||
|
||||
private String streamId = null;
|
||||
private int smVersion = 3;
|
||||
private SparseArray<String> messageReceipts = new SparseArray<>();
|
||||
private final SparseArray<String> messageReceipts = new SparseArray<>();
|
||||
|
||||
private boolean enabledEncryption = false;
|
||||
private boolean enabledCarbons = false;
|
||||
@ -100,20 +104,20 @@ public class XmppConnection implements Runnable {
|
||||
private long lastConnect = 0;
|
||||
private long lastSessionStarted = 0;
|
||||
private int attempt = 0;
|
||||
private Hashtable<String, PacketReceived> packetCallbacks = new Hashtable<>();
|
||||
private final Map<String, PacketReceived> packetCallbacks = new Hashtable<>();
|
||||
private OnPresencePacketReceived presenceListener = null;
|
||||
private OnJinglePacketReceived jingleListener = null;
|
||||
private OnIqPacketReceived unregisteredIqListener = null;
|
||||
private OnMessagePacketReceived messageListener = null;
|
||||
private OnStatusChanged statusListener = null;
|
||||
private OnBindListener bindListener = null;
|
||||
private ArrayList<OnAdvancedStreamFeaturesLoaded> advancedStreamFeaturesLoadedListeners = new ArrayList<>();
|
||||
private final ArrayList<OnAdvancedStreamFeaturesLoaded> advancedStreamFeaturesLoadedListeners = new ArrayList<>();
|
||||
private OnMessageAcknowledged acknowledgedListener = null;
|
||||
private XmppConnectionService mXmppConnectionService = null;
|
||||
|
||||
private SaslMechanism saslMechanism;
|
||||
|
||||
public XmppConnection(Account account, XmppConnectionService service) {
|
||||
public XmppConnection(final Account account, final XmppConnectionService service) {
|
||||
this.account = account;
|
||||
this.wakeLock = service.getPowerManager().newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, account.getJid().toBareJid().toString());
|
||||
@ -153,15 +157,15 @@ public class XmppConnection implements Runnable {
|
||||
tagWriter = new TagWriter();
|
||||
packetCallbacks.clear();
|
||||
this.changeStatus(Account.State.CONNECTING);
|
||||
Bundle result = DNSHelper.getSRVRecord(account.getServer());
|
||||
ArrayList<Parcelable> values = result.getParcelableArrayList("values");
|
||||
final Bundle result = DNSHelper.getSRVRecord(account.getServer());
|
||||
final ArrayList<Parcelable> values = result.getParcelableArrayList("values");
|
||||
if ("timeout".equals(result.getString("error"))) {
|
||||
throw new IOException("timeout in dns");
|
||||
} else if (values != null) {
|
||||
int i = 0;
|
||||
boolean socketError = true;
|
||||
while (socketError && values.size() > i) {
|
||||
Bundle namePort = (Bundle) values.get(i);
|
||||
final Bundle namePort = (Bundle) values.get(i);
|
||||
try {
|
||||
String srvRecordServer;
|
||||
try {
|
||||
@ -170,9 +174,9 @@ public class XmppConnection implements Runnable {
|
||||
// TODO: Handle me?`
|
||||
srvRecordServer = "";
|
||||
}
|
||||
int srvRecordPort = namePort.getInt("port");
|
||||
String srvIpServer = namePort.getString("ip");
|
||||
InetSocketAddress addr;
|
||||
final int srvRecordPort = namePort.getInt("port");
|
||||
final String srvIpServer = namePort.getString("ip");
|
||||
final InetSocketAddress addr;
|
||||
if (srvIpServer != null) {
|
||||
addr = new InetSocketAddress(srvIpServer, srvRecordPort);
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
|
||||
@ -187,10 +191,10 @@ public class XmppConnection implements Runnable {
|
||||
socket = new Socket();
|
||||
socket.connect(addr, 20000);
|
||||
socketError = false;
|
||||
} catch (UnknownHostException e) {
|
||||
} catch (final UnknownHostException e) {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
|
||||
i++;
|
||||
} catch (IOException e) {
|
||||
} catch (final IOException e) {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
|
||||
i++;
|
||||
}
|
||||
@ -204,9 +208,9 @@ public class XmppConnection implements Runnable {
|
||||
} else {
|
||||
throw new IOException("timeout in dns");
|
||||
}
|
||||
OutputStream out = socket.getOutputStream();
|
||||
final OutputStream out = socket.getOutputStream();
|
||||
tagWriter.setOutputStream(out);
|
||||
InputStream in = socket.getInputStream();
|
||||
final InputStream in = socket.getInputStream();
|
||||
tagReader.setInputStream(in);
|
||||
tagWriter.beginDocument();
|
||||
sendStartStream();
|
||||
@ -222,14 +226,9 @@ public class XmppConnection implements Runnable {
|
||||
if (socket.isConnected()) {
|
||||
socket.close();
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
} catch (final UnknownHostException | ConnectException e) {
|
||||
this.changeStatus(Account.State.SERVER_NOT_FOUND);
|
||||
} catch (final ConnectException e) {
|
||||
this.changeStatus(Account.State.SERVER_NOT_FOUND);
|
||||
} catch (final IOException | XmlPullParserException e) {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
|
||||
this.changeStatus(Account.State.OFFLINE);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
} catch (final IOException | XmlPullParserException | NoSuchAlgorithmException e) {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
|
||||
this.changeStatus(Account.State.OFFLINE);
|
||||
} finally {
|
||||
@ -289,7 +288,7 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
tagWriter.writeElement(response);
|
||||
} else if (nextTag.isStart("enabled")) {
|
||||
Element enabled = tagReader.readElement(nextTag);
|
||||
final Element enabled = tagReader.readElement(nextTag);
|
||||
if ("true".equals(enabled.getAttribute("resume"))) {
|
||||
this.streamId = enabled.getAttribute("id");
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
|
||||
@ -301,14 +300,14 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
this.lastSessionStarted = SystemClock.elapsedRealtime();
|
||||
this.stanzasReceived = 0;
|
||||
RequestPacket r = new RequestPacket(smVersion);
|
||||
final RequestPacket r = new RequestPacket(smVersion);
|
||||
tagWriter.writeStanzaAsync(r);
|
||||
} else if (nextTag.isStart("resumed")) {
|
||||
lastPaketReceived = SystemClock.elapsedRealtime();
|
||||
Element resumed = tagReader.readElement(nextTag);
|
||||
String h = resumed.getAttribute("h");
|
||||
final Element resumed = tagReader.readElement(nextTag);
|
||||
final String h = resumed.getAttribute("h");
|
||||
try {
|
||||
int serverCount = Integer.parseInt(h);
|
||||
final int serverCount = Integer.parseInt(h);
|
||||
if (serverCount != stanzasSent) {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
|
||||
+ ": session resumed with lost packages");
|
||||
@ -327,20 +326,19 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
messageReceipts.clear();
|
||||
} catch (final NumberFormatException ignored) {
|
||||
|
||||
}
|
||||
sendServiceDiscoveryInfo(account.getServer());
|
||||
sendServiceDiscoveryItems(account.getServer());
|
||||
sendInitialPing();
|
||||
} else if (nextTag.isStart("r")) {
|
||||
tagReader.readElement(nextTag);
|
||||
AckPacket ack = new AckPacket(this.stanzasReceived, smVersion);
|
||||
final AckPacket ack = new AckPacket(this.stanzasReceived, smVersion);
|
||||
tagWriter.writeStanzaAsync(ack);
|
||||
} else if (nextTag.isStart("a")) {
|
||||
Element ack = tagReader.readElement(nextTag);
|
||||
final Element ack = tagReader.readElement(nextTag);
|
||||
lastPaketReceived = SystemClock.elapsedRealtime();
|
||||
int serverSequence = Integer.parseInt(ack.getAttribute("h"));
|
||||
String msgId = this.messageReceipts.get(serverSequence);
|
||||
final int serverSequence = Integer.parseInt(ack.getAttribute("h"));
|
||||
final String msgId = this.messageReceipts.get(serverSequence);
|
||||
if (msgId != null) {
|
||||
if (this.acknowledgedListener != null) {
|
||||
this.acknowledgedListener.onMessageAcknowledged(
|
||||
@ -374,13 +372,12 @@ public class XmppConnection implements Runnable {
|
||||
|
||||
private void sendInitialPing() {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": sending intial ping");
|
||||
IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
|
||||
final IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
|
||||
iq.setFrom(account.getJid());
|
||||
iq.addChild("ping", "urn:xmpp:ping");
|
||||
this.sendIqPacket(iq, new OnIqPacketReceived() {
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||
public void onIqPacketReceived(final Account account, final IqPacket packet) {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
|
||||
+ ": online with resource " + account.getResource());
|
||||
changeStatus(Account.State.ONLINE);
|
||||
@ -388,7 +385,7 @@ public class XmppConnection implements Runnable {
|
||||
});
|
||||
}
|
||||
|
||||
private Element processPacket(Tag currentTag, int packetType)
|
||||
private Element processPacket(final Tag currentTag, final int packetType)
|
||||
throws XmlPullParserException, IOException {
|
||||
Element element;
|
||||
switch (packetType) {
|
||||
@ -411,8 +408,8 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
while (!nextTag.isEnd(element.getName())) {
|
||||
if (!nextTag.isNo()) {
|
||||
Element child = tagReader.readElement(nextTag);
|
||||
String type = currentTag.getAttribute("type");
|
||||
final Element child = tagReader.readElement(nextTag);
|
||||
final String type = currentTag.getAttribute("type");
|
||||
if (packetType == PACKET_IQ
|
||||
&& "jingle".equals(child.getName())
|
||||
&& ("set".equalsIgnoreCase(type) || "get"
|
||||
@ -432,9 +429,9 @@ public class XmppConnection implements Runnable {
|
||||
return element;
|
||||
}
|
||||
|
||||
private void processIq(Tag currentTag) throws XmlPullParserException,
|
||||
private void processIq(final Tag currentTag) throws XmlPullParserException,
|
||||
IOException {
|
||||
IqPacket packet = (IqPacket) processPacket(currentTag, PACKET_IQ);
|
||||
final IqPacket packet = (IqPacket) processPacket(currentTag, PACKET_IQ);
|
||||
|
||||
if (packet.getId() == null) {
|
||||
return; // an iq packet without id is definitely invalid
|
||||
@ -461,11 +458,11 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void processMessage(Tag currentTag) throws XmlPullParserException,
|
||||
private void processMessage(final Tag currentTag) throws XmlPullParserException,
|
||||
IOException {
|
||||
MessagePacket packet = (MessagePacket) processPacket(currentTag,
|
||||
final MessagePacket packet = (MessagePacket) processPacket(currentTag,
|
||||
PACKET_MESSAGE);
|
||||
String id = packet.getAttribute("id");
|
||||
final String id = packet.getAttribute("id");
|
||||
if ((id != null) && (packetCallbacks.containsKey(id))) {
|
||||
if (packetCallbacks.get(id) instanceof OnMessagePacketReceived) {
|
||||
((OnMessagePacketReceived) packetCallbacks.get(id))
|
||||
@ -477,11 +474,11 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void processPresence(Tag currentTag) throws XmlPullParserException,
|
||||
private void processPresence(final Tag currentTag) throws XmlPullParserException,
|
||||
IOException {
|
||||
PresencePacket packet = (PresencePacket) processPacket(currentTag,
|
||||
PACKET_PRESENCE);
|
||||
String id = packet.getAttribute("id");
|
||||
final String id = packet.getAttribute("id");
|
||||
if ((id != null) && (packetCallbacks.containsKey(id))) {
|
||||
if (packetCallbacks.get(id) instanceof OnPresencePacketReceived) {
|
||||
((OnPresencePacketReceived) packetCallbacks.get(id))
|
||||
@ -494,7 +491,7 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
|
||||
private void sendStartTLS() throws IOException {
|
||||
Tag startTLS = Tag.empty("starttls");
|
||||
final Tag startTLS = Tag.empty("starttls");
|
||||
startTLS.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls");
|
||||
tagWriter.writeTag(startTLS);
|
||||
}
|
||||
@ -512,11 +509,11 @@ public class XmppConnection implements Runnable {
|
||||
IOException {
|
||||
tagReader.readTag();
|
||||
try {
|
||||
SSLContext sc = SSLContext.getInstance("TLS");
|
||||
final SSLContext sc = SSLContext.getInstance("TLS");
|
||||
sc.init(null,
|
||||
new X509TrustManager[]{this.mXmppConnectionService.getMemorizingTrustManager()},
|
||||
mXmppConnectionService.getRNG());
|
||||
SSLSocketFactory factory = sc.getSocketFactory();
|
||||
final SSLSocketFactory factory = sc.getSocketFactory();
|
||||
|
||||
if (factory == null) {
|
||||
throw new IOException("SSLSocketFactory was null");
|
||||
@ -541,7 +538,7 @@ public class XmppConnection implements Runnable {
|
||||
if (enableLegacySSL()) {
|
||||
supportProtocols = sslSocket.getSupportedProtocols();
|
||||
} else {
|
||||
final List<String> supportedProtocols = new LinkedList<>(
|
||||
final Collection<String> supportedProtocols = new LinkedList<>(
|
||||
Arrays.asList(sslSocket.getSupportedProtocols()));
|
||||
supportedProtocols.remove("SSLv3");
|
||||
supportProtocols = new String[supportedProtocols.size()];
|
||||
@ -569,7 +566,7 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void processStreamFeatures(Tag currentTag)
|
||||
private void processStreamFeatures(final Tag currentTag)
|
||||
throws XmlPullParserException, IOException {
|
||||
this.streamFeatures = tagReader.readElement(currentTag);
|
||||
if (this.streamFeatures.hasChild("starttls") && !enabledEncryption) {
|
||||
@ -618,7 +615,7 @@ public class XmppConnection implements Runnable {
|
||||
} else if (this.streamFeatures.hasChild("sm", "urn:xmpp:sm:"
|
||||
+ smVersion)
|
||||
&& streamId != null) {
|
||||
ResumePacket resume = new ResumePacket(this.streamId,
|
||||
final ResumePacket resume = new ResumePacket(this.streamId,
|
||||
stanzasReceived, smVersion);
|
||||
this.tagWriter.writeStanzaAsync(resume);
|
||||
} else if (this.streamFeatures.hasChild("bind") && shouldBind) {
|
||||
@ -629,38 +626,37 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> extractMechanisms(Element stream) {
|
||||
ArrayList<String> mechanisms = new ArrayList<>(stream
|
||||
private List<String> extractMechanisms(final Element stream) {
|
||||
final ArrayList<String> mechanisms = new ArrayList<>(stream
|
||||
.getChildren().size());
|
||||
for (Element child : stream.getChildren()) {
|
||||
for (final Element child : stream.getChildren()) {
|
||||
mechanisms.add(child.getContent());
|
||||
}
|
||||
return mechanisms;
|
||||
}
|
||||
|
||||
private void sendRegistryRequest() {
|
||||
IqPacket register = new IqPacket(IqPacket.TYPE_GET);
|
||||
final IqPacket register = new IqPacket(IqPacket.TYPE_GET);
|
||||
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");
|
||||
public void onIqPacketReceived(final Account account, final IqPacket packet) {
|
||||
final Element instructions = packet.query().findChild("instructions");
|
||||
if (packet.query().hasChild("username")
|
||||
&& (packet.query().hasChild("password"))) {
|
||||
IqPacket register = new IqPacket(IqPacket.TYPE_SET);
|
||||
Element username = new Element("username")
|
||||
final IqPacket register = new IqPacket(IqPacket.TYPE_SET);
|
||||
final Element username = new Element("username")
|
||||
.setContent(account.getUsername());
|
||||
Element password = new Element("password")
|
||||
final 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) {
|
||||
public void onIqPacketReceived(final Account account, final IqPacket packet) {
|
||||
if (packet.getType() == IqPacket.TYPE_RESULT) {
|
||||
account.setOption(Account.OPTION_REGISTER,
|
||||
false);
|
||||
@ -687,14 +683,14 @@ public class XmppConnection implements Runnable {
|
||||
});
|
||||
}
|
||||
|
||||
private void sendBindRequest() throws IOException {
|
||||
IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
|
||||
private void sendBindRequest() {
|
||||
final IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
|
||||
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) {
|
||||
Element bind = packet.findChild("bind");
|
||||
public void onIqPacketReceived(final Account account, final IqPacket packet) {
|
||||
final Element bind = packet.findChild("bind");
|
||||
if (bind != null) {
|
||||
final Element jid = bind.findChild("jid");
|
||||
if (jid != null && jid.getContent() != null) {
|
||||
@ -705,14 +701,14 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
if (streamFeatures.hasChild("sm", "urn:xmpp:sm:3")) {
|
||||
smVersion = 3;
|
||||
EnablePacket enable = new EnablePacket(smVersion);
|
||||
final EnablePacket enable = new EnablePacket(smVersion);
|
||||
tagWriter.writeStanzaAsync(enable);
|
||||
stanzasSent = 0;
|
||||
messageReceipts.clear();
|
||||
} else if (streamFeatures.hasChild("sm",
|
||||
"urn:xmpp:sm:2")) {
|
||||
smVersion = 2;
|
||||
EnablePacket enable = new EnablePacket(smVersion);
|
||||
final EnablePacket enable = new EnablePacket(smVersion);
|
||||
tagWriter.writeStanzaAsync(enable);
|
||||
stanzasSent = 0;
|
||||
messageReceipts.clear();
|
||||
@ -736,7 +732,7 @@ public class XmppConnection implements Runnable {
|
||||
if (this.streamFeatures.hasChild("session")) {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid()
|
||||
+ ": sending deprecated session");
|
||||
IqPacket startSession = new IqPacket(IqPacket.TYPE_SET);
|
||||
final IqPacket startSession = new IqPacket(IqPacket.TYPE_SET);
|
||||
startSession.addChild("session",
|
||||
"urn:ietf:params:xml:ns:xmpp-session");
|
||||
this.sendUnboundIqPacket(startSession, null);
|
||||
@ -755,10 +751,10 @@ public class XmppConnection implements Runnable {
|
||||
this.sendIqPacket(iq, new OnIqPacketReceived() {
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||
public void onIqPacketReceived(final Account account, final IqPacket packet) {
|
||||
final List<Element> elements = packet.query().getChildren();
|
||||
final List<String> features = new ArrayList<>();
|
||||
for (Element element : elements) {
|
||||
for (final Element element : elements) {
|
||||
if (element.getName().equals("identity")) {
|
||||
if ("irc".equals(element.getAttribute("type"))) {
|
||||
//add fake feature to not confuse irc and real muc
|
||||
@ -772,7 +768,7 @@ public class XmppConnection implements Runnable {
|
||||
|
||||
if (account.getServer().equals(server.toDomainJid())) {
|
||||
enableAdvancedStreamFeatures();
|
||||
for(OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) {
|
||||
for (final OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) {
|
||||
listener.onAdvancedStreamFeaturesAvailable(account);
|
||||
}
|
||||
}
|
||||
@ -787,6 +783,10 @@ public class XmppConnection implements Runnable {
|
||||
sendEnableCarbons();
|
||||
}
|
||||
}
|
||||
if (getFeatures().blocking()) {
|
||||
Log.d(Config.LOGTAG, "Requesting block list");
|
||||
this.sendIqPacket(getIqGenerator().generateGetBlockList(), mXmppConnectionService.getIqParser());
|
||||
}
|
||||
}
|
||||
|
||||
private void sendServiceDiscoveryItems(final Jid server) {
|
||||
@ -796,9 +796,9 @@ public class XmppConnection implements Runnable {
|
||||
this.sendIqPacket(iq, new OnIqPacketReceived() {
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||
List<Element> elements = packet.query().getChildren();
|
||||
for (Element element : elements) {
|
||||
public void onIqPacketReceived(final Account account, final IqPacket packet) {
|
||||
final List<Element> elements = packet.query().getChildren();
|
||||
for (final Element element : elements) {
|
||||
if (element.getName().equals("item")) {
|
||||
final Jid jid = element.getAttributeAsJid("jid");
|
||||
if (jid != null && !jid.equals(account.getServer())) {
|
||||
@ -811,12 +811,12 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
|
||||
private void sendEnableCarbons() {
|
||||
IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
|
||||
final IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
|
||||
iq.addChild("enable", "urn:xmpp:carbons:2");
|
||||
this.sendIqPacket(iq, new OnIqPacketReceived() {
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||
public void onIqPacketReceived(final Account account, final IqPacket packet) {
|
||||
if (!packet.hasChild("error")) {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid()
|
||||
+ ": successfully enabled carbons");
|
||||
@ -829,9 +829,9 @@ public class XmppConnection implements Runnable {
|
||||
});
|
||||
}
|
||||
|
||||
private void processStreamError(Tag currentTag)
|
||||
private void processStreamError(final Tag currentTag)
|
||||
throws XmlPullParserException, IOException {
|
||||
Element streamError = tagReader.readElement(currentTag);
|
||||
final Element streamError = tagReader.readElement(currentTag);
|
||||
if (streamError != null && streamError.hasChild("conflict")) {
|
||||
final String resource = account.getResource().split("\\.")[0];
|
||||
account.setResource(resource + "." + nextRandomId());
|
||||
@ -842,7 +842,7 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
|
||||
private void sendStartStream() throws IOException {
|
||||
Tag stream = Tag.start("stream:stream");
|
||||
final Tag stream = Tag.start("stream:stream");
|
||||
stream.setAttribute("from", account.getJid().toBareJid().toString());
|
||||
stream.setAttribute("to", account.getServer().toString());
|
||||
stream.setAttribute("version", "1.0");
|
||||
@ -856,33 +856,32 @@ public class XmppConnection implements Runnable {
|
||||
return new BigInteger(50, mXmppConnectionService.getRNG()).toString(32);
|
||||
}
|
||||
|
||||
public void sendIqPacket(IqPacket packet, OnIqPacketReceived callback) {
|
||||
public void sendIqPacket(final IqPacket packet, final PacketReceived callback) {
|
||||
if (packet.getId() == null) {
|
||||
String id = nextRandomId();
|
||||
final String id = nextRandomId();
|
||||
packet.setAttribute("id", id);
|
||||
}
|
||||
packet.setFrom(account.getJid());
|
||||
this.sendPacket(packet, callback);
|
||||
}
|
||||
|
||||
public void sendUnboundIqPacket(IqPacket packet, OnIqPacketReceived callback) {
|
||||
public void sendUnboundIqPacket(final IqPacket packet, final PacketReceived callback) {
|
||||
if (packet.getId() == null) {
|
||||
String id = nextRandomId();
|
||||
final String id = nextRandomId();
|
||||
packet.setAttribute("id", id);
|
||||
}
|
||||
this.sendPacket(packet, callback);
|
||||
}
|
||||
|
||||
public void sendMessagePacket(MessagePacket packet) {
|
||||
public void sendMessagePacket(final MessagePacket packet) {
|
||||
this.sendPacket(packet, null);
|
||||
}
|
||||
|
||||
public void sendPresencePacket(PresencePacket packet) {
|
||||
public void sendPresencePacket(final PresencePacket packet) {
|
||||
this.sendPacket(packet, null);
|
||||
}
|
||||
|
||||
private synchronized void sendPacket(final AbstractStanza packet,
|
||||
PacketReceived callback) {
|
||||
private synchronized void sendPacket(final AbstractStanza packet, final PacketReceived callback) {
|
||||
if (packet.getName().equals("iq") || packet.getName().equals("message")
|
||||
|| packet.getName().equals("presence")) {
|
||||
++stanzasSent;
|
||||
@ -907,7 +906,7 @@ public class XmppConnection implements Runnable {
|
||||
if (streamFeatures.hasChild("sm")) {
|
||||
tagWriter.writeStanzaAsync(new RequestPacket(smVersion));
|
||||
} else {
|
||||
IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
|
||||
final IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
|
||||
iq.setFrom(account.getJid());
|
||||
iq.addChild("ping", "urn:xmpp:ping");
|
||||
this.sendIqPacket(iq, null);
|
||||
@ -916,44 +915,44 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
|
||||
public void setOnMessagePacketReceivedListener(
|
||||
OnMessagePacketReceived listener) {
|
||||
final OnMessagePacketReceived listener) {
|
||||
this.messageListener = listener;
|
||||
}
|
||||
|
||||
public void setOnUnregisteredIqPacketReceivedListener(
|
||||
OnIqPacketReceived listener) {
|
||||
final OnIqPacketReceived listener) {
|
||||
this.unregisteredIqListener = listener;
|
||||
}
|
||||
|
||||
public void setOnPresencePacketReceivedListener(
|
||||
OnPresencePacketReceived listener) {
|
||||
final OnPresencePacketReceived listener) {
|
||||
this.presenceListener = listener;
|
||||
}
|
||||
|
||||
public void setOnJinglePacketReceivedListener(
|
||||
OnJinglePacketReceived listener) {
|
||||
final OnJinglePacketReceived listener) {
|
||||
this.jingleListener = listener;
|
||||
}
|
||||
|
||||
public void setOnStatusChangedListener(OnStatusChanged listener) {
|
||||
public void setOnStatusChangedListener(final OnStatusChanged listener) {
|
||||
this.statusListener = listener;
|
||||
}
|
||||
|
||||
public void setOnBindListener(OnBindListener listener) {
|
||||
public void setOnBindListener(final OnBindListener listener) {
|
||||
this.bindListener = listener;
|
||||
}
|
||||
|
||||
public void setOnMessageAcknowledgeListener(OnMessageAcknowledged listener) {
|
||||
public void setOnMessageAcknowledgeListener(final OnMessageAcknowledged listener) {
|
||||
this.acknowledgedListener = listener;
|
||||
}
|
||||
|
||||
public void addOnAdvancedStreamFeaturesAvailableListener(OnAdvancedStreamFeaturesLoaded listener) {
|
||||
public void addOnAdvancedStreamFeaturesAvailableListener(final OnAdvancedStreamFeaturesLoaded listener) {
|
||||
if (!this.advancedStreamFeaturesLoadedListeners.contains(listener)) {
|
||||
this.advancedStreamFeaturesLoadedListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnect(boolean force) {
|
||||
public void disconnect(final boolean force) {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": disconnecting");
|
||||
try {
|
||||
if (force) {
|
||||
@ -973,23 +972,23 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
tagWriter.writeTag(Tag.end("stream:stream"));
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
} catch (final IOException e) {
|
||||
Log.d(Config.LOGTAG,
|
||||
"io exception during disconnect");
|
||||
} catch (InterruptedException e) {
|
||||
} catch (final InterruptedException e) {
|
||||
Log.d(Config.LOGTAG, "interrupted");
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
} catch (IOException e) {
|
||||
} catch (final IOException e) {
|
||||
Log.d(Config.LOGTAG, "io exception during disconnect");
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> findDiscoItemsByFeature(String feature) {
|
||||
public List<String> findDiscoItemsByFeature(final String feature) {
|
||||
final List<String> items = new ArrayList<>();
|
||||
for (Entry<String, List<String>> cursor : disco.entrySet()) {
|
||||
for (final Entry<String, List<String>> cursor : disco.entrySet()) {
|
||||
if (cursor.getValue().contains(feature)) {
|
||||
items.add(cursor.getKey());
|
||||
}
|
||||
@ -997,8 +996,8 @@ public class XmppConnection implements Runnable {
|
||||
return items;
|
||||
}
|
||||
|
||||
public String findDiscoItemByFeature(String feature) {
|
||||
List<String> items = findDiscoItemsByFeature(feature);
|
||||
public String findDiscoItemByFeature(final String feature) {
|
||||
final List<String> items = findDiscoItemsByFeature(feature);
|
||||
if (items.size() >= 1) {
|
||||
return items.get(0);
|
||||
}
|
||||
@ -1010,8 +1009,7 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
|
||||
public String getMucServer() {
|
||||
final List<String> items = new ArrayList<>();
|
||||
for (Entry<String, List<String>> cursor : disco.entrySet()) {
|
||||
for (final Entry<String, List<String>> cursor : disco.entrySet()) {
|
||||
final List<String> value = cursor.getValue();
|
||||
if (value.contains("http://jabber.org/protocol/muc") && !value.contains("jabber:iq:gateway") && !value.contains("siacs:no:muc")) {
|
||||
return cursor.getKey();
|
||||
@ -1021,8 +1019,8 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
|
||||
public int getTimeToNextAttempt() {
|
||||
int interval = (int) (25 * Math.pow(1.5, attempt));
|
||||
int secondsSinceLast = (int) ((SystemClock.elapsedRealtime() - this.lastConnect) / 1000);
|
||||
final int interval = (int) (25 * Math.pow(1.5, attempt));
|
||||
final int secondsSinceLast = (int) ((SystemClock.elapsedRealtime() - this.lastConnect) / 1000);
|
||||
return interval - secondsSinceLast;
|
||||
}
|
||||
|
||||
@ -1035,7 +1033,7 @@ public class XmppConnection implements Runnable {
|
||||
}
|
||||
|
||||
public long getLastSessionEstablished() {
|
||||
long diff;
|
||||
final long diff;
|
||||
if (this.lastSessionStarted == 0) {
|
||||
diff = SystemClock.elapsedRealtime() - this.lastConnect;
|
||||
} else {
|
||||
@ -1067,7 +1065,7 @@ public class XmppConnection implements Runnable {
|
||||
public class Features {
|
||||
XmppConnection connection;
|
||||
|
||||
public Features(XmppConnection connection) {
|
||||
public Features(final XmppConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
@ -1080,6 +1078,10 @@ public class XmppConnection implements Runnable {
|
||||
return hasDiscoFeature(account.getServer(), "urn:xmpp:carbons:2");
|
||||
}
|
||||
|
||||
public boolean blocking() {
|
||||
return hasDiscoFeature(account.getServer(), Xmlns.BLOCKING);
|
||||
}
|
||||
|
||||
public boolean sm() {
|
||||
return streamId != null;
|
||||
}
|
||||
@ -1110,4 +1112,8 @@ public class XmppConnection implements Runnable {
|
||||
.findDiscoItemByFeature("http://jabber.org/protocol/bytestreams") != null;
|
||||
}
|
||||
}
|
||||
|
||||
private IqGenerator getIqGenerator() {
|
||||
return mXmppConnectionService.getIqGenerator();
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ public final class Jid {
|
||||
return resourcepart;
|
||||
}
|
||||
|
||||
public static Jid fromSessionID(SessionID id) throws InvalidJidException{
|
||||
public static Jid fromSessionID(final SessionID id) throws InvalidJidException{
|
||||
if (id.getUserID().isEmpty()) {
|
||||
return Jid.fromString(id.getAccountID());
|
||||
} else {
|
||||
@ -190,4 +190,8 @@ public final class Jid {
|
||||
public boolean isBareJid() {
|
||||
return this.resourcepart.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isDomainJid() {
|
||||
return !this.hasLocalpart();
|
||||
}
|
||||
}
|
||||
|
@ -9,11 +9,11 @@ public class IqPacket extends AbstractStanza {
|
||||
public static final int TYPE_RESULT = 1;
|
||||
public static final int TYPE_GET = 2;
|
||||
|
||||
private IqPacket(String name) {
|
||||
private IqPacket(final String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public IqPacket(int type) {
|
||||
public IqPacket(final int type) {
|
||||
super("iq");
|
||||
switch (type) {
|
||||
case TYPE_SET:
|
||||
@ -45,29 +45,30 @@ public class IqPacket extends AbstractStanza {
|
||||
return query;
|
||||
}
|
||||
|
||||
public Element query(String xmlns) {
|
||||
Element query = query();
|
||||
public Element query(final String xmlns) {
|
||||
final Element query = query();
|
||||
query.setAttribute("xmlns", xmlns);
|
||||
return query();
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
String type = getAttribute("type");
|
||||
if ("error".equals(type)) {
|
||||
final String type = getAttribute("type");
|
||||
switch (type) {
|
||||
case "error":
|
||||
return TYPE_ERROR;
|
||||
} else if ("result".equals(type)) {
|
||||
case "result":
|
||||
return TYPE_RESULT;
|
||||
} else if ("set".equals(type)) {
|
||||
case "set":
|
||||
return TYPE_SET;
|
||||
} else if ("get".equals(type)) {
|
||||
case "get":
|
||||
return TYPE_GET;
|
||||
} else {
|
||||
default:
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
|
||||
public IqPacket generateRespone(int type) {
|
||||
IqPacket packet = new IqPacket(type);
|
||||
public IqPacket generateRespone(final int type) {
|
||||
final IqPacket packet = new IqPacket(type);
|
||||
packet.setTo(this.getFrom());
|
||||
packet.setId(this.getId());
|
||||
return packet;
|
||||
|
@ -7,6 +7,9 @@
|
||||
<item
|
||||
android:id="@+id/context_contact_details"
|
||||
android:title="@string/view_contact_details"/>
|
||||
<item
|
||||
android:id="@+id/context_contact_block_unblock"
|
||||
android:title="@string/block_contact"/>
|
||||
<item
|
||||
android:id="@+id/context_delete_contact"
|
||||
android:title="@string/delete_contact"/>
|
||||
|
@ -56,6 +56,18 @@
|
||||
android:showAsAction="never"
|
||||
android:title="@string/enable_notifications"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_block"
|
||||
android:orderInCategory="72"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/action_block_contact"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_unblock"
|
||||
android:orderInCategory="73"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/action_unblock_contact"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_accounts"
|
||||
android:orderInCategory="90"
|
||||
|
@ -4,5 +4,9 @@
|
||||
android:id="@+id/action_show_qr_code"
|
||||
android:title="@string/show_qr_code"
|
||||
android:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/action_show_block_list"
|
||||
android:title="@string/show_block_list"
|
||||
android:showAsAction="never" />
|
||||
|
||||
</menu>
|
@ -13,6 +13,10 @@
|
||||
<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="action_block_contact">Block contact</string>
|
||||
<string name="action_unblock_contact">Unblock contact</string>
|
||||
<string name="action_block_domain">Block domain</string>
|
||||
<string name="action_unblock_domain">Unblock domain</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>
|
||||
@ -21,6 +25,7 @@
|
||||
<string name="title_activity_sharewith">Share with Conversation</string>
|
||||
<string name="title_activity_start_conversation">Start Conversation</string>
|
||||
<string name="title_activity_choose_contact">Choose contact</string>
|
||||
<string name="title_activity_block_list">Block list</string>
|
||||
<string name="just_now">just now</string>
|
||||
<string name="minute_ago">1 min ago</string>
|
||||
<string name="minutes_ago">%d mins ago</string>
|
||||
@ -34,6 +39,11 @@
|
||||
<string name="participant">Participant</string>
|
||||
<string name="visitor">Visitor</string>
|
||||
<string name="remove_contact_text">Would you like to remove %s from your roster? The conversation associated with this contact will not be removed.</string>
|
||||
<string name="block_contact_text">Would you like to block %s from sending you messages?</string>
|
||||
<string name="unblock_contact_text">Would you like to unblock %s and allow them to send you messages?</string>
|
||||
<string name="block_domain_text">Block all contacts from %s?</string>
|
||||
<string name="unblock_domain_text">Unblock all contacts from %s?</string>
|
||||
<string name="contact_blocked">Contact blocked</string>
|
||||
<string name="remove_bookmark_text">Would you like to remove %s as a bookmark? The conversation associated with this bookmark will not be removed.</string>
|
||||
<string name="register_account">Register new account on server</string>
|
||||
<string name="share_with">Share with</string>
|
||||
@ -45,6 +55,8 @@
|
||||
<string name="add">Add</string>
|
||||
<string name="edit">Edit</string>
|
||||
<string name="delete">Delete</string>
|
||||
<string name="block">Block</string>
|
||||
<string name="unblock">Unblock</string>
|
||||
<string name="save">Save</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="crash_report_title">Conversations has crashed</string>
|
||||
@ -202,6 +214,8 @@
|
||||
<string name="join_conference">Join Conference</string>
|
||||
<string name="delete_contact">Delete Contact</string>
|
||||
<string name="view_contact_details">View contact details</string>
|
||||
<string name="block_contact">Block contact</string>
|
||||
<string name="unblock_contact">Unblock contact</string>
|
||||
<string name="create">Create</string>
|
||||
<string name="contact_already_exists">The contact already exists</string>
|
||||
<string name="join">Join</string>
|
||||
@ -318,6 +332,7 @@
|
||||
<string name="image_transmission_failed">Image transmission failed</string>
|
||||
<string name="scan_qr_code">Scan QR code</string>
|
||||
<string name="show_qr_code">Show QR code</string>
|
||||
<string name="show_block_list">Show block list</string>
|
||||
<string name="account_details">Account details</string>
|
||||
<string name="verify_otr">Verify OTR</string>
|
||||
<string name="remote_fingerprint">Remote Fingerprint</string>
|
||||
|
Loading…
Reference in New Issue
Block a user