aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/OtrEngine.java2
-rw-r--r--src/main/java/eu/siacs/conversations/generator/MessageGenerator.java1
-rw-r--r--src/main/java/eu/siacs/conversations/parser/MessageParser.java40
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/FileBackend.java138
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java28
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationActivity.java8
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationFragment.java28
-rw-r--r--src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java2
-rw-r--r--src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java3
-rw-r--r--src/main/java/eu/siacs/conversations/utils/CryptoHelper.java3
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java75
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java3
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java17
13 files changed, 203 insertions, 145 deletions
diff --git a/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java b/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java
index 263f6089..0dc7c37e 100644
--- a/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java
+++ b/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java
@@ -182,7 +182,7 @@ public class OtrEngine extends OtrCryptoEngineImpl implements OtrEngineHost {
packet.setBody(body);
packet.addChild("private", "urn:xmpp:carbons:2");
packet.addChild("no-copy", "urn:xmpp:hints");
- packet.addChild("no-store", "urn:xmpp:hints");
+ packet.addChild("no-permanent-store", "urn:xmpp:hints");
try {
Jid jid = Jid.fromSessionID(session);
diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
index a60c5613..474a3e1d 100644
--- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
+++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
@@ -71,6 +71,7 @@ public class MessageGenerator extends AbstractGenerator {
MessagePacket packet = preparePacket(message, addDelay);
packet.addChild("private", "urn:xmpp:carbons:2");
packet.addChild("no-copy", "urn:xmpp:hints");
+ packet.addChild("no-permanent-store", "urn:xmpp:hints");
try {
packet.setBody(otrSession.transformSending(message.getBody())[0]);
return packet;
diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
index 8ae9b642..76d01468 100644
--- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
@@ -391,15 +391,17 @@ public class MessageParser extends AbstractParser implements
private void parseNonMessage(Element packet, Account account) {
final Jid from = packet.getAttributeAsJid("from");
+ if (account.getJid().equals(from)) {
+ return;
+ }
if (extractChatState(from == null ? null : mXmppConnectionService.find(account,from), packet)) {
mXmppConnectionService.updateConversationUi();
}
- Element invite = extractInvite(packet);
- if (invite != null) {
- Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, from, true);
+ Invite invite = extractInvite(packet);
+ if (invite != null && invite.jid != null) {
+ Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, invite.jid, true);
if (!conversation.getMucOptions().online()) {
- Element password = invite.findChild("password");
- conversation.getMucOptions().setPassword(password == null ? null : password.getContent());
+ conversation.getMucOptions().setPassword(invite.password);
mXmppConnectionService.databaseBackend.updateConversation(conversation);
mXmppConnectionService.joinMuc(conversation);
mXmppConnectionService.updateConversationUi();
@@ -439,16 +441,30 @@ public class MessageParser extends AbstractParser implements
}
}
- private Element extractInvite(Element message) {
- Element x = message.findChild("x","http://jabber.org/protocol/muc#user");
- if (x == null) {
- x = message.findChild("x","jabber:x:conference");
+ private class Invite {
+ Jid jid;
+ String password;
+ Invite(Jid jid, String password) {
+ this.jid = jid;
+ this.password = password;
}
- if (x != null && x.hasChild("invite")) {
- return x;
+ }
+
+ private Invite extractInvite(Element message) {
+ Element x = message.findChild("x","http://jabber.org/protocol/muc#user");
+ if (x != null) {
+ Element invite = x.findChild("invite");
+ if (invite != null) {
+ Element pw = x.findChild("password");
+ return new Invite(message.getAttributeAsJid("from"), pw != null ? pw.getContent(): null);
+ }
} else {
- return null;
+ x = message.findChild("x","jabber:x:conference");
+ if (x != null) {
+ return new Invite(x.getAttributeAsJid("jid"),x.getAttribute("password"));
+ }
}
+ return null;
}
private void parseEvent(final Element event, final Jid from, final Account account) {
diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
index c499d499..cb79b0e9 100644
--- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
@@ -1,6 +1,7 @@
package eu.siacs.conversations.persistance;
import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -42,8 +43,7 @@ public class FileBackend {
private static int IMAGE_SIZE = 1920;
- private SimpleDateFormat imageDateFormat = new SimpleDateFormat(
- "yyyyMMdd_HHmmssSSS", Locale.US);
+ private final SimpleDateFormat imageDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US);
private XmppConnectionService mXmppConnectionService;
@@ -110,9 +110,7 @@ public class FileBackend {
scalledW = size;
scalledH = (int) (h / ((double) w / size));
}
- Bitmap scalledBitmap = Bitmap.createScaledBitmap(originalBitmap,
- scalledW, scalledH, true);
- return scalledBitmap;
+ return Bitmap.createScaledBitmap(originalBitmap, scalledW, scalledH, true);
} else {
return originalBitmap;
}
@@ -148,31 +146,34 @@ public class FileBackend {
}
public DownloadableFile copyFileToPrivateStorage(Message message, Uri uri) throws FileCopyException {
+ Log.d(Config.LOGTAG, "copy " + uri.toString() + " to private storage");
+ String mime = mXmppConnectionService.getContentResolver().getType(uri);
+ String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mime);
+ message.setRelativeFilePath(message.getUuid() + "." + extension);
+ DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message);
+ file.getParentFile().mkdirs();
+ OutputStream os = null;
+ InputStream is = null;
try {
- Log.d(Config.LOGTAG, "copy " + uri.toString() + " to private storage");
- String mime = mXmppConnectionService.getContentResolver().getType(uri);
- String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mime);
- message.setRelativeFilePath(message.getUuid() + "." + extension);
- DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message);
- file.getParentFile().mkdirs();
- file.createNewFile();
- OutputStream os = new FileOutputStream(file);
- InputStream is = mXmppConnectionService.getContentResolver().openInputStream(uri);
+ if (!file.createNewFile()) {
+ throw new FileCopyException(R.string.error_io_exception);
+ }
+ os = new FileOutputStream(file);
+ is = mXmppConnectionService.getContentResolver().openInputStream(uri);
byte[] buffer = new byte[1024];
- int length;
- while ((length = is.read(buffer)) > 0) {
+ int length;
+ while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
- }
+ }
os.flush();
- os.close();
- is.close();
- Log.d(Config.LOGTAG, "output file name " + mXmppConnectionService.getFileBackend().getFile(message));
- return file;
- } catch (FileNotFoundException e) {
- throw new FileCopyException(R.string.error_file_not_found);
} catch (IOException e) {
throw new FileCopyException(R.string.error_io_exception);
+ } finally {
+ close(os);
+ close(is);
}
+ Log.d(Config.LOGTAG, "output file name " + mXmppConnectionService.getFileBackend().getFile(message));
+ return file;
}
public DownloadableFile copyImageToPrivateStorage(Message message, Uri image)
@@ -182,40 +183,41 @@ public class FileBackend {
private DownloadableFile copyImageToPrivateStorage(Message message,
Uri image, int sampleSize) throws FileCopyException {
+ DownloadableFile file = getFile(message);
+ file.getParentFile().mkdirs();
+ InputStream is = null;
+ OutputStream os = null;
try {
- InputStream is = mXmppConnectionService.getContentResolver()
- .openInputStream(image);
- DownloadableFile file = getFile(message);
- file.getParentFile().mkdirs();
- file.createNewFile();
+ if (!file.createNewFile()) {
+ throw new FileCopyException(R.string.error_io_exception);
+ }
+ is = mXmppConnectionService.getContentResolver().openInputStream(image);
+ os = new FileOutputStream(file);
+
Bitmap originalBitmap;
BitmapFactory.Options options = new BitmapFactory.Options();
int inSampleSize = (int) Math.pow(2, sampleSize);
- Log.d(Config.LOGTAG, "reading bitmap with sample size "
- + inSampleSize);
+ Log.d(Config.LOGTAG, "reading bitmap with sample size " + inSampleSize);
options.inSampleSize = inSampleSize;
originalBitmap = BitmapFactory.decodeStream(is, null, options);
is.close();
if (originalBitmap == null) {
throw new FileCopyException(R.string.error_not_an_image_file);
}
- Bitmap scalledBitmap = resize(originalBitmap, IMAGE_SIZE);
- originalBitmap = null;
+ Bitmap scaledBitmap = resize(originalBitmap, IMAGE_SIZE);
int rotation = getRotation(image);
if (rotation > 0) {
- scalledBitmap = rotate(scalledBitmap, rotation);
+ scaledBitmap = rotate(scaledBitmap, rotation);
}
- OutputStream os = new FileOutputStream(file);
- boolean success = scalledBitmap.compress(
- Bitmap.CompressFormat.WEBP, 75, os);
+
+ boolean success = scaledBitmap.compress(Bitmap.CompressFormat.WEBP, 75, os);
if (!success) {
throw new FileCopyException(R.string.error_compressing_image);
}
os.flush();
- os.close();
long size = file.getSize();
- int width = scalledBitmap.getWidth();
- int height = scalledBitmap.getHeight();
+ int width = scaledBitmap.getWidth();
+ int height = scaledBitmap.getHeight();
message.setBody(Long.toString(size) + ',' + width + ',' + height);
return file;
} catch (FileNotFoundException e) {
@@ -223,8 +225,7 @@ public class FileBackend {
} catch (IOException e) {
throw new FileCopyException(R.string.error_io_exception);
} catch (SecurityException e) {
- throw new FileCopyException(
- R.string.error_security_exception_during_image_copy);
+ throw new FileCopyException(R.string.error_security_exception_during_image_copy);
} catch (OutOfMemoryError e) {
++sampleSize;
if (sampleSize <= 3) {
@@ -232,23 +233,24 @@ public class FileBackend {
} else {
throw new FileCopyException(R.string.error_out_of_memory);
}
+ } finally {
+ close(os);
+ close(is);
}
}
private int getRotation(Uri image) {
+ InputStream is = null;
try {
- InputStream is = mXmppConnectionService.getContentResolver()
- .openInputStream(image);
+ is = mXmppConnectionService.getContentResolver().openInputStream(image);
return ExifHelper.getOrientation(is);
} catch (FileNotFoundException e) {
return 0;
+ } finally {
+ close(is);
}
}
- public Bitmap getImageFromMessage(Message message) {
- return BitmapFactory.decodeFile(getFile(message).getAbsolutePath());
- }
-
public Bitmap getThumbnail(Message message, int size, boolean cacheOnly)
throws FileNotFoundException {
Bitmap thumbnail = mXmppConnectionService.getBitmapCache().get(
@@ -257,8 +259,7 @@ public class FileBackend {
File file = getFile(message);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = calcSampleSize(file, size);
- Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(),
- options);
+ Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(),options);
if (fullsize == null) {
throw new FileNotFoundException();
}
@@ -271,13 +272,11 @@ public class FileBackend {
public Uri getTakePhotoUri() {
StringBuilder pathBuilder = new StringBuilder();
- pathBuilder.append(Environment
- .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
+ pathBuilder.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
pathBuilder.append('/');
pathBuilder.append("Camera");
pathBuilder.append('/');
- pathBuilder.append("IMG_" + this.imageDateFormat.format(new Date())
- + ".jpg");
+ pathBuilder.append("IMG_" + this.imageDateFormat.format(new Date()) + ".jpg");
Uri uri = Uri.parse("file://" + pathBuilder.toString());
File file = new File(uri.toString());
file.getParentFile().mkdirs();
@@ -325,13 +324,13 @@ public class FileBackend {
String filename = getAvatarPath(avatar.getFilename());
file = new File(filename + ".tmp");
file.getParentFile().mkdirs();
+ OutputStream os = null;
try {
file.createNewFile();
- FileOutputStream mFileOutputStream = new FileOutputStream(file);
+ os = new FileOutputStream(file);
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.reset();
- DigestOutputStream mDigestOutputStream = new DigestOutputStream(
- mFileOutputStream, digest);
+ DigestOutputStream mDigestOutputStream = new DigestOutputStream(os, digest);
mDigestOutputStream.write(avatar.getImageAsBytes());
mDigestOutputStream.flush();
mDigestOutputStream.close();
@@ -349,6 +348,8 @@ public class FileBackend {
return false;
} catch (NoSuchAlgorithmException e) {
return false;
+ } finally {
+ close(os);
}
}
avatar.size = file.length();
@@ -356,8 +357,7 @@ public class FileBackend {
}
public String getAvatarPath(String avatar) {
- return mXmppConnectionService.getFilesDir().getAbsolutePath()
- + "/avatars/" + avatar;
+ return mXmppConnectionService.getFilesDir().getAbsolutePath()+ "/avatars/" + avatar;
}
public Uri getAvatarUri(String avatar) {
@@ -368,10 +368,11 @@ public class FileBackend {
if (image == null) {
return null;
}
+ InputStream is = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = calcSampleSize(image, size);
- InputStream is = mXmppConnectionService.getContentResolver().openInputStream(image);
+ is = mXmppConnectionService.getContentResolver().openInputStream(image);
Bitmap input = BitmapFactory.decodeStream(is, null, options);
if (input == null) {
return null;
@@ -384,6 +385,8 @@ public class FileBackend {
}
} catch (FileNotFoundException e) {
return null;
+ } finally {
+ close(is);
}
}
@@ -391,10 +394,11 @@ public class FileBackend {
if (image == null) {
return null;
}
+ InputStream is = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = calcSampleSize(image,Math.max(newHeight, newWidth));
- InputStream is = mXmppConnectionService.getContentResolver().openInputStream(image);
+ is = mXmppConnectionService.getContentResolver().openInputStream(image);
Bitmap source = BitmapFactory.decodeStream(is, null, options);
int sourceWidth = source.getWidth();
@@ -414,8 +418,11 @@ public class FileBackend {
return dest;
} catch (FileNotFoundException e) {
return null;
+ } catch (IOException e) {
+ return null;
+ } finally {
+ close(is);
}
-
}
public Bitmap cropCenterSquare(Bitmap input, int size) {
@@ -522,4 +529,13 @@ public class FileBackend {
public boolean isFileAvailable(Message message) {
return getFile(message).exists();
}
+
+ public static void close(Closeable stream) {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index 3e8ce65f..ec0b3f92 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -36,6 +36,7 @@ import org.openintents.openpgp.util.OpenPgpServiceConnection;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -174,13 +175,22 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public void onContactStatusChanged(Contact contact, boolean online) {
Conversation conversation = find(getConversations(), contact);
if (conversation != null) {
- if (online && contact.getPresences().size() > 1) {
+ if (online) {
conversation.endOtrIfNeeded();
+ if (contact.getPresences().size() == 1) {
+ sendUnsentMessages(conversation);
+ }
} else {
- conversation.resetOtrSession();
- }
- if (online && (contact.getPresences().size() == 1)) {
- sendUnsentMessages(conversation);
+ if (contact.getPresences().size() >= 1) {
+ if (conversation.hasValidOtrSession()) {
+ String otrResource = conversation.getOtrSession().getSessionID().getUserID();
+ if (!(Arrays.asList(contact.getPresences().asStringArray()).contains(otrResource))) {
+ conversation.endOtrIfNeeded();
+ }
+ }
+ } else {
+ conversation.endOtrIfNeeded();
+ }
}
}
}
@@ -1537,6 +1547,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
for (Jid invite : jids) {
invite(conversation, invite);
}
+ if (account.countPresences() > 1) {
+ directInvite(conversation, account.getJid().toBareJid());
+ }
if (callback != null) {
callback.success(conversation);
}
@@ -2022,6 +2035,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
sendMessagePacket(conversation.getAccount(), packet);
}
+ public void directInvite(Conversation conversation, Jid jid) {
+ MessagePacket packet = mMessageGenerator.directInvite(conversation,jid);
+ sendMessagePacket(conversation.getAccount(),packet);
+ }
+
public void resetSendingToWaiting(Account account) {
for (Conversation conversation : getConversations()) {
if (conversation.getAccount() == account) {
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
index a44311b4..e5389dd6 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
@@ -929,10 +929,10 @@ public class ConversationActivity extends XmppActivity
}
private void handleViewConversationIntent(final Intent intent) {
- final String uuid = (String) intent.getExtras().get(CONVERSATION);
- final String downloadUuid = (String) intent.getExtras().get(MESSAGE);
- final String text = intent.getExtras().getString(TEXT, "");
- final String nick = intent.getExtras().getString(NICK, null);
+ final String uuid = intent.getStringExtra(CONVERSATION);
+ final String downloadUuid = intent.getStringExtra(MESSAGE);
+ final String text = intent.getStringExtra(TEXT);
+ final String nick = intent.getStringExtra(NICK);
if (selectConversationByUuid(uuid)) {
this.mConversationFragment.reInit(getSelectedConversation());
if (nick != null) {
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index a3a02b27..5b1e9b4d 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -8,7 +8,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
-import android.net.Uri;
import android.os.Bundle;
import android.text.InputType;
import android.view.ContextMenu;
@@ -315,8 +314,8 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
@Override
public View onCreateView(final LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
- final View view = inflater.inflate(R.layout.fragment_conversation,
- container, false);
+ final View view = inflater.inflate(R.layout.fragment_conversation,container, false);
+ view.setOnClickListener(null);
mEditMessage = (EditMessage) view.findViewById(R.id.textinput);
setupIme();
mEditMessage.setOnClickListener(new OnClickListener() {
@@ -719,21 +718,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
final ConversationActivity activity = (ConversationActivity) getActivity();
if (this.conversation != null) {
updateSnackBar(this.conversation);
- final Contact contact = this.conversation.getContact();
- if (this.conversation.isBlocked()) {
-
- } else if (!contact.showInRoster()
- && contact
- .getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
-
- } else if (conversation.getMode() == Conversation.MODE_SINGLE) {
- makeFingerprintWarning();
- } else if (!conversation.getMucOptions().online()
- && conversation.getAccount().getStatus() == Account.State.ONLINE) {
-
- } else if (this.conversation.isMuted()) {
-
- }
conversation.populateWithMessages(ConversationFragment.this.messageList);
for (final Message message : this.messageList) {
if (message.getEncryption() == Message.ENCRYPTION_PGP
@@ -780,6 +764,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
} catch (final NoSuchElementException ignored) {
}
+ askForPassphraseIntent = null;
activity.xmppConnectionService.updateMessage(message);
}
@@ -879,10 +864,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
}
- protected void makeFingerprintWarning() {
-
- }
-
protected void showSnackbar(final int message, final int action,
final OnClickListener clickListener) {
snackbar.setVisibility(View.VISIBLE);
@@ -1019,6 +1000,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
public void appendText(String text) {
+ if (text == null) {
+ return;
+ }
String previous = this.mEditMessage.getText().toString();
if (previous.length() != 0 && !previous.endsWith(" ")) {
text = " " + text;
diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
index dbad9e00..7aa7b1c2 100644
--- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
@@ -468,7 +468,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
} else {
this.mServerInfoSm.setText(R.string.server_info_unavailable);
}
- if (features.pubsub()) {
+ if (features.pep()) {
this.mServerInfoPep.setText(R.string.server_info_available);
} else {
this.mServerInfoPep.setText(R.string.server_info_unavailable);
diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
index 3f72b723..e8ab8dae 100644
--- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
@@ -163,8 +163,7 @@ public class PublishProfilePictureActivity extends XmppActivity {
if (jid != null) {
this.account = xmppConnectionService.findAccountByJid(jid);
if (this.account.getXmppConnection() != null) {
- this.support = this.account.getXmppConnection()
- .getFeatures().pubsub();
+ this.support = this.account.getXmppConnection().getFeatures().pep();
}
if (this.avatarUri == null) {
if (this.account.getAvatar() != null
diff --git a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java
index eb7e2c3c..466bc409 100644
--- a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java
+++ b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java
@@ -91,6 +91,9 @@ public final class CryptoHelper {
}
public static String prettifyFingerprint(String fingerprint) {
+ if (fingerprint.length() < 40) {
+ return fingerprint;
+ }
StringBuilder builder = new StringBuilder(fingerprint);
builder.insert(8, " ");
builder.insert(17, " ");
diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
index 1351226b..cf580df1 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -90,7 +90,7 @@ public class XmppConnection implements Runnable {
private boolean shouldBind = true;
private boolean shouldAuthenticate = true;
private Element streamFeatures;
- private final HashMap<String, List<String>> disco = new HashMap<>();
+ private final HashMap<Jid, Info> disco = new HashMap<>();
private String streamId = null;
private int smVersion = 3;
@@ -334,6 +334,7 @@ public class XmppConnection implements Runnable {
} catch (final NumberFormatException ignored) {
}
sendServiceDiscoveryInfo(account.getServer());
+ sendServiceDiscoveryInfo(account.getJid().toBareJid());
sendServiceDiscoveryItems(account.getServer());
sendInitialPing();
} else if (nextTag.isStart("r")) {
@@ -734,6 +735,7 @@ public class XmppConnection implements Runnable {
features.blockListRequested = false;
disco.clear();
sendServiceDiscoveryInfo(account.getServer());
+ sendServiceDiscoveryInfo(account.getJid().toBareJid());
sendServiceDiscoveryItems(account.getServer());
if (bindListener != null) {
bindListener.onBind(account);
@@ -741,34 +743,35 @@ public class XmppConnection implements Runnable {
sendInitialPing();
}
- private void sendServiceDiscoveryInfo(final Jid server) {
- if (disco.containsKey(server.toDomainJid().toString())) {
- if (account.getServer().equals(server.toDomainJid())) {
+ private void sendServiceDiscoveryInfo(final Jid jid) {
+ if (disco.containsKey(jid)) {
+ if (account.getServer().equals(jid)) {
enableAdvancedStreamFeatures();
}
} else {
final IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
- iq.setTo(server.toDomainJid());
+ iq.setTo(jid);
iq.query("http://jabber.org/protocol/disco#info");
this.sendIqPacket(iq, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(final Account account, final IqPacket packet) {
final List<Element> elements = packet.query().getChildren();
- final List<String> features = new ArrayList<>();
+ final Info info = new Info();
for (final Element element : elements) {
if (element.getName().equals("identity")) {
- if ("irc".equals(element.getAttribute("type"))) {
- //add fake feature to not confuse irc and real muc
- features.add("siacs:no:muc");
+ String type = element.getAttribute("type");
+ String category = element.getAttribute("category");
+ if (type != null && category != null) {
+ info.identities.add(new Pair<>(category,type));
}
} else if (element.getName().equals("feature")) {
- features.add(element.getAttribute("var"));
+ info.features.add(element.getAttribute("var"));
}
}
- disco.put(server.toDomainJid().toString(), features);
+ disco.put(jid, info);
- if (account.getServer().equals(server.toDomainJid())) {
+ if (account.getServer().equals(jid)) {
enableAdvancedStreamFeatures();
for (final OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) {
listener.onAdvancedStreamFeaturesAvailable(account);
@@ -987,9 +990,9 @@ public class XmppConnection implements Runnable {
public List<String> findDiscoItemsByFeature(final String feature) {
final List<String> items = new ArrayList<>();
- for (final Entry<String, List<String>> cursor : disco.entrySet()) {
- if (cursor.getValue().contains(feature)) {
- items.add(cursor.getKey());
+ for (final Entry<Jid, Info> cursor : disco.entrySet()) {
+ if (cursor.getValue().features.contains(feature)) {
+ items.add(cursor.getKey().toString());
}
}
return items;
@@ -1008,10 +1011,12 @@ public class XmppConnection implements Runnable {
}
public String getMucServer() {
- for (final Entry<String, List<String>> cursor : disco.entrySet()) {
- final List<String> value = cursor.getValue();
- if (value.contains("http://jabber.org/protocol/muc") && !value.contains("jabber:iq:gateway") && !value.contains("siacs:no:muc")) {
- return cursor.getKey();
+ for (final Entry<Jid, Info> cursor : disco.entrySet()) {
+ final Info value = cursor.getValue();
+ if (value.features.contains("http://jabber.org/protocol/muc")
+ && !value.features.contains("jabber:iq:gateway")
+ && !value.identities.contains(new Pair<>("conference","irc"))) {
+ return cursor.getKey().toString();
}
}
return null;
@@ -1066,6 +1071,11 @@ public class XmppConnection implements Runnable {
this.lastConnect = 0;
}
+ private class Info {
+ public final ArrayList<String> features = new ArrayList<>();
+ public final ArrayList<Pair<String,String>> identities = new ArrayList<>();
+ }
+
public class Features {
XmppConnection connection;
private boolean carbonsEnabled = false;
@@ -1077,8 +1087,8 @@ public class XmppConnection implements Runnable {
}
private boolean hasDiscoFeature(final Jid server, final String feature) {
- return connection.disco.containsKey(server.toDomainJid().toString()) &&
- connection.disco.get(server.toDomainJid().toString()).contains(feature);
+ return connection.disco.containsKey(server) &&
+ connection.disco.get(server).features.contains(feature);
}
public boolean carbons() {
@@ -1094,24 +1104,35 @@ public class XmppConnection implements Runnable {
}
public boolean sm() {
- return streamId != null;
+ return streamId != null
+ || (connection.streamFeatures != null && connection.streamFeatures.hasChild("sm"));
}
public boolean csi() {
return connection.streamFeatures != null && connection.streamFeatures.hasChild("csi", "urn:xmpp:csi:0");
}
- public boolean pubsub() {
- return hasDiscoFeature(account.getServer(),
- "http://jabber.org/protocol/pubsub#publish");
+ public boolean pep() {
+ final Pair<String,String> needle = new Pair<>("pubsub","pep");
+ Info info = disco.get(account.getServer());
+ if (info != null && info.identities.contains(needle)) {
+ return true;
+ } else {
+ info = disco.get(account.getJid().toBareJid());
+ return info != null && info.identities.contains(needle);
+ }
}
public boolean mam() {
- return hasDiscoFeature(account.getServer(), "urn:xmpp:mam:0");
+ if (hasDiscoFeature(account.getJid().toBareJid(), "urn:xmpp:mam:0")) {
+ return true;
+ } else {
+ return hasDiscoFeature(account.getServer(), "urn:xmpp:mam:0");
+ }
}
public boolean advancedStreamFeaturesLoaded() {
- return disco.containsKey(account.getServer().toString());
+ return disco.containsKey(account.getServer());
}
public boolean rosterVersioning() {
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 3677bf4f..9866af03 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java
@@ -11,6 +11,7 @@ import android.util.Base64;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.DownloadableFile;
+import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
@@ -172,6 +173,7 @@ public class JingleInbandTransport extends JingleTransport {
connection.updateProgress((int) ((((double) (this.fileSize - this.remainingSize)) / this.fileSize) * 100));
}
} catch (IOException e) {
+ FileBackend.close(fileInputStream);
this.onFileTransmissionStatusChanged.onFileTransferAborted();
}
}
@@ -198,6 +200,7 @@ public class JingleInbandTransport extends JingleTransport {
connection.updateProgress((int) ((((double) (this.fileSize - this.remainingSize)) / this.fileSize) * 100));
}
} catch (IOException e) {
+ FileBackend.close(fileOutputStream);
this.onFileTransmissionStatusChanged.onFileTransferAborted();
}
}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java
index c3419580..72015a05 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java
@@ -11,6 +11,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import eu.siacs.conversations.entities.DownloadableFile;
+import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.utils.CryptoHelper;
public class JingleSocks5Transport extends JingleTransport {
@@ -126,25 +127,19 @@ public class JingleSocks5Transport extends JingleTransport {
} catch (NoSuchAlgorithmException e) {
callback.onFileTransferAborted();
} finally {
- try {
- if (fileInputStream != null) {
- fileInputStream.close();
- }
- } catch (IOException e) {
- callback.onFileTransferAborted();
- }
+ FileBackend.close(fileInputStream);
}
}
}).start();
}
- public void receive(final DownloadableFile file,
- final OnFileTransmissionStatusChanged callback) {
+ public void receive(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) {
new Thread(new Runnable() {
@Override
public void run() {
+ OutputStream fileOutputStream = null;
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.reset();
@@ -152,7 +147,7 @@ public class JingleSocks5Transport extends JingleTransport {
socket.setSoTimeout(30000);
file.getParentFile().mkdirs();
file.createNewFile();
- OutputStream fileOutputStream = file.createOutputStream();
+ fileOutputStream = file.createOutputStream();
if (fileOutputStream == null) {
callback.onFileTransferAborted();
return;
@@ -183,6 +178,8 @@ public class JingleSocks5Transport extends JingleTransport {
callback.onFileTransferAborted();
} catch (NoSuchAlgorithmException e) {
callback.onFileTransferAborted();
+ } finally {
+ FileBackend.close(fileOutputStream);
}
}
}).start();