diff options
Diffstat (limited to 'src')
40 files changed, 1052 insertions, 862 deletions
diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index b5a1897d..8cb48635 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -395,7 +395,7 @@ public class Message extends AbstractEntity { String[] pathParts = url.getPath().split("/"); String filename; if (pathParts.length > 0) { - filename = pathParts[pathParts.length - 1]; + filename = pathParts[pathParts.length - 1].toLowerCase(); } else { return false; } diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 97a63532..ce2c5b04 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -4,15 +4,55 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.stanzas.PresencePacket; + import android.annotation.SuppressLint; @SuppressLint("DefaultLocale") public class MucOptions { + + public enum Affiliation { + OWNER(R.string.owner), + ADMIN(R.string.admin), + MEMBER(R.string.member), + OUTCAST(R.string.outcast), + NONE(R.string.no_affiliation); + + private Affiliation(int resId) { + this.resId = resId; + } + + private int resId; + + public int getResId() { + return resId; + } + } + + ; + + public enum Role { + MODERATOR(R.string.moderator), + VISITOR(R.string.visitor), + PARTICIPANT(R.string.participant), + NONE(R.string.no_role); + + private Role(int resId) { + this.resId = resId; + } + + private int resId; + + public int getResId() { + return resId; + } + } + public static final int ERROR_NO_ERROR = 0; public static final int ERROR_NICK_IN_USE = 1; public static final int ERROR_UNKNOWN = 2; @@ -30,6 +70,7 @@ public class MucOptions { private interface OnEventListener { public void onSuccess(); + public void onFailure(); } @@ -42,18 +83,8 @@ public class MucOptions { } public class User { - public static final int ROLE_MODERATOR = 3; - public static final int ROLE_NONE = 0; - public static final int ROLE_PARTICIPANT = 2; - public static final int ROLE_VISITOR = 1; - public static final int AFFILIATION_ADMIN = 4; - public static final int AFFILIATION_OWNER = 3; - public static final int AFFILIATION_MEMBER = 2; - public static final int AFFILIATION_OUTCAST = 1; - public static final int AFFILIATION_NONE = 0; - - private int role; - private int affiliation; + private Role role; + private Affiliation affiliation; private String name; private Jid jid; private long pgpKeyId = 0; @@ -74,7 +105,7 @@ public class MucOptions { return this.jid; } - public int getRole() { + public Role getRole() { return this.role; } @@ -82,35 +113,41 @@ public class MucOptions { role = role.toLowerCase(); switch (role) { case "moderator": - this.role = ROLE_MODERATOR; + this.role = Role.MODERATOR; break; case "participant": - this.role = ROLE_PARTICIPANT; + this.role = Role.PARTICIPANT; break; case "visitor": - this.role = ROLE_VISITOR; + this.role = Role.VISITOR; break; default: - this.role = ROLE_NONE; + this.role = Role.NONE; break; } } - public int getAffiliation() { + public Affiliation getAffiliation() { return this.affiliation; } public void setAffiliation(String affiliation) { - if (affiliation.equalsIgnoreCase("admin")) { - this.affiliation = AFFILIATION_ADMIN; - } else if (affiliation.equalsIgnoreCase("owner")) { - this.affiliation = AFFILIATION_OWNER; - } else if (affiliation.equalsIgnoreCase("member")) { - this.affiliation = AFFILIATION_MEMBER; - } else if (affiliation.equalsIgnoreCase("outcast")) { - this.affiliation = AFFILIATION_OUTCAST; - } else { - this.affiliation = AFFILIATION_NONE; + affiliation = affiliation.toLowerCase(); + switch (affiliation) { + case "admin": + this.affiliation = Affiliation.ADMIN; + break; + case "owner": + this.affiliation = Affiliation.OWNER; + break; + case "member": + this.affiliation = Affiliation.MEMBER; + break; + case "outcast": + this.affiliation = Affiliation.OUTCAST; + break; + default: + this.affiliation = Affiliation.NONE; } } @@ -168,7 +205,7 @@ public class MucOptions { if (!from.isBareJid()) { final String name = from.getResourcepart(); final String type = packet.getAttribute("type"); - final Element x = packet.findChild("x","http://jabber.org/protocol/muc#user"); + final Element x = packet.findChild("x", "http://jabber.org/protocol/muc#user"); final List<String> codes = getStatusCodes(x); if (type == null) { User user = new User(); @@ -204,7 +241,7 @@ public class MucOptions { msg = ""; } user.setPgpKeyId(pgp.fetchKeyId(account, msg, - signed.getContent())); + signed.getContent())); } } } @@ -261,10 +298,10 @@ public class MucOptions { private List<String> getStatusCodes(Element x) { List<String> codes = new ArrayList<String>(); if (x != null) { - for(Element child : x.getChildren()) { + for (Element child : x.getChildren()) { if (child.getName().equals("status")) { String code = child.getAttribute("code"); - if (code!=null) { + if (code != null) { codes.add(code); } } @@ -389,7 +426,7 @@ public class MucOptions { public Jid createJoinJid(String nick) { try { - return Jid.fromString(this.conversation.getJid().toBareJid().toString() + "/"+nick); + return Jid.fromString(this.conversation.getJid().toBareJid().toString() + "/" + nick); } catch (final InvalidJidException e) { return null; } diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java index f94dc5d7..58933692 100644 --- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java @@ -21,7 +21,7 @@ public class IqGenerator extends AbstractGenerator { } public IqPacket discoResponse(final IqPacket request) { - final IqPacket packet = new IqPacket(IqPacket.TYPE_RESULT); + final IqPacket packet = new IqPacket(IqPacket.TYPE.RESULT); packet.setId(request.getId()); packet.setTo(request.getFrom()); final Element query = packet.addChild("query", @@ -40,7 +40,7 @@ public class IqGenerator extends AbstractGenerator { } protected IqPacket publish(final String node, final Element item) { - final IqPacket packet = new IqPacket(IqPacket.TYPE_SET); + final IqPacket packet = new IqPacket(IqPacket.TYPE.SET); final Element pubsub = packet.addChild("pubsub", "http://jabber.org/protocol/pubsub"); final Element publish = pubsub.addChild("publish"); @@ -50,7 +50,7 @@ public class IqGenerator extends AbstractGenerator { } protected IqPacket retrieve(String node, Element item) { - final IqPacket packet = new IqPacket(IqPacket.TYPE_GET); + final IqPacket packet = new IqPacket(IqPacket.TYPE.GET); final Element pubsub = packet.addChild("pubsub", "http://jabber.org/protocol/pubsub"); final Element items = pubsub.addChild("items"); @@ -100,7 +100,7 @@ public class IqGenerator extends AbstractGenerator { } public IqPacket queryMessageArchiveManagement(final MessageArchiveService.Query mam) { - final IqPacket packet = new IqPacket(IqPacket.TYPE_SET); + final IqPacket packet = new IqPacket(IqPacket.TYPE.SET); final Element query = packet.query("urn:xmpp:mam:0"); query.setAttribute("queryid",mam.getQueryId()); final Data data = new Data(); @@ -119,28 +119,28 @@ public class IqGenerator extends AbstractGenerator { return packet; } public IqPacket generateGetBlockList() { - final IqPacket iq = new IqPacket(IqPacket.TYPE_GET); + 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 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 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; } public IqPacket generateSetPassword(final Account account, final String newPassword) { - final IqPacket packet = new IqPacket(IqPacket.TYPE_SET); + final IqPacket packet = new IqPacket(IqPacket.TYPE.SET); packet.setTo(account.getServer()); final Element query = packet.addChild("query", Xmlns.REGISTER); final Jid jid = account.getJid(); diff --git a/src/main/java/eu/siacs/conversations/http/HttpConnection.java b/src/main/java/eu/siacs/conversations/http/HttpConnection.java index 5348e395..b715c3f3 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpConnection.java +++ b/src/main/java/eu/siacs/conversations/http/HttpConnection.java @@ -65,7 +65,7 @@ public class HttpConnection implements Downloadable { this.message.setDownloadable(this); try { mUrl = new URL(message.getBody()); - String path = mUrl.getPath(); + String path = mUrl.getPath().toLowerCase(); if (path != null && (path.endsWith(".pgp") || path.endsWith(".gpg"))) { this.message.setEncryption(Message.ENCRYPTION_PGP); } else if (message.getEncryption() != Message.ENCRYPTION_OTR) { diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java index e84545fc..6430c296 100644 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java @@ -71,24 +71,17 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { return super.avatarData(items); } - public static boolean fromServer(final Account account, final IqPacket packet) { - return packet.getFrom() == null - || packet.getFrom().equals(account.getServer()) - || packet.getFrom().equals(account.getJid().toBareJid()) - || packet.getFrom().equals(account.getJid()); - } - @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - if (packet.hasChild("query", Xmlns.ROSTER) && fromServer(account, packet)) { + if (packet.hasChild("query", Xmlns.ROSTER) && packet.fromServer(account)) { final Element query = packet.findChild("query"); // If this is in response to a query for the whole roster: - if (packet.getType() == IqPacket.TYPE_RESULT) { + if (packet.getType() == IqPacket.TYPE.RESULT) { account.getRoster().markAllAsNotInRoster(); } this.rosterItems(account, query); } else if ((packet.hasChild("block", Xmlns.BLOCKING) || packet.hasChild("blocklist", Xmlns.BLOCKING)) && - fromServer(account, packet)) { + packet.fromServer(account)) { // Block list or block push. Log.d(Config.LOGTAG, "Received blocklist update from server"); final Element blocklist = packet.findChild("blocklist", Xmlns.BLOCKING); @@ -97,8 +90,9 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { (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) { + if (packet.getType() == IqPacket.TYPE.RESULT) { account.clearBlocklist(); + account.getXmppConnection().getFeatures().setBlockListRequested(true); } if (items != null) { final Collection<Jid> jids = new ArrayList<>(items.size()); @@ -116,7 +110,7 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { // Update the UI mXmppConnectionService.updateBlocklistUi(OnUpdateBlocklist.Status.BLOCKED); } else if (packet.hasChild("unblock", Xmlns.BLOCKING) && - fromServer(account, packet) && packet.getType() == IqPacket.TYPE_SET) { + packet.fromServer(account) && packet.getType() == IqPacket.TYPE.SET) { Log.d(Config.LOGTAG, "Received unblock update from server"); final Collection<Element> items = packet.findChild("unblock", Xmlns.BLOCKING).getChildren(); if (items.size() == 0) { @@ -144,12 +138,12 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { .discoResponse(packet); account.getXmppConnection().sendIqPacket(response, null); } else if (packet.hasChild("ping", "urn:xmpp:ping")) { - final IqPacket response = packet.generateResponse(IqPacket.TYPE_RESULT); + final IqPacket response = packet.generateResponse(IqPacket.TYPE.RESULT); mXmppConnectionService.sendIqPacket(account, response, null); } else { - if ((packet.getType() == IqPacket.TYPE_GET) - || (packet.getType() == IqPacket.TYPE_SET)) { - final IqPacket response = packet.generateResponse(IqPacket.TYPE_ERROR); + if ((packet.getType() == IqPacket.TYPE.GET) + || (packet.getType() == IqPacket.TYPE.SET)) { + final IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR); final Element error = response.addChild("error"); error.setAttribute("type", "cancel"); error.addChild("feature-not-implemented", diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 44cda261..65a8f9e6 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -245,6 +245,10 @@ public class MessageParser extends AbstractParser implements return null; } } + if (message.hasChild("x","http://jabber.org/protocol/muc#user") + && "chat".equals(message.getAttribute("type"))) { + return null; + } Conversation conversation = mXmppConnectionService .findOrCreateConversation(account, fullJid.toBareJid(), false); String pgpBody = getPgpBody(message); @@ -482,7 +486,6 @@ public class MessageParser extends AbstractParser implements public void onMessagePacketReceived(Account account, MessagePacket packet) { Message message = null; this.parseNick(packet, account); - if ((packet.getType() == MessagePacket.TYPE_CHAT || packet.getType() == MessagePacket.TYPE_NORMAL)) { if ((packet.getBody() != null) && (packet.getBody().startsWith("?OTR"))) { @@ -490,9 +493,7 @@ public class MessageParser extends AbstractParser implements if (message != null) { message.markUnread(); } - } else if (packet.hasChild("body") - && !(packet.hasChild("x", - "http://jabber.org/protocol/muc#user"))) { + } else if (packet.hasChild("body")) { message = this.parseChat(packet, account); if (message != null) { message.markUnread(); diff --git a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java index 82111243..5fb50f90 100644 --- a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java +++ b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java @@ -111,7 +111,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { this.mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType() == IqPacket.TYPE_ERROR) { + if (packet.getType() == IqPacket.TYPE.ERROR) { Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": error executing mam: " + packet.toString()); finalizeQuery(query); } diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index a30cf2f1..594b356f 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -21,11 +21,15 @@ import android.util.Log; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.Calendar; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.json.JSONArray; +import org.json.JSONObject; + import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; @@ -65,6 +69,24 @@ public class NotificationService { ); } + public void notifyPebble(Message message) { + final Intent i = new Intent("com.getpebble.action.SEND_NOTIFICATION"); + + final HashMap data = new HashMap(); + final Conversation conversation = message.getConversation(); + data.put("title", conversation.getName()); + data.put("body", message.getBody()); + final JSONObject jsonData = new JSONObject(data); + final String notificationData = new JSONArray().put(jsonData).toString(); + + i.putExtra("messageType", "PEBBLE_ALERT"); + i.putExtra("sender", "Conversations"); /* XXX: Shouldn't be hardcoded, e.g., AbstractGenerator.APP_NAME); */ + i.putExtra("notificationData", notificationData); + + mXmppConnectionService.sendBroadcast(i); + } + + public boolean notificationsEnabled() { return mXmppConnectionService.getPreferences().getBoolean("show_notification", true); } @@ -110,9 +132,13 @@ public class NotificationService { notifications.put(conversationUuid, mList); } final Account account = message.getConversation().getAccount(); - updateNotification((!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn) + final boolean doNotify = (!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn) && !account.inGracePeriod() - && !this.inMiniGracePeriod(account)); + && !this.inMiniGracePeriod(account); + updateNotification(doNotify); + if (doNotify) { + notifyPebble(message); + } } } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 6bdc55a1..cf3f72dc 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -84,7 +84,6 @@ 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; @@ -189,12 +188,12 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } syncDirtyContacts(account); - scheduleWakeupCall(Config.PING_MAX_INTERVAL, true); + scheduleWakeUpCall(Config.PING_MAX_INTERVAL,account.getUuid().hashCode()); } else if (account.getStatus() == Account.State.OFFLINE) { resetSendingToWaiting(account); if (!account.isOptionSet(Account.OPTION_DISABLED)) { int timeToReconnect = mRandom.nextInt(50) + 10; - scheduleWakeupCall(timeToReconnect, false); + scheduleWakeUpCall(timeToReconnect,account.getUuid().hashCode()); } } else if (account.getStatus() == Account.State.REGISTRATION_SUCCESSFUL) { databaseBackend.updateAccount(account); @@ -207,7 +206,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa + ": error connecting account. try again in " + next + "s for the " + (connection.getAttempt() + 1) + " time"); - scheduleWakeupCall((int) (next * 1.2), false); + scheduleWakeUpCall(next,account.getUuid().hashCode()); } } getNotificationService().updateErrorNotification(); @@ -242,8 +241,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa private OpenPgpServiceConnection pgpServiceConnection; private PgpEngine mPgpEngine = null; - private Intent pingIntent; - private PendingIntent pendingPingIntent = null; private WakeLock wakeLock; private PowerManager pm; private final OnBindListener mOnBindListener = new OnBindListener() { @@ -389,16 +386,17 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public int onStartCommand(Intent intent, int flags, int startId) { - if (intent != null && intent.getAction() != null) { - if (intent.getAction().equals(ACTION_MERGE_PHONE_CONTACTS)) { + final String action = intent == null ? null : intent.getAction(); + if (action != null) { + if (action.equals(ACTION_MERGE_PHONE_CONTACTS)) { PhoneHelper.loadPhoneContacts(getApplicationContext(), new ArrayList<Bundle>(), this); return START_STICKY; - } else if (intent.getAction().equals(Intent.ACTION_SHUTDOWN)) { + } else if (action.equals(Intent.ACTION_SHUTDOWN)) { logoutAndSave(); return START_NOT_STICKY; - } else if (intent.getAction().equals(ACTION_CLEAR_NOTIFICATION)) { + } else if (action.equals(ACTION_CLEAR_NOTIFICATION)) { mNotificationService.clear(); - } else if (intent.getAction().equals(ACTION_DISABLE_FOREGROUND)) { + } else if (action.equals(ACTION_DISABLE_FOREGROUND)) { getPreferences().edit().putBoolean("keep_foreground_service",false).commit(); toggleForegroundService(); } @@ -420,37 +418,36 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } if (account.getStatus() == Account.State.ONLINE) { - long lastReceived = account.getXmppConnection() - .getLastPacketReceived(); - long lastSent = account.getXmppConnection() - .getLastPingSent(); - if (lastSent - lastReceived >= Config.PING_TIMEOUT * 1000) { - Log.d(Config.LOGTAG, account.getJid() - + ": ping timeout"); + long lastReceived = account.getXmppConnection().getLastPacketReceived(); + long lastSent = account.getXmppConnection().getLastPingSent(); + long pingInterval = "ui".equals(action) ? Config.PING_MIN_INTERVAL * 1000 : Config.PING_MAX_INTERVAL * 1000; + long msToNextPing = (Math.max(lastReceived,lastSent) + pingInterval) - SystemClock.elapsedRealtime(); + if (lastSent > lastReceived && (lastSent + Config.PING_TIMEOUT * 1000) < SystemClock.elapsedRealtime()) { + Log.d(Config.LOGTAG, account.getJid().toBareJid()+ ": ping timeout"); this.reconnectAccount(account, true); - } else if (SystemClock.elapsedRealtime() - lastReceived >= Config.PING_MIN_INTERVAL * 1000) { + } else if (msToNextPing <= 0) { account.getXmppConnection().sendPing(); - this.scheduleWakeupCall(2, false); + Log.d(Config.LOGTAG, account.getJid().toBareJid()+" send ping"); + this.scheduleWakeUpCall(Config.PING_TIMEOUT,account.getUuid().hashCode()); + } else { + this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode()); } } else if (account.getStatus() == Account.State.OFFLINE) { if (account.getXmppConnection() == null) { - account.setXmppConnection(this - .createConnection(account)); + account.setXmppConnection(this.createConnection(account)); } new Thread(account.getXmppConnection()).start(); } else if ((account.getStatus() == Account.State.CONNECTING) && ((SystemClock.elapsedRealtime() - account .getXmppConnection().getLastConnect()) / 1000 >= Config.CONNECT_TIMEOUT)) { - Log.d(Config.LOGTAG, account.getJid() - + ": time out during connect reconnecting"); + Log.d(Config.LOGTAG, account.getJid()+ ": time out during connect reconnecting"); reconnectAccount(account, true); } else { if (account.getXmppConnection().getTimeToNextAttempt() <= 0) { reconnectAccount(account, true); } } - // in any case. reschedule wakup call - this.scheduleWakeupCall(Config.PING_MAX_INTERVAL, true); + } if (mOnAccountUpdate != null) { mOnAccountUpdate.onAccountUpdate(); @@ -547,42 +544,16 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa stopSelf(); } - protected void scheduleWakeupCall(int seconds, boolean ping) { - long timeToWake = SystemClock.elapsedRealtime() + seconds * 1000; - Context context = getApplicationContext(); - AlarmManager alarmManager = (AlarmManager) context - .getSystemService(Context.ALARM_SERVICE); + protected void scheduleWakeUpCall(int seconds, int requestCode) { + final long timeToWake = SystemClock.elapsedRealtime() + seconds * 1000; - if (ping) { - if (this.pingIntent == null) { - this.pingIntent = new Intent(context, EventReceiver.class); - this.pingIntent.setAction("ping"); - this.pingIntent.putExtra("time", timeToWake); - this.pendingPingIntent = PendingIntent.getBroadcast(context, 0, - this.pingIntent, 0); - alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - timeToWake, pendingPingIntent); - } else { - long scheduledTime = this.pingIntent.getLongExtra("time", 0); - if (scheduledTime < SystemClock.elapsedRealtime() - || (scheduledTime > timeToWake)) { - this.pingIntent.putExtra("time", timeToWake); - alarmManager.cancel(this.pendingPingIntent); - this.pendingPingIntent = PendingIntent.getBroadcast( - context, 0, this.pingIntent, 0); - alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - timeToWake, pendingPingIntent); - } - } - } else { - Intent intent = new Intent(context, EventReceiver.class); - intent.setAction("ping_check"); - PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, - intent, 0); - alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeToWake, - alarmIntent); - } + Context context = getApplicationContext(); + AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + Intent intent = new Intent(context, EventReceiver.class); + intent.setAction("ping"); + PendingIntent alarmIntent = PendingIntent.getBroadcast(context, requestCode, intent, 0); + alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeToWake, alarmIntent); } public XmppConnection createConnection(final Account account) { @@ -787,7 +758,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void fetchRosterFromServer(final Account account) { - final IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET); + final IqPacket iqPacket = new IqPacket(IqPacket.TYPE.GET); if (!"".equals(account.getRosterVersion())) { Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": fetching roster version " + account.getRosterVersion()); @@ -800,10 +771,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void fetchBookmarks(final Account account) { - final IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET); + final IqPacket iqPacket = new IqPacket(IqPacket.TYPE.GET); final Element query = iqPacket.query("jabber:iq:private"); query.addChild("storage", "storage:bookmarks"); - final PacketReceived callback = new OnIqPacketReceived() { + final OnIqPacketReceived callback = new OnIqPacketReceived() { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { @@ -835,7 +806,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void pushBookmarks(Account account) { - IqPacket iqPacket = new IqPacket(IqPacket.TYPE_SET); + IqPacket iqPacket = new IqPacket(IqPacket.TYPE.SET); Element query = iqPacket.query("jabber:iq:private"); Element storage = query.addChild("storage", "storage:bookmarks"); for (Bookmark bookmark : account.getBookmarks()) { @@ -979,7 +950,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa query.setCallback(callback); } callback.informUser(R.string.fetching_history_from_server); - } + } } }).start(); } @@ -1053,11 +1024,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } this.databaseBackend.createConversation(conversation); } - if (query == null) { - this.mMessageArchiveService.query(conversation); - } else { - if (query.getConversation() == null) { - this.mMessageArchiveService.query(conversation,query.getStart()); + if (account.getXmppConnection() != null && account.getXmppConnection().getFeatures().mam()) { + if (query == null) { + this.mMessageArchiveService.query(conversation); + } else { + if (query.getConversation() == null) { + this.mMessageArchiveService.query(conversation, query.getStart()); + } } } this.conversations.add(conversation); @@ -1107,7 +1080,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa sendIqPacket(account, iq, new OnIqPacketReceived() { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - if (packet.getType() == IqPacket.TYPE_RESULT) { + if (packet.getType() == IqPacket.TYPE.RESULT) { account.setPassword(newPassword); databaseBackend.updateAccount(account); callback.onPasswordChangeSucceeded(); @@ -1500,13 +1473,13 @@ 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); + IqPacket request = new IqPacket(IqPacket.TYPE.GET); request.setTo(conversation.getJid().toBareJid()); request.query("http://jabber.org/protocol/muc#owner"); sendIqPacket(conversation.getAccount(),request,new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType() != IqPacket.TYPE_ERROR) { + if (packet.getType() != IqPacket.TYPE.ERROR) { Data data = Data.parse(packet.query().findChild("x", "jabber:x:data")); for (Field field : data.getFields()) { if (options.containsKey(field.getName())) { @@ -1514,13 +1487,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } data.submit(); - IqPacket set = new IqPacket(IqPacket.TYPE_SET); + IqPacket set = new IqPacket(IqPacket.TYPE.SET); set.setTo(conversation.getJid().toBareJid()); set.query("http://jabber.org/protocol/muc#owner").addChild(data); sendIqPacket(account, set, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType() == IqPacket.TYPE_RESULT) { + if (packet.getType() == IqPacket.TYPE.RESULT) { if (callback != null) { callback.onPushSucceeded(); } @@ -1662,7 +1635,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa final boolean sendUpdates = contact .getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST) && contact.getOption(Contact.Options.PREEMPTIVE_GRANT); - final IqPacket iq = new IqPacket(IqPacket.TYPE_SET); + final IqPacket iq = new IqPacket(IqPacket.TYPE.SET); iq.query(Xmlns.ROSTER).addChild(contact.asElement()); account.getXmppConnection().sendIqPacket(iq, null); if (sendUpdates) { @@ -1702,7 +1675,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public void onIqPacketReceived(Account account, IqPacket result) { - if (result.getType() == IqPacket.TYPE_RESULT) { + if (result.getType() == IqPacket.TYPE.RESULT) { final IqPacket packet = XmppConnectionService.this.mIqGenerator .publishAvatarMetadata(avatar); sendIqPacket(account, packet, new OnIqPacketReceived() { @@ -1710,7 +1683,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public void onIqPacketReceived(Account account, IqPacket result) { - if (result.getType() == IqPacket.TYPE_RESULT) { + if (result.getType() == IqPacket.TYPE.RESULT) { if (account.setAvatar(avatar.getFilename())) { databaseBackend.updateAccount(account); } @@ -1747,7 +1720,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void onIqPacketReceived(Account account, IqPacket result) { final String ERROR = account.getJid().toBareJid() + ": fetching avatar for " + avatar.owner + " failed "; - if (result.getType() == IqPacket.TYPE_RESULT) { + if (result.getType() == IqPacket.TYPE.RESULT) { avatar.image = mIqParser.avatarData(result); if (avatar.image != null) { if (getFileBackend().save(avatar)) { @@ -1801,7 +1774,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType() == IqPacket.TYPE_RESULT) { + if (packet.getType() == IqPacket.TYPE.RESULT) { Element pubsub = packet.findChild("pubsub", "http://jabber.org/protocol/pubsub"); if (pubsub != null) { @@ -1835,7 +1808,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa contact.setOption(Contact.Options.DIRTY_DELETE); Account account = contact.getAccount(); if (account.getStatus() == Account.State.ONLINE) { - IqPacket iq = new IqPacket(IqPacket.TYPE_SET); + IqPacket iq = new IqPacket(IqPacket.TYPE.SET); Element item = iq.query(Xmlns.ROSTER).addChild("item"); item.setAttribute("jid", contact.getJid().toString()); item.setAttribute("subscription", "remove"); @@ -1861,8 +1834,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } Thread thread = new Thread(account.getXmppConnection()); thread.start(); - scheduleWakeupCall((int) (Config.CONNECT_TIMEOUT * 1.2), - false); + scheduleWakeUpCall(Config.CONNECT_TIMEOUT,account.getUuid().hashCode()); } else { account.getRoster().clearPresences(); account.setXmppConnection(null); @@ -2090,7 +2062,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } - public void sendIqPacket(final Account account, final IqPacket packet, final PacketReceived callback) { + public void sendIqPacket(final Account account, final IqPacket packet, final OnIqPacketReceived callback) { final XmppConnection connection = account.getXmppConnection(); if (connection != null) { connection.sendIqPacket(packet, callback); @@ -2202,7 +2174,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - if (packet.getType() == IqPacket.TYPE_RESULT) { + if (packet.getType() == IqPacket.TYPE.RESULT) { account.getBlocklist().add(jid); updateBlocklistUi(OnUpdateBlocklist.Status.BLOCKED); } @@ -2217,7 +2189,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa 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) { + if (packet.getType() == IqPacket.TYPE.RESULT) { account.getBlocklist().remove(jid); updateBlocklistUi(OnUpdateBlocklist.Status.UNBLOCKED); } diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index eeb015f3..5a30d761 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -31,6 +31,7 @@ import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Bookmark; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.MucOptions.User; import eu.siacs.conversations.services.XmppConnectionService.OnMucRosterUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate; @@ -59,6 +60,8 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers private List<User> users = new ArrayList<>(); private User mSelectedUser = null; + private boolean mAdvancedMode = false; + private UiCallback<Conversation> renameCallback = new UiCallback<Conversation>() { @Override public void success(Conversation object) { @@ -66,7 +69,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers @Override public void run() { Toast.makeText(ConferenceDetailsActivity.this,getString(R.string.your_nick_has_been_changed),Toast.LENGTH_SHORT).show(); - populateView(); + updateView(); } }); @@ -94,7 +97,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers @Override public void run() { - populateView(); + updateView(); } }); } @@ -105,7 +108,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers @Override public void run() { - populateView(); + updateView(); } }); } @@ -171,23 +174,16 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers case R.id.action_delete_bookmark: deleteBookmark(); break; + case R.id.action_advanced_mode: + this.mAdvancedMode = !menuItem.isChecked(); + menuItem.setChecked(this.mAdvancedMode); + invalidateOptionsMenu(); + updateView(); + break; } return super.onOptionsItemSelected(menuItem); } - public String getReadableRole(int role) { - switch (role) { - case User.ROLE_MODERATOR: - return getString(R.string.moderator); - case User.ROLE_PARTICIPANT: - return getString(R.string.participant); - case User.ROLE_VISITOR: - return getString(R.string.visitor); - default: - return ""; - } - } - @Override protected String getShareableUri() { if (mConversation != null) { @@ -201,6 +197,8 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers public boolean onPrepareOptionsMenu(Menu menu) { MenuItem menuItemSaveBookmark = menu.findItem(R.id.action_save_as_bookmark); MenuItem menuItemDeleteBookmark = menu.findItem(R.id.action_delete_bookmark); + MenuItem menuItemAdvancedMode = menu.findItem(R.id.action_advanced_mode); + menuItemAdvancedMode.setChecked(mAdvancedMode); Account account = mConversation.getAccount(); if (account.hasBookmarkFor(mConversation.getJid().toBareJid())) { menuItemSaveBookmark.setVisible(false); @@ -290,16 +288,15 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers this.mConversation = xmppConnectionService .findConversationByUuid(uuid); if (this.mConversation != null) { - populateView(); + updateView(); } } } - private void populateView() { + private void updateView() { mAccountJid.setText(getString(R.string.using_account, mConversation .getAccount().getJid().toBareJid())); - mYourPhoto.setImageBitmap(avatarService().get( - mConversation.getAccount(), getPixel(48))); + mYourPhoto.setImageBitmap(avatarService().get(mConversation.getAccount(), getPixel(48))); setTitle(mConversation.getName()); mFullJid.setText(mConversation.getJid().toBareJid().toString()); mYourNick.setText(mConversation.getMucOptions().getActualNick()); @@ -307,18 +304,12 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers if (mConversation.getMucOptions().online()) { mMoreDetails.setVisibility(View.VISIBLE); User self = mConversation.getMucOptions().getSelf(); - switch (self.getAffiliation()) { - case User.AFFILIATION_ADMIN: - mRoleAffiliaton.setText(getReadableRole(self.getRole()) + " (" - + getString(R.string.admin) + ")"); - break; - case User.AFFILIATION_OWNER: - mRoleAffiliaton.setText(getReadableRole(self.getRole()) + " (" - + getString(R.string.owner) + ")"); - break; - default: - mRoleAffiliaton.setText(getReadableRole(self.getRole())); - break; + final String status = getStatus(self); + if (status != null) { + mRoleAffiliaton.setVisibility(View.VISIBLE); + mRoleAffiliaton.setText(status); + } else { + mRoleAffiliaton.setVisibility(View.GONE); } } this.users.clear(); @@ -337,32 +328,31 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers }); registerForContextMenu(view); view.setTag(user); - TextView name = (TextView) view - .findViewById(R.id.contact_display_name); - TextView key = (TextView) view.findViewById(R.id.key); - TextView role = (TextView) view.findViewById(R.id.contact_jid); - if (user.getPgpKeyId() != 0) { - key.setVisibility(View.VISIBLE); - key.setOnClickListener(new OnClickListener() { + TextView tvDisplayName = (TextView) view.findViewById(R.id.contact_display_name); + TextView tvKey = (TextView) view.findViewById(R.id.key); + TextView tvStatus = (TextView) view.findViewById(R.id.contact_jid); + if (mAdvancedMode && user.getPgpKeyId() != 0) { + tvKey.setVisibility(View.VISIBLE); + tvKey.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { viewPgpKey(user); } }); - key.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId())); + tvKey.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId())); } Bitmap bm; Contact contact = user.getContact(); if (contact != null) { bm = avatarService().get(contact, getPixel(48)); - name.setText(contact.getDisplayName()); - role.setText(user.getName() + " \u2022 " - + getReadableRole(user.getRole())); + tvDisplayName.setText(contact.getDisplayName()); + tvStatus.setText(user.getName() + " \u2022 " + getStatus(user)); } else { bm = avatarService().get(user.getName(), getPixel(48)); - name.setText(user.getName()); - role.setText(getReadableRole(user.getRole())); + tvDisplayName.setText(user.getName()); + tvStatus.setText(getStatus(user)); + } ImageView iv = (ImageView) view.findViewById(R.id.contact_photo); iv.setImageBitmap(bm); @@ -370,6 +360,19 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } } + private String getStatus(User user) { + if (mAdvancedMode) { + StringBuilder builder = new StringBuilder(); + builder.append(getString(user.getAffiliation().getResId())); + builder.append(" ("); + builder.append(getString(user.getRole().getResId())); + builder.append(')'); + return builder.toString(); + } else { + return getString(user.getAffiliation().getResId()); + } + } + @SuppressWarnings("deprecation") @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void setListItemBackgroundOnView(View view) { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 5cfc1116..e71f4cbb 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -1050,10 +1050,10 @@ public class ConversationActivity extends XmppActivity @Override public void OnUpdateBlocklist(Status status) { - invalidateOptionsMenu(); runOnUiThread(new Runnable() { @Override public void run() { + invalidateOptionsMenu(); ConversationActivity.this.mConversationFragment.updateMessages(); } }); diff --git a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java index 5e770376..a3904d21 100644 --- a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java @@ -134,11 +134,12 @@ public class ShareWithActivity extends XmppActivity { @Override public void onStart() { final String type = getIntent().getType(); - if (type != null && !type.startsWith("text/")) { - this.share.uri = (Uri) getIntent().getParcelableExtra(Intent.EXTRA_STREAM); + final Uri uri = getIntent().getParcelableExtra(Intent.EXTRA_STREAM); + if (type != null && uri != null && !type.startsWith("text/")) { + this.share.uri = uri; try { - this.share.image = type.startsWith("image/") - || URLConnection.guessContentTypeFromName(this.share.uri.toString()).startsWith("image/"); + String guess = URLConnection.guessContentTypeFromName(uri.toString()); + this.share.image = type.startsWith("image/") || (guess != null && guess.startsWith("image/")); } catch (final StringIndexOutOfBoundsException ignored) { this.share.image = false; } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 478586b9..5b5664c6 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -10,6 +10,7 @@ import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.text.style.StyleSpan; import android.util.DisplayMetrics; +import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; @@ -23,6 +24,7 @@ import android.widget.Toast; 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.Contact; @@ -103,9 +105,9 @@ public class MessageAdapter extends ArrayAdapter<Message> { if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE || message.getDownloadable() != null) { ImageParams params = message.getImageParams(); if (params.size > (1.5 * 1024 * 1024)) { - filesize = params.size / (1024 * 1024)+ " MB"; + filesize = params.size / (1024 * 1024)+ " MiB"; } else if (params.size > 0) { - filesize = params.size / 1024 + " KB"; + filesize = params.size / 1024 + " KiB"; } if (message.getDownloadable() != null && message.getDownloadable().getStatus() == Downloadable.STATUS_FAILED) { error = true; @@ -430,6 +432,11 @@ public class MessageAdapter extends ArrayAdapter<Message> { } return view; } else if (type == NULL) { + if (viewHolder.message_box != null) { + Log.e(Config.LOGTAG, "detected type=NULL but with wrong cached view"); + view = activity.getLayoutInflater().inflate(R.layout.message_null, parent, false); + view.setTag(new ViewHolder()); + } if (position == getCount() - 1) { view.getLayoutParams().height = 1; } else { @@ -438,6 +445,9 @@ public class MessageAdapter extends ArrayAdapter<Message> { } view.setLayoutParams(view.getLayoutParams()); return view; + } else if (message.wasMergedIntoPrevious()) { + Log.e(Config.LOGTAG,"detected wasMergedIntoPrevious with wrong type"); + return view; } else if (viewHolder.messageBody == null || viewHolder.image == null) { return view; //avoiding weird platform bugs } else if (type == RECEIVED) { diff --git a/src/main/java/eu/siacs/conversations/utils/XmppUri.java b/src/main/java/eu/siacs/conversations/utils/XmppUri.java index aacb6362..0f1b18c3 100644 --- a/src/main/java/eu/siacs/conversations/utils/XmppUri.java +++ b/src/main/java/eu/siacs/conversations/utils/XmppUri.java @@ -18,7 +18,11 @@ public class XmppUri { try { parse(Uri.parse(uri)); } catch (IllegalArgumentException e) { - jid = null; + try { + jid = Jid.fromString(uri).toBareJid().toString(); + } catch (InvalidJidException e2) { + jid = null; + } } } @@ -42,6 +46,13 @@ public class XmppUri { try { jid = URLDecoder.decode(uri.getEncodedPath(), "UTF-8").split("/")[1]; } catch (final UnsupportedEncodingException ignored) { + jid = null; + } + } else { + try { + jid = Jid.fromString(uri.toString()).toBareJid().toString(); + } catch (final InvalidJidException ignored) { + jid = null; } } } @@ -62,7 +73,7 @@ public class XmppUri { public Jid getJid() { try { - return Jid.fromString(this.jid); + return this.jid == null ? null :Jid.fromString(this.jid); } catch (InvalidJidException e) { return null; } @@ -71,8 +82,4 @@ public class XmppUri { public String getFingerprint() { return this.fingerprint; } - - public boolean isMuc() { - return this.muc; - } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index f7f0c346..30437575 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -9,6 +9,7 @@ import android.os.PowerManager.WakeLock; import android.os.SystemClock; import android.preference.PreferenceManager; import android.util.Log; +import android.util.Pair; import android.util.SparseArray; import org.apache.http.conn.ssl.StrictHostnameVerifier; @@ -94,17 +95,14 @@ public class XmppConnection implements Runnable { private int smVersion = 3; private final SparseArray<String> messageReceipts = new SparseArray<>(); - private boolean enabledEncryption = false; - private boolean enabledCarbons = false; - private int stanzasReceived = 0; private int stanzasSent = 0; - private long lastPaketReceived = 0; + private long lastPacketReceived = 0; private long lastPingSent = 0; private long lastConnect = 0; private long lastSessionStarted = 0; private int attempt = 0; - private final Map<String, PacketReceived> packetCallbacks = new Hashtable<>(); + private final Map<String, Pair<IqPacket, OnIqPacketReceived>> packetCallbacks = new Hashtable<>(); private OnPresencePacketReceived presenceListener = null; private OnJinglePacketReceived jingleListener = null; private OnIqPacketReceived unregisteredIqListener = null; @@ -146,13 +144,12 @@ public class XmppConnection implements Runnable { protected void connect() { Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": connecting"); - enabledEncryption = false; + features.encryptionEnabled = false; lastConnect = SystemClock.elapsedRealtime(); lastPingSent = SystemClock.elapsedRealtime(); this.attempt++; try { - shouldAuthenticate = shouldBind = !account - .isOptionSet(Account.OPTION_REGISTER); + shouldAuthenticate = shouldBind = !account.isOptionSet(Account.OPTION_REGISTER); tagReader = new XmlReader(wakeLock); tagWriter = new TagWriter(); packetCallbacks.clear(); @@ -303,7 +300,7 @@ public class XmppConnection implements Runnable { final RequestPacket r = new RequestPacket(smVersion); tagWriter.writeStanzaAsync(r); } else if (nextTag.isStart("resumed")) { - lastPaketReceived = SystemClock.elapsedRealtime(); + lastPacketReceived = SystemClock.elapsedRealtime(); final Element resumed = tagReader.readElement(nextTag); final String h = resumed.getAttribute("h"); try { @@ -336,7 +333,7 @@ public class XmppConnection implements Runnable { tagWriter.writeStanzaAsync(ack); } else if (nextTag.isStart("a")) { final Element ack = tagReader.readElement(nextTag); - lastPaketReceived = SystemClock.elapsedRealtime(); + lastPacketReceived = SystemClock.elapsedRealtime(); final int serverSequence = Integer.parseInt(ack.getAttribute("h")); final String msgId = this.messageReceipts.get(serverSequence); if (msgId != null) { @@ -372,7 +369,7 @@ public class XmppConnection implements Runnable { private void sendInitialPing() { Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": sending intial ping"); - final 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() { @@ -425,69 +422,54 @@ public class XmppConnection implements Runnable { } } ++stanzasReceived; - lastPaketReceived = SystemClock.elapsedRealtime(); + lastPacketReceived = SystemClock.elapsedRealtime(); return element; } - private void processIq(final Tag currentTag) throws XmlPullParserException, - IOException { - final IqPacket packet = (IqPacket) processPacket(currentTag, PACKET_IQ); - - if (packet.getId() == null) { - return; // an iq packet without id is definitely invalid - } + private void processIq(final Tag currentTag) throws XmlPullParserException, IOException { + final IqPacket packet = (IqPacket) processPacket(currentTag, PACKET_IQ); - if (packet instanceof JinglePacket) { - if (this.jingleListener != null) { - this.jingleListener.onJinglePacketReceived(account, - (JinglePacket) packet); - } - } else { - if (packetCallbacks.containsKey(packet.getId())) { - if (packetCallbacks.get(packet.getId()) instanceof OnIqPacketReceived) { - ((OnIqPacketReceived) packetCallbacks.get(packet.getId())) - .onIqPacketReceived(account, packet); - } + if (packet.getId() == null) { + return; // an iq packet without id is definitely invalid + } - packetCallbacks.remove(packet.getId()); - } else if ((packet.getType() == IqPacket.TYPE_GET || packet - .getType() == IqPacket.TYPE_SET) - && this.unregisteredIqListener != null) { - this.unregisteredIqListener.onIqPacketReceived(account, packet); - } - } + if (packet instanceof JinglePacket) { + if (this.jingleListener != null) { + this.jingleListener.onJinglePacketReceived(account,(JinglePacket) packet); + } + } else { + if (packetCallbacks.containsKey(packet.getId())) { + final Pair<IqPacket, OnIqPacketReceived> packetCallbackDuple = packetCallbacks.get(packet.getId()); + // Packets to the server should have responses from the server + if (packetCallbackDuple.first.toServer(account)) { + if (packet.fromServer(account)) { + packetCallbackDuple.second.onIqPacketReceived(account, packet); + packetCallbacks.remove(packet.getId()); + } else { + Log.e(Config.LOGTAG,account.getJid().toBareJid().toString()+": ignoring spoofed iq packet"); + } + } else { + if (packet.getFrom().equals(packetCallbackDuple.first.getTo())) { + packetCallbackDuple.second.onIqPacketReceived(account, packet); + packetCallbacks.remove(packet.getId()); + } else { + Log.e(Config.LOGTAG,account.getJid().toBareJid().toString()+": ignoring spoofed iq packet"); + } + } + } else if (packet.getType() == IqPacket.TYPE.GET|| packet.getType() == IqPacket.TYPE.SET) { + this.unregisteredIqListener.onIqPacketReceived(account, packet); + } + } } - private void processMessage(final Tag currentTag) throws XmlPullParserException, - IOException { - final MessagePacket packet = (MessagePacket) processPacket(currentTag, - PACKET_MESSAGE); - final String id = packet.getAttribute("id"); - if ((id != null) && (packetCallbacks.containsKey(id))) { - if (packetCallbacks.get(id) instanceof OnMessagePacketReceived) { - ((OnMessagePacketReceived) packetCallbacks.get(id)) - .onMessagePacketReceived(account, packet); - } - packetCallbacks.remove(id); - } else if (this.messageListener != null) { - this.messageListener.onMessagePacketReceived(account, packet); - } + private void processMessage(final Tag currentTag) throws XmlPullParserException, IOException { + final MessagePacket packet = (MessagePacket) processPacket(currentTag,PACKET_MESSAGE); + this.messageListener.onMessagePacketReceived(account, packet); } - private void processPresence(final Tag currentTag) throws XmlPullParserException, - IOException { - PresencePacket packet = (PresencePacket) processPacket(currentTag, - PACKET_PRESENCE); - final String id = packet.getAttribute("id"); - if ((id != null) && (packetCallbacks.containsKey(id))) { - if (packetCallbacks.get(id) instanceof OnPresencePacketReceived) { - ((OnPresencePacketReceived) packetCallbacks.get(id)) - .onPresencePacketReceived(account, packet); - } - packetCallbacks.remove(id); - } else if (this.presenceListener != null) { - this.presenceListener.onPresencePacketReceived(account, packet); - } + private void processPresence(final Tag currentTag) throws XmlPullParserException, IOException { + PresencePacket packet = (PresencePacket) processPacket(currentTag, PACKET_PRESENCE); + this.presenceListener.onPresencePacketReceived(account, packet); } private void sendStartTLS() throws IOException { @@ -497,8 +479,7 @@ public class XmppConnection implements Runnable { } private SharedPreferences getPreferences() { - return PreferenceManager - .getDefaultSharedPreferences(applicationContext); + return PreferenceManager.getDefaultSharedPreferences(applicationContext); } private boolean enableLegacySSL() { @@ -506,19 +487,19 @@ public class XmppConnection implements Runnable { } private void switchOverToTls(final Tag currentTag) throws XmlPullParserException, IOException { - tagReader.readTag(); - try { + tagReader.readTag(); + try { final SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null,new X509TrustManager[]{this.mXmppConnectionService.getMemorizingTrustManager()},mXmppConnectionService.getRNG()); final SSLSocketFactory factory = sc.getSocketFactory(); final HostnameVerifier verifier = this.mXmppConnectionService.getMemorizingTrustManager().wrapHostnameVerifier(new StrictHostnameVerifier()); - final InetAddress address = socket == null ? null : socket.getInetAddress(); + final InetAddress address = socket == null ? null : socket.getInetAddress(); if (factory == null || address == null || verifier == null) { throw new IOException("could not setup ssl"); } - final SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket,address.getHostAddress(), socket.getPort(),true); + final SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket,address.getHostAddress(), socket.getPort(),true); if (sslSocket == null) { throw new IOException("could not initialize ssl socket"); @@ -533,43 +514,43 @@ public class XmppConnection implements Runnable { supportedProtocols.remove("SSLv3"); supportProtocols = new String[supportedProtocols.size()]; supportedProtocols.toArray(supportProtocols); - } + } sslSocket.setEnabledProtocols(supportProtocols); - if (!verifier.verify(account.getServer().getDomainpart(),sslSocket.getSession())) { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": TLS certificate verification failed"); - disconnect(true); - changeStatus(Account.State.SECURITY_ERROR); + if (!verifier.verify(account.getServer().getDomainpart(),sslSocket.getSession())) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": TLS certificate verification failed"); + disconnect(true); + changeStatus(Account.State.SECURITY_ERROR); } tagReader.setInputStream(sslSocket.getInputStream()); tagWriter.setOutputStream(sslSocket.getOutputStream()); sendStartStream(); Log.d(Config.LOGTAG, account.getJid().toBareJid()+ ": TLS connection established"); - enabledEncryption = true; + features.encryptionEnabled = true; processStream(tagReader.readTag()); sslSocket.close(); - } catch (final NoSuchAlgorithmException | KeyManagementException e1) { + } catch (final NoSuchAlgorithmException | KeyManagementException e1) { Log.d(Config.LOGTAG,account.getJid().toBareJid()+": TLS certificate verification failed"); disconnect(true); changeStatus(Account.State.SECURITY_ERROR); - } + } } private void processStreamFeatures(final Tag currentTag) throws XmlPullParserException, IOException { this.streamFeatures = tagReader.readElement(currentTag); - if (this.streamFeatures.hasChild("starttls") && !enabledEncryption) { + if (this.streamFeatures.hasChild("starttls") && !features.encryptionEnabled) { sendStartTLS(); } else if (this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER) - && enabledEncryption) { + && features.encryptionEnabled) { sendRegistryRequest(); } else if (!this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER)) { changeStatus(Account.State.REGISTRATION_NOT_SUPPORTED); disconnect(true); } else if (this.streamFeatures.hasChild("mechanisms") - && shouldAuthenticate && enabledEncryption) { + && shouldAuthenticate && features.encryptionEnabled) { final List<String> mechanisms = extractMechanisms(streamFeatures .findChild("mechanisms")); final Element auth = new Element("auth"); @@ -625,7 +606,7 @@ public class XmppConnection implements Runnable { } private void sendRegistryRequest() { - final 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() { @@ -635,7 +616,7 @@ public class XmppConnection implements Runnable { final Element instructions = packet.query().findChild("instructions"); if (packet.query().hasChild("username") && (packet.query().hasChild("password"))) { - final IqPacket register = new IqPacket(IqPacket.TYPE_SET); + final IqPacket register = new IqPacket(IqPacket.TYPE.SET); final Element username = new Element("username") .setContent(account.getUsername()); final Element password = new Element("password") @@ -646,7 +627,7 @@ public class XmppConnection implements Runnable { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - if (packet.getType() == IqPacket.TYPE_RESULT) { + if (packet.getType() == IqPacket.TYPE.RESULT) { account.setOption(Account.OPTION_REGISTER, false); changeStatus(Account.State.REGISTRATION_SUCCESSFUL); @@ -673,10 +654,10 @@ public class XmppConnection implements Runnable { } private void sendBindRequest() { - final IqPacket iq = new IqPacket(IqPacket.TYPE_SET); + 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() { + this.sendUnmodifiedIqPacket(iq, new OnIqPacketReceived() { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { final Element bind = packet.findChild("bind"); @@ -694,15 +675,15 @@ public class XmppConnection implements Runnable { tagWriter.writeStanzaAsync(enable); stanzasSent = 0; messageReceipts.clear(); - } else if (streamFeatures.hasChild("sm", - "urn:xmpp:sm:2")) { + } else if (streamFeatures.hasChild("sm", "urn:xmpp:sm:2")) { smVersion = 2; final EnablePacket enable = new EnablePacket(smVersion); tagWriter.writeStanzaAsync(enable); stanzasSent = 0; messageReceipts.clear(); } - enabledCarbons = false; + features.carbonsEnabled = false; + features.blockListRequested = false; disco.clear(); sendServiceDiscoveryInfo(account.getServer()); sendServiceDiscoveryItems(account.getServer()); @@ -719,12 +700,10 @@ public class XmppConnection implements Runnable { } }); if (this.streamFeatures.hasChild("session")) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() - + ": sending deprecated session"); - final IqPacket startSession = new IqPacket(IqPacket.TYPE_SET); - startSession.addChild("session", - "urn:ietf:params:xml:ns:xmpp-session"); - this.sendUnboundIqPacket(startSession, null); + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": sending deprecated session"); + final IqPacket startSession = new IqPacket(IqPacket.TYPE.SET); + startSession.addChild("session","urn:ietf:params:xml:ns:xmpp-session"); + this.sendUnmodifiedIqPacket(startSession, null); } } @@ -734,7 +713,7 @@ public class XmppConnection implements Runnable { enableAdvancedStreamFeatures(); } } else { - final IqPacket iq = new IqPacket(IqPacket.TYPE_GET); + final IqPacket iq = new IqPacket(IqPacket.TYPE.GET); iq.setTo(server.toDomainJid()); iq.query("http://jabber.org/protocol/disco#info"); this.sendIqPacket(iq, new OnIqPacketReceived() { @@ -767,19 +746,17 @@ public class XmppConnection implements Runnable { } private void enableAdvancedStreamFeatures() { - if (getFeatures().carbons()) { - if (!enabledCarbons) { - sendEnableCarbons(); - } + if (getFeatures().carbons() && !features.carbonsEnabled) { + sendEnableCarbons(); } - if (getFeatures().blocking()) { + if (getFeatures().blocking() && !features.blockListRequested) { Log.d(Config.LOGTAG, "Requesting block list"); this.sendIqPacket(getIqGenerator().generateGetBlockList(), mXmppConnectionService.getIqParser()); } } private void sendServiceDiscoveryItems(final Jid server) { - final IqPacket iq = new IqPacket(IqPacket.TYPE_GET); + final IqPacket iq = new IqPacket(IqPacket.TYPE.GET); iq.setTo(server.toDomainJid()); iq.query("http://jabber.org/protocol/disco#items"); this.sendIqPacket(iq, new OnIqPacketReceived() { @@ -800,7 +777,7 @@ public class XmppConnection implements Runnable { } private void sendEnableCarbons() { - final 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() { @@ -809,7 +786,7 @@ public class XmppConnection implements Runnable { if (!packet.hasChild("error")) { Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": successfully enabled carbons"); - enabledCarbons = true; + features.carbonsEnabled = true; } else { Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": error enableing carbons " + packet.toString()); @@ -845,49 +822,44 @@ public class XmppConnection implements Runnable { return new BigInteger(50, mXmppConnectionService.getRNG()).toString(32); } - public void sendIqPacket(final IqPacket packet, final PacketReceived callback) { - if (packet.getId() == null) { - final String id = nextRandomId(); - packet.setAttribute("id", id); - } + public void sendIqPacket(final IqPacket packet, final OnIqPacketReceived callback) { packet.setFrom(account.getJid()); - this.sendPacket(packet, callback); + this.sendUnmodifiedIqPacket(packet,callback); + } - public void sendUnboundIqPacket(final IqPacket packet, final PacketReceived callback) { + private synchronized void sendUnmodifiedIqPacket(final IqPacket packet, final OnIqPacketReceived callback) { if (packet.getId() == null) { final String id = nextRandomId(); packet.setAttribute("id", id); } - this.sendPacket(packet, callback); + if (callback != null) { + if (packet.getId() == null) { + packet.setId(nextRandomId()); + } + packetCallbacks.put(packet.getId(), new Pair<>(packet, callback)); + } + this.sendPacket(packet); } public void sendMessagePacket(final MessagePacket packet) { - this.sendPacket(packet, null); + this.sendPacket(packet); } public void sendPresencePacket(final PresencePacket packet) { - this.sendPacket(packet, null); + this.sendPacket(packet); } - private synchronized void sendPacket(final AbstractStanza packet, final PacketReceived callback) { - if (packet.getName().equals("iq") || packet.getName().equals("message") - || packet.getName().equals("presence")) { + private synchronized void sendPacket(final AbstractStanza packet) { + final String name = packet.getName(); + if (name.equals("iq") || name.equals("message") || name.equals("presence")) { ++stanzasSent; - } + } tagWriter.writeStanzaAsync(packet); - if (packet instanceof MessagePacket && packet.getId() != null - && this.streamId != null) { - Log.d(Config.LOGTAG, "request delivery report for stanza " - + stanzasSent); + if (packet instanceof MessagePacket && packet.getId() != null && this.streamId != null) { + Log.d(Config.LOGTAG, "request delivery report for stanza " + stanzasSent); this.messageReceipts.put(stanzasSent, packet.getId()); tagWriter.writeStanzaAsync(new RequestPacket(this.smVersion)); - } - if (callback != null) { - if (packet.getId() == null) { - packet.setId(nextRandomId()); - } - packetCallbacks.put(packet.getId(), callback); } } @@ -895,7 +867,7 @@ public class XmppConnection implements Runnable { if (streamFeatures.hasChild("sm")) { tagWriter.writeStanzaAsync(new RequestPacket(smVersion)); } else { - final 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); @@ -1040,19 +1012,22 @@ public class XmppConnection implements Runnable { } public long getLastPacketReceived() { - return this.lastPaketReceived; + return this.lastPacketReceived; } public void sendActive() { - this.sendPacket(new ActivePacket(), null); + this.sendPacket(new ActivePacket()); } public void sendInactive() { - this.sendPacket(new InactivePacket(), null); + this.sendPacket(new InactivePacket()); } public class Features { XmppConnection connection; + private boolean carbonsEnabled = false; + private boolean encryptionEnabled = false; + private boolean blockListRequested = false; public Features(final XmppConnection connection) { this.connection = connection; @@ -1100,9 +1075,8 @@ public class XmppConnection implements Runnable { return connection.streamFeatures != null && connection.streamFeatures.hasChild("ver"); } - public boolean streamhost() { - return connection - .findDiscoItemByFeature("http://jabber.org/protocol/bytestreams") != null; + public void setBlockListRequested(boolean value) { + this.blockListRequested = value; } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index d578ca38..fe37596c 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -75,7 +75,7 @@ public class JingleConnection implements Downloadable { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType() == IqPacket.TYPE_ERROR) { + if (packet.getType() == IqPacket.TYPE.ERROR) { fail(); } } @@ -191,10 +191,10 @@ public class JingleConnection implements Downloadable { } IqPacket response; if (returnResult) { - response = packet.generateResponse(IqPacket.TYPE_RESULT); + response = packet.generateResponse(IqPacket.TYPE.RESULT); } else { - response = packet.generateResponse(IqPacket.TYPE_ERROR); + response = packet.generateResponse(IqPacket.TYPE.ERROR); } account.getXmppConnection().sendIqPacket(response, null); } @@ -280,7 +280,7 @@ public class JingleConnection implements Downloadable { Element fileNameElement = fileOffer.findChild("name"); if (fileNameElement != null) { String[] filename = fileNameElement.getContent() - .toLowerCase(Locale.US).split("\\."); + .toLowerCase(Locale.US).toLowerCase().split("\\."); if (Arrays.asList(VALID_IMAGE_EXTENSIONS).contains( filename[filename.length - 1])) { message.setType(Message.TYPE_IMAGE); @@ -552,7 +552,7 @@ public class JingleConnection implements Downloadable { Log.d(Config.LOGTAG, "candidate " + connection.getCandidate().getCid() + " was our proxy. going to activate"); - IqPacket activation = new IqPacket(IqPacket.TYPE_SET); + IqPacket activation = new IqPacket(IqPacket.TYPE.SET); activation.setTo(connection.getCandidate().getJid()); activation.query("http://jabber.org/protocol/bytestreams") .setAttribute("sid", this.getSessionId()); @@ -564,7 +564,7 @@ public class JingleConnection implements Downloadable { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType() == IqPacket.TYPE_ERROR) { + if (packet.getType() == IqPacket.TYPE.ERROR) { onProxyActivated.failed(); } else { onProxyActivated.success(); @@ -707,8 +707,7 @@ public class JingleConnection implements Downloadable { private void receiveSuccess() { this.mJingleStatus = JINGLE_STATUS_FINISHED; - this.mXmppConnectionService.markMessage(this.message, - Message.STATUS_SEND); + this.mXmppConnectionService.markMessage(this.message,Message.STATUS_SEND_RECEIVED); this.disconnectSocks5Connections(); if (this.transport != null && this.transport instanceof JingleInbandTransport) { this.transport.disconnect(); diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index b0a730b1..57c74ad9 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -46,7 +46,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { return; } } - IqPacket response = packet.generateResponse(IqPacket.TYPE_ERROR); + IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR); Element error = response.addChild("error"); error.setAttribute("type", "cancel"); error.addChild("item-not-found", @@ -84,7 +84,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { final String proxy = account.getXmppConnection() .findDiscoItemByFeature(xmlns); if (proxy != null) { - IqPacket iq = new IqPacket(IqPacket.TYPE_GET); + IqPacket iq = new IqPacket(IqPacket.TYPE.GET); iq.setAttribute("to", proxy); iq.query(xmlns); account.getXmppConnection().sendIqPacket(iq, diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java index e25f7e65..174f70fa 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java @@ -44,7 +44,7 @@ public class JingleInbandTransport extends JingleTransport { private OnIqPacketReceived onAckReceived = new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - if (connected && packet.getType() == IqPacket.TYPE_RESULT) { + if (connected && packet.getType() == IqPacket.TYPE.RESULT) { sendNextBlock(); } } @@ -60,7 +60,7 @@ public class JingleInbandTransport extends JingleTransport { } public void connect(final OnTransportConnected callback) { - IqPacket iq = new IqPacket(IqPacket.TYPE_SET); + IqPacket iq = new IqPacket(IqPacket.TYPE.SET); iq.setTo(this.counterpart); Element open = iq.addChild("open", "http://jabber.org/protocol/ibb"); open.setAttribute("sid", this.sessionId); @@ -73,7 +73,7 @@ public class JingleInbandTransport extends JingleTransport { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType() == IqPacket.TYPE_ERROR) { + if (packet.getType() == IqPacket.TYPE.ERROR) { callback.failed(); } else { callback.established(); @@ -157,7 +157,7 @@ public class JingleInbandTransport extends JingleTransport { this.remainingSize -= count; this.digest.update(buffer); String base64 = Base64.encodeToString(buffer, Base64.NO_WRAP); - IqPacket iq = new IqPacket(IqPacket.TYPE_SET); + IqPacket iq = new IqPacket(IqPacket.TYPE.SET); iq.setTo(this.counterpart); Element data = iq.addChild("data", "http://jabber.org/protocol/ibb"); @@ -208,15 +208,15 @@ public class JingleInbandTransport extends JingleTransport { established = true; connected = true; this.account.getXmppConnection().sendIqPacket( - packet.generateResponse(IqPacket.TYPE_RESULT), null); + packet.generateResponse(IqPacket.TYPE.RESULT), null); } else { this.account.getXmppConnection().sendIqPacket( - packet.generateResponse(IqPacket.TYPE_ERROR), null); + packet.generateResponse(IqPacket.TYPE.ERROR), null); } } else if (connected && payload.getName().equals("data")) { this.receiveNextBlock(payload.getContent()); this.account.getXmppConnection().sendIqPacket( - packet.generateResponse(IqPacket.TYPE_RESULT), null); + packet.generateResponse(IqPacket.TYPE.RESULT), null); } else { // TODO some sort of exception } diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java index 1a49b45e..55256ece 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java +++ b/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java @@ -1,11 +1,12 @@ package eu.siacs.conversations.xmpp.stanzas; +import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.jid.Jid; public class AbstractStanza extends Element { - protected AbstractStanza(String name) { + protected AbstractStanza(final String name) { super(name); } @@ -36,4 +37,18 @@ public class AbstractStanza extends Element { public void setId(final String id) { setAttribute("id", id); } + + public boolean fromServer(final Account account) { + return getFrom() == null + || getFrom().equals(account.getServer()) + || getFrom().equals(account.getJid().toBareJid()) + || getFrom().equals(account.getJid()); + } + + public boolean toServer(final Account account) { + return getTo() == null + || getTo().equals(account.getServer()) + || getTo().equals(account.getJid().toBareJid()) + || getTo().equals(account.getJid()); + } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/IqPacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/IqPacket.java index 2481112b..7b36fc49 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/IqPacket.java +++ b/src/main/java/eu/siacs/conversations/xmpp/stanzas/IqPacket.java @@ -4,32 +4,18 @@ import eu.siacs.conversations.xml.Element; public class IqPacket extends AbstractStanza { - public static final int TYPE_ERROR = -1; - public static final int TYPE_SET = 0; - public static final int TYPE_RESULT = 1; - public static final int TYPE_GET = 2; - - private IqPacket(final String name) { - super(name); + public static enum TYPE { + ERROR, + SET, + RESULT, + GET, + INVALID } - public IqPacket(final int type) { + public IqPacket(final TYPE type) { super("iq"); - switch (type) { - case TYPE_SET: - this.setAttribute("type", "set"); - break; - case TYPE_GET: - this.setAttribute("type", "get"); - break; - case TYPE_RESULT: - this.setAttribute("type", "result"); - break; - case TYPE_ERROR: - this.setAttribute("type", "error"); - break; - default: - break; + if (type != TYPE.INVALID) { + this.setAttribute("type", type.toString().toLowerCase()); } } @@ -51,23 +37,23 @@ public class IqPacket extends AbstractStanza { return query(); } - public int getType() { + public TYPE getType() { final String type = getAttribute("type"); switch (type) { case "error": - return TYPE_ERROR; + return TYPE.ERROR; case "result": - return TYPE_RESULT; + return TYPE.RESULT; case "set": - return TYPE_SET; + return TYPE.SET; case "get": - return TYPE_GET; + return TYPE.GET; default: - return 1000; + return TYPE.INVALID; } } - public IqPacket generateResponse(final int type) { + public IqPacket generateResponse(final TYPE type) { final IqPacket packet = new IqPacket(type); packet.setTo(this.getFrom()); packet.setId(this.getId()); diff --git a/src/main/res/menu/muc_details.xml b/src/main/res/menu/muc_details.xml index 341d438a..7587e55c 100644 --- a/src/main/res/menu/muc_details.xml +++ b/src/main/res/menu/muc_details.xml @@ -21,6 +21,13 @@ android:title="@string/delete_bookmark" android:orderInCategory="80" android:showAsAction="never" /> + <item + android:id="@+id/action_advanced_mode" + android:title="@string/advanced_mode" + android:checkable="true" + android:checked="false" + android:orderInCategory="85" + android:showAsAction="never" /> <item android:id="@+id/action_accounts" android:orderInCategory="90" diff --git a/src/main/res/values-ca/arrays.xml b/src/main/res/values-ca/arrays.xml index ff1a0d4b..4ce49172 100644 --- a/src/main/res/values-ca/arrays.xml +++ b/src/main/res/values-ca/arrays.xml @@ -1,24 +1,26 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>Mòbil</item> - <item>Telèfon</item> - <item>Tauleta</item> - <item>Conversations</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>mai</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - -</resources>
\ No newline at end of file + <string-array name="resources"> + <item>Mòbil</item> + <item>Telèfon</item> + <item>Tauleta</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>mai</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> +</resources> diff --git a/src/main/res/values-cs/arrays.xml b/src/main/res/values-cs/arrays.xml index 4510cf84..896c6d9a 100644 --- a/src/main/res/values-cs/arrays.xml +++ b/src/main/res/values-cs/arrays.xml @@ -1,39 +1,40 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>Mobil</item> - <item>Telefon</item> - <item>Tablet</item> - <item>Konverzace</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>nikdy</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - <string-array name="mute_options_descriptions"> - <item>30 minut</item> - <item>jedna hodina</item> - <item>2 hodiny</item> - <item>8 hodin</item> - <item>než opět změním</item> - </string-array> - - <integer-array name="mute_options_durations"> - <item>1800</item> - <item>3600</item> - <item>7200</item> - <item>28800</item> - <item>-1</item> - </integer-array> - + <string-array name="resources"> + <item>Mobil</item> + <item>Telefon</item> + <item>Tablet</item> + <item>Konverzace</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>nikdy</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> + <string-array name="mute_options_descriptions"> + <item>30 minut</item> + <item>jedna hodina</item> + <item>2 hodiny</item> + <item>8 hodin</item> + <item>než opět změním</item> + </string-array> + <integer-array name="mute_options_durations"> + <item>1800</item> + <item>3600</item> + <item>7200</item> + <item>28800</item> + <item>-1</item> + </integer-array> </resources> diff --git a/src/main/res/values-cs/strings.xml b/src/main/res/values-cs/strings.xml index 33c7310b..ba8ae998 100644 --- a/src/main/res/values-cs/strings.xml +++ b/src/main/res/values-cs/strings.xml @@ -12,6 +12,10 @@ <string name="action_edit_contact">Upravit jméno</string> <string name="action_add_phone_book">Přidat do telefonního seznamu</string> <string name="action_delete_contact">Smazat ze seznamu</string> + <string name="action_block_contact">Zablokovat kontakt</string> + <string name="action_unblock_contact">Odblokovat kontakt</string> + <string name="action_block_domain">Zablokovat doménu</string> + <string name="action_unblock_domain">Odblokovat doménu</string> <string name="title_activity_manage_accounts">Nastavení účtů</string> <string name="title_activity_settings">Nastavení</string> <string name="title_activity_conference_details">Detaily konference</string> @@ -20,6 +24,7 @@ <string name="title_activity_sharewith">Sdílet s konverzací</string> <string name="title_activity_start_conversation">Začít konverzaci</string> <string name="title_activity_choose_contact">Vybrat kontakt</string> + <string name="title_activity_block_list">Seznam blokovaných</string> <string name="just_now">právě teď</string> <string name="minute_ago">před minutou</string> <string name="minutes_ago">před %d minutami</string> @@ -33,8 +38,14 @@ <string name="participant">Účastník</string> <string name="visitor">Návštěvník</string> <string name="remove_contact_text">Chcete odstranit %s ze svého seznamu? Konverzace spojené s tímto kontaktem nebudou odstraněny.</string> + <string name="block_contact_text">Chcete zablokovat příjem zpráv od %s?</string> + <string name="unblock_contact_text">Chcete odblokovat příjem zpráv od %s?</string> + <string name="block_domain_text">Zablokovat všechny kontakty z %s?</string> + <string name="unblock_domain_text">Odblokovat všechny kontakty z %s?</string> + <string name="contact_blocked">Kontakty zablokovány</string> <string name="remove_bookmark_text">Chcete odstranit %s ze záložek? Konverzace spojené s touto záložkou nebudou odstraněny.</string> <string name="register_account">Registrovat nový účet na serveru</string> + <string name="change_password_on_server">Změnit heslo na serveru</string> <string name="share_with">Sdílet s</string> <string name="start_conversation">Začít konverzaci</string> <string name="invite_contact">Pozvat kontakt</string> @@ -44,6 +55,8 @@ <string name="add">Přidat</string> <string name="edit">Upravit</string> <string name="delete">Smazat</string> + <string name="block">Zablokovat</string> + <string name="unblock">Odblokovat</string> <string name="save">Uložit</string> <string name="ok">OK</string> <string name="crash_report_title">Aplikace Konverzace přestala reagovat</string> @@ -173,7 +186,12 @@ <string name="contact_status_offline">offline</string> <string name="muc_details_conference">Konference</string> <string name="muc_details_other_members">Ostatní členové</string> + <string name="server_info_show_more">Údaje serveru</string> + <string name="server_info_mam">XEP-0313: MAM</string> <string name="server_info_carbon_messages">XEP-0280: Kopie zpráv</string> + <string name="server_info_csi">XEP-0352: Zobrazování stavu klienta</string> + <string name="server_info_blocking">XEP-0191: Příkaz blokování</string> + <string name="server_info_roster_version">XEP-0237: Verzování seznamu</string> <string name="server_info_stream_management">XEP-0198: Nastavení proudu</string> <string name="server_info_pep">XEP-0163: PEP (Avatars)</string> <string name="server_info_available">dostupný</string> @@ -201,6 +219,8 @@ <string name="join_conference">Připojit ke konferenci</string> <string name="delete_contact">Smazat kontakt</string> <string name="view_contact_details">Zobrazit detaily kontaktu</string> + <string name="block_contact">Zablokovat kontakt</string> + <string name="unblock_contact">Odblokovat kontakt</string> <string name="create">Vytvořit</string> <string name="contact_already_exists">Kontakt již existuje</string> <string name="join">Vstoupit</string> @@ -293,6 +313,7 @@ <string name="image_transmission_failed">Přenos obrázku selhal</string> <string name="scan_qr_code">Skenovat QR kód</string> <string name="show_qr_code">Zobrazit QR kód</string> + <string name="show_block_list">Zobrazit seznam blokovaných</string> <string name="account_details">Detaily účtu</string> <string name="verify_otr">Ověřit OTR</string> <string name="remote_fingerprint">Vzdálený otisk</string> @@ -343,4 +364,26 @@ <string name="copy_otr_clipboard_description">Zkopírovat otisk OTR do schránky</string> <string name="fetching_history_from_server">Načíst historii ze serveru</string> <string name="no_more_history_on_server">Na serveru není žádná další historie</string> -</resources> + <string name="updating">Aktualizuji...</string> + <string name="password_changed">Heslo změněno!</string> + <string name="could_not_change_password">Nelze změnit heslo</string> + <string name="otr_session_not_started">Zaslat zprávu pro spuštění šifrovaného chatu</string> + <string name="ask_question">Položit otázku</string> + <string name="smp_explain_question">Pokud máte vy i váš kontakt společné tajemství které neví nikdo jiný (něco jako společný vtip nebo co jste spolu měli k obědu při svém posledním setkání), můžete toto tajemství použít pro ověření pravosti svých šifrovacích otisků.\n\nZadáte nápovědu nebo otázku a kontakt na ni správně odpoví.</string> + <string name="smp_explain_answer">Váš kontakt by rád ověřil pravost šifrovacího otisku dotazem na společné tajemství. Váš kontakt zadal následující nápovědu nebo otázku pro zodpovězení tajemství.</string> + <string name="shared_secret_hint_should_not_be_empty">Nápověda by měla být vyplněna</string> + <string name="shared_secret_can_not_be_empty">Společně tajemství nemůže být nevyplněno</string> + <string name="manual_verification_explanation">Opatrně porovnejte otisk zobrazený níže s otiskem vašeho kontatku.\nMůžete využít jakoukoliv bezpečnou formu komunikace pro jejich výměnu, jako třeba šifrovaný email nebo telefonát.</string> + <string name="change_password">Změnit heslo</string> + <string name="current_password">Současné heslo</string> + <string name="new_password">Nové heslo</string> + <string name="password_should_not_be_empty">Heslo nemá být prázdné</string> + <string name="enable_all_accounts">Povolit všechny účty</string> + <string name="disable_all_accounts">Vypnout všechny účty</string> + <string name="perform_action_with">Provést akci s</string> + <string name="no_affiliation">Nepřidružený</string> + <string name="no_role">Bez role</string> + <string name="outcast">Vyloučený</string> + <string name="member">Člen</string> + <string name="advanced_mode">Pokročilý mód</string> +</resources>
\ No newline at end of file diff --git a/src/main/res/values-de/arrays.xml b/src/main/res/values-de/arrays.xml index ed5d47b5..f28263c8 100644 --- a/src/main/res/values-de/arrays.xml +++ b/src/main/res/values-de/arrays.xml @@ -1,31 +1,33 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>Mobile</item> - <item>Phone</item> - <item>Tablet</item> - <item>Conversations</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>nie</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - <string-array name="mute_options_descriptions"> - <item>30 Minuten</item> - <item>1 Stunde</item> - <item>2 Stunden</item> - <item>8 Stunden</item> - <item>bis auf Widerruf</item> - </string-array> - -</resources>
\ No newline at end of file + <string-array name="resources"> + <item>Mobile</item> + <item>Phone</item> + <item>Tablet</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>nie</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> + <string-array name="mute_options_descriptions"> + <item>30 Minuten</item> + <item>1 Stunde</item> + <item>2 Stunden</item> + <item>8 Stunden</item> + <item>bis auf Widerruf</item> + </string-array> +</resources> diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index 9e8e3b3d..aa87f758 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -28,7 +28,7 @@ <string name="minute_ago">vor einer Minute</string> <string name="minutes_ago">vor %d Minuten</string> <string name="unread_conversations">ungelesene Unterhaltungen</string> - <string name="sending">senden…</string> + <string name="sending">Senden…</string> <string name="encrypted_message">Entschlüssele Nachricht. Bitte warten…</string> <string name="nick_in_use">Nickname wird bereits verwendet</string> <string name="admin">Administrator</string> @@ -133,8 +133,8 @@ <string name="send_presence_updates">Anwesenheitsbenachrichtigungen senden</string> <string name="receive_presence_updates">Empfange Anwesenheitsbenachrichtigungen</string> <string name="ask_for_presence_updates">Frage um Erlaubnis, Anwesenheitsbenachrichtigungen sehen zu dürfen</string> - <string name="attach_choose_picture">Foto auswählen</string> - <string name="attach_take_picture">Foto aufnehmen</string> + <string name="attach_choose_picture">Bild auswählen</string> + <string name="attach_take_picture">Bild aufnehmen</string> <string name="preemptively_grant">Erlaube Statusanfrage vorab</string> <string name="error_not_an_image_file">Die ausgewählte Datei ist kein Bild</string> <string name="error_compressing_image">Fehler beim Umwandeln des Bildes</string> @@ -165,7 +165,7 @@ <string name="mgmt_account_publish_pgp">Öffentlichen OpenPGP-Schlüssel veröffentlichen</string> <string name="mgmt_account_enable">Anschalten</string> <string name="mgmt_account_are_you_sure">Bist du dir sicher?</string> - <string name="mgmt_account_delete_confirm_text">Wenn du dein Konto löscht, gehen alle Gesprächsverläufe verloren</string> + <string name="mgmt_account_delete_confirm_text">Wenn du dein Konto löschst, gehen alle Gesprächsverläufe verloren</string> <string name="attach_record_voice">Sprache aufzeichnen</string> <string name="account_settings_jabber_id">Jabber-ID:</string> <string name="account_settings_password">Passwort:</string> @@ -188,13 +188,13 @@ <string name="server_info_show_more">Server Info</string> <string name="server_info_mam">XEP-0313: MAM</string> <string name="server_info_carbon_messages">XEP-0280: Message Carbons</string> - <string name="server_info_csi">XEP-0352: Client State Indication</string> + <string name="server_info_csi">XEP-0352: CSI</string> <string name="server_info_blocking">XEP-0191: Blocking Command</string> <string name="server_info_roster_version">XEP-0237: Roster Versioning</string> <string name="server_info_stream_management">XEP-0198: Stream Management</string> <string name="server_info_pep">XEP-0163: PEP (Avatare)</string> - <string name="server_info_available">verfügbar</string> - <string name="server_info_unavailable">nicht verfügbar</string> + <string name="server_info_available">ja</string> + <string name="server_info_unavailable">nein</string> <string name="missing_public_keys">Öffentlicher Schlüssel fehlt</string> <string name="last_seen_now">online</string> <string name="last_seen_min">vor einer Minute gesehen</string> @@ -219,7 +219,7 @@ <string name="delete_contact">Kontakt löschen</string> <string name="view_contact_details">Kontaktdetails anzeigen</string> <string name="block_contact">Kontakt sperren</string> - <string name="unblock_contact">Kontakte entsperren</string> + <string name="unblock_contact">Kontakt entsperren</string> <string name="create">Erstellen</string> <string name="contact_already_exists">Der Kontakt existiert bereits</string> <string name="join">Beitreten</string> @@ -236,7 +236,7 @@ <string name="add_back">Auch hinzufügen</string> <string name="contact_has_read_up_to_this_point">%s hat bis zu diesem Punkt gelesen</string> <string name="publish">Veröffentlichen</string> - <string name="touch_to_choose_picture">Klicke hier, um einen Avatar auszuwählen</string> + <string name="touch_to_choose_picture">Hier klicken, um einen Avatar auszuwählen</string> <string name="publish_avatar_explanation">Achtung: Jeder, der deinen Status sehen darf, sieht auch deinen Avatar.</string> <string name="publishing">Veröffentliche…</string> <string name="error_publish_avatar_server_reject">Der Server hat die Veröffentlichung des Avatars abgelehnt.</string> @@ -245,12 +245,12 @@ <string name="or_long_press_for_default">(Oder klicke lange, um Standard wiederherzustellen)</string> <string name="error_publish_avatar_no_server_support">Dein Server unterstützt die Veröffentlichung von Avataren nicht.</string> <string name="private_message">private Nachricht</string> - <string name="private_message_to">an %s</string> + <string name="private_message_to">an %s:</string> <string name="send_private_message_to">Sende private Nachricht an %s</string> <string name="connect">Verbinden</string> <string name="account_already_exists">Das Konto existiert bereits</string> <string name="next">Weiter</string> - <string name="server_info_session_established">Aktuelle Sitzung wiederhergestellt</string> + <string name="server_info_session_established">Sitzung wiederhergestellt</string> <string name="additional_information">Zusätzliche Informationen</string> <string name="skip">Überspringen</string> <string name="disable_notifications">Benachrichtigungen deaktivieren</string> @@ -329,17 +329,17 @@ <string name="try_again">Erneut versuchen</string> <string name="finish">Fertig</string> <string name="verified">Überprüft!</string> - <string name="smp_requested">Kontakt forder SMP Überprüfung an</string> + <string name="smp_requested">Kontakt fordert eine Überprüfung an</string> <string name="no_otr_session_found">Keine gültige OTR Sitzung gefunden!</string> <string name="conversations_foreground_service">Conversations</string> <string name="touch_to_disable">Berühren, um den Vordergrund-Dient zu deaktiveren.</string> <string name="pref_keep_foreground_service">Den Dienst im Vordergrund ausführen.</string> - <string name="pref_keep_foreground_service_summary">Verhindert, dass das Betriebssystem die Verbindung unterbricht</string> + <string name="pref_keep_foreground_service_summary">Verhindert, dass Android die Verbindung unterbricht</string> <string name="choose_file">Datei auswählen</string> <string name="receiving_file">Empfange %1$s Datei (%2$d%% heruntergeladen)</string> <string name="download_file">Download %s Datei</string> <string name="open_file">Öffne %s Datei</string> - <string name="sending_file">sende (%1$d%% gesendet)</string> + <string name="sending_file">Sende (%1$d%% gesendet)</string> <string name="preparing_file">Bereite Datei für die Übertragung vor</string> <string name="file_offered_for_download">Datei zum Download angeboten</string> <string name="file">%s Datei</string> @@ -353,7 +353,7 @@ <string name="pref_show_dynamic_tags">Dynamische Tags anzeigen</string> <string name="pref_show_dynamic_tags_summary">Zeige schreibgeschützte Tags unterhalb der Kontakte</string> <string name="enable_notifications">Aktiviere Benachrichtigungen</string> - <string name="conference_with">Starte Konferenze mit…</string> + <string name="conference_with">Starte Konferenz mit…</string> <string name="no_conference_server_found">Konferenz-Server kann nicht gefunden werden</string> <string name="conference_creation_failed">Starten der Konferenz fehlgeschlagen!</string> <string name="conference_created">Konferenz erstellt!</string> @@ -361,8 +361,8 @@ <string name="reset">Zurücksetzen</string> <string name="account_image_description">Konto-Avatar</string> <string name="copy_otr_clipboard_description">OTR-Fingerabdruck in Zwischenablage kopieren</string> - <string name="fetching_history_from_server">Hole Chatverlauf vom Server</string> - <string name="no_more_history_on_server">Keine weiteren Nachrichten auf dem Server vorhanden.</string> + <string name="fetching_history_from_server">Lade Chatverlauf</string> + <string name="no_more_history_on_server">Keine weiteren Nachrichten vorhanden</string> <string name="updating">Aktualisiere…</string> <string name="password_changed">Passwort geändert.</string> <string name="could_not_change_password">Passwort kann nicht geändert werden.</string> diff --git a/src/main/res/values-es/arrays.xml b/src/main/res/values-es/arrays.xml index 15231955..d6e0127a 100644 --- a/src/main/res/values-es/arrays.xml +++ b/src/main/res/values-es/arrays.xml @@ -1,39 +1,40 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>Móvil</item> - <item>Teléfono</item> - <item>Tablet</item> - <item>Conversations</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>nunca</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - <string-array name="mute_options_descriptions"> - <item>30 minutos</item> - <item>1 hora</item> - <item>2 horas</item> - <item>8 horas</item> - <item>Hasta nuevo aviso</item> - </string-array> - - <integer-array name="mute_options_durations"> - <item>1800</item> - <item>3600</item> - <item>7200</item> - <item>28800</item> - <item>-1</item> - </integer-array> - -</resources>
\ No newline at end of file + <string-array name="resources"> + <item>Móvil</item> + <item>Teléfono</item> + <item>Tablet</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>nunca</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> + <string-array name="mute_options_descriptions"> + <item>30 minutos</item> + <item>1 hora</item> + <item>2 horas</item> + <item>8 horas</item> + <item>Hasta nuevo aviso</item> + </string-array> + <integer-array name="mute_options_durations"> + <item>1800</item> + <item>3600</item> + <item>7200</item> + <item>28800</item> + <item>-1</item> + </integer-array> +</resources> diff --git a/src/main/res/values-eu/arrays.xml b/src/main/res/values-eu/arrays.xml index a34d3c6a..fec7d60d 100644 --- a/src/main/res/values-eu/arrays.xml +++ b/src/main/res/values-eu/arrays.xml @@ -1,39 +1,40 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>Mugikorra</item> - <item>Telefonoa</item> - <item>Tableta</item> - <item>Conversations</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>inoiz</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - <string-array name="mute_options_descriptions"> - <item>30 minutu</item> - <item>ordu bat</item> - <item>2 ordu</item> - <item>8 ordu</item> - <item>abisatu arte</item> - </string-array> - - <integer-array name="mute_options_durations"> - <item>1800</item> - <item>3600</item> - <item>7200</item> - <item>28800</item> - <item>-1</item> - </integer-array> - -</resources>
\ No newline at end of file + <string-array name="resources"> + <item>Mugikorra</item> + <item>Telefonoa</item> + <item>Tableta</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>inoiz</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> + <string-array name="mute_options_descriptions"> + <item>30 minutu</item> + <item>ordu bat</item> + <item>2 ordu</item> + <item>8 ordu</item> + <item>abisatu arte</item> + </string-array> + <integer-array name="mute_options_durations"> + <item>1800</item> + <item>3600</item> + <item>7200</item> + <item>28800</item> + <item>-1</item> + </integer-array> +</resources> diff --git a/src/main/res/values-fr/arrays.xml b/src/main/res/values-fr/arrays.xml index ae140796..7667be0a 100644 --- a/src/main/res/values-fr/arrays.xml +++ b/src/main/res/values-fr/arrays.xml @@ -1,24 +1,26 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>Mobile</item> - <item>Téléphone</item> - <item>Tablette</item> - <item>Conversations</item> - <item>Android</item> + <string-array name="resources"> + <item>Mobile</item> + <item>Téléphone</item> + <item>Tablette</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>jamais</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> </string-array> - <string-array name="filesizes"> - <item>jamais</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - -</resources>
\ No newline at end of file +</resources> diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml index b3b86f1f..daae6076 100644 --- a/src/main/res/values-fr/strings.xml +++ b/src/main/res/values-fr/strings.xml @@ -268,5 +268,90 @@ <string name="checking_image">Vérification de l\'image</string> <string name="image_file_deleted">L\'image a été suprimée</string> <string name="not_connected_try_again">Vous n\'êtes pas connecté. Merci de retenter plus tard.</string> - +<string name="check_image_filesize">Vérifier la taille de l\'image</string> +<string name="message_options">Options du message</string> +<string name="copy_text">Copier le texte</string> +<string name="share_image">Partager l\'image</string> +<string name="copy_original_url">Copier l\'URL</string> +<string name="send_again">Envoyer de nouveau</string> +<string name="image_url">URL de l\'image</string> +<string name="message_text">Message texte</string> +<string name="url_copied_to_clipboard">URL copiée dans le presse-papier</string> +<string name="message_copied_to_clipboard">Message copié dans le presse-papier</string> +<string name="image_transmission_failed">Echec lors de l\'envoi de l\'image</string> +<string name="scan_qr_code">Scanner un QR code</string> +<string name="show_qr_code">Afficher le QR code</string> +<string name="show_block_list">Afficher la liste des contacts bloqués</string> +<string name="account_details">Détails du compte</string> +<string name="verify_otr">Vérifier l\'OTR</string> +<string name="remote_fingerprint">Supprimer l\'empreinte</string> +<string name="scan">Scanner</string> +<string name="or_touch_phones">(ou les touches)</string> +<string name="smp">Socialist Millionaire Protocol</string> +<string name="shared_secret_hint">Indice ou question</string> +<string name="shared_secret_secret">Secret partagé</string> +<string name="confirm">Confirmer</string> +<string name="in_progress">En cours</string> +<string name="respond">Répondre</string> +<string name="failed">Echoué</string> +<string name="secrets_do_not_match">Les secrets ne correspondent pas</string> +<string name="try_again">Réessayer</string> +<string name="finish">Terminé</string> +<string name="verified">Vérifié!</string> +<string name="smp_requested">Le contact requiert la vérification du SMP</string> +<string name="no_otr_session_found">Aucune session valide d\'OTR n\'a été trouvée!</string> +<string name="conversations_foreground_service">Conversations</string> +<string name="touch_to_disable">Toucher pour désactiver le service au premier-plan</string> +<string name="pref_keep_foreground_service">Garder le service au premier-plan</string> +<string name="pref_keep_foreground_service_summary">Evite que le système ferme votre connexion</string> +<string name="choose_file">Choix d\'un fichier</string> +<string name="receiving_file">Réception %1$s fichier (%2$d%% complété)</string> +<string name="download_file">Télecharger %s fichier</string> +<string name="open_file">Ouvrir %s fichier</string> +<string name="sending_file">envoi (%1$d%% complété)</string> +<string name="preparing_file">Préparation du fichier pour l\'envoi</string> +<string name="file_offered_for_download">Fichier disponible pour téléchargement</string> +<string name="file">%s fichier</string> +<string name="cancel_transmission">Annuler l\'envoi</string> +<string name="file_transmission_failed">Envoi du fichier échoué</string> +<string name="file_deleted">Le fichier a été supprimé</string> +<string name="no_application_found_to_open_file">Aucune application disponible pour ouvrir le fichier</string> +<string name="could_not_verify_fingerprint">Impossible de vérifier l\'empreinte</string> +<string name="manually_verify">Vérifier manuellement</string> +<string name="are_you_sure_verify_fingerprint">Etes-vous sûr de vouloir vérifier l\'empreinte OTR de vos contacts?</string> +<string name="pref_show_dynamic_tags">Afficher les tags dynamiques</string> +<string name="pref_show_dynamic_tags_summary">Afficher les tags en lecture-seule sous les contacts</string> +<string name="enable_notifications">Activer les notifications</string> +<string name="conference_with">Créer une conférence avec…</string> +<string name="no_conference_server_found">Aucun serveur de conférence disponible</string> +<string name="conference_creation_failed">Echec de la création de la conférence!</string> +<string name="conference_created">Conférence créée!</string> +<string name="secret_accepted">Secret commun accepté!</string> +<string name="reset">Réinitialiser</string> +<string name="account_image_description">Image du compte</string> +<string name="copy_otr_clipboard_description">Copier l\'empreinte OTR dans le presse-papier</string> +<string name="fetching_history_from_server">Récupérer l\'historique depuis le serveur</string> +<string name="no_more_history_on_server">Fin de l\'historique sur le serveur</string> +<string name="updating">Mise à jour…</string> +<string name="password_changed">Mot de passe modifié!</string> +<string name="could_not_change_password">Impossible de changer le mot de passe</string> +<string name="otr_session_not_started">Envoyez un message pour commencer la conversation chiffrée</string> +<string name="ask_question">Poser une question</string> +<string name="smp_explain_question">Si vous et votre contact avez un secret en commun connu par vous deux uniquement (comme une histoire personnelle ou même comme ce que vous avez mangé lors de votre dernière rencontre) vous pouvez utiliser ce secret pour vérifier vos empreintes respectives.\n\nVous envoyez un indice ou une question à votre contact qui devra répondre en faisant attention à la casse.</string> +<string name="smp_explain_answer">Votre contact voudrait vous identifier de manière sûre grâce à un secret commun. Il vous envoie le message ou la question suivante.</string> +<string name="shared_secret_hint_should_not_be_empty">Votre indice ne devrait pas être vide</string> +<string name="shared_secret_can_not_be_empty">Votre secret ne peut être vide</string> +<string name="manual_verification_explanation">Comparez avec soin l\'empreinte de votre contact avec celle indiquée ci-dessous.\nVous pouvez utiliser n\'importe quel moyen de communication sécurisée pour cela, tel que le télephone ou l\'envoi d\'un e-mail chiffré.</string> +<string name="change_password">Changer de mot de passe</string> +<string name="current_password">Mot de passe actuel</string> +<string name="new_password">Nouveau mot de passe</string> +<string name="password_should_not_be_empty">Le mot de passe ne peut être vide</string> +<string name="enable_all_accounts">Activer tous les comptes</string> +<string name="disable_all_accounts">Désactiver tous les comptes</string> +<string name="perform_action_with">Faire une action avec</string> +<string name="no_affiliation">Aucune affiliation</string> +<string name="no_role">Aucun rôle</string> +<string name="outcast">Banni</string> +<string name="member">Membre</string> +<string name="advanced_mode">Mode avancé</string> </resources> diff --git a/src/main/res/values-gl/arrays.xml b/src/main/res/values-gl/arrays.xml index 19424a78..c6d1b22e 100644 --- a/src/main/res/values-gl/arrays.xml +++ b/src/main/res/values-gl/arrays.xml @@ -1,24 +1,26 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>Móvil</item> - <item>Teléfono</item> - <item>Tablet</item> - <item>Conversations</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>nunca</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - -</resources>
\ No newline at end of file + <string-array name="resources"> + <item>Móvil</item> + <item>Teléfono</item> + <item>Tablet</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>nunca</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> +</resources> diff --git a/src/main/res/values-it/arrays.xml b/src/main/res/values-it/arrays.xml index 60c0b04f..2a6a64a8 100644 --- a/src/main/res/values-it/arrays.xml +++ b/src/main/res/values-it/arrays.xml @@ -1,39 +1,40 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>Cellulare</item> - <item>Telefono</item> - <item>Tablet</item> - <item>Conversations</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>mai</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - <string-array name="mute_options_descriptions"> - <item>30 minuti</item> - <item>un\'ora</item> - <item>2 ore</item> - <item>8 ore</item> - <item>fino a nuovo avviso</item> - </string-array> - - <integer-array name="mute_options_durations"> - <item>1800</item> - <item>3600</item> - <item>7200</item> - <item>28800</item> - <item>-1</item> - </integer-array> - + <string-array name="resources"> + <item>Cellulare</item> + <item>Telefono</item> + <item>Tablet</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>mai</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> + <string-array name="mute_options_descriptions"> + <item>30 minuti</item> + <item>un\'ora</item> + <item>2 ore</item> + <item>8 ore</item> + <item>fino a nuovo avviso</item> + </string-array> + <integer-array name="mute_options_durations"> + <item>1800</item> + <item>3600</item> + <item>7200</item> + <item>28800</item> + <item>-1</item> + </integer-array> </resources> diff --git a/src/main/res/values-iw/arrays.xml b/src/main/res/values-iw/arrays.xml index 28768d6c..d5e73e3d 100644 --- a/src/main/res/values-iw/arrays.xml +++ b/src/main/res/values-iw/arrays.xml @@ -1,24 +1,26 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>נייד</item> - <item>טלפון</item> - <item>טאבלט</item> - <item>Conversations</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>אף פעם</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - -</resources>
\ No newline at end of file + <string-array name="resources"> + <item>נייד</item> + <item>טלפון</item> + <item>טאבלט</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>אף פעם</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> +</resources> diff --git a/src/main/res/values-nl/arrays.xml b/src/main/res/values-nl/arrays.xml index e5ae27e7..77a1afbe 100644 --- a/src/main/res/values-nl/arrays.xml +++ b/src/main/res/values-nl/arrays.xml @@ -1,39 +1,40 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>Mobiel</item> - <item>Telefoon</item> - <item>Tablet</item> - <item>Conversations</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>nooit</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - <string-array name="mute_options_descriptions"> - <item>30 minuten</item> - <item>1 uur</item> - <item>2 uur</item> - <item>8 uur</item> - <item>voor onbepaalde duur</item> - </string-array> - - <integer-array name="mute_options_durations"> - <item>1800</item> - <item>3600</item> - <item>7200</item> - <item>28800</item> - <item>-1</item> - </integer-array> - + <string-array name="resources"> + <item>Mobiel</item> + <item>Telefoon</item> + <item>Tablet</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>nooit</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> + <string-array name="mute_options_descriptions"> + <item>30 minuten</item> + <item>1 uur</item> + <item>2 uur</item> + <item>8 uur</item> + <item>voor onbepaalde duur</item> + </string-array> + <integer-array name="mute_options_durations"> + <item>1800</item> + <item>3600</item> + <item>7200</item> + <item>28800</item> + <item>-1</item> + </integer-array> </resources> diff --git a/src/main/res/values-ru/arrays.xml b/src/main/res/values-ru/arrays.xml index d01d4eb9..f4bd94fe 100644 --- a/src/main/res/values-ru/arrays.xml +++ b/src/main/res/values-ru/arrays.xml @@ -1,24 +1,26 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>Мобильный</item> - <item>Телефон</item> - <item>Планшет</item> - <item>Conversations</item> - <item>Андроид</item> - </string-array> - <string-array name="filesizes"> - <item>никогда</item> - <item>256 Кб</item> - <item>512 Кб</item> - <item>1 Мб</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - -</resources>
\ No newline at end of file + <string-array name="resources"> + <item>Мобильный</item> + <item>Телефон</item> + <item>Планшет</item> + <item>Conversations</item> + <item>Андроид</item> + </string-array> + <string-array name="filesizes"> + <item>никогда</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> +</resources> diff --git a/src/main/res/values-sv/arrays.xml b/src/main/res/values-sv/arrays.xml index 890e2915..fa156f8e 100644 --- a/src/main/res/values-sv/arrays.xml +++ b/src/main/res/values-sv/arrays.xml @@ -1,24 +1,26 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>Mobile</item> - <item>Phone</item> - <item>Tablet</item> - <item>Conversations</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>aldrig</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - -</resources>
\ No newline at end of file + <string-array name="resources"> + <item>Mobile</item> + <item>Phone</item> + <item>Tablet</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>aldrig</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> +</resources> diff --git a/src/main/res/values-zh-rCN/arrays.xml b/src/main/res/values-zh-rCN/arrays.xml index 1a243079..b7f184d8 100644 --- a/src/main/res/values-zh-rCN/arrays.xml +++ b/src/main/res/values-zh-rCN/arrays.xml @@ -1,39 +1,40 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>手机</item> - <item>电话</item> - <item>平板电脑</item> - <item>Conversations</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>永不</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - <string-array name="mute_options_descriptions"> - <item>30 分钟</item> - <item>1 小时</item> - <item>2 小时</item> - <item>8 小时</item> - <item>直至另行取消</item> - </string-array> - - <integer-array name="mute_options_durations"> - <item>1800</item> - <item>3600</item> - <item>7200</item> - <item>28800</item> - <item>-1</item> - </integer-array> - -</resources>
\ No newline at end of file + <string-array name="resources"> + <item>手机</item> + <item>电话</item> + <item>平板电脑</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>永不</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> + <string-array name="mute_options_descriptions"> + <item>30 分钟</item> + <item>1 小时</item> + <item>2 小时</item> + <item>8 小时</item> + <item>直至另行取消</item> + </string-array> + <integer-array name="mute_options_durations"> + <item>1800</item> + <item>3600</item> + <item>7200</item> + <item>28800</item> + <item>-1</item> + </integer-array> +</resources> diff --git a/src/main/res/values-zh-rTW/arrays.xml b/src/main/res/values-zh-rTW/arrays.xml index b9c261ad..335233a4 100644 --- a/src/main/res/values-zh-rTW/arrays.xml +++ b/src/main/res/values-zh-rTW/arrays.xml @@ -1,39 +1,40 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <string-array name="resources"> - <item>手機</item> - <item>電話</item> - <item>平板電腦</item> - <item>Conversations</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>永不</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - <string-array name="mute_options_descriptions"> - <item>30 分鐘</item> - <item>1 小時</item> - <item>2 小時</item> - <item>8 小時</item> - <item>直至另行取消</item> - </string-array> - - <integer-array name="mute_options_durations"> - <item>1800</item> - <item>3600</item> - <item>7200</item> - <item>28800</item> - <item>-1</item> - </integer-array> - -</resources>
\ No newline at end of file + <string-array name="resources"> + <item>手機</item> + <item>電話</item> + <item>平板電腦</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>永不</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> + <string-array name="mute_options_descriptions"> + <item>30 分鐘</item> + <item>1 小時</item> + <item>2 小時</item> + <item>8 小時</item> + <item>直至另行取消</item> + </string-array> + <integer-array name="mute_options_durations"> + <item>1800</item> + <item>3600</item> + <item>7200</item> + <item>28800</item> + <item>-1</item> + </integer-array> +</resources> diff --git a/src/main/res/values/arrays.xml b/src/main/res/values/arrays.xml index 4acc9e62..0fc55776 100644 --- a/src/main/res/values/arrays.xml +++ b/src/main/res/values/arrays.xml @@ -1,39 +1,43 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <string-array name="resources"> - <item>Mobile</item> - <item>Phone</item> - <item>Tablet</item> - <item>Conversations</item> - <item>Android</item> - </string-array> - <string-array name="filesizes"> - <item>never</item> - <item>256 KB</item> - <item>512 KB</item> - <item>1 MB</item> - </string-array> - <string-array name="filesizes_values"> - <item>0</item> - <item>262144</item> - <item>524288</item> - <item>1048576</item> - </string-array> - <string-array name="mute_options_descriptions"> - <item>30 minutes</item> - <item>1 hour</item> - <item>2 hours</item> - <item>8 hours</item> - <item>until further notice</item> - </string-array> + <string-array name="resources"> + <item>Mobile</item> + <item>Phone</item> + <item>Tablet</item> + <item>Conversations</item> + <item>Android</item> + </string-array> + <string-array name="filesizes"> + <item>never</item> + <item>256 KiB</item> + <item>512 KiB</item> + <item>1 MiB</item> + <item>5 MiB</item> + <item>10 MiB</item> + </string-array> + <string-array name="filesizes_values"> + <item>0</item> + <item>262144</item> + <item>524288</item> + <item>1048576</item> + <item>5242880</item> + <item>10485760</item> + </string-array> + <string-array name="mute_options_descriptions"> + <item>30 minutes</item> + <item>1 hour</item> + <item>2 hours</item> + <item>8 hours</item> + <item>until further notice</item> + </string-array> - <integer-array name="mute_options_durations"> - <item>1800</item> - <item>3600</item> - <item>7200</item> - <item>28800</item> - <item>-1</item> - </integer-array> + <integer-array name="mute_options_durations"> + <item>1800</item> + <item>3600</item> + <item>7200</item> + <item>28800</item> + <item>-1</item> + </integer-array> </resources> diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 45174cd8..bb358610 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -406,4 +406,9 @@ <string name="enable_all_accounts">Enable all accounts</string> <string name="disable_all_accounts">Disable all accounts</string> <string name="perform_action_with">Perform action with</string> + <string name="no_affiliation">No affiliation</string> + <string name="no_role">No role</string> + <string name="outcast">Outcast</string> + <string name="member">Member</string> + <string name="advanced_mode">Advanced mode</string> </resources> |