diff options
Diffstat (limited to 'src/main/java/de/pixart/messenger/utils')
12 files changed, 223 insertions, 38 deletions
diff --git a/src/main/java/de/pixart/messenger/utils/BackupFileHeader.java b/src/main/java/de/pixart/messenger/utils/BackupFileHeader.java new file mode 100644 index 000000000..19ad9bff9 --- /dev/null +++ b/src/main/java/de/pixart/messenger/utils/BackupFileHeader.java @@ -0,0 +1,84 @@ +package de.pixart.messenger.utils; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import rocks.xmpp.addr.Jid; + +public class BackupFileHeader { + + private static final int VERSION = 1; + + private String app; + private Jid jid; + private long timestamp; + private byte[] iv; + private byte[] salt; + + + @Override + public String toString() { + return "BackupFileHeader{" + + "app='" + app + '\'' + + ", jid=" + jid + + ", timestamp=" + timestamp + + ", iv=" + CryptoHelper.bytesToHex(iv) + + ", salt=" + CryptoHelper.bytesToHex(salt) + + '}'; + } + + public BackupFileHeader(String app, Jid jid, long timestamp, byte[] iv, byte[] salt) { + this.app = app; + this.jid = jid; + this.timestamp = timestamp; + this.iv = iv; + this.salt = salt; + } + + public void write(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeInt(VERSION); + dataOutputStream.writeUTF(app); + dataOutputStream.writeUTF(jid.asBareJid().toEscapedString()); + dataOutputStream.writeLong(timestamp); + dataOutputStream.write(iv); + dataOutputStream.write(salt); + } + + public static BackupFileHeader read(DataInputStream inputStream) throws IOException { + final int version = inputStream.readInt(); + if (version > VERSION) { + throw new IllegalArgumentException("Backup File version was " + version + " but app only supports up to version " + VERSION); + } + String app = inputStream.readUTF(); + String jid = inputStream.readUTF(); + long timestamp = inputStream.readLong(); + byte[] iv = new byte[12]; + inputStream.readFully(iv); + byte[] salt = new byte[16]; + inputStream.readFully(salt); + + return new BackupFileHeader(app, Jid.of(jid), timestamp, iv, salt); + + } + + public byte[] getSalt() { + return salt; + } + + public byte[] getIv() { + return iv; + } + + public Jid getJid() { + return jid; + } + + public String getApp() { + return app; + } + + public long getTimestamp() { + return timestamp; + } +}
\ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/utils/Compatibility.java b/src/main/java/de/pixart/messenger/utils/Compatibility.java index 38f9db378..c8922e18b 100644 --- a/src/main/java/de/pixart/messenger/utils/Compatibility.java +++ b/src/main/java/de/pixart/messenger/utils/Compatibility.java @@ -1,6 +1,7 @@ package de.pixart.messenger.utils; import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -11,15 +12,19 @@ import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.support.annotation.BoolRes; import android.support.v4.content.ContextCompat; +import android.util.Log; import java.util.Arrays; import java.util.Collections; import java.util.List; +import de.pixart.messenger.Config; import de.pixart.messenger.R; import de.pixart.messenger.ui.SettingsActivity; import de.pixart.messenger.ui.SettingsFragment; +import static de.pixart.messenger.services.EventReceiver.EXTRA_NEEDS_FOREGROUND_SERVICE; + public class Compatibility { private static final List<String> UNUSED_SETTINGS_POST_TWENTYSIX = Arrays.asList( SettingsActivity.SHOW_FOREGROUND_SERVICE, @@ -102,4 +107,17 @@ public class Compatibility { } } } + + public static void startService(Context context, Intent intent) { + try { + if (Compatibility.runsAndTargetsTwentySix(context)) { + intent.putExtra(EXTRA_NEEDS_FOREGROUND_SERVICE, true); + ContextCompat.startForegroundService(context, intent); + } else { + context.startService(intent); + } + } catch (RuntimeException e) { + Log.d(Config.LOGTAG, context.getClass().getSimpleName() + " was unable to start service"); + } + } }
\ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/utils/ConversationsFileObserver.java b/src/main/java/de/pixart/messenger/utils/ConversationsFileObserver.java index 73d5589e4..5e2948b5b 100644 --- a/src/main/java/de/pixart/messenger/utils/ConversationsFileObserver.java +++ b/src/main/java/de/pixart/messenger/utils/ConversationsFileObserver.java @@ -8,6 +8,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Stack; +import java.util.concurrent.atomic.AtomicBoolean; import de.pixart.messenger.Config; @@ -21,16 +22,26 @@ public abstract class ConversationsFileObserver { private final String path; private final List<SingleFileObserver> mObservers = new ArrayList<>(); + private final AtomicBoolean shouldStop = new AtomicBoolean(true); protected ConversationsFileObserver(String path) { this.path = path; } - public synchronized void startWatching() { + public void startWatching() { + shouldStop.set(false); + startWatchingInternal(); + } + + private synchronized void startWatchingInternal() { Stack<String> stack = new Stack<>(); stack.push(path); while (!stack.empty()) { + if (shouldStop.get()) { + Log.d(Config.LOGTAG, "file observer received command to stop"); + return; + } String parent = stack.pop(); mObservers.add(new SingleFileObserver(parent, FileObserver.DELETE | FileObserver.MOVED_FROM)); final File path = new File(parent); @@ -44,6 +55,10 @@ public abstract class ConversationsFileObserver { continue; } for (File file : files) { + if (shouldStop.get()) { + Log.d(Config.LOGTAG, "file observer received command to stop"); + return; + } if (file.isDirectory() && file.getName().charAt(0) != '.') { final String currentPath = file.getAbsolutePath(); if (depth(file) <= 8 && !stack.contains(currentPath) && !observing(currentPath)) { @@ -74,7 +89,12 @@ public abstract class ConversationsFileObserver { return false; } - public synchronized void stopWatching() { + public void stopWatching() { + shouldStop.set(true); + stopWatchingInternal(); + } + + private synchronized void stopWatchingInternal() { for (FileObserver observer : mObservers) { observer.stopWatching(); } diff --git a/src/main/java/de/pixart/messenger/utils/CryptoHelper.java b/src/main/java/de/pixart/messenger/utils/CryptoHelper.java index 2104349d8..5d1e7980c 100644 --- a/src/main/java/de/pixart/messenger/utils/CryptoHelper.java +++ b/src/main/java/de/pixart/messenger/utils/CryptoHelper.java @@ -63,7 +63,8 @@ public final class CryptoHelper { } public static String pronounceable(SecureRandom random) { - char[] output = new char[random.nextInt(4) * 2 + 5]; + final int rand = random.nextInt(4); + char[] output = new char[rand * 2 + (5 - rand)]; boolean vowel = random.nextBoolean(); for (int i = 0; i < output.length; ++i) { output[i] = vowel ? VOWELS[random.nextInt(VOWELS.length)] : CONSONANTS[random.nextInt(CONSONANTS.length)]; diff --git a/src/main/java/de/pixart/messenger/utils/ExceptionHelper.java b/src/main/java/de/pixart/messenger/utils/ExceptionHelper.java index 18238ae60..428aa616e 100644 --- a/src/main/java/de/pixart/messenger/utils/ExceptionHelper.java +++ b/src/main/java/de/pixart/messenger/utils/ExceptionHelper.java @@ -17,7 +17,6 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.List; import java.util.Locale; import de.pixart.messenger.Config; @@ -27,7 +26,6 @@ import de.pixart.messenger.entities.Conversation; import de.pixart.messenger.entities.Message; import de.pixart.messenger.services.XmppConnectionService; import de.pixart.messenger.ui.XmppActivity; -import rocks.xmpp.addr.Jid; public class ExceptionHelper { private static final String FILENAME = "stacktrace.txt"; diff --git a/src/main/java/de/pixart/messenger/utils/GeoHelper.java b/src/main/java/de/pixart/messenger/utils/GeoHelper.java index 209fd75db..d978c89e0 100644 --- a/src/main/java/de/pixart/messenger/utils/GeoHelper.java +++ b/src/main/java/de/pixart/messenger/utils/GeoHelper.java @@ -4,6 +4,8 @@ import android.content.Context; import android.content.Intent; import android.net.Uri; +import org.osmdroid.util.GeoPoint; + import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; @@ -11,8 +13,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import de.pixart.messenger.Config; +import de.pixart.messenger.R; import de.pixart.messenger.entities.Contact; -import de.pixart.messenger.entities.Conversation; import de.pixart.messenger.entities.Conversational; import de.pixart.messenger.entities.Message; import de.pixart.messenger.ui.ShowLocationActivity; @@ -43,41 +45,43 @@ public class GeoHelper { return "https://xmpp.pix-art.de/staticmap/staticmap.php?center=" + latitude + "," + longitude + "&size=500x500&markers=" + latitude + "," + longitude + "&zoom= " + Config.DEFAULT_ZOOM; } - public static ArrayList<Intent> createGeoIntentsFromMessage(Message message, Context context) { - final ArrayList<Intent> intents = new ArrayList<>(); - Matcher matcher = GEO_URI.matcher(message.getBody()); + private static GeoPoint parseGeoPoint(String body) throws IllegalArgumentException { + Matcher matcher = GEO_URI.matcher(body); + ; if (!matcher.matches()) { - return intents; + throw new IllegalArgumentException("Invalid geo uri"); } double latitude; double longitude; try { latitude = Double.parseDouble(matcher.group(1)); if (latitude > 90.0 || latitude < -90.0) { - return intents; + throw new IllegalArgumentException("Invalid geo uri"); } longitude = Double.parseDouble(matcher.group(2)); if (longitude > 180.0 || longitude < -180.0) { - return intents; + throw new IllegalArgumentException("Invalid geo uri"); } - } catch (NumberFormatException nfe) { + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid geo uri", e); + } + return new GeoPoint(latitude, longitude); + } + + public static ArrayList<Intent> createGeoIntentsFromMessage(Context context, Message message) { + final ArrayList<Intent> intents = new ArrayList<>(); + final GeoPoint geoPoint; + try { + geoPoint = parseGeoPoint(message.getBody()); + } catch (IllegalArgumentException e) { return intents; } final Conversational conversation = message.getConversation(); - String label; - if (conversation instanceof Conversation && conversation.getMode() == Conversation.MODE_SINGLE && message.getStatus() == Message.STATUS_RECEIVED) { - try { - label = "(" + URLEncoder.encode(((Conversation) conversation).getName().toString(), "UTF-8") + ")"; - } catch (UnsupportedEncodingException e) { - label = ""; - } - } else { - label = ""; - } + final String label = getLabel(context, message); Intent locationPluginIntent = new Intent(context, ShowLocationActivity.class); - locationPluginIntent.putExtra("latitude", latitude); - locationPluginIntent.putExtra("longitude", longitude); + locationPluginIntent.putExtra("latitude", geoPoint.getLatitude()); + locationPluginIntent.putExtra("longitude", geoPoint.getLongitude()); if (message.getStatus() != Message.STATUS_RECEIVED) { locationPluginIntent.putExtra("jid", conversation.getAccount().getJid().toString()); locationPluginIntent.putExtra("name", conversation.getAccount().getJid().getLocal()); @@ -93,8 +97,38 @@ public class GeoHelper { intents.add(locationPluginIntent); Intent geoIntent = new Intent(Intent.ACTION_VIEW); - geoIntent.setData(Uri.parse("geo:" + String.valueOf(latitude) + "," + String.valueOf(longitude) + "?q=" + String.valueOf(latitude) + "," + String.valueOf(longitude) + label)); + geoIntent.setData(Uri.parse("geo:" + String.valueOf(geoPoint.getLatitude()) + "," + String.valueOf(geoPoint.getLongitude()) + "?q=" + String.valueOf(geoPoint.getLatitude()) + "," + String.valueOf(geoPoint.getLongitude()) + label)); intents.add(geoIntent); return intents; } + + public static void view(Context context, Message message) { + final GeoPoint geoPoint = parseGeoPoint(message.getBody()); + final String label = getLabel(context, message); + context.startActivity(geoIntent(geoPoint, label)); + } + + private static Intent geoIntent(GeoPoint geoPoint, String label) { + Intent geoIntent = new Intent(Intent.ACTION_VIEW); + geoIntent.setData(Uri.parse("geo:" + String.valueOf(geoPoint.getLatitude()) + "," + String.valueOf(geoPoint.getLongitude()) + "?q=" + String.valueOf(geoPoint.getLatitude()) + "," + String.valueOf(geoPoint.getLongitude()) + "(" + label + ")")); + return geoIntent; + } + + public static boolean openInOsmAnd(Context context, Message message) { + final GeoPoint geoPoint = parseGeoPoint(message.getBody()); + final String label = getLabel(context, message); + return geoIntent(geoPoint, label).resolveActivity(context.getPackageManager()) != null; + } + + private static String getLabel(Context context, Message message) { + if (message.getStatus() == Message.STATUS_RECEIVED) { + try { + return URLEncoder.encode(UIHelper.getMessageDisplayName(message), "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new AssertionError(e); + } + } else { + return context.getString(R.string.me); + } + } }
\ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/utils/Namespace.java b/src/main/java/de/pixart/messenger/utils/Namespace.java index 83d63cdaa..3a3e32f73 100644 --- a/src/main/java/de/pixart/messenger/utils/Namespace.java +++ b/src/main/java/de/pixart/messenger/utils/Namespace.java @@ -24,4 +24,5 @@ public final class Namespace { public static final String BOOKMARKS_CONVERSION = "urn:xmpp:bookmarks-conversion:0"; public static final String BOOKMARKS = "storage:bookmarks"; public static final String SYNCHRONIZATION = "im.quicksy.synchronization:0"; + public static final String AVATAR_CONVERSION = "urn:xmpp:pep-vcard-conversion:0"; } diff --git a/src/main/java/de/pixart/messenger/utils/PermissionUtils.java b/src/main/java/de/pixart/messenger/utils/PermissionUtils.java new file mode 100644 index 000000000..b21ca8869 --- /dev/null +++ b/src/main/java/de/pixart/messenger/utils/PermissionUtils.java @@ -0,0 +1,34 @@ +package de.pixart.messenger.utils; + +import android.Manifest; +import android.content.pm.PackageManager; + +public class PermissionUtils { + + public static boolean allGranted(int[] grantResults) { + for (int grantResult : grantResults) { + if (grantResult != PackageManager.PERMISSION_GRANTED) { + return false; + } + } + return true; + } + + public static boolean writeGranted(int[] grantResults, String[] permission) { + for (int i = 0; i < grantResults.length; ++i) { + if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permission[i])) { + return grantResults[i] == PackageManager.PERMISSION_GRANTED; + } + } + return false; + } + + public static String getFirstDenied(int[] grantResults, String[] permissions) { + for (int i = 0; i < grantResults.length; ++i) { + if (grantResults[i] == PackageManager.PERMISSION_DENIED) { + return permissions[i]; + } + } + return null; + } +}
\ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/utils/PhoneHelper.java b/src/main/java/de/pixart/messenger/utils/PhoneHelper.java index 327ae1904..86a9bed1a 100644 --- a/src/main/java/de/pixart/messenger/utils/PhoneHelper.java +++ b/src/main/java/de/pixart/messenger/utils/PhoneHelper.java @@ -3,20 +3,13 @@ package de.pixart.messenger.utils; import android.Manifest; import android.annotation.SuppressLint; import android.content.Context; -import android.content.CursorLoader; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.os.Build; -import android.os.Bundle; -import android.provider.ContactsContract; import android.provider.ContactsContract.Profile; import android.provider.Settings; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.RejectedExecutionException; - public class PhoneHelper { @SuppressLint("HardwareIds") diff --git a/src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java b/src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java index 9846146a8..dc2f2bc09 100644 --- a/src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java +++ b/src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java @@ -1,6 +1,5 @@ package de.pixart.messenger.utils; -import android.os.Looper; import android.util.Log; import java.util.ArrayDeque; diff --git a/src/main/java/de/pixart/messenger/utils/UIHelper.java b/src/main/java/de/pixart/messenger/utils/UIHelper.java index 03af31e23..ea1878557 100644 --- a/src/main/java/de/pixart/messenger/utils/UIHelper.java +++ b/src/main/java/de/pixart/messenger/utils/UIHelper.java @@ -263,8 +263,6 @@ public class UIHelper { case Transferable.STATUS_OFFER_CHECK_FILESIZE: return new Pair<>(context.getString(R.string.x_file_offered_for_download, getFileDescriptionString(context, message)), true); - case Transferable.STATUS_DELETED: - return new Pair<>(context.getString(R.string.file_deleted), true); case Transferable.STATUS_FAILED: return new Pair<>(context.getString(R.string.file_transmission_failed), true); case Transferable.STATUS_UPLOADING: @@ -278,6 +276,8 @@ public class UIHelper { default: return new Pair<>("", false); } + } else if (message.isFileOrImage() && message.isFileDeleted()) { + return new Pair<>(context.getString(R.string.file_deleted), true); } else if (message.getEncryption() == Message.ENCRYPTION_PGP) { return new Pair<>(context.getString(R.string.pgp_message), true); } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { @@ -286,7 +286,7 @@ public class UIHelper { return new Pair<>(context.getString(R.string.not_encrypted_for_this_device), true); } else if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL_FAILED) { return new Pair<>(context.getString(R.string.omemo_decryption_failed), true); - } else if (message.getType() == Message.TYPE_FILE || message.getType() == Message.TYPE_IMAGE) { + } else if (message.isFileOrImage()) { return new Pair<>(getFileDescriptionString(context, message), true); } else { final String body = MessageUtils.filterLtrRtl(message.getBody()); @@ -307,6 +307,9 @@ public class UIHelper { SpannableStringBuilder builder = new SpannableStringBuilder(); for (CharSequence l : CharSequenceUtils.split(styledBody, '\n')) { if (l.length() > 0) { + if (l.toString().equals("```")) { + continue; + } char first = l.charAt(0); if ((first != '>' || !isPositionFollowedByQuoteableCharacter(l,0)) && first != '\u00bb') { CharSequence line = CharSequenceUtils.trim(l); diff --git a/src/main/java/de/pixart/messenger/utils/XmppUri.java b/src/main/java/de/pixart/messenger/utils/XmppUri.java index 9c0b3e666..1ee90aa84 100644 --- a/src/main/java/de/pixart/messenger/utils/XmppUri.java +++ b/src/main/java/de/pixart/messenger/utils/XmppUri.java @@ -171,7 +171,7 @@ public class XmppUri { private boolean hasAction(String query, String action) { for(String pair : query == null ? new String[0] : query.split(";")) { final String[] parts = pair.split("=",2); - if (parts.length == 1 && parts[0].equals(action)) { + if (parts.length == 1 && parts[0].toLowerCase(Locale.US).startsWith(action)) { return true; } } |