Merge tag '2.5.6' into develop

This commit is contained in:
Martin/Geno 2019-08-28 11:22:27 +02:00
commit e304b6b152
No known key found for this signature in database
GPG Key ID: 9D7D3C6BFF600C6A
45 changed files with 464 additions and 276 deletions

View File

@ -1,5 +1,9 @@
# Changelog # Changelog
### Version 2.5.6
* fixes for Jingle file transfer
* fixed some rare crashes
### Version 2.5.5 ### Version 2.5.5
* allow backups to be restored from anywhere * allow backups to be restored from anywhere
* bug fixes * bug fixes

View File

@ -81,8 +81,8 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 25 targetSdkVersion 25
versionCode 334 versionCode 336
versionName "2.5.5" versionName "2.5.6"
archivesBaseName += "-$versionName" archivesBaseName += "-$versionName"
applicationId "eu.sum7.conversations" applicationId "eu.sum7.conversations"
resValue "string", "applicationId", applicationId resValue "string", "applicationId", applicationId

View File

@ -137,7 +137,7 @@ public class ImportBackupService extends Service {
} else { } else {
backupFiles.add(backupFile); backupFiles.add(backupFile);
} }
} catch (IOException e) { } catch (IOException | IllegalArgumentException e) {
Log.d(Config.LOGTAG, "unable to read backup file ", e); Log.d(Config.LOGTAG, "unable to read backup file ", e);
} }
} }

View File

@ -124,7 +124,7 @@ public class ImportBackupActivity extends ActionBarActivity implements ServiceCo
try { try {
final ImportBackupService.BackupFile backupFile = ImportBackupService.BackupFile.read(this, uri); final ImportBackupService.BackupFile backupFile = ImportBackupService.BackupFile.read(this, uri);
showEnterPasswordDialog(backupFile, finishOnCancel); showEnterPasswordDialog(backupFile, finishOnCancel);
} catch (IOException e) { } catch (IOException | IllegalArgumentException e) {
Snackbar.make(binding.coordinator, R.string.not_a_backup_file, Snackbar.LENGTH_LONG).show(); Snackbar.make(binding.coordinator, R.string.not_a_backup_file, Snackbar.LENGTH_LONG).show();
} }
} }

View File

@ -113,6 +113,7 @@ public final class Config {
public static final boolean ONLY_INTERNAL_STORAGE = false; //use internal storage instead of sdcard to save attachments public static final boolean ONLY_INTERNAL_STORAGE = false; //use internal storage instead of sdcard to save attachments
public static final boolean IGNORE_ID_REWRITE_IN_MUC = true; public static final boolean IGNORE_ID_REWRITE_IN_MUC = true;
public static final boolean MUC_LEAVE_BEFORE_JOIN = true;
public static final long MAM_MAX_CATCHUP = MILLISECONDS_IN_DAY * 5; public static final long MAM_MAX_CATCHUP = MILLISECONDS_IN_DAY * 5;
public static final int MAM_MAX_MESSAGES = 750; public static final int MAM_MAX_MESSAGES = 750;

View File

@ -426,6 +426,11 @@ public class MucOptions {
} else if (!conversation.getJid().isBareJid()) { } else if (!conversation.getJid().isBareJid()) {
return conversation.getJid().getResource(); return conversation.getJid().getResource();
} else { } else {
return defaultNick(account);
}
}
public static String defaultNick(final Account account) {
final String displayName = normalize(account.getJid(), account.getDisplayName()); final String displayName = normalize(account.getJid(), account.getDisplayName());
if (displayName == null) { if (displayName == null) {
return JidHelper.localPartOrFallback(account.getJid()); return JidHelper.localPartOrFallback(account.getJid());
@ -433,7 +438,6 @@ public class MucOptions {
return displayName; return displayName;
} }
} }
}
private static String normalize(Jid account, String nick) { private static String normalize(Jid account, String nick) {
if (account == null || TextUtils.isEmpty(nick)) { if (account == null || TextUtils.isEmpty(nick)) {

View File

@ -87,6 +87,18 @@ public class ServiceDiscoveryResult {
} }
} }
private ServiceDiscoveryResult() {
this.hash = "sha-1";
this.features = Collections.emptyList();
this.identities = Collections.emptyList();
this.ver = null;
this.forms = Collections.emptyList();
}
public static ServiceDiscoveryResult empty() {
return new ServiceDiscoveryResult();
}
public ServiceDiscoveryResult(Cursor cursor) throws JSONException { public ServiceDiscoveryResult(Cursor cursor) throws JSONException {
this( this(
cursor.getString(cursor.getColumnIndex(HASH)), cursor.getString(cursor.getColumnIndex(HASH)),

View File

@ -68,8 +68,8 @@ public abstract class AbstractGenerator {
return this.mVersion; return this.mVersion;
} }
public String getIdentityName() { String getIdentityName() {
return mXmppConnectionService.getString(R.string.app_name) + ' ' + getIdentityVersion(); return mXmppConnectionService.getString(R.string.app_name);
} }
public String getUserAgent() { public String getUserAgent() {

View File

@ -50,16 +50,21 @@ public class PresenceGenerator extends AbstractGenerator {
return selfPresence(account, status, true); return selfPresence(account, status, true);
} }
public PresencePacket selfPresence(Account account, Presence.Status status, boolean includePgpAnnouncement) { public PresencePacket selfPresence(final Account account, final Presence.Status status, final boolean personal) {
PresencePacket packet = new PresencePacket(); final PresencePacket packet = new PresencePacket();
if (personal) {
final String sig = account.getPgpSignature();
final String message = account.getPresenceStatusMessage();
if(status.toShowString() != null) { if(status.toShowString() != null) {
packet.addChild("show").setContent(status.toShowString()); packet.addChild("show").setContent(status.toShowString());
} }
packet.setFrom(account.getJid()); if (!TextUtils.isEmpty(message)) {
final String sig = account.getPgpSignature(); packet.addChild(new Element("status").setContent(message));
if (includePgpAnnouncement && sig != null && mXmppConnectionService.getPgpEngine() != null) { }
if (sig != null && mXmppConnectionService.getPgpEngine() != null) {
packet.addChild("x", "jabber:x:signed").setContent(sig); packet.addChild("x", "jabber:x:signed").setContent(sig);
} }
}
final String capHash = getCapHash(account); final String capHash = getCapHash(account);
if (capHash != null) { if (capHash != null) {
Element cap = packet.addChild("c", Element cap = packet.addChild("c",

View File

@ -22,7 +22,6 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.DownloadableFile;
import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.Transferable;
import eu.siacs.conversations.entities.TransferablePlaceholder;
import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.AbstractConnectionManager;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
@ -77,22 +76,20 @@ public class HttpDownloadConnection implements Transferable {
} else { } else {
mUrl = CryptoHelper.toHttpsUrl(new URL(message.getBody().split("\n")[0])); mUrl = CryptoHelper.toHttpsUrl(new URL(message.getBody().split("\n")[0]));
} }
String[] parts = mUrl.getPath().toLowerCase().split("\\."); final AbstractConnectionManager.Extension extension = AbstractConnectionManager.Extension.of(mUrl.getPath());
String lastPart = parts.length >= 1 ? parts[parts.length - 1] : null; if (VALID_CRYPTO_EXTENSIONS.contains(extension.main)) {
String secondToLast = parts.length >= 2 ? parts[parts.length - 2] : null;
if ("pgp".equals(lastPart) || "gpg".equals(lastPart)) {
this.message.setEncryption(Message.ENCRYPTION_PGP); this.message.setEncryption(Message.ENCRYPTION_PGP);
} else if (message.getEncryption() != Message.ENCRYPTION_OTR } else if (message.getEncryption() != Message.ENCRYPTION_OTR
&& message.getEncryption() != Message.ENCRYPTION_AXOLOTL) { && message.getEncryption() != Message.ENCRYPTION_AXOLOTL) {
this.message.setEncryption(Message.ENCRYPTION_NONE); this.message.setEncryption(Message.ENCRYPTION_NONE);
} }
String extension; final String ext;
if (VALID_CRYPTO_EXTENSIONS.contains(lastPart)) { if (VALID_CRYPTO_EXTENSIONS.contains(extension.main)) {
extension = secondToLast; ext = extension.secondary;
} else { } else {
extension = lastPart; ext = extension.main;
} }
message.setRelativeFilePath(message.getUuid() + (extension != null ? ("." + extension) : "")); message.setRelativeFilePath(message.getUuid() + (ext != null ? ("." + ext) : ""));
this.file = mXmppConnectionService.getFileBackend().getFile(message, false); this.file = mXmppConnectionService.getFileBackend().getFile(message, false);
final String reference = mUrl.getRef(); final String reference = mUrl.getRef();
if (reference != null && AesGcmURLStreamHandler.IV_KEY.matcher(reference).matches()) { if (reference != null && AesGcmURLStreamHandler.IV_KEY.matcher(reference).matches()) {

View File

@ -109,4 +109,23 @@ public class AbstractConnectionManager {
PowerManager powerManager = (PowerManager) mXmppConnectionService.getSystemService(Context.POWER_SERVICE); PowerManager powerManager = (PowerManager) mXmppConnectionService.getSystemService(Context.POWER_SERVICE);
return powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name); return powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name);
} }
public static class Extension {
public final String main;
public final String secondary;
private Extension(String main, String secondary) {
this.main = main;
this.secondary = secondary;
}
public static Extension of(String path) {
final int pos = path.lastIndexOf('/');
final String filename = path.substring(pos + 1).toLowerCase();
final String[] parts = filename.split("\\.");
final String main = parts.length >= 2 ? parts[parts.length - 1] : null;
final String secondary = parts.length >= 3 ? parts[parts.length - 2] : null;
return new Extension(main, secondary);
}
}
} }

View File

@ -68,13 +68,9 @@ import java.util.Set;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.R; import eu.siacs.conversations.R;
import eu.siacs.conversations.android.JabberIdContact; import eu.siacs.conversations.android.JabberIdContact;
@ -101,9 +97,8 @@ import eu.siacs.conversations.generator.AbstractGenerator;
import eu.siacs.conversations.generator.IqGenerator; import eu.siacs.conversations.generator.IqGenerator;
import eu.siacs.conversations.generator.MessageGenerator; import eu.siacs.conversations.generator.MessageGenerator;
import eu.siacs.conversations.generator.PresenceGenerator; import eu.siacs.conversations.generator.PresenceGenerator;
import eu.siacs.conversations.http.HttpConnectionManager;
import eu.siacs.conversations.http.CustomURLStreamHandlerFactory; import eu.siacs.conversations.http.CustomURLStreamHandlerFactory;
import eu.siacs.conversations.http.services.MuclumbusService; import eu.siacs.conversations.http.HttpConnectionManager;
import eu.siacs.conversations.parser.AbstractParser; import eu.siacs.conversations.parser.AbstractParser;
import eu.siacs.conversations.parser.IqParser; import eu.siacs.conversations.parser.IqParser;
import eu.siacs.conversations.parser.MessageParser; import eu.siacs.conversations.parser.MessageParser;
@ -129,9 +124,9 @@ import eu.siacs.conversations.utils.Resolver;
import eu.siacs.conversations.utils.SerialSingleThreadExecutor; import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
import eu.siacs.conversations.utils.StringUtils; import eu.siacs.conversations.utils.StringUtils;
import eu.siacs.conversations.utils.WakeLockHelper; import eu.siacs.conversations.utils.WakeLockHelper;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.utils.XmppUri; import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.OnBindListener; import eu.siacs.conversations.xmpp.OnBindListener;
import eu.siacs.conversations.xmpp.OnContactStatusChanged; import eu.siacs.conversations.xmpp.OnContactStatusChanged;
import eu.siacs.conversations.xmpp.OnIqPacketReceived; import eu.siacs.conversations.xmpp.OnIqPacketReceived;
@ -155,11 +150,6 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket; import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
import eu.siacs.conversations.xmpp.stanzas.PresencePacket; import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
import me.leolin.shortcutbadger.ShortcutBadger; import me.leolin.shortcutbadger.ShortcutBadger;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import rocks.xmpp.addr.Jid; import rocks.xmpp.addr.Jid;
public class XmppConnectionService extends Service { public class XmppConnectionService extends Service {
@ -428,11 +418,11 @@ public class XmppConnectionService extends Service {
final int next = connection.getTimeToNextAttempt(); final int next = connection.getTimeToNextAttempt();
final boolean lowPingTimeoutMode = isInLowPingTimeoutMode(account); final boolean lowPingTimeoutMode = isInLowPingTimeoutMode(account);
if (next <= 0) { if (next <= 0) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": error connecting account. reconnecting now. lowPingTimeout=" + Boolean.toString(lowPingTimeoutMode)); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": error connecting account. reconnecting now. lowPingTimeout=" + lowPingTimeoutMode);
reconnectAccount(account, true, false); reconnectAccount(account, true, false);
} else { } else {
final int attempt = connection.getAttempt() + 1; final int attempt = connection.getAttempt() + 1;
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": error connecting account. try again in " + next + "s for the " + attempt + " time. lowPingTimeout=" + Boolean.toString(lowPingTimeoutMode)); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": error connecting account. try again in " + next + "s for the " + attempt + " time. lowPingTimeout=" + lowPingTimeoutMode);
scheduleWakeUpCall(next, account.getUuid().hashCode()); scheduleWakeUpCall(next, account.getUuid().hashCode());
} }
} }
@ -1395,7 +1385,7 @@ public class XmppConnectionService extends Service {
final boolean inProgressJoin; final boolean inProgressJoin;
synchronized (account.inProgressConferenceJoins) { synchronized (account.inProgressConferenceJoins) {
inProgressJoin = conversation.getMode() == Conversational.MODE_MULTI && account.inProgressConferenceJoins.contains(conversation); inProgressJoin = conversation.getMode() == Conversational.MODE_MULTI && (account.inProgressConferenceJoins.contains(conversation) || account.pendingConferenceJoins.contains(conversation));
} }
if (account.isOnlineAndConnected() && !inProgressJoin) { if (account.isOnlineAndConnected() && !inProgressJoin) {
@ -1522,7 +1512,6 @@ public class XmppConnectionService extends Service {
packet.addChild(ChatState.toElement(conversation.getOutgoingChatState())); packet.addChild(ChatState.toElement(conversation.getOutgoingChatState()));
} }
} }
Log.d(Config.LOGTAG,packet.toString());
sendMessagePacket(account, packet); sendMessagePacket(account, packet);
} }
} }
@ -2546,7 +2535,9 @@ public class XmppConnectionService extends Service {
synchronized (account.inProgressConferenceJoins) { synchronized (account.inProgressConferenceJoins) {
account.inProgressConferenceJoins.add(conversation); account.inProgressConferenceJoins.add(conversation);
} }
if (Config.MUC_LEAVE_BEFORE_JOIN) {
sendPresencePacket(account, mPresenceGenerator.leave(conversation.getMucOptions())); sendPresencePacket(account, mPresenceGenerator.leave(conversation.getMucOptions()));
}
conversation.resetMucOptions(); conversation.resetMucOptions();
if (onConferenceJoined != null) { if (onConferenceJoined != null) {
conversation.getMucOptions().flagNoAutoPushConfiguration(); conversation.getMucOptions().flagNoAutoPushConfiguration();
@ -2800,7 +2791,13 @@ public class XmppConnectionService extends Service {
final Bookmark bookmark = conversation.getBookmark(); final Bookmark bookmark = conversation.getBookmark();
final String bookmarkedNick = bookmark == null ? null : bookmark.getNick(); final String bookmarkedNick = bookmark == null ? null : bookmark.getNick();
if (bookmark != null && (tookProposedNickFromBookmark || TextUtils.isEmpty(bookmarkedNick)) && !full.getResource().equals(bookmarkedNick)) { if (bookmark != null && (tookProposedNickFromBookmark || TextUtils.isEmpty(bookmarkedNick)) && !full.getResource().equals(bookmarkedNick)) {
Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": persist nick '" + full.getResource() + "' into bookmark for " + conversation.getJid().asBareJid()); final Account account = conversation.getAccount();
final String defaultNick = MucOptions.defaultNick(account);
if (TextUtils.isEmpty(bookmarkedNick) && full.getResource().equals(defaultNick)) {
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": do not overwrite empty bookmark nick with default nick for "+conversation.getJid().asBareJid());
return;
}
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": persist nick '" + full.getResource() + "' into bookmark for " + conversation.getJid().asBareJid());
bookmark.setNick(full.getResource()); bookmark.setNick(full.getResource());
pushBookmarks(bookmark.getAccount()); pushBookmarks(bookmark.getAccount());
} }
@ -2827,15 +2824,8 @@ public class XmppConnectionService extends Service {
} }
}); });
PresencePacket packet = new PresencePacket(); final PresencePacket packet = mPresenceGenerator.selfPresence(account, Presence.Status.ONLINE, options.nonanonymous());
packet.setTo(joinJid); packet.setTo(joinJid);
packet.setFrom(conversation.getAccount().getJid());
String sig = account.getPgpSignature();
if (sig != null) {
packet.addChild("status").setContent("online");
packet.addChild("x", "jabber:x:signed").setContent(sig);
}
sendPresencePacket(account, packet); sendPresencePacket(account, packet);
} else { } else {
conversation.setContactJid(joinJid); conversation.setContactJid(joinJid);
@ -4105,11 +4095,7 @@ public class XmppConnectionService extends Service {
} else { } else {
status = getTargetPresence(); status = getTargetPresence();
} }
PresencePacket packet = mPresenceGenerator.selfPresence(account, status); final PresencePacket packet = mPresenceGenerator.selfPresence(account, status);
String message = account.getPresenceStatusMessage();
if (message != null && !message.isEmpty()) {
packet.addChild(new Element("status").setContent(message));
}
if (mLastActivity > 0 && includeIdleTimestamp) { if (mLastActivity > 0 && includeIdleTimestamp) {
long since = Math.min(mLastActivity, System.currentTimeMillis()); //don't send future dates long since = Math.min(mLastActivity, System.currentTimeMillis()); //don't send future dates
packet.addChild("idle", Namespace.IDLE).setAttribute("since", AbstractGenerator.getTimestamp(since)); packet.addChild("idle", Namespace.IDLE).setAttribute("since", AbstractGenerator.getTimestamp(since));
@ -4419,10 +4405,11 @@ public class XmppConnectionService extends Service {
} }
public void saveConversationAsBookmark(Conversation conversation, String name) { public void saveConversationAsBookmark(Conversation conversation, String name) {
Account account = conversation.getAccount(); final Account account = conversation.getAccount();
Bookmark bookmark = new Bookmark(account, conversation.getJid().asBareJid()); final Bookmark bookmark = new Bookmark(account, conversation.getJid().asBareJid());
if (!conversation.getJid().isBareJid()) { final String nick = conversation.getJid().getResource();
bookmark.setNick(conversation.getJid().getResource()); if (nick != null && !nick.isEmpty() && !nick.equals(MucOptions.defaultNick(account))) {
bookmark.setNick(nick);
} }
if (!TextUtils.isEmpty(name)) { if (!TextUtils.isEmpty(name)) {
bookmark.setBookmarkName(name); bookmark.setBookmarkName(name);

View File

@ -257,6 +257,11 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
@Override @Override
public boolean onContextItemSelected(MenuItem item) { public boolean onContextItemSelected(MenuItem item) {
final User user = mUserPreviewAdapter.getSelectedUser();
if (user == null) {
Toast.makeText(this, R.string.unable_to_perform_this_action, Toast.LENGTH_SHORT).show();
return true;
}
if (!MucDetailsContextMenuHelper.onContextItemSelected(item, mUserPreviewAdapter.getSelectedUser(), this)) { if (!MucDetailsContextMenuHelper.onContextItemSelected(item, mUserPreviewAdapter.getSelectedUser(), this)) {
return super.onContextItemSelected(item); return super.onContextItemSelected(item);
} }

View File

@ -24,13 +24,11 @@ import org.osmdroid.api.IMapController;
import org.osmdroid.config.Configuration; import org.osmdroid.config.Configuration;
import org.osmdroid.config.IConfigurationProvider; import org.osmdroid.config.IConfigurationProvider;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory; import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.tileprovider.tilesource.XYTileSource;
import org.osmdroid.util.GeoPoint; import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.CustomZoomButtonsController; import org.osmdroid.views.CustomZoomButtonsController;
import org.osmdroid.views.MapView; import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.Overlay; import org.osmdroid.views.overlay.Overlay;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import eu.siacs.conversations.BuildConfig; import eu.siacs.conversations.BuildConfig;
@ -41,7 +39,6 @@ import eu.siacs.conversations.services.QuickConversationsService;
import eu.siacs.conversations.ui.util.LocationHelper; import eu.siacs.conversations.ui.util.LocationHelper;
import eu.siacs.conversations.ui.widget.Marker; import eu.siacs.conversations.ui.widget.Marker;
import eu.siacs.conversations.ui.widget.MyLocation; import eu.siacs.conversations.ui.widget.MyLocation;
import eu.siacs.conversations.utils.LocationProvider;
import eu.siacs.conversations.utils.ThemeHelper; import eu.siacs.conversations.utils.ThemeHelper;
public abstract class LocationActivity extends ActionBarActivity implements LocationListener { public abstract class LocationActivity extends ActionBarActivity implements LocationListener {
@ -136,7 +133,7 @@ public abstract class LocationActivity extends ActionBarActivity implements Loca
map.setTileSource(TileSourceFactory.MAPNIK); map.setTileSource(TileSourceFactory.MAPNIK);
map.getZoomController().setVisibility(CustomZoomButtonsController.Visibility.NEVER); map.getZoomController().setVisibility(CustomZoomButtonsController.Visibility.NEVER);
map.setMultiTouchControls(true); map.setMultiTouchControls(true);
map.setTilesScaledToDpi(true); map.setTilesScaledToDpi(false);
mapController = map.getController(); mapController = map.getController();
mapController.setZoom(Config.Map.INITIAL_ZOOM_LEVEL); mapController.setZoom(Config.Map.INITIAL_ZOOM_LEVEL);
mapController.setCenter(pos); mapController.setCenter(pos);

View File

@ -21,6 +21,8 @@ import java.io.IOException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.R; import eu.siacs.conversations.R;
@ -37,6 +39,8 @@ public class RecordingActivity extends Activity implements View.OnClickListener
private MediaRecorder mRecorder; private MediaRecorder mRecorder;
private long mStartTime = 0; private long mStartTime = 0;
private CountDownLatch outputFileWrittenLatch = new CountDownLatch(1);
private Handler mHandler = new Handler(); private Handler mHandler = new Handler();
private Runnable mTickExecutor = new Runnable() { private Runnable mTickExecutor = new Runnable() {
@Override @Override
@ -47,7 +51,6 @@ public class RecordingActivity extends Activity implements View.OnClickListener
}; };
private File mOutputFile; private File mOutputFile;
private boolean mShouldFinishAfterWrite = false;
private FileObserver mFileObserver; private FileObserver mFileObserver;
@ -55,7 +58,7 @@ public class RecordingActivity extends Activity implements View.OnClickListener
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.findDialog(this)); setTheme(ThemeHelper.findDialog(this));
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
this.binding = DataBindingUtil.setContentView(this,R.layout.activity_recording); this.binding = DataBindingUtil.setContentView(this, R.layout.activity_recording);
this.binding.cancelButton.setOnClickListener(this); this.binding.cancelButton.setOnClickListener(this);
this.binding.shareButton.setOnClickListener(this); this.binding.shareButton.setOnClickListener(this);
this.setFinishOnTouchOutside(false); this.setFinishOnTouchOutside(false);
@ -107,14 +110,14 @@ public class RecordingActivity extends Activity implements View.OnClickListener
} }
} }
protected void stopRecording(boolean saveFile) { protected void stopRecording(final boolean saveFile) {
mShouldFinishAfterWrite = saveFile;
try { try {
mRecorder.stop(); mRecorder.stop();
mRecorder.release(); mRecorder.release();
} catch (Exception e) { } catch (Exception e) {
if (saveFile) { if (saveFile) {
Toast.makeText(this,R.string.unable_to_save_recording, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.unable_to_save_recording, Toast.LENGTH_SHORT).show();
return;
} }
} finally { } finally {
mRecorder = null; mRecorder = null;
@ -122,9 +125,24 @@ public class RecordingActivity extends Activity implements View.OnClickListener
} }
if (!saveFile && mOutputFile != null) { if (!saveFile && mOutputFile != null) {
if (mOutputFile.delete()) { if (mOutputFile.delete()) {
Log.d(Config.LOGTAG,"deleted canceled recording"); Log.d(Config.LOGTAG, "deleted canceled recording");
} }
} }
if (saveFile) {
new Thread(() -> {
try {
if (!outputFileWrittenLatch.await(2, TimeUnit.SECONDS)) {
Log.d(Config.LOGTAG, "time out waiting for output file to be written");
}
} catch (InterruptedException e) {
Log.d(Config.LOGTAG, "interrupted while waiting for output file to be written" ,e);
}
runOnUiThread(() -> {
setResult(Activity.RESULT_OK, new Intent().setData(Uri.fromFile(mOutputFile)));
finish();
});
}).start();
}
} }
private static File generateOutputFilename(Context context) { private static File generateOutputFilename(Context context) {
@ -157,10 +175,7 @@ public class RecordingActivity extends Activity implements View.OnClickListener
@Override @Override
public void onEvent(int event, String s) { public void onEvent(int event, String s) {
if (s != null && s.equals(mOutputFile.getName()) && event == FileObserver.CLOSE_WRITE) { if (s != null && s.equals(mOutputFile.getName()) && event == FileObserver.CLOSE_WRITE) {
if (mShouldFinishAfterWrite) { outputFileWrittenLatch.countDown();
setResult(Activity.RESULT_OK, new Intent().setData(Uri.fromFile(mOutputFile)));
finish();
}
} }
} }
}; };

View File

@ -12,6 +12,7 @@ import android.view.MenuItem;
import android.widget.Toast; import android.widget.Toast;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
@ -142,7 +143,8 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
this.share.text = text; this.share.text = text;
} }
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) { } else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) {
this.share.uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); final ArrayList<Uri> uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
this.share.uris = uris == null ? new ArrayList<>() : uris;
} }
if (xmppConnectionServiceBound) { if (xmppConnectionServiceBound) {
xmppConnectionService.populateWithOrderedConversations(mConversations, this.share.uris.size() == 0, false); xmppConnectionService.populateWithOrderedConversations(mConversations, this.share.uris.size() == 0, false);

View File

@ -62,6 +62,7 @@ import eu.siacs.conversations.entities.Bookmark;
import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.ListItem; import eu.siacs.conversations.entities.ListItem;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.Presence; import eu.siacs.conversations.entities.Presence;
import eu.siacs.conversations.services.QuickConversationsService; import eu.siacs.conversations.services.QuickConversationsService;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
@ -1021,8 +1022,8 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
} else { } else {
final Bookmark bookmark = new Bookmark(account, conferenceJid.asBareJid()); final Bookmark bookmark = new Bookmark(account, conferenceJid.asBareJid());
bookmark.setAutojoin(getBooleanPreference("autojoin", R.bool.autojoin)); bookmark.setAutojoin(getBooleanPreference("autojoin", R.bool.autojoin));
String nick = conferenceJid.getResource(); final String nick = conferenceJid.getResource();
if (nick != null && !nick.isEmpty()) { if (nick != null && !nick.isEmpty() && !nick.equals(MucOptions.defaultNick(account))) {
bookmark.setNick(nick); bookmark.setNick(nick);
} }
account.getBookmarks().add(bookmark); account.getBookmarks().add(bookmark);

View File

@ -49,7 +49,7 @@ public class BackupFileHeader {
public static BackupFileHeader read(DataInputStream inputStream) throws IOException { public static BackupFileHeader read(DataInputStream inputStream) throws IOException {
final int version = inputStream.readInt(); final int version = inputStream.readInt();
if (version > VERSION) { if (version > VERSION) {
throw new IllegalArgumentException("Backup File version was "+version+" but app only supports up to version "+VERSION); throw new IllegalArgumentException("Backup File version was " + version + " but app only supports up to version " + VERSION);
} }
String app = inputStream.readUTF(); String app = inputStream.readUTF();
String jid = inputStream.readUTF(); String jid = inputStream.readUTF();
@ -59,7 +59,7 @@ public class BackupFileHeader {
byte[] salt = new byte[16]; byte[] salt = new byte[16];
inputStream.readFully(salt); inputStream.readFully(salt);
return new BackupFileHeader(app,Jid.of(jid),timestamp,iv,salt); return new BackupFileHeader(app, Jid.of(jid), timestamp, iv, salt);
} }

View File

@ -1184,8 +1184,21 @@ public class XmppConnection implements Runnable {
if (advancedStreamFeaturesLoaded && (jid.equals(Jid.of(account.getServer())) || jid.equals(account.getJid().asBareJid()))) { if (advancedStreamFeaturesLoaded && (jid.equals(Jid.of(account.getServer())) || jid.equals(account.getJid().asBareJid()))) {
enableAdvancedStreamFeatures(); enableAdvancedStreamFeatures();
} }
} else { } else if (packet.getType() == IqPacket.TYPE.ERROR) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": could not query disco info for " + jid.toString()); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": could not query disco info for " + jid.toString());
final boolean serverOrAccount = jid.equals(Jid.of(account.getServer())) || jid.equals(account.getJid().asBareJid());
final boolean advancedStreamFeaturesLoaded;
if (serverOrAccount) {
synchronized (XmppConnection.this.disco) {
disco.put(jid, ServiceDiscoveryResult.empty());
advancedStreamFeaturesLoaded = disco.containsKey(Jid.of(account.getServer())) && disco.containsKey(account.getJid().asBareJid());
}
} else {
advancedStreamFeaturesLoaded = false;
}
if (advancedStreamFeaturesLoaded) {
enableAdvancedStreamFeatures();
}
} }
if (packet.getType() != IqPacket.TYPE.TIMEOUT) { if (packet.getType() != IqPacket.TYPE.TIMEOUT) {
if (mPendingServiceDiscoveries.decrementAndGet() == 0 if (mPendingServiceDiscoveries.decrementAndGet() == 0
@ -1294,11 +1307,10 @@ public class XmppConnection implements Runnable {
throw new IOException(); throw new IOException();
} else if (streamError.hasChild("host-unknown")) { } else if (streamError.hasChild("host-unknown")) {
throw new StateChangingException(Account.State.HOST_UNKNOWN); throw new StateChangingException(Account.State.HOST_UNKNOWN);
} else if (streamError.hasChild("policy-violation")) { ; } else if (streamError.hasChild("policy-violation")) {
this.lastConnect = SystemClock.elapsedRealtime();
final String text = streamError.findChildContent("text"); final String text = streamError.findChildContent("text");
if (text != null) {
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": policy violation. "+text); Log.d(Config.LOGTAG,account.getJid().asBareJid()+": policy violation. "+text);
}
throw new StateChangingException(Account.State.POLICY_VIOLATION); throw new StateChangingException(Account.State.POLICY_VIOLATION);
} else { } else {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": stream error " + streamError.toString()); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": stream error " + streamError.toString());
@ -1545,7 +1557,8 @@ public class XmppConnection implements Runnable {
} }
public int getTimeToNextAttempt() { public int getTimeToNextAttempt() {
final int interval = Math.min((int) (25 * Math.pow(1.3, attempt)), 300); final int additionalTime = account.getLastErrorStatus() == Account.State.POLICY_VIOLATION ? 3 : 0;
final int interval = Math.min((int) (25 * Math.pow(1.3, (additionalTime + attempt))), 300);
final int secondsSinceLast = (int) ((SystemClock.elapsedRealtime() - this.lastConnect) / 1000); final int secondsSinceLast = (int) ((SystemClock.elapsedRealtime() - this.lastConnect) / 1000);
return interval - secondsSinceLast; return interval - secondsSinceLast;
} }

View File

@ -119,6 +119,8 @@ public class JingleConnection implements Transferable {
} }
Log.d(Config.LOGTAG, "successfully transmitted file:" + file.getAbsolutePath() + " (" + CryptoHelper.bytesToHex(file.getSha1Sum()) + ")"); Log.d(Config.LOGTAG, "successfully transmitted file:" + file.getAbsolutePath() + " (" + CryptoHelper.bytesToHex(file.getSha1Sum()) + ")");
return; return;
} else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
account.getPgpDecryptionService().decrypt(message, true);
} }
} else { } else {
if (ftVersion == Content.Version.FT_5) { //older Conversations will break when receiving a session-info if (ftVersion == Content.Version.FT_5) { //older Conversations will break when receiving a session-info
@ -414,41 +416,26 @@ public class JingleConnection implements Transferable {
this.mXmppAxolotlMessage = XmppAxolotlMessage.fromElement(encrypted, packet.getFrom().asBareJid()); this.mXmppAxolotlMessage = XmppAxolotlMessage.fromElement(encrypted, packet.getFrom().asBareJid());
} }
Element fileSize = fileOffer.findChild("size"); Element fileSize = fileOffer.findChild("size");
Element fileNameElement = fileOffer.findChild("name"); final String path = fileOffer.findChildContent("name");
if (fileNameElement != null) { if (path != null) {
String[] filename = fileNameElement.getContent() AbstractConnectionManager.Extension extension = AbstractConnectionManager.Extension.of(path);
.toLowerCase(Locale.US).toLowerCase().split("\\."); if (VALID_IMAGE_EXTENSIONS.contains(extension.main)) {
String extension = filename[filename.length - 1];
if (VALID_IMAGE_EXTENSIONS.contains(extension)) {
message.setType(Message.TYPE_IMAGE); message.setType(Message.TYPE_IMAGE);
message.setRelativeFilePath(message.getUuid() + "." + extension); message.setRelativeFilePath(message.getUuid() + "." + extension.main);
} else if (VALID_CRYPTO_EXTENSIONS.contains( } else if (VALID_CRYPTO_EXTENSIONS.contains(extension.main)) {
filename[filename.length - 1])) { if (VALID_IMAGE_EXTENSIONS.contains(extension.secondary)) {
if (filename.length == 3) {
extension = filename[filename.length - 2];
if (VALID_IMAGE_EXTENSIONS.contains(extension)) {
message.setType(Message.TYPE_IMAGE); message.setType(Message.TYPE_IMAGE);
message.setRelativeFilePath(message.getUuid() + "." + extension); message.setRelativeFilePath(message.getUuid() + "." + extension.secondary);
} else { } else {
message.setType(Message.TYPE_FILE); message.setType(Message.TYPE_FILE);
message.setRelativeFilePath(message.getUuid() + (extension.secondary != null ? ("." + extension.secondary) : ""));
} }
message.setEncryption(Message.ENCRYPTION_PGP); message.setEncryption(Message.ENCRYPTION_PGP);
}
} else { } else {
message.setType(Message.TYPE_FILE); message.setType(Message.TYPE_FILE);
message.setRelativeFilePath(message.getUuid() + (extension.main != null ? ("." + extension.main) : ""));
} }
if (message.getType() == Message.TYPE_FILE) { long size = parseLong(fileSize, 0);
String suffix = "";
if (!fileNameElement.getContent().isEmpty()) {
String parts[] = fileNameElement.getContent().split("/");
suffix = parts[parts.length - 1];
if (message.getEncryption() == Message.ENCRYPTION_PGP && (suffix.endsWith(".pgp") || suffix.endsWith(".gpg"))) {
suffix = suffix.substring(0, suffix.length() - 4);
}
}
message.setRelativeFilePath(message.getUuid() + "_" + suffix);
}
long size = Long.parseLong(fileSize.getContent());
message.setBody(Long.toString(size)); message.setBody(Long.toString(size));
conversation.add(message); conversation.add(message);
mJingleConnectionManager.updateConversationUi(true); mJingleConnectionManager.updateConversationUi(true);
@ -493,6 +480,18 @@ public class JingleConnection implements Transferable {
} }
} }
private static long parseLong(final Element element, final long l) {
final String input = element == null ? null : element.getContent();
if (input == null) {
return l;
}
try {
return Long.parseLong(input);
} catch (Exception e) {
return l;
}
}
private void sendInitRequest() { private void sendInitRequest() {
JinglePacket packet = this.bootstrapPacket("session-initiate"); JinglePacket packet = this.bootstrapPacket("session-initiate");
Content content = new Content(this.contentCreator, this.contentName); Content content = new Content(this.contentCreator, this.contentName);
@ -841,18 +840,17 @@ public class JingleConnection implements Transferable {
private boolean receiveFallbackToIbb(JinglePacket packet) { private boolean receiveFallbackToIbb(JinglePacket packet) {
Log.d(Config.LOGTAG, "receiving fallack to ibb"); Log.d(Config.LOGTAG, "receiving fallack to ibb");
String receivedBlockSize = packet.getJingleContent().ibbTransport() final String receivedBlockSize = packet.getJingleContent().ibbTransport().getAttribute("block-size");
.getAttribute("block-size");
if (receivedBlockSize != null) { if (receivedBlockSize != null) {
int bs = Integer.parseInt(receivedBlockSize); final int bs = Integer.parseInt(receivedBlockSize);
if (bs > this.ibbBlockSize) { if (bs < this.ibbBlockSize) {
this.ibbBlockSize = bs; this.ibbBlockSize = bs;
} }
} }
this.transportId = packet.getJingleContent().getTransportId(); this.transportId = packet.getJingleContent().getTransportId();
this.transport = new JingleInbandTransport(this, this.transportId, this.ibbBlockSize); this.transport = new JingleInbandTransport(this, this.transportId, this.ibbBlockSize);
JinglePacket answer = bootstrapPacket("transport-accept"); final JinglePacket answer = bootstrapPacket("transport-accept");
final Content content = new Content(contentCreator, contentName); final Content content = new Content(contentCreator, contentName);
content.setFileOffer(fileOffer, ftVersion); content.setFileOffer(fileOffer, ftVersion);

View File

@ -26,6 +26,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/color_background_primary" android:background="?attr/color_background_primary"
android:orientation="vertical" android:orientation="vertical"
android:scrollbars="vertical"
app:layoutManager="android.support.v7.widget.LinearLayoutManager" /> app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
</android.support.design.widget.CoordinatorLayout> </android.support.design.widget.CoordinatorLayout>

View File

@ -864,4 +864,12 @@
<string name="this_looks_like_a_domain">Dies sieht aus wie eine Domain-Adresse</string> <string name="this_looks_like_a_domain">Dies sieht aus wie eine Domain-Adresse</string>
<string name="add_anway">Trotzdem hinzufügen</string> <string name="add_anway">Trotzdem hinzufügen</string>
<string name="this_looks_like_channel">Dies sieht aus wie eine Channel-Adresse</string> <string name="this_looks_like_channel">Dies sieht aus wie eine Channel-Adresse</string>
<string name="share_backup_files">Sicherungsdateien teilen</string>
<string name="conversations_backup">Sicherung für Conversations</string>
<string name="event">Ereignis</string>
<string name="open_backup">Sicherung öffnen</string>
<string name="not_a_backup_file">Die von dir ausgewählte Datei ist keine Sicherungsdatei von Conversations</string>
<string name="account_already_setup">Dieses Konto wurde bereits eingerichtet</string>
<string name="please_enter_password">Bitte gib das Passwort für dieses Konto ein</string>
<string name="unable_to_perform_this_action">Diese Aktion kann nicht ausgeführt werden</string>
</resources> </resources>

View File

@ -864,4 +864,11 @@
<string name="this_looks_like_a_domain">Esto parece una dirección de dominio</string> <string name="this_looks_like_a_domain">Esto parece una dirección de dominio</string>
<string name="add_anway">Añadir de todas formas</string> <string name="add_anway">Añadir de todas formas</string>
<string name="this_looks_like_channel">Esto parece una dirección de un canal</string> <string name="this_looks_like_channel">Esto parece una dirección de un canal</string>
<string name="share_backup_files">Compartir ficheros de respaldo</string>
<string name="conversations_backup">Respaldo de Conversations</string>
<string name="event">Evento</string>
<string name="open_backup">Abrir respaldo</string>
<string name="not_a_backup_file">El fichero seleccionado no es un respaldo de Conversations</string>
<string name="account_already_setup">Esta cuenta ya fue configurada</string>
<string name="please_enter_password">Por favor ingrese la contraseña para esta cuenta</string>
</resources> </resources>

View File

@ -17,6 +17,8 @@
<string name="action_unblock_contact">Kontaktua desblokeatu</string> <string name="action_unblock_contact">Kontaktua desblokeatu</string>
<string name="action_block_domain">Domeinua blokeatu</string> <string name="action_block_domain">Domeinua blokeatu</string>
<string name="action_unblock_domain">Domeinua desblokeatu</string> <string name="action_unblock_domain">Domeinua desblokeatu</string>
<string name="action_block_participant">Parte-hartzailea blokeatu</string>
<string name="action_unblock_participant">Parte-hartzaileari blokeoa kendu</string>
<string name="title_activity_manage_accounts">Kontuak kudeatu</string> <string name="title_activity_manage_accounts">Kontuak kudeatu</string>
<string name="title_activity_settings">Ezarpenak</string> <string name="title_activity_settings">Ezarpenak</string>
<string name="title_activity_sharewith">Elkarrizketa batekin partekatu</string> <string name="title_activity_sharewith">Elkarrizketa batekin partekatu</string>
@ -860,4 +862,11 @@
<string name="this_looks_like_a_domain">Honek domeinu helbide baten itxura dauka</string> <string name="this_looks_like_a_domain">Honek domeinu helbide baten itxura dauka</string>
<string name="add_anway">Gehitu hala ere</string> <string name="add_anway">Gehitu hala ere</string>
<string name="this_looks_like_channel">Honek kanal helbide baten itxura dauka</string> <string name="this_looks_like_channel">Honek kanal helbide baten itxura dauka</string>
<string name="share_backup_files">Babes-kopia fitxategiak partekatu</string>
<string name="conversations_backup">Conversations babes-kopia</string>
<string name="event">Gertaera</string>
<string name="open_backup">Babes-kopia ireki</string>
<string name="not_a_backup_file">Hautatu duzun fitxategia ez da Conversations babes-kopia bat</string>
<string name="account_already_setup">Kontu hau konfiguratuta dago jada</string>
<string name="please_enter_password">Mesedez idatzi ezazu kontu honetarako pasahitza</string>
</resources> </resources>

View File

@ -864,4 +864,12 @@
<string name="this_looks_like_a_domain">Esto semella un enderezo de dominio</string> <string name="this_looks_like_a_domain">Esto semella un enderezo de dominio</string>
<string name="add_anway">Engadir igualmente</string> <string name="add_anway">Engadir igualmente</string>
<string name="this_looks_like_channel">Esto semella o enderezo de un canal</string> <string name="this_looks_like_channel">Esto semella o enderezo de un canal</string>
<string name="share_backup_files">Compartir ficheiros de respaldo</string>
<string name="conversations_backup">Respaldar Conversations</string>
<string name="event">Evento</string>
<string name="open_backup">Abrir respaldo</string>
<string name="not_a_backup_file">O ficheiro seleccionado non é un ficheiro de respaldo Conversations</string>
<string name="account_already_setup">Esta conta xa foi configurada</string>
<string name="please_enter_password">Introduza o contrasinal de esta conta</string>
<string name="unable_to_perform_this_action">Non se puido completar a acción</string>
</resources> </resources>

View File

@ -17,6 +17,8 @@
<string name="action_unblock_contact">Tiltás feloldása</string> <string name="action_unblock_contact">Tiltás feloldása</string>
<string name="action_block_domain">Tartomány tiltása</string> <string name="action_block_domain">Tartomány tiltása</string>
<string name="action_unblock_domain">Tartomány feloldása</string> <string name="action_unblock_domain">Tartomány feloldása</string>
<string name="action_block_participant">Résztvevő letiltása</string>
<string name="action_unblock_participant">Résztvevő feloldása</string>
<string name="title_activity_manage_accounts">Fiókok kezelése</string> <string name="title_activity_manage_accounts">Fiókok kezelése</string>
<string name="title_activity_settings">Beállítások</string> <string name="title_activity_settings">Beállítások</string>
<string name="title_activity_sharewith">Megosztás Conversation-nel</string> <string name="title_activity_sharewith">Megosztás Conversation-nel</string>
@ -862,4 +864,11 @@
<string name="this_looks_like_a_domain">Ez egy domain címnek tűnik</string> <string name="this_looks_like_a_domain">Ez egy domain címnek tűnik</string>
<string name="add_anway">Akkor is adja hozzá</string> <string name="add_anway">Akkor is adja hozzá</string>
<string name="this_looks_like_channel">Ez egy csatorna címnek tűnik</string> <string name="this_looks_like_channel">Ez egy csatorna címnek tűnik</string>
<string name="share_backup_files">Biztonsági mentések megosztása</string>
<string name="conversations_backup">Conversations biztonsági mentés</string>
<string name="event">Esemény</string>
<string name="open_backup">Biztonsági mentés megnyitása</string>
<string name="not_a_backup_file">A kiválasztott fájl nem a Conversations biztonsági mentése</string>
<string name="account_already_setup">Ez a fiók már be lett állítva</string>
<string name="please_enter_password">Kérem, adja meg a fiókhoz tartozó jelszót</string>
</resources> </resources>

View File

@ -17,6 +17,8 @@
<string name="action_unblock_contact">Sblocca contatto</string> <string name="action_unblock_contact">Sblocca contatto</string>
<string name="action_block_domain">Blocca dominio</string> <string name="action_block_domain">Blocca dominio</string>
<string name="action_unblock_domain">Sblocca dominio</string> <string name="action_unblock_domain">Sblocca dominio</string>
<string name="action_block_participant">Blocca partecipante</string>
<string name="action_unblock_participant">Sblocca partecipante</string>
<string name="title_activity_manage_accounts">Gestisci account</string> <string name="title_activity_manage_accounts">Gestisci account</string>
<string name="title_activity_settings">Impostazioni</string> <string name="title_activity_settings">Impostazioni</string>
<string name="title_activity_sharewith">Condividi con Conversation</string> <string name="title_activity_sharewith">Condividi con Conversation</string>

View File

@ -17,6 +17,8 @@
<string name="action_unblock_contact">Contact deblokkeren</string> <string name="action_unblock_contact">Contact deblokkeren</string>
<string name="action_block_domain">Domein blokkeren</string> <string name="action_block_domain">Domein blokkeren</string>
<string name="action_unblock_domain">Domein deblokkeren</string> <string name="action_unblock_domain">Domein deblokkeren</string>
<string name="action_block_participant">Deelnemer blokkeren</string>
<string name="action_unblock_participant">Deelnemer deblokkeren</string>
<string name="title_activity_manage_accounts">Accounts beheren</string> <string name="title_activity_manage_accounts">Accounts beheren</string>
<string name="title_activity_settings">Instellingen</string> <string name="title_activity_settings">Instellingen</string>
<string name="title_activity_sharewith">Delen in gesprek</string> <string name="title_activity_sharewith">Delen in gesprek</string>
@ -861,4 +863,12 @@
<string name="this_looks_like_a_domain">Dit lijkt op een domeinadres</string> <string name="this_looks_like_a_domain">Dit lijkt op een domeinadres</string>
<string name="add_anway">Tóch toevoegen</string> <string name="add_anway">Tóch toevoegen</string>
<string name="this_looks_like_channel">Dit lijkt op een kanaaladres</string> <string name="this_looks_like_channel">Dit lijkt op een kanaaladres</string>
<string name="share_backup_files">Back-upbestanden delen</string>
<string name="conversations_backup">Back-up van Conversations</string>
<string name="event">Gebeurtenis</string>
<string name="open_backup">Back-up openen</string>
<string name="not_a_backup_file">Het geselecteerde bestand is geen Conversations-back-upbestand</string>
<string name="account_already_setup">Deze account is al ingesteld</string>
<string name="please_enter_password">Voer het wachtwoord voor deze account in</string>
<string name="unable_to_perform_this_action">Kan deze actie niet uitvoeren</string>
</resources> </resources>

View File

@ -881,4 +881,12 @@ Administrator twojego serwera będzie mógł czytać twoje wiadomości, ale moż
<string name="this_looks_like_a_domain">To wygląda jak nazwa domeny</string> <string name="this_looks_like_a_domain">To wygląda jak nazwa domeny</string>
<string name="add_anway">Dodaj i tak</string> <string name="add_anway">Dodaj i tak</string>
<string name="this_looks_like_channel">To wygląda jak adres kanału</string> <string name="this_looks_like_channel">To wygląda jak adres kanału</string>
<string name="share_backup_files">Udostępnij pliki kopii zapasowych</string>
<string name="conversations_backup">Kopia zapasowa Conversations</string>
<string name="event">Zdarzenie</string>
<string name="open_backup">Otwórz kopię zapasową</string>
<string name="not_a_backup_file">Plik który otworzyłeś nie jest plikiem kopii zapasowej Conversations</string>
<string name="account_already_setup">To konto zostało już ustawione</string>
<string name="please_enter_password">Proszę podać hasło dla tego konta</string>
<string name="unable_to_perform_this_action">Nie można wykonać tej akcji</string>
</resources> </resources>

View File

@ -873,4 +873,12 @@ sau chiar pierderea mesajelor.\nÎn continuare veți fi rugați să dezactivați
<string name="this_looks_like_a_domain">Aceasta pare să fie o adresă de domeniu</string> <string name="this_looks_like_a_domain">Aceasta pare să fie o adresă de domeniu</string>
<string name="add_anway">Adaugă oricum</string> <string name="add_anway">Adaugă oricum</string>
<string name="this_looks_like_channel">Aceasta pare o adresă de canal</string> <string name="this_looks_like_channel">Aceasta pare o adresă de canal</string>
<string name="share_backup_files">Partajează fișierele copiei de siguranță</string>
<string name="conversations_backup">Copie de siguranță Conversations</string>
<string name="event">Eveniment</string>
<string name="open_backup">Deschide o copie de siguranță</string>
<string name="not_a_backup_file">Fișierul selectat nu este o copie de siguranța Conversations</string>
<string name="account_already_setup">Acest cont a fost deja configurat</string>
<string name="please_enter_password">Va rugăm să introduceți parola pentru acest cont</string>
<string name="unable_to_perform_this_action">Nu se poate realiza această acțiune</string>
</resources> </resources>

View File

@ -873,4 +873,5 @@
<string name="not_a_backup_file">The file you selected is not a Conversations backup file</string> <string name="not_a_backup_file">The file you selected is not a Conversations backup file</string>
<string name="account_already_setup">This account has already been setup</string> <string name="account_already_setup">This account has already been setup</string>
<string name="please_enter_password">Please enter the password for this account</string> <string name="please_enter_password">Please enter the password for this account</string>
<string name="unable_to_perform_this_action">Unable to perform this action</string>
</resources> </resources>

View File

@ -147,7 +147,14 @@ public class PushManagementService {
} }
private void retrieveFcmInstanceToken(final OnGcmInstanceTokenRetrieved instanceTokenRetrieved) { private void retrieveFcmInstanceToken(final OnGcmInstanceTokenRetrieved instanceTokenRetrieved) {
FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(task -> { final FirebaseInstanceId firebaseInstanceId;
try {
firebaseInstanceId = FirebaseInstanceId.getInstance();
} catch (IllegalStateException e) {
Log.d(Config.LOGTAG, "unable to get firebase instance token ",e);
return;
}
firebaseInstanceId.getInstanceId().addOnCompleteListener(task -> {
if (!task.isSuccessful()) { if (!task.isSuccessful()) {
Log.d(Config.LOGTAG, "unable to get Firebase instance token", task.getException()); Log.d(Config.LOGTAG, "unable to get Firebase instance token", task.getException());
} }

View File

@ -8,13 +8,17 @@ import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.net.ConnectException; import java.net.ConnectException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL; import java.net.URL;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -29,10 +33,11 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLPeerUnverifiedException;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.android.JabberIdContact;
import eu.siacs.conversations.android.PhoneNumberContact; import eu.siacs.conversations.android.PhoneNumberContact;
import eu.siacs.conversations.crypto.sasl.Plain; import eu.siacs.conversations.crypto.sasl.Plain;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
@ -44,8 +49,6 @@ import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
import eu.siacs.conversations.utils.SerialSingleThreadExecutor; import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
import eu.siacs.conversations.xmpp.XmppConnection;
import eu.siacs.conversations.xmpp.stanzas.IqPacket; import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import io.michaelrocks.libphonenumber.android.Phonenumber; import io.michaelrocks.libphonenumber.android.Phonenumber;
import rocks.xmpp.addr.Jid; import rocks.xmpp.addr.Jid;
@ -58,6 +61,9 @@ public class QuickConversationsService extends AbstractQuickConversationsService
public static final int API_ERROR_CONNECT = -3; public static final int API_ERROR_CONNECT = -3;
public static final int API_ERROR_SSL_HANDSHAKE = -4; public static final int API_ERROR_SSL_HANDSHAKE = -4;
public static final int API_ERROR_AIRPLANE_MODE = -5; public static final int API_ERROR_AIRPLANE_MODE = -5;
public static final int API_ERROR_SSL_CERTIFICATE = -6;
public static final int API_ERROR_SSL_GENERAL = -7;
public static final int API_ERROR_TIMEOUT = -8;
private static final String API_DOMAIN = "api." + Config.QUICKSY_DOMAIN; private static final String API_DOMAIN = "api." + Config.QUICKSY_DOMAIN;
@ -135,7 +141,7 @@ public class QuickConversationsService extends AbstractQuickConversationsService
} }
} }
} }
} catch (Exception e) { } catch (IOException e) {
final int code = getApiErrorCode(e); final int code = getApiErrorCode(e);
synchronized (mOnVerificationRequested) { synchronized (mOnVerificationRequested) {
for (OnVerificationRequested onVerificationRequested : mOnVerificationRequested) { for (OnVerificationRequested onVerificationRequested : mOnVerificationRequested) {
@ -232,7 +238,7 @@ public class QuickConversationsService extends AbstractQuickConversationsService
} }
} }
} }
} catch (Exception e) { } catch (IOException e) {
final int code = getApiErrorCode(e); final int code = getApiErrorCode(e);
synchronized (mOnVerification) { synchronized (mOnVerification) {
for (OnVerification onVerification : mOnVerification) { for (OnVerification onVerification : mOnVerification) {
@ -265,7 +271,7 @@ public class QuickConversationsService extends AbstractQuickConversationsService
} }
private int getApiErrorCode(Exception e) { private int getApiErrorCode(final Exception e) {
if (!service.hasInternetConnection()) { if (!service.hasInternetConnection()) {
return API_ERROR_AIRPLANE_MODE; return API_ERROR_AIRPLANE_MODE;
} else if (e instanceof UnknownHostException) { } else if (e instanceof UnknownHostException) {
@ -274,6 +280,12 @@ public class QuickConversationsService extends AbstractQuickConversationsService
return API_ERROR_CONNECT; return API_ERROR_CONNECT;
} else if (e instanceof SSLHandshakeException) { } else if (e instanceof SSLHandshakeException) {
return API_ERROR_SSL_HANDSHAKE; return API_ERROR_SSL_HANDSHAKE;
} else if (e instanceof SSLPeerUnverifiedException || e instanceof CertificateException) {
return API_ERROR_SSL_CERTIFICATE;
} else if (e instanceof SSLException || e instanceof GeneralSecurityException) {
return API_ERROR_SSL_GENERAL;
} else if (e instanceof SocketTimeoutException) {
return API_ERROR_TIMEOUT;
} else { } else {
Log.d(Config.LOGTAG, e.getClass().getName()); Log.d(Config.LOGTAG, e.getClass().getName());
return API_ERROR_OTHER; return API_ERROR_OTHER;

View File

@ -33,6 +33,15 @@ public class ApiDialogHelper {
case QuickConversationsService.API_ERROR_UNKNOWN_HOST: case QuickConversationsService.API_ERROR_UNKNOWN_HOST:
res = R.string.unable_to_find_server; res = R.string.unable_to_find_server;
break; break;
case QuickConversationsService.API_ERROR_SSL_CERTIFICATE:
res = R.string.unable_to_verify_server_identity;
break;
case QuickConversationsService.API_ERROR_SSL_GENERAL:
res = R.string.unknown_security_error;
break;
case QuickConversationsService.API_ERROR_TIMEOUT:
res = R.string.timeout_while_connecting_to_server;
break;
case 400: case 400:
res = R.string.invalid_user_input; res = R.string.invalid_user_input;
break; break;

View File

@ -46,7 +46,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:cursorVisible="false" android:cursorVisible="false"
android:inputType="textNoSuggestions"
android:drawableEnd="@drawable/ic_arrow_drop_down_black_18dp" android:drawableEnd="@drawable/ic_arrow_drop_down_black_18dp"
android:drawableRight="@drawable/ic_arrow_drop_down_black_18dp"
android:focusable="false" android:focusable="false"
android:gravity="bottom|center_horizontal" android:gravity="bottom|center_horizontal"
android:longClickable="false" /> android:longClickable="false" />

View File

@ -20,4 +20,4 @@
<string name="foreground_service_channel_description">Тази категория известия се използва за показване на постоянно известие, което показва, че Quicksy работи.</string> <string name="foreground_service_channel_description">Тази категория известия се използва за показване на постоянно известие, което показва, че Quicksy работи.</string>
<string name="set_profile_picture">Профилна снимка за Quicksy</string> <string name="set_profile_picture">Профилна снимка за Quicksy</string>
<string name="not_available_in_your_country">Quicksy не може да се използва във Вашата страна.</string> <string name="not_available_in_your_country">Quicksy не може да се използва във Вашата страна.</string>
</resources> </resources>

View File

@ -20,4 +20,7 @@
<string name="foreground_service_channel_description">Diese Benachrichtigungsart wird verwendet, um eine permanente Benachrichtigung anzuzeigen, die anzeigt, dass Quicksy gerade ausgeführt wird.</string> <string name="foreground_service_channel_description">Diese Benachrichtigungsart wird verwendet, um eine permanente Benachrichtigung anzuzeigen, die anzeigt, dass Quicksy gerade ausgeführt wird.</string>
<string name="set_profile_picture">Quicksy Profilbild</string> <string name="set_profile_picture">Quicksy Profilbild</string>
<string name="not_available_in_your_country">Quicksy ist in deinem Land nicht verfügbar.</string> <string name="not_available_in_your_country">Quicksy ist in deinem Land nicht verfügbar.</string>
<string name="unable_to_verify_server_identity">Die Überprüfung der Serveridentität ist nicht möglich.</string>
<string name="unknown_security_error">Unbekannter Sicherheitsfehler.</string>
<string name="timeout_while_connecting_to_server">Zeitüberschreitung bei der Verbindung zum Server.</string>
</resources> </resources>

View File

@ -20,4 +20,7 @@
<string name="foreground_service_channel_description">Esta categoría de notificación se usa para mostrar una notificación permantente indicando que Quicksy está ejecutándose.</string> <string name="foreground_service_channel_description">Esta categoría de notificación se usa para mostrar una notificación permantente indicando que Quicksy está ejecutándose.</string>
<string name="set_profile_picture">Foto de perfil en Quicksy</string> <string name="set_profile_picture">Foto de perfil en Quicksy</string>
<string name="not_available_in_your_country">Quicksy no está disponible en tu país.</string> <string name="not_available_in_your_country">Quicksy no está disponible en tu país.</string>
<string name="unable_to_verify_server_identity">No se ha podido verificar la identidad del servidor.</string>
<string name="unknown_security_error">Error de seguridad desconocido.</string>
<string name="timeout_while_connecting_to_server">Se ha superado el tiempo máximo de espera conectando al servidor.</string>
</resources> </resources>

View File

@ -20,4 +20,7 @@
<string name="foreground_service_channel_description">Esta categoría de notificacións utilízase para mostrar unha notificación permanente que indica que Quicksy está funcionando.</string> <string name="foreground_service_channel_description">Esta categoría de notificacións utilízase para mostrar unha notificación permanente que indica que Quicksy está funcionando.</string>
<string name="set_profile_picture">Imaxe de perfil Quicksy</string> <string name="set_profile_picture">Imaxe de perfil Quicksy</string>
<string name="not_available_in_your_country">Quicksy non está dispoñible no seu país.</string> <string name="not_available_in_your_country">Quicksy non está dispoñible no seu país.</string>
<string name="unable_to_verify_server_identity">Non se puido validar a identidade do servidor.</string>
<string name="unknown_security_error">Fallo de seguridade descoñecido.</string>
<string name="timeout_while_connecting_to_server">Caducou a conexión mentras conectaba co servidor.</string>
</resources> </resources>

View File

@ -19,4 +19,8 @@
<string name="no_microphone_permission">A Quicksy-nek hozzáférésre lenne szüksége a mikrofonhoz</string> <string name="no_microphone_permission">A Quicksy-nek hozzáférésre lenne szüksége a mikrofonhoz</string>
<string name="foreground_service_channel_description">Ez az értesítési kategória állandó értesítést jelenít meg arról, hogy a Quicksy fut.</string> <string name="foreground_service_channel_description">Ez az értesítési kategória állandó értesítést jelenít meg arról, hogy a Quicksy fut.</string>
<string name="set_profile_picture">Quicksy profilkép</string> <string name="set_profile_picture">Quicksy profilkép</string>
</resources> <string name="not_available_in_your_country">A Quicksy nem érhető el az Ön országában.</string>
<string name="unable_to_verify_server_identity">Nem sikerült ellenőrizni a szerver azonosságát.</string>
<string name="unknown_security_error">Ismeretlen biztonsági hiba.</string>
<string name="timeout_while_connecting_to_server">Időtúllépés történt a szerverhez való csatlakozás közben.</string>
</resources>

View File

@ -19,4 +19,5 @@
<string name="no_microphone_permission">Quicksy ha bisogno di accedere al microfono</string> <string name="no_microphone_permission">Quicksy ha bisogno di accedere al microfono</string>
<string name="foreground_service_channel_description">Questa categoria di notifiche è usata per mostrare una notifica permanente per indicare che Quicksy è in esecuzione.</string> <string name="foreground_service_channel_description">Questa categoria di notifiche è usata per mostrare una notifica permanente per indicare che Quicksy è in esecuzione.</string>
<string name="set_profile_picture">Immagine profilo di Quicksy</string> <string name="set_profile_picture">Immagine profilo di Quicksy</string>
<string name="not_available_in_your_country">Quicksy non è disponibile nella tua nazione.</string>
</resources> </resources>

View File

@ -19,4 +19,8 @@
<string name="no_microphone_permission">Quicksy heeft toegang nodig tot de microfoon</string> <string name="no_microphone_permission">Quicksy heeft toegang nodig tot de microfoon</string>
<string name="foreground_service_channel_description">Deze meldingscategorie wordt gebruikt om een permanente melding weer te geven dat Quicksy wordt uitgevoerd.</string> <string name="foreground_service_channel_description">Deze meldingscategorie wordt gebruikt om een permanente melding weer te geven dat Quicksy wordt uitgevoerd.</string>
<string name="set_profile_picture">Quicksy-profielafbeelding</string> <string name="set_profile_picture">Quicksy-profielafbeelding</string>
</resources> <string name="not_available_in_your_country">Quicksy is niet beschikbaar in je land.</string>
<string name="unable_to_verify_server_identity">Kan serveridentiteit niet verifiëren.</string>
<string name="unknown_security_error">Onbekende beveiligingsfout.</string>
<string name="timeout_while_connecting_to_server">Time-out bij verbinden met server.</string>
</resources>

View File

@ -20,4 +20,7 @@
<string name="foreground_service_channel_description">Ta kategoria powiadomień jest używana do wyświetlania ciągłego powiadomienia o tym, że Quicksy działa.</string> <string name="foreground_service_channel_description">Ta kategoria powiadomień jest używana do wyświetlania ciągłego powiadomienia o tym, że Quicksy działa.</string>
<string name="set_profile_picture">Obrazek profilowy Quicksy</string> <string name="set_profile_picture">Obrazek profilowy Quicksy</string>
<string name="not_available_in_your_country">Quicksy nie jest dostępne w twoim kraju</string> <string name="not_available_in_your_country">Quicksy nie jest dostępne w twoim kraju</string>
<string name="unable_to_verify_server_identity">Nie udało się sprawdzić tożsamości serwera.</string>
<string name="unknown_security_error">Nieznany błąd bezpieczeństwa.</string>
<string name="timeout_while_connecting_to_server">Błąd czasu oczekiwania na połączenie z serwerem.</string>
</resources> </resources>

View File

@ -22,4 +22,7 @@ sau chiar pierderea mesajelor.\nÎn continuare veți fi rugați să dezactivați
<string name="foreground_service_channel_description">Această categorie de notificări este folosită pentru a arăta o notificare permanentă ce indică rularea Quicksy</string> <string name="foreground_service_channel_description">Această categorie de notificări este folosită pentru a arăta o notificare permanentă ce indică rularea Quicksy</string>
<string name="set_profile_picture">Poză profil Quicksy</string> <string name="set_profile_picture">Poză profil Quicksy</string>
<string name="not_available_in_your_country">Quicksy nu este disponibilă în țara dumneavoastră.</string> <string name="not_available_in_your_country">Quicksy nu este disponibilă în țara dumneavoastră.</string>
<string name="unable_to_verify_server_identity">Nu s-a putut verifica identitatea serverului.</string>
<string name="unknown_security_error">Eroare de securitate necunoscută.</string>
<string name="timeout_while_connecting_to_server">A expirat timpul de așteptare conexiune server.</string>
</resources> </resources>

View File

@ -20,4 +20,7 @@
<string name="foreground_service_channel_description">This notification category is used to display a permanent notification indicating that Quicksy is running.</string> <string name="foreground_service_channel_description">This notification category is used to display a permanent notification indicating that Quicksy is running.</string>
<string name="set_profile_picture">Quicksy profile picture</string> <string name="set_profile_picture">Quicksy profile picture</string>
<string name="not_available_in_your_country">Quicksy is not available in your country.</string> <string name="not_available_in_your_country">Quicksy is not available in your country.</string>
<string name="unable_to_verify_server_identity">Unable to verify server identity.</string>
<string name="unknown_security_error">Unknown security error.</string>
<string name="timeout_while_connecting_to_server">Timeout while connecting to server.</string>
</resources> </resources>