Commit 797bf743 authored by Grigory Fedorov's avatar Grigory Fedorov

Merge branch 'Semenchikus-XEP-0280' into develop (thanks to @aelmahmoudy)

parents f8222bbe cd53ba41
...@@ -35,6 +35,7 @@ import com.xabber.android.service.XabberService; ...@@ -35,6 +35,7 @@ import com.xabber.android.service.XabberService;
import com.xabber.android.ui.adapter.ComparatorByName; import com.xabber.android.ui.adapter.ComparatorByName;
import com.xabber.android.ui.adapter.ComparatorByStatus; import com.xabber.android.ui.adapter.ComparatorByStatus;
import com.xabber.androiddev.R; import com.xabber.androiddev.R;
import com.xabber.xmpp.carbon.CarbonManager;
import java.util.Comparator; import java.util.Comparator;
...@@ -557,6 +558,11 @@ public class SettingsManager implements OnInitializedListener, ...@@ -557,6 +558,11 @@ public class SettingsManager implements OnInitializedListener,
R.bool.connection_load_vcard_default); R.bool.connection_load_vcard_default);
} }
public static boolean connectionUseCarbons() {
return getBoolean(R.string.connection_use_carbons_key,
R.bool.connection_use_carbons_default);
}
public static boolean connectionAdjustPriority() { public static boolean connectionAdjustPriority() {
return getBoolean(R.string.connection_adjust_priority_key, return getBoolean(R.string.connection_adjust_priority_key,
R.bool.connection_adjust_priority_default); R.bool.connection_adjust_priority_default);
...@@ -750,6 +756,9 @@ public class SettingsManager implements OnInitializedListener, ...@@ -750,6 +756,9 @@ public class SettingsManager implements OnInitializedListener,
} else if (key.equals(Application.getInstance().getString( } else if (key.equals(Application.getInstance().getString(
R.string.connection_wifi_lock_key))) { R.string.connection_wifi_lock_key))) {
NetworkManager.getInstance().onWifiLockSettingsChanged(); NetworkManager.getInstance().onWifiLockSettingsChanged();
} else if (key.equals(Application.getInstance().getString(
R.string.connection_use_carbons_key))) {
CarbonManager.getInstance().onUseCarbonsSettingsChanged();
} else if (key.equals(Application.getInstance().getString( } else if (key.equals(Application.getInstance().getString(
R.string.events_show_text_key))) { R.string.events_show_text_key))) {
NotificationManager.getInstance().onMessageNotification(); NotificationManager.getInstance().onMessageNotification();
...@@ -762,4 +771,4 @@ public class SettingsManager implements OnInitializedListener, ...@@ -762,4 +771,4 @@ public class SettingsManager implements OnInitializedListener,
} }
} }
} }
\ No newline at end of file
...@@ -30,6 +30,7 @@ import com.xabber.android.data.extension.otr.SecurityLevel; ...@@ -30,6 +30,7 @@ import com.xabber.android.data.extension.otr.SecurityLevel;
import com.xabber.android.data.message.chat.ChatManager; import com.xabber.android.data.message.chat.ChatManager;
import com.xabber.android.data.notification.NotificationManager; import com.xabber.android.data.notification.NotificationManager;
import com.xabber.xmpp.archive.SaveMode; import com.xabber.xmpp.archive.SaveMode;
import com.xabber.xmpp.carbon.CarbonManager;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Message.Type; import org.jivesoftware.smack.packet.Message.Type;
...@@ -579,6 +580,8 @@ public abstract class AbstractChat extends BaseEntity { ...@@ -579,6 +580,8 @@ public abstract class AbstractChat extends BaseEntity {
message); message);
ReceiptManager.getInstance().updateOutgoingMessage(this, ReceiptManager.getInstance().updateOutgoingMessage(this,
message, messageItem); message, messageItem);
CarbonManager.getInstance().updateOutgoingMessage(this,
message, messageItem);
if (messageItem != intent) if (messageItem != intent)
message.addExtension(new DelayInformation(messageItem message.addExtension(new DelayInformation(messageItem
.getTimestamp())); .getTimestamp()));
...@@ -688,4 +691,4 @@ public abstract class AbstractChat extends BaseEntity { ...@@ -688,4 +691,4 @@ public abstract class AbstractChat extends BaseEntity {
public boolean isLastMessageIncoming() { public boolean isLastMessageIncoming() {
return isLastMessageIncoming; return isLastMessageIncoming;
} }
} }
\ No newline at end of file
...@@ -41,6 +41,7 @@ import com.xabber.android.data.roster.RosterManager; ...@@ -41,6 +41,7 @@ import com.xabber.android.data.roster.RosterManager;
import com.xabber.android.utils.StringUtils; import com.xabber.android.utils.StringUtils;
import com.xabber.androiddev.R; import com.xabber.androiddev.R;
import com.xabber.xmpp.address.Jid; import com.xabber.xmpp.address.Jid;
import com.xabber.xmpp.carbon.CarbonManager.Direction;
import com.xabber.xmpp.delay.Delay; import com.xabber.xmpp.delay.Delay;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
...@@ -499,6 +500,56 @@ public class MessageManager implements OnLoadListener, OnPacketListener, OnDisco ...@@ -499,6 +500,56 @@ public class MessageManager implements OnLoadListener, OnPacketListener, OnDisco
} }
} }
public void displayForwardedMessage(ConnectionItem connection, Message message, Direction direction) {
if (!(connection instanceof AccountItem))
return;
String account = ((AccountItem) connection).getAccount();
if (MessageArchiveManager.getInstance().isModificationsSucceed(account)
&& Delay.isOfflineMessage(Jid.getServer(account), message)) {
// Ignore offline message if modification from server side message
// archive have been received.
return;
}
if (direction == Direction.sent) {
String companion = Jid.getBareAddress(message.getTo());
if (companion == null) {
return;
}
AbstractChat chat = getChat(account, companion);
if (chat == null) {
chat = createChat(account, companion);
}
String body = message.getBody();
if (body == null) {
return;
}
chat.newMessage(body);
return;
}
String companion = Jid.getBareAddress(message.getFrom());
boolean processed = false;
for (AbstractChat chat : chats.getNested(account).values()) {
if (chat.onPacket(companion, message)) {
processed = true;
break;
}
}
if (getChat(account, companion) != null) {
return;
}
if (processed) {
return;
}
final String body = message.getBody();
if (body == null) {
return;
}
createChat(account, companion).onPacket(companion, message);
}
@Override @Override
public void onRosterReceived(AccountItem accountItem) { public void onRosterReceived(AccountItem accountItem) {
String account = accountItem.getAccount(); String account = accountItem.getAccount();
...@@ -618,4 +669,4 @@ public class MessageManager implements OnLoadListener, OnPacketListener, OnDisco ...@@ -618,4 +669,4 @@ public class MessageManager implements OnLoadListener, OnPacketListener, OnDisco
} }
} }
} }
\ No newline at end of file
package com.xabber.xmpp.carbon;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smackx.ServiceDiscoveryManager;
import com.xabber.android.data.Application;
import com.xabber.android.data.LogManager;
import com.xabber.android.data.SettingsManager;
import com.xabber.android.data.SettingsManager.SecurityOtrMode;
import com.xabber.android.data.account.AccountItem;
import com.xabber.android.data.connection.ConnectionItem;
import com.xabber.android.data.connection.OnPacketListener;
import com.xabber.android.data.extension.capability.OnServerInfoReceivedListener;
import com.xabber.android.data.extension.capability.ServerInfoManager;
import com.xabber.android.data.extension.otr.OTRManager;
import com.xabber.android.data.extension.otr.SecurityLevel;
import com.xabber.android.data.message.AbstractChat;
import com.xabber.android.data.message.MessageItem;
import com.xabber.android.data.message.MessageManager;
/**
* Packet extension for XEP-0280: Message Carbons. This class implements
* the manager for registering {@link Carbon} support, enabling and disabling
* message carbons.
*
* You should call enableCarbons() before sending your first undirected
* presence.
*
* @author Georg Lukas, Semyon Baranov
*/
public class CarbonManager implements OnServerInfoReceivedListener, OnPacketListener
{
private final static CarbonManager instance;
private Connection connection;
private volatile boolean enabled_state = false;
public static final String NAMESPACE = "urn:xmpp:carbons:2";
static {
instance = new CarbonManager();
Application.getInstance().addManager(instance);
Connection.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(final Connection connection) {
if (!(connection instanceof XMPPConnection)) {
return;
}
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
if (sdm != null) {
sdm.addFeature(NAMESPACE);
sdm.addFeature(Forwarded.NAMESPACE);
}
instance.connection = connection;
}
});
}
public static CarbonManager getInstance() {
return instance;
}
private CarbonManager() {
}
private IQ carbonsEnabledIQ(final boolean new_state) {
if (!checkConnected()) {
return null;
}
IQ setIQ = new IQ() {
public String getChildElementXML() {
return String.format("<%s xmlns='%s'/>", new_state ? "enable" : "disable", NAMESPACE);
}
};
setIQ.setType(IQ.Type.SET);
setIQ.setFrom(connection.getUser());
return setIQ;
}
private boolean checkConnected() {
if (connection == null) {
LogManager.exception(this, new Exception("connection is null"));
return false;
}
if (!connection.isConnected()) {
LogManager.exception(this, new Exception("not connected"));
return false;
}
return true;
}
/**
* Returns true if XMPP Carbons are supported by the server.
*
* @return true if supported
*/
public boolean isSupportedByServer() {
if (!checkConnected()) {
return false;
}
boolean isCarbonSupported = ServerInfoManager.getInstance().isProtocolSupported(connection.getUser(), NAMESPACE);
return isCarbonSupported;
}
/**
* Notify server to change the carbons state. This method returns
* immediately and changes the variable when the reply arrives.
*
* You should first check for support using isSupportedByServer().
*
* @param new_state whether carbons should be enabled or disabled
*/
public void sendCarbonsEnabled(final boolean new_state) {
LogManager.d(this, "sendCarbonsEnabled " + String.valueOf(new_state));
if (!checkConnected()) {
return;
}
IQ setIQ = carbonsEnabledIQ(new_state);
connection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
IQ result = (IQ)packet;
if (result.getType() == IQ.Type.RESULT) {
enabled_state = new_state;
}
connection.removePacketListener(this);
}
}, new PacketIDFilter(setIQ.getPacketID()));
connection.sendPacket(setIQ);
}
/**
* Helper method to enable carbons.
*/
public void enableCarbons() {
sendCarbonsEnabled(true);
}
/**
* Helper method to disable carbons.
*/
public void disableCarbons() {
sendCarbonsEnabled(false);
}
/**
* Check if carbons are enabled on this connection.
*/
public boolean getCarbonsEnabled() {
return enabled_state;
}
/**
* Mark a message as "private", so it will not be carbon-copied.
*
* @param msg Message object to mark private
*/
public static void disableCarbons(Message msg) {
msg.addExtension(new Private());
}
@Override
public void onPacket(ConnectionItem connection, String bareAddress,
Packet packet) {
if (!(connection instanceof AccountItem)) {
return;
}
if (!SettingsManager.connectionUseCarbons()) {
return;
}
final String user = packet.getFrom();
if (user == null)
return;
if (!(packet instanceof Message))
return;
final Message message = (Message) packet;
if (!getCarbonsEnabled()) {
return;
}
PacketExtension carbonExtension = null;
Direction dir = null;
for (PacketExtension packetExtension : message.getExtensions()) {
if (packetExtension instanceof Received) {
carbonExtension = packetExtension;
dir = Direction.received;
} else if (packetExtension instanceof Sent) {
carbonExtension = packetExtension;
dir = Direction.sent;
} else {
continue;
}
}
if (carbonExtension == null) {
return;
}
Forwarded forwarded = null;
if (dir == Direction.sent) {
Sent carbon = (Sent) carbonExtension;
forwarded = carbon.getForwarded();
} else {
Received carbon = (Received) carbonExtension;
forwarded = carbon.getForwarded();
}
if (forwarded == null) {
return;
}
Message forwardedMsg = (Message) forwarded.getForwardedPacket();
MessageManager.getInstance().displayForwardedMessage(connection, forwardedMsg, dir);
}
@Override
public void onServerInfoReceived(ConnectionItem connection) {
if (isSupportedByServer()) {
onUseCarbonsSettingsChanged();
}
}
/**
* Sends the new state of message carbons to the server
* when this setting has been changed
*/
public void onUseCarbonsSettingsChanged() {
sendCarbonsEnabled(SettingsManager.connectionUseCarbons());
}
/**
* Update outgoing message before sending.
* Marks the message as non-carbon-copied in the following cases:
* - Message Carbons is enabled and OTR mode is enabled.
* - Message Carbons is enabled and OTR security level != plain.
* @param abstractChat
* @param message the <tt>Message</tt> to be sent
* @param messageItem
*/
public void updateOutgoingMessage(AbstractChat abstractChat, Message message, MessageItem messageItem) {
if (!SettingsManager.connectionUseCarbons()) {
return;
}
if (SettingsManager.securityOtrMode() == SecurityOtrMode.disabled) {
return;
}
if (OTRManager.getInstance().getSecurityLevel(abstractChat.getAccount(),
abstractChat.getUser()) != SecurityLevel.plain) {
return;
}
message.addExtension(new Private());
}
public enum Direction {
sent, received
}
}
\ No newline at end of file
package com.xabber.xmpp.carbon;
import java.io.IOException;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smackx.packet.DelayInfo;
import org.xmlpull.v1.XmlSerializer;
import com.xabber.xmpp.Container;
import com.xabber.xmpp.PacketExtension;
/**
* Packet extension for XEP-0297: Stanza Forwarding. This class implements
* the packet extension to parse
* forwarded messages from a packet. The extension
* <a href="http://xmpp.org/extensions/xep-0297.html">XEP-0297</a> is
* a prerequisite for XEP-0280 (Message Carbons).
*
* @author Semyon Baranov
*/
public class Forwarded extends PacketExtension implements Container {
public static final String NAMESPACE = "urn:xmpp:forward:0";
public static final String ELEMENT_NAME = "forwarded";
private DelayInfo delay;
private Packet forwardedPacket;
public Forwarded() {
}
/**
* Creates a new Forwarded packet extension.
*
* @param delay an optional {@link DelayInfo} timestamp of the packet.
* @param fwdPacket the packet that is forwarded (required).
*/
public Forwarded(DelayInfo delay, Packet fwdPacket) {
this();
this.delay = delay;
this.forwardedPacket = fwdPacket;
}
@Override
public String getElementName() {
return ELEMENT_NAME;
}
@Override
public String getNamespace() {
return NAMESPACE;
}
@Override
public boolean isValid() {
return forwardedPacket != null;
}
@Override
public void serialize(XmlSerializer serializer) throws IOException {
}
@Override
public void serializeContent(XmlSerializer serializer) throws IOException {
}
/**
* get the packet forwarded by this stanza.
*
* @return the {@link Packet} instance (typically a message) that was forwarded.
*/
public Packet getForwardedPacket() {
return forwardedPacket;
}
/**
* get the timestamp of the forwarded packet.
*
* @return the {@link DelayInfo} representing the time when the original packet was sent. May be null.
*/
public DelayInfo getDelayInfo() {
return delay;
}
}
\ No newline at end of file
package com.xabber.xmpp.carbon;
import java.io.IOException;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smackx.packet.DelayInfo;
import org.jivesoftware.smackx.provider.DelayInfoProvider;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import com.xabber.android.data.LogManager;
import com.xabber.xmpp.AbstractExtensionProvider;
/**
* Packet extension for XEP-0297: Stanza Forwarding. This class implements
* a {@link PacketExtensionProvider} to parse forwarded messages from a packet.
* The extension <a href="http://xmpp.org/extensions/xep-0297.html">XEP-0297</a>
* is a prerequisite for XEP-0280 (Message Carbons).
*
* <p>The {@link ForwardedProvider} must be registered in the
* <b>smack.providers</b> file for the element <b>forwarded</b> with
* namespace <b>urn:xmpp:forwarded:0</b></p> to be used.
*
* @author Semyon Baranov
*/
public class ForwardedProvider extends AbstractExtensionProvider<Forwarded> {
DelayInfoProvider dip = new DelayInfoProvider();
@Override
protected Forwarded createInstance(XmlPullParser parser) {
return new Forwarded(null, null);
}
@Override
public Forwarded parseExtension(XmlPullParser parser) throws Exception {
DelayInfoProvider dip = new DelayInfoProvider();
DelayInfo di = null;
Packet packet = null;
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("delay"))
di = (DelayInfo)dip.parseExtension(parser);
else if (parser.getName().equals("message"))
packet = PacketParserUtils.parseMessage(parser);
else throw new Exception("Unsupported forwarded packet type: " + parser.getName());
}
else if (eventType == XmlPullParser.END_TAG && parser.getName().equals(Forwarded.ELEMENT_NAME))
done = true;
}
if (packet == null)
throw new Exception("forwarded extension must contain a packet");
return new Forwarded(di, packet);
}
}
package com.xabber.xmpp.carbon;
import java.io.IOException;
import org.xmlpull.v1.XmlSerializer;
import com.xabber.xmpp.PacketExtension;
/**
* Packet extension for XEP-0280: Message Carbons. This class implements
* the packet extension to exclude a <message/> from being forwarded
* to other Carbons-enabled resources.
* The extension <a href="http://xmpp.org/extensions/xep-0280.html">XEP-0280</a>
* is meant to synchronize a message flow to multiple presences of a user.
*
* @author Semyon Baranov
*/
public class Private extends PacketExtension {
public static final String ELEMENT_NAME = "private";
public static final String NAMESPACE = "urn:xmpp:carbons:2";
@Override
public String getElementName() {
return ELEMENT_NAME;
}
@Override
public String getNamespace() {
return NAMESPACE;
}
@Override
public void serializeContent(XmlSerializer serializer) throws IOException {
}
@Override
public boolean isValid() {
return true;
}
}
package com.xabber.xmpp.carbon;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
import com.xabber.xmpp.AbstractExtensionProvider;
/**
* Packet extension for XEP-0280: Message Carbons. This class implements
* a {@link PacketExtensionProvider} to exclude a <message/> from being
* forwarded to other Carbons-enabled resources.
* The extension <a href="http://xmpp.org/extensions/xep-0280.html">XEP-0280</a>
* is meant to synchronize a message flow to multiple presences of a user.
*
* @author Semyon Baranov
*/
public class PrivateProvider extends AbstractExtensionProvider<Private> {
@Override
protected Private createInstance(XmlPullParser parser) {
return new Private();
}
}
package com.xabber.xmpp.carbon;
import java.io.IOException;
import org.xmlpull.v1.XmlSerializer;
import com.xabber.xmpp.PacketExtension;
/**
* Packet extension for XEP-0280: Message Carbons. This class implements
* the packet extension to parse a received message from a packet.
* The extension <a href="http://xmpp.org/extensions/xep-0280.html">XEP-0280</a>
* is meant to synchronize a message flow to multiple presences of a user.
*
* @author Semyon Baranov
*/
public class Received extends PacketExtension {
public static final String ELEMENT_NAME = "received";
public static final String NAMESPACE = "urn:xmpp:carbons:2";
private Forwarded fwd;
public Received() {
}
@Override
public String getElementName() {
return ELEMENT_NAME;
}
@Override
public String getNamespace() {
return NAMESPACE;
}
@Override
public void serializeContent(XmlSerializer serializer) throws IOException {
}
@Override
public boolean isValid() {
return fwd != null;
}
/**
* Gets the forwarded packet or null if the forwarded has not been set.
*
* @return the {@link Forwarded} message contained in this Carbon.
*/
public Forwarded getForwarded() {
return fwd;
}
/**
* Sets the forwarded packet.
* @param fwd - the {@link Forwarded} message contained in this Carbon.
*/
public void setForwarded(Forwarded fwd) {
this.fwd = fwd;
}
}
package com.xabber.xmpp.carbon;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.xmlpull.v1.XmlPullParser;
import com.xabber.android.data.LogManager;
import com.xabber.xmpp.AbstractExtensionProvider;
/**
* Packet extension for XEP-0280: Message Carbons. This class implements
* a {@link PacketExtensionProvider} to parse a received message from a packet.
* The extension <a href="http://xmpp.org/extensions/xep-0280.html">XEP-0280</a>
* is meant to synchronize a message flow to multiple presences of a user.
*
* @author Semyon Baranov
*/
public class ReceivedProvider extends AbstractExtensionProvider<Received> {
@Override
protected Received createInstance(XmlPullParser parser) {
return new Received();
}
@Override
protected boolean parseInner(XmlPullParser parser, Received instance)
throws Exception {
Forwarded forwarded = null;
if (parser.getName().equals(Forwarded.ELEMENT_NAME)) {
try {
forwarded = (Forwarded) PacketParserUtils.parsePacketExtension(Forwarded.ELEMENT_NAME, Forwarded.NAMESPACE, parser);
} catch (Exception e) {
LogManager.exception(this, e);
}
}
if (forwarded == null) {
LogManager.exception(this, new Exception("received extension must contain a forwarded extension"));
return false;
}
instance.setForwarded(forwarded);
return true;
}
}
package com.xabber.xmpp.carbon;
import java.io.IOException;
import org.xmlpull.v1.XmlSerializer;
import com.xabber.xmpp.PacketExtension;
/**
* Packet extension for XEP-0280: Message Carbons. This class implements
* the packet extension to parse a sent message from a packet.
* The extension <a href="http://xmpp.org/extensions/xep-0280.html">XEP-0280</a>
* is meant to synchronize a message flow to multiple presences of a user.
*
* @author Semyon Baranov
*/
public class Sent extends PacketExtension {
public static final String ELEMENT_NAME = "sent";
public static final String NAMESPACE = "urn:xmpp:carbons:2";
private Forwarded fwd;
public Sent() {
}
@Override
public String getElementName() {
return ELEMENT_NAME;
}
@Override
public String getNamespace() {
return NAMESPACE;
}
@Override
public void serializeContent(XmlSerializer serializer) throws IOException {
}
@Override
public boolean isValid() {
return fwd != null;
}
/**
* Gets the forwarded packet or null if the forwarded has not been set.
*
* @return the {@link Forwarded} message contained in this Carbon.
*/
public Forwarded getForwarded() {
return fwd;
}
/**
* Sets the forwarded packet.
* @param fwd - the {@link Forwarded} message contained in this Carbon.
*/
public void setForwarded(Forwarded fwd) {
this.fwd = fwd;
}
}
package com.xabber.xmpp.carbon;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.xmlpull.v1.XmlPullParser;
import com.xabber.android.data.LogManager;
import com.xabber.xmpp.AbstractExtensionProvider;
/**
* Packet extension for XEP-0280: Message Carbons. This class implements
* a {@link PacketExtensionProvider} to parse a sent message from a packet.
* The extension <a href="http://xmpp.org/extensions/xep-0280.html">XEP-0280</a>
* is meant to synchronize a message flow to multiple presences of a user.
*
* @author Semyon Baranov
*/
public class SentProvider extends AbstractExtensionProvider<Sent> {
@Override
protected Sent createInstance(XmlPullParser parser) {
return new Sent();
}
@Override
protected boolean parseInner(XmlPullParser parser, Sent instance)
throws Exception {
Forwarded forwarded = null;
if (parser.getName().equals(Forwarded.ELEMENT_NAME)) {
try {
forwarded = (Forwarded) PacketParserUtils.parsePacketExtension(Forwarded.ELEMENT_NAME, Forwarded.NAMESPACE, parser);
} catch (Exception e) {
LogManager.exception(this, e);
}
}
if (forwarded == null) {
LogManager.exception(this, new Exception("sent extension must contain a forwarded extension"));
return false;
}
instance.setForwarded(forwarded);
return true;
}
}
...@@ -247,4 +247,29 @@ ...@@ -247,4 +247,29 @@
<className>com.xabber.xmpp.attention.AttentionProvider</className> <className>com.xabber.xmpp.attention.AttentionProvider</className>
</extensionProvider> </extensionProvider>
<!-- Message Carbons -->
<extensionProvider>
<elementName>sent</elementName>
<namespace>urn:xmpp:carbons:2</namespace>
<className>com.xabber.xmpp.carbon.SentProvider</className>
</extensionProvider>
<extensionProvider>
<elementName>received</elementName>
<namespace>urn:xmpp:carbons:2</namespace>
<className>com.xabber.xmpp.carbon.ReceivedProvider</className>
</extensionProvider>
<extensionProvider>
<elementName>private</elementName>
<namespace>urn:xmpp:carbons:2</namespace>
<className>com.xabber.xmpp.carbon.PrivateProvider</className>
</extensionProvider>
<!-- Message Forwarding -->
<extensionProvider>
<elementName>forwarded</elementName>
<namespace>urn:xmpp:forward:0</namespace>
<className>com.xabber.xmpp.carbon.ForwardedProvider</className>
</extensionProvider>
</smackProviders> </smackProviders>
\ No newline at end of file
...@@ -147,6 +147,7 @@ ...@@ -147,6 +147,7 @@
<string name="chats_attention">Привлечение внимания\nОтзываться на запросы привлечения внимания</string> <string name="chats_attention">Привлечение внимания\nОтзываться на запросы привлечения внимания</string>
<string name="chats_attention_sound">Звук привлечения внимания\nВыберите мелодию звонка</string> <string name="chats_attention_sound">Звук привлечения внимания\nВыберите мелодию звонка</string>
<string name="connection_load_vcard">Загружать vCard\nЗагружать и обновлять персональную информацию и аватары контактов. Отключение поможет сэкономить трафик.</string> <string name="connection_load_vcard">Загружать vCard\nЗагружать и обновлять персональную информацию и аватары контактов. Отключение поможет сэкономить трафик.</string>
<string name="connection_use_carbons">Сообщения carbons\nПринимать сообщения других сессий Вашей учетной записи. Отключение поможет сэкономить трафик.</string>
<string name="events_phrases">Ключевые фразы\nНастройки уведомлений о сообщениях содержащих ключевые фразы</string> <string name="events_phrases">Ключевые фразы\nНастройки уведомлений о сообщениях содержащих ключевые фразы</string>
<!-- http://dl.dropbox.com/u/1029995/com.xabber.android/preference_editor_security_remove.png --> <!-- http://dl.dropbox.com/u/1029995/com.xabber.android/preference_editor_security_remove.png -->
<string name="security_clear_certificate_warning">Вы действительно хотите удалить все игнорируемые сертификаты?</string> <string name="security_clear_certificate_warning">Вы действительно хотите удалить все игнорируемые сертификаты?</string>
......
...@@ -147,6 +147,7 @@ ...@@ -147,6 +147,7 @@
<string name="chats_attention">Attention\nReact for the incoming attention requests</string> <string name="chats_attention">Attention\nReact for the incoming attention requests</string>
<string name="chats_attention_sound">Attention sound\nChoose ring-tone</string> <string name="chats_attention_sound">Attention sound\nChoose ring-tone</string>
<string name="connection_load_vcard">Load vCard\nLoad and update contact\'s personal info and avatar. Disable to reduce traffic usage.</string> <string name="connection_load_vcard">Load vCard\nLoad and update contact\'s personal info and avatar. Disable to reduce traffic usage.</string>
<string name="connection_use_carbons">Carbon-copied mode\nWill share the sessions for the same account on this client. Disable to reduce traffic usage.</string>
<string name="events_phrases">Key phrases\nCustom sound notifications about messages with preset phrases</string> <string name="events_phrases">Key phrases\nCustom sound notifications about messages with preset phrases</string>
<!-- http://dl.dropbox.com/u/1029995/com.xabber.android/preference_editor_security_remove.png --> <!-- http://dl.dropbox.com/u/1029995/com.xabber.android/preference_editor_security_remove.png -->
<string name="security_clear_certificate_warning">Do you really want to remove all the ignored certificates?</string> <string name="security_clear_certificate_warning">Do you really want to remove all the ignored certificates?</string>
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
<item>com.xabber.android.data.extension.capability.ServerInfoManager</item> <item>com.xabber.android.data.extension.capability.ServerInfoManager</item>
<item>com.xabber.android.data.extension.time.TimeManager</item> <item>com.xabber.android.data.extension.time.TimeManager</item>
<item>com.xabber.android.data.extension.attention.AttentionManager</item> <item>com.xabber.android.data.extension.attention.AttentionManager</item>
<item>com.xabber.xmpp.carbon.CarbonManager</item>
</string-array> </string-array>
<string-array name="contact_managers"> <string-array name="contact_managers">
...@@ -127,10 +128,10 @@ ...@@ -127,10 +128,10 @@
<string name="contacts_show_offline_key">contacts_show_offline</string> <string name="contacts_show_offline_key">contacts_show_offline</string>
<bool name="contacts_show_offline_default">false</bool> <bool name="contacts_show_offline_default">false</bool>
<string name="contacts_show_groups_key">contacts_show_groups</string> <string name="contacts_show_groups_key">contacts_show_groups</string>
<bool name="contacts_show_groups_default">true</bool> <bool name="contacts_show_groups_default">true</bool>
<string name="contacts_show_accounts_key">contacts_show_accounts</string> <string name="contacts_show_accounts_key">contacts_show_accounts</string>
<bool name="contacts_show_accounts_default">true</bool> <bool name="contacts_show_accounts_default">true</bool>
...@@ -142,7 +143,7 @@ ...@@ -142,7 +143,7 @@
<string name="contacts_show_empty_groups_key">contacts_show_empty_groups</string> <string name="contacts_show_empty_groups_key">contacts_show_empty_groups</string>
<bool name="contacts_show_empty_groups_default">false</bool> <bool name="contacts_show_empty_groups_default">false</bool>
<string name="contacts_order_key">contacts_order</string> <string name="contacts_order_key">contacts_order</string>
<string name="contacts_order_status_value">status</string> <string name="contacts_order_status_value">status</string>
<string name="contacts_order_alphabet_value">alphabet</string> <string name="contacts_order_alphabet_value">alphabet</string>
...@@ -198,7 +199,7 @@ ...@@ -198,7 +199,7 @@
<string name="events_visible_chat_key">events_visible_chat</string> <string name="events_visible_chat_key">events_visible_chat</string>
<bool name="events_visible_chat_default">false</bool> <bool name="events_visible_chat_default">false</bool>
<string name="events_first_only_key">events_first_only</string> <string name="events_first_only_key">events_first_only</string>
<bool name="events_first_only_default">false</bool> <bool name="events_first_only_default">false</bool>
...@@ -362,6 +363,9 @@ ...@@ -362,6 +363,9 @@
<string name="connection_load_vcard_key">connection_load_vcard</string> <string name="connection_load_vcard_key">connection_load_vcard</string>
<bool name="connection_load_vcard_default">true</bool> <bool name="connection_load_vcard_default">true</bool>
<string name="connection_use_carbons_key">connection_use_carbons</string>
<bool name="connection_use_carbons_default">true</bool>
<!-- preference_cache --> <!-- preference_cache -->
<string name="cache_clear_key">cache_clear</string> <string name="cache_clear_key">cache_clear</string>
......
...@@ -34,6 +34,11 @@ ...@@ -34,6 +34,11 @@
android:key="@string/connection_load_vcard_key" android:key="@string/connection_load_vcard_key"
android:defaultValue="@bool/connection_load_vcard_default" android:defaultValue="@bool/connection_load_vcard_default"
/> />
<CheckBoxPreference
android:title="@string/connection_use_carbons"
android:key="@string/connection_use_carbons_key"
android:defaultValue="@bool/connection_use_carbons_default"
/>
<PreferenceCategory <PreferenceCategory
android:title="@string/connection_priority" android:title="@string/connection_priority"
> >
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment