~singpolyma/cheogram-android

1accf9d961b3852b6e43332152198511680e6b98 — Daniel Gultsch 5 years ago 0add9a0
migrate to xmpp-addr
79 files changed, 706 insertions(+), 1040 deletions(-)

M build.gradle
M proguard-rules.pro
M src/main/java/eu/siacs/conversations/crypto/PgpEngine.java
M src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
M src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java
M src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java
M src/main/java/eu/siacs/conversations/crypto/sasl/External.java
M src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java
M src/main/java/eu/siacs/conversations/entities/Account.java
M src/main/java/eu/siacs/conversations/entities/Blockable.java
M src/main/java/eu/siacs/conversations/entities/Bookmark.java
M src/main/java/eu/siacs/conversations/entities/Contact.java
M src/main/java/eu/siacs/conversations/entities/Conversation.java
M src/main/java/eu/siacs/conversations/entities/ListItem.java
M src/main/java/eu/siacs/conversations/entities/Message.java
M src/main/java/eu/siacs/conversations/entities/MucOptions.java
M src/main/java/eu/siacs/conversations/entities/ReadByMarker.java
M src/main/java/eu/siacs/conversations/entities/ReceiptRequest.java
M src/main/java/eu/siacs/conversations/entities/Roster.java
M src/main/java/eu/siacs/conversations/generator/IqGenerator.java
M src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
M src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java
M src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java
M src/main/java/eu/siacs/conversations/parser/AbstractParser.java
M src/main/java/eu/siacs/conversations/parser/IqParser.java
M src/main/java/eu/siacs/conversations/parser/MessageParser.java
M src/main/java/eu/siacs/conversations/parser/PresenceParser.java
M src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
M src/main/java/eu/siacs/conversations/services/AvatarService.java
M src/main/java/eu/siacs/conversations/services/BarcodeProvider.java
M src/main/java/eu/siacs/conversations/services/ExportLogsService.java
M src/main/java/eu/siacs/conversations/services/MessageArchiveService.java
M src/main/java/eu/siacs/conversations/services/NotificationService.java
M src/main/java/eu/siacs/conversations/services/ShortcutService.java
M src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
M src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java
M src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java
M src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java
M src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
M src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
M src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
M src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
M src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
M src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java
M src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java
M src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java
M src/main/java/eu/siacs/conversations/ui/SettingsActivity.java
M src/main/java/eu/siacs/conversations/ui/ShareViaAccountActivity.java
M src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
M src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
M src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java
M src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java
M src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java
M src/main/java/eu/siacs/conversations/ui/XmppActivity.java
M src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java
M src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java
M src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java
M src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
M src/main/java/eu/siacs/conversations/ui/forms/FormJidSingleFieldWrapper.java
M src/main/java/eu/siacs/conversations/ui/util/PresenceSelector.java
M src/main/java/eu/siacs/conversations/utils/CryptoHelper.java
M src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java
M src/main/java/eu/siacs/conversations/utils/GeoHelper.java
M src/main/java/eu/siacs/conversations/utils/JidHelper.java
M src/main/java/eu/siacs/conversations/utils/NickValidityChecker.java
M src/main/java/eu/siacs/conversations/utils/UIHelper.java
M src/main/java/eu/siacs/conversations/utils/XmppUri.java
M src/main/java/eu/siacs/conversations/xml/Element.java
M src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
D src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java
D src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java
M src/main/java/eu/siacs/conversations/xmpp/jingle/JingleCandidate.java
M src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
M src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
M src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java
M src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java
M src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java
M src/main/java/eu/siacs/conversations/xmpp/pep/Avatar.java
M src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java
M build.gradle => build.gradle +1 -0
@@ 53,6 53,7 @@ dependencies {
    implementation 'com.makeramen:roundedimageview:2.3.0'
    implementation "com.wefika:flowlayout:0.4.1"
    implementation 'net.ypresto.androidtranscoder:android-transcoder:0.2.0'
    implementation 'rocks.xmpp:xmpp-addr:0.7.5'
}

ext {

M proguard-rules.pro => proguard-rules.pro +1 -0
@@ 16,3 16,4 @@
-dontwarn org.bouncycastle.x509.util.LDAPStoreHelper
-dontwarn org.bouncycastle.jce.provider.X509LDAPCertStoreSpi
-dontwarn org.bouncycastle.cert.dane.**
-dontwarn rocks.xmpp.addr.**

M src/main/java/eu/siacs/conversations/crypto/PgpEngine.java => src/main/java/eu/siacs/conversations/crypto/PgpEngine.java +3 -3
@@ 39,9 39,9 @@ public class PgpEngine {

	private static void logError(Account account, OpenPgpError error) {
		if (error != null) {
			Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": OpenKeychain error '" + error.getMessage() + "' code=" + error.getErrorId());
			Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": OpenKeychain error '" + error.getMessage() + "' code=" + error.getErrorId());
		} else {
			Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": OpenKeychain error with no message");
			Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": OpenKeychain error with no message");
		}
	}



@@ 208,7 208,7 @@ public class PgpEngine {
		params.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, account.getPgpId());
		InputStream is = new ByteArrayInputStream(status.getBytes());
		final OutputStream os = new ByteArrayOutputStream();
		Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": signing status message \"" + status + "\"");
		Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": signing status message \"" + status + "\"");
		api.executeApiAsync(params, is, os, result -> {
			switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
				case OpenPgpApi.RESULT_CODE_SUCCESS:

M src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java => src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +66 -67
@@ 51,11 51,10 @@ import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.PublishOptions;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
import rocks.xmpp.addr.Jid;

public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {



@@ 94,7 93,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
				&& account.getXmppConnection().getFeatures().pep()) {
			publishBundlesIfNeeded(true, false);
		} else {
			Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": skipping OMEMO initialization");
			Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": skipping OMEMO initialization");
		}
	}



@@ 102,7 101,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
		for (Jid jid : jids) {
			if (deviceIds.get(jid) != null) {
				for (Integer foreignId : this.deviceIds.get(jid)) {
					SignalProtocolAddress address = new SignalProtocolAddress(jid.toPreppedString(), foreignId);
					SignalProtocolAddress address = new SignalProtocolAddress(jid.toString(), foreignId);
					if (fetchStatusMap.getAll(address.getName()).containsValue(FetchStatus.ERROR)) {
						return true;
					}


@@ 113,11 112,11 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
	}

	public void preVerifyFingerprint(Contact contact, String fingerprint) {
		axolotlStore.preVerifyFingerprint(contact.getAccount(), contact.getJid().toBareJid().toPreppedString(), fingerprint);
		axolotlStore.preVerifyFingerprint(contact.getAccount(), contact.getJid().asBareJid().toString(), fingerprint);
	}

	public void preVerifyFingerprint(Account account, String fingerprint) {
		axolotlStore.preVerifyFingerprint(account, account.getJid().toBareJid().toPreppedString(), fingerprint);
		axolotlStore.preVerifyFingerprint(account, account.getJid().asBareJid().toString(), fingerprint);
	}

	public boolean hasVerifiedKeys(String name) {


@@ 202,10 201,10 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
						Bundle information = CryptoHelper.extractCertificateInformation(certificate);
						try {
							final String cn = information.getString("subject_cn");
							final Jid jid = Jid.fromString(bareJid);
							final Jid jid = Jid.of(bareJid);
							Log.d(Config.LOGTAG, "setting common name for " + jid + " to " + cn);
							account.getRoster().getContact(jid).setCommonName(cn);
						} catch (final InvalidJidException ignored) {
						} catch (final IllegalArgumentException ignored) {
							//ignored
						}
					}


@@ 215,8 214,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
		}

		private void fillMap(SQLiteAxolotlStore store) {
			List<Integer> deviceIds = store.getSubDeviceSessions(account.getJid().toBareJid().toPreppedString());
			putDevicesForJid(account.getJid().toBareJid().toPreppedString(), deviceIds, store);
			List<Integer> deviceIds = store.getSubDeviceSessions(account.getJid().asBareJid().toString());
			putDevicesForJid(account.getJid().asBareJid().toString(), deviceIds, store);
			for (String address : store.getKnownAddresses()) {
				deviceIds = store.getSubDeviceSessions(address);
				putDevicesForJid(address, deviceIds, store);


@@ 247,13 246,13 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {

		public void clearErrorFor(Jid jid) {
			synchronized (MAP_LOCK) {
				Map<Integer, FetchStatus> devices = this.map.get(jid.toBareJid().toPreppedString());
				Map<Integer, FetchStatus> devices = this.map.get(jid.asBareJid().toString());
				if (devices == null) {
					return;
				}
				for (Map.Entry<Integer, FetchStatus> entry : devices.entrySet()) {
					if (entry.getValue() == FetchStatus.ERROR) {
						Log.d(Config.LOGTAG, "resetting error for " + jid.toBareJid() + "(" + entry.getKey() + ")");
						Log.d(Config.LOGTAG, "resetting error for " + jid.asBareJid() + "(" + entry.getKey() + ")");
						entry.setValue(FetchStatus.TIMEOUT);
					}
				}


@@ 262,7 261,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
	}

	public static String getLogprefix(Account account) {
		return LOGPREFIX + " (" + account.getJid().toBareJid().toString() + "): ";
		return LOGPREFIX + " (" + account.getJid().asBareJid().toString() + "): ";
	}

	public AxolotlService(Account account, XmppConnectionService connectionService) {


@@ 287,28 286,28 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
	}

	public Set<IdentityKey> getKeysWithTrust(FingerprintStatus status) {
		return axolotlStore.getContactKeysWithTrust(account.getJid().toBareJid().toPreppedString(), status);
		return axolotlStore.getContactKeysWithTrust(account.getJid().asBareJid().toString(), status);
	}

	public Set<IdentityKey> getKeysWithTrust(FingerprintStatus status, Jid jid) {
		return axolotlStore.getContactKeysWithTrust(jid.toBareJid().toPreppedString(), status);
		return axolotlStore.getContactKeysWithTrust(jid.asBareJid().toString(), status);
	}

	public Set<IdentityKey> getKeysWithTrust(FingerprintStatus status, List<Jid> jids) {
		Set<IdentityKey> keys = new HashSet<>();
		for (Jid jid : jids) {
			keys.addAll(axolotlStore.getContactKeysWithTrust(jid.toPreppedString(), status));
			keys.addAll(axolotlStore.getContactKeysWithTrust(jid.toString(), status));
		}
		return keys;
	}

	public long getNumTrustedKeys(Jid jid) {
		return axolotlStore.getContactNumTrustedKeys(jid.toBareJid().toPreppedString());
		return axolotlStore.getContactNumTrustedKeys(jid.asBareJid().toString());
	}

	public boolean anyTargetHasNoTrustedKeys(List<Jid> jids) {
		for (Jid jid : jids) {
			if (axolotlStore.getContactNumTrustedKeys(jid.toBareJid().toPreppedString()) == 0) {
			if (axolotlStore.getContactNumTrustedKeys(jid.asBareJid().toString()) == 0) {
				return true;
			}
		}


@@ 316,11 315,11 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
	}

	private SignalProtocolAddress getAddressForJid(Jid jid) {
		return new SignalProtocolAddress(jid.toPreppedString(), 0);
		return new SignalProtocolAddress(jid.toString(), 0);
	}

	public Collection<XmppAxolotlSession> findOwnSessions() {
		SignalProtocolAddress ownAddress = getAddressForJid(account.getJid().toBareJid());
		SignalProtocolAddress ownAddress = getAddressForJid(account.getJid().asBareJid());
		ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(ownAddress.getName()).values());
		Collections.sort(s);
		return s;


@@ 373,12 372,12 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
	}

	public void destroy() {
		Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": destroying old axolotl service. no longer in use");
		Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": destroying old axolotl service. no longer in use");
		mXmppConnectionService.databaseBackend.wipeAxolotlDb(account);
	}

	public AxolotlService makeNew() {
		Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": make new axolotl service");
		Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": make new axolotl service");
		return new AxolotlService(this.account, this.mXmppConnectionService);
	}



@@ 387,19 386,19 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
	}

	public SignalProtocolAddress getOwnAxolotlAddress() {
		return new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(), getOwnDeviceId());
		return new SignalProtocolAddress(account.getJid().asBareJid().toString(), getOwnDeviceId());
	}

	public Set<Integer> getOwnDeviceIds() {
		return this.deviceIds.get(account.getJid().toBareJid());
		return this.deviceIds.get(account.getJid().asBareJid());
	}

	public void registerDevices(final Jid jid, @NonNull final Set<Integer> deviceIds) {
		final int hash = deviceIds.hashCode();
		final boolean me = jid.toBareJid().equals(account.getJid().toBareJid());
		final boolean me = jid.asBareJid().equals(account.getJid().asBareJid());
		if (me) {
			if (hash != 0 && hash == this.lastDeviceListNotificationHash) {
				Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": ignoring duplicate own device id list");
				Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ignoring duplicate own device id list");
				return;
			}
			this.lastDeviceListNotificationHash = hash;


@@ 408,10 407,10 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
		if (me) {
			deviceIds.remove(getOwnDeviceId());
		}
		Set<Integer> expiredDevices = new HashSet<>(axolotlStore.getSubDeviceSessions(jid.toBareJid().toPreppedString()));
		Set<Integer> expiredDevices = new HashSet<>(axolotlStore.getSubDeviceSessions(jid.asBareJid().toString()));
		expiredDevices.removeAll(deviceIds);
		for (Integer deviceId : expiredDevices) {
			SignalProtocolAddress address = new SignalProtocolAddress(jid.toBareJid().toPreppedString(), deviceId);
			SignalProtocolAddress address = new SignalProtocolAddress(jid.asBareJid().toString(), deviceId);
			XmppAxolotlSession session = sessions.get(address);
			if (session != null && session.getFingerprint() != null) {
				if (session.getTrust().isActive()) {


@@ 421,7 420,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
		}
		Set<Integer> newDevices = new HashSet<>(deviceIds);
		for (Integer deviceId : newDevices) {
			SignalProtocolAddress address = new SignalProtocolAddress(jid.toBareJid().toPreppedString(), deviceId);
			SignalProtocolAddress address = new SignalProtocolAddress(jid.asBareJid().toString(), deviceId);
			XmppAxolotlSession session = sessions.get(address);
			if (session != null && session.getFingerprint() != null) {
				if (!session.getTrust().isActive()) {


@@ 436,7 435,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
			}
			needsPublishing |= this.changeAccessMode.get();
			for (Integer deviceId : deviceIds) {
				SignalProtocolAddress ownDeviceAddress = new SignalProtocolAddress(jid.toBareJid().toPreppedString(), deviceId);
				SignalProtocolAddress ownDeviceAddress = new SignalProtocolAddress(jid.asBareJid().toString(), deviceId);
				if (sessions.get(ownDeviceAddress) == null) {
					FetchStatus status = fetchStatusMap.get(ownDeviceAddress);
					if (status == null || status == FetchStatus.TIMEOUT) {


@@ 475,7 474,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
			Log.d(Config.LOGTAG, getLogprefix(account) + "publishOwnDeviceIdIfNeeded called, but PEP is broken. Ignoring... ");
			return;
		}
		IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveDeviceIds(account.getJid().toBareJid());
		IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveDeviceIds(account.getJid().asBareJid());
		mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
			@Override
			public void onIqPacketReceived(Account account, IqPacket packet) {


@@ 484,8 483,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
				} else {
					Element item = mXmppConnectionService.getIqParser().getItem(packet);
					Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item);
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": retrieved own device list: " + deviceIds);
					registerDevices(account.getJid().toBareJid(), deviceIds);
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": retrieved own device list: " + deviceIds);
					registerDevices(account.getJid().asBareJid(), deviceIds);
				}
			}
		});


@@ 502,9 501,9 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
					if (lastMessageDiff > Config.OMEMO_AUTO_EXPIRY) {
						devices.add(session.getRemoteAddress().getDeviceId());
						session.setTrust(session.getTrust().toInactive());
						Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": added own device " + session.getFingerprint() + " to list of expired devices. Last message received " + hours + " hours ago");
						Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": added own device " + session.getFingerprint() + " to list of expired devices. Last message received " + hours + " hours ago");
					} else {
						Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": own device " + session.getFingerprint() + " was active " + hours + " hours ago");
						Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": own device " + session.getFingerprint() + " was active " + hours + " hours ago");
					}
				}
			}


@@ 543,7 542,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
			public void onIqPacketReceived(Account account, IqPacket packet) {
				Element error = packet.getType() == IqPacket.TYPE.ERROR ? packet.findChild("error") : null;
				if (firstAttempt && error != null && error.hasChild("precondition-not-met", Namespace.PUBSUB_ERROR)) {
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": precondition wasn't met for device list. pushing node configuration");
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": precondition wasn't met for device list. pushing node configuration");
					mXmppConnectionService.pushNodeConfiguration(account, AxolotlService.PEP_DEVICE_LIST, publishOptions, new XmppConnectionService.OnConfigurationPushed() {
						@Override
						public void onPushSucceeded() {


@@ 557,7 556,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
					});
				} else {
					if (AxolotlService.this.changeAccessMode.compareAndSet(true, false)) {
						Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": done changing access mode");
						Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": done changing access mode");
						account.setOption(Account.OPTION_REQUIRES_ACCESS_MODE_CHANGE, false);
						mXmppConnectionService.databaseBackend.updateAccount(account);
					}


@@ 618,14 617,14 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
			this.changeAccessMode.set(account.isOptionSet(Account.OPTION_REQUIRES_ACCESS_MODE_CHANGE));
		} else {
			if (account.setOption(Account.OPTION_REQUIRES_ACCESS_MODE_CHANGE, true)) {
				Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": server doesn’t support publish-options. setting for later access mode change");
				Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": server doesn’t support publish-options. setting for later access mode change");
				mXmppConnectionService.databaseBackend.updateAccount(account);
			}
		}
		if (this.changeAccessMode.get()) {
			Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": server gained publish-options capabilities. changing access model");
			Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": server gained publish-options capabilities. changing access model");
		}
		IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveBundlesForDevice(account.getJid().toBareJid(), getOwnDeviceId());
		IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveBundlesForDevice(account.getJid().asBareJid(), getOwnDeviceId());
		mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
			@Override
			public void onIqPacketReceived(Account account, IqPacket packet) {


@@ 754,7 753,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
			public void onIqPacketReceived(final Account account, IqPacket packet) {
				Element error = packet.getType() == IqPacket.TYPE.ERROR ? packet.findChild("error") : null;
				if (firstAttempt && error != null && error.hasChild("precondition-not-met", Namespace.PUBSUB_ERROR)) {
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": precondition wasn't met for bundle. pushing node configuration");
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": precondition wasn't met for bundle. pushing node configuration");
					final String node = AxolotlService.PEP_BUNDLES + ":" + getOwnDeviceId();
					mXmppConnectionService.pushNodeConfiguration(account, node, publishOptions, new XmppConnectionService.OnConfigurationPushed() {
						@Override


@@ 821,7 820,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
		final List<Jid> jids;
		if (conversation.getMode() == Conversation.MODE_SINGLE) {
			jids = new ArrayList<>();
			jids.add(conversation.getJid().toBareJid());
			jids.add(conversation.getJid().asBareJid());
		} else {
			jids = conversation.getMucOptions().getMembers();
		}


@@ 845,7 844,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
		final SignalProtocolAddress address = session.getRemoteAddress();
		final IdentityKey identityKey = session.getIdentityKey();
		try {
			IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveVerificationForDevice(Jid.fromString(address.getName()), address.getDeviceId());
			IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveVerificationForDevice(Jid.of(address.getName()), address.getDeviceId());
			mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
				@Override
				public void onIqPacketReceived(Account account, IqPacket packet) {


@@ 866,10 865,10 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
									Bundle information = CryptoHelper.extractCertificateInformation(verification.first[0]);
									try {
										final String cn = information.getString("subject_cn");
										final Jid jid = Jid.fromString(address.getName());
										final Jid jid = Jid.of(address.getName());
										Log.d(Config.LOGTAG, "setting common name for " + jid + " to " + cn);
										account.getRoster().getContact(jid).setCommonName(cn);
									} catch (final InvalidJidException ignored) {
									} catch (final IllegalArgumentException ignored) {
										//ignored
									}
									finishBuildingSessionsFromPEP(address);


@@ 888,7 887,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
					finishBuildingSessionsFromPEP(address);
				}
			});
		} catch (InvalidJidException e) {
		} catch (IllegalArgumentException e) {
			fetchStatusMap.put(address, FetchStatus.SUCCESS);
			finishBuildingSessionsFromPEP(address);
		}


@@ 897,7 896,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
	private final Set<Integer> PREVIOUSLY_REMOVED_FROM_ANNOUNCEMENT = new HashSet<>();

	private void finishBuildingSessionsFromPEP(final SignalProtocolAddress address) {
		SignalProtocolAddress ownAddress = new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(), 0);
		SignalProtocolAddress ownAddress = new SignalProtocolAddress(account.getJid().asBareJid().toString(), 0);
		Map<Integer, FetchStatus> own = fetchStatusMap.getAll(ownAddress.getName());
		Map<Integer, FetchStatus> remote = fetchStatusMap.getAll(address.getName());
		if (!own.containsValue(FetchStatus.PENDING) && !remote.containsValue(FetchStatus.PENDING)) {


@@ 920,7 919,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
				int id = entry.getKey();
				if (entry.getValue() == FetchStatus.ERROR && PREVIOUSLY_REMOVED_FROM_ANNOUNCEMENT.add(id) && ownDeviceIds.remove(id)) {
					publish = true;
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": error fetching own device with id " + id + ". removing from announcement");
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": error fetching own device with id " + id + ". removing from announcement");
				}
			}
			if (publish) {


@@ 952,14 951,14 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
				if (callback != null) {
					callbacks.add(callback);
				}
				Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": fetching device ids for " + jid + " already running. adding callback");
				Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": fetching device ids for " + jid + " already running. adding callback");
			} else {
				callbacks = new ArrayList<>();
				if (callback != null) {
					callbacks.add(callback);
				}
				this.fetchDeviceIdsMap.put(jid, callbacks);
				Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": fetching device ids for " + jid);
				Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": fetching device ids for " + jid);
				IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveDeviceIds(jid);
				mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
					@Override


@@ 1017,7 1016,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {

		try {
			IqPacket bundlesPacket = mXmppConnectionService.getIqGenerator().retrieveBundlesForDevice(
					Jid.fromString(address.getName()), address.getDeviceId());
					Jid.of(address.getName()), address.getDeviceId());
			Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Retrieving bundle: " + bundlesPacket);
			mXmppConnectionService.sendIqPacket(account, bundlesPacket, new OnIqPacketReceived() {



@@ 1083,7 1082,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
					}
				}
			});
		} catch (InvalidJidException e) {
		} catch (IllegalArgumentException e) {
			Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Got address with invalid jid: " + address.getName());
		}
	}


@@ 1094,7 1093,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
			Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Finding devices without session for " + jid);
			if (deviceIds.get(jid) != null) {
				for (Integer foreignId : this.deviceIds.get(jid)) {
					SignalProtocolAddress address = new SignalProtocolAddress(jid.toPreppedString(), foreignId);
					SignalProtocolAddress address = new SignalProtocolAddress(jid.toString(), foreignId);
					if (sessions.get(address) == null) {
						IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey();
						if (identityKey != null) {


@@ 1116,9 1115,9 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
				Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Have no target devices in PEP!");
			}
		}
		if (deviceIds.get(account.getJid().toBareJid()) != null) {
			for (Integer ownId : this.deviceIds.get(account.getJid().toBareJid())) {
				SignalProtocolAddress address = new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(), ownId);
		if (deviceIds.get(account.getJid().asBareJid()) != null) {
			for (Integer ownId : this.deviceIds.get(account.getJid().asBareJid())) {
				SignalProtocolAddress address = new SignalProtocolAddress(account.getJid().asBareJid().toString(), ownId);
				if (sessions.get(address) == null) {
					IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey();
					if (identityKey != null) {


@@ 1126,7 1125,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
						XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, identityKey);
						sessions.put(address, session);
					} else {
						Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Found device " + account.getJid().toBareJid() + ":" + ownId);
						Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Found device " + account.getJid().asBareJid() + ":" + ownId);
						if (fetchStatusMap.get(address) != FetchStatus.ERROR) {
							addresses.add(address);
						} else {


@@ 1148,7 1147,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
				iterator.remove();
			}
		}
		Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": createSessionsIfNeeded() - jids with empty device list: " + jidsWithEmptyDeviceList);
		Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": createSessionsIfNeeded() - jids with empty device list: " + jidsWithEmptyDeviceList);
		if (jidsWithEmptyDeviceList.size() > 0) {
			fetchDeviceIds(jidsWithEmptyDeviceList, new OnMultipleDeviceIdFetched() {
				@Override


@@ 1201,13 1200,13 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
	}

	public boolean hasPendingKeyFetches(Account account, List<Jid> jids) {
		SignalProtocolAddress ownAddress = new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(), 0);
		SignalProtocolAddress ownAddress = new SignalProtocolAddress(account.getJid().asBareJid().toString(), 0);
		if (fetchStatusMap.getAll(ownAddress.getName()).containsValue(FetchStatus.PENDING)) {
			return true;
		}
		synchronized (this.fetchDeviceIdsMap) {
			for (Jid jid : jids) {
				SignalProtocolAddress foreignAddress = new SignalProtocolAddress(jid.toBareJid().toPreppedString(), 0);
				SignalProtocolAddress foreignAddress = new SignalProtocolAddress(jid.asBareJid().toString(), 0);
				if (fetchStatusMap.getAll(foreignAddress.getName()).containsValue(FetchStatus.PENDING) || this.fetchDeviceIdsMap.containsKey(jid)) {
					return true;
				}


@@ 1253,7 1252,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {

	@Nullable
	public XmppAxolotlMessage encrypt(Message message) {
		final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().toBareJid(), getOwnDeviceId());
		final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId());
		final String content;
		if (message.hasFileOnRemoteHost()) {
			content = message.getFileParams().url.toString();


@@ 1297,7 1296,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
		executor.execute(new Runnable() {
			@Override
			public void run() {
				final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().toBareJid(), getOwnDeviceId());
				final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId());
				if (buildHeader(axolotlMessage, conversation)) {
					onMessageCreatedCallback.run(axolotlMessage);
				} else {


@@ 1326,7 1325,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
	}

	private XmppAxolotlSession getReceivingSession(XmppAxolotlMessage message) {
		SignalProtocolAddress senderAddress = new SignalProtocolAddress(message.getFrom().toPreppedString(),
		SignalProtocolAddress senderAddress = new SignalProtocolAddress(message.getFrom().toString(),
				message.getSenderDeviceId());
		XmppAxolotlSession session = sessions.get(senderAddress);
		if (session == null) {


@@ 1382,13 1381,13 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
	}

	private void completeSession(XmppAxolotlSession session) {
		final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().toBareJid(), getOwnDeviceId());
		final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId());
		axolotlMessage.addDevice(session);
		try {
			Jid jid = Jid.fromString(session.getRemoteAddress().getName());
			Jid jid = Jid.of(session.getRemoteAddress().getName());
			MessagePacket packet = mXmppConnectionService.getMessageGenerator().generateKeyTransportMessage(jid, axolotlMessage);
			mXmppConnectionService.sendMessagePacket(account, packet);
		} catch (InvalidJidException e) {
		} catch (IllegalArgumentException e) {
			throw new Error("Remote addresses are created from jid and should convert back to jid", e);
		}
	}


@@ 1423,7 1422,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
			if (session.getIdentityKey() != null) {
				verifySessionWithPEP(session);
			} else {
				Log.e(Config.LOGTAG, account.getJid().toBareJid() + ": identity key was empty after reloading for x509 verification");
				Log.e(Config.LOGTAG, account.getJid().asBareJid() + ": identity key was empty after reloading for x509 verification");
			}
		}
	}

M src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java => src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java +1 -1
@@ 191,7 191,7 @@ public class SQLiteAxolotlStore implements SignalProtocolStore {
			FingerprintStatus status = getFingerprintStatus(fingerprint);
			if (status == null) {
				if (mXmppConnectionService.blindTrustBeforeVerification() && !account.getAxolotlService().hasVerifiedKeys(address.getName())) {
					Log.d(Config.LOGTAG,account.getJid().toBareJid()+": blindly trusted "+fingerprint+" of "+address.getName());
					Log.d(Config.LOGTAG,account.getJid().asBareJid()+": blindly trusted "+fingerprint+" of "+address.getName());
					status = FingerprintStatus.createActiveTrusted();
				} else {
					status = FingerprintStatus.createActiveUndecided();

M src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java => src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java +1 -1
@@ 25,7 25,7 @@ import javax.crypto.spec.SecretKeySpec;

import eu.siacs.conversations.Config;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class XmppAxolotlMessage {
	public static final String CONTAINERTAG = "encrypted";

M src/main/java/eu/siacs/conversations/crypto/sasl/External.java => src/main/java/eu/siacs/conversations/crypto/sasl/External.java +1 -1
@@ 24,6 24,6 @@ public class External extends SaslMechanism {

	@Override
	public String getClientFirstMessage() {
		return Base64.encodeToString(account.getJid().toBareJid().toString().getBytes(),Base64.NO_WRAP);
		return Base64.encodeToString(account.getJid().asBareJid().toString().getBytes(),Base64.NO_WRAP);
	}
}

M src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java => src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java +1 -1
@@ 149,7 149,7 @@ abstract class ScramMechanism extends SaslMechanism {

				// Map keys are "bytesToHex(JID),bytesToHex(password),bytesToHex(salt),iterations".
				final KeyPair keys = CACHE.get(
						CryptoHelper.bytesToHex(account.getJid().toBareJid().toString().getBytes()) + ","
						CryptoHelper.bytesToHex(account.getJid().asBareJid().toString().getBytes()) + ","
						+ CryptoHelper.bytesToHex(account.getPassword().getBytes()) + ","
						+ CryptoHelper.bytesToHex(salt.getBytes()) + ","
						+ String.valueOf(iterationCount)

M src/main/java/eu/siacs/conversations/entities/Account.java => src/main/java/eu/siacs/conversations/entities/Account.java +26 -31
@@ 3,8 3,10 @@ package eu.siacs.conversations.entities;
import android.content.ContentValues;
import android.database.Cursor;
import android.os.SystemClock;
import android.util.Log;
import android.util.Pair;

import eu.siacs.conversations.Config;
import eu.siacs.conversations.crypto.PgpDecryptionService;

import org.json.JSONException;


@@ 23,8 25,7 @@ import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xmpp.XmppConnection;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class Account extends AbstractEntity {



@@ 276,13 277,16 @@ public class Account extends AbstractEntity {
	}

	public static Account fromCursor(final Cursor cursor) {
		Jid jid = null;
		final Jid jid;
		try {
			jid = Jid.fromParts(
			String resource = cursor.getString(cursor.getColumnIndex(RESOURCE));
			jid = Jid.of(
					cursor.getString(cursor.getColumnIndex(USERNAME)),
					cursor.getString(cursor.getColumnIndex(SERVER)),
					cursor.getString(cursor.getColumnIndex(RESOURCE)));
		} catch (final InvalidJidException ignored) {
					resource == null || resource.trim().isEmpty() ? null : resource);
		} catch (final IllegalArgumentException ignored) {
			Log.d(Config.LOGTAG,cursor.getString(cursor.getColumnIndex(USERNAME))+"@"+cursor.getString(cursor.getColumnIndex(SERVER)));
			throw new AssertionError(ignored);
		}
		return new Account(cursor.getString(cursor.getColumnIndex(UUID)),
				jid,


@@ 313,13 317,13 @@ public class Account extends AbstractEntity {
	}

	public String getUsername() {
		return jid.getLocalpart();
		return jid.getLocal();
	}

	public boolean setJid(final Jid next) {
		final Jid previousFull = this.jid;
		final Jid prev = this.jid != null ? this.jid.toBareJid() : null;
		final boolean changed = prev == null || (next != null && !prev.equals(next.toBareJid()));
		final Jid prev = this.jid != null ? this.jid.asBareJid() : null;
		final boolean changed = prev == null || (next != null && !prev.equals(next.asBareJid()));
		if (changed) {
			final AxolotlService oldAxolotlService = this.axolotlService;
			if (oldAxolotlService != null) {


@@ 329,11 333,11 @@ public class Account extends AbstractEntity {
			}
		}
		this.jid = next;
		return next != null && next.equals(previousFull);
		return next != null && !next.equals(previousFull);
	}

	public Jid getServer() {
		return jid.toDomainJid();
		return Jid.ofDomain(jid.getDomain());
	}

	public String getPassword() {


@@ 408,20 412,11 @@ public class Account extends AbstractEntity {
	}

	public String getResource() {
		return jid.getResourcepart();
		return jid.getResource();
	}

	public boolean setResource(final String resource) {
		final String oldResource = jid.getResourcepart();
		if (oldResource == null || !oldResource.equals(resource)) {
			try {
				jid = Jid.fromParts(jid.getLocalpart(), jid.getDomainpart(), resource);
				return true;
			} catch (final InvalidJidException ignored) {
				return true;
			}
		}
		return false;
	public void setResource(final String resource) {
		this.jid = this.jid.withResource(resource);
	}

	public Jid getJid() {


@@ 470,8 465,8 @@ public class Account extends AbstractEntity {
	public ContentValues getContentValues() {
		final ContentValues values = new ContentValues();
		values.put(UUID, uuid);
		values.put(USERNAME, jid.getLocalpart());
		values.put(SERVER, jid.getDomainpart());
		values.put(USERNAME, jid.getLocal());
		values.put(SERVER, jid.getDomain());
		values.put(PASSWORD, password);
		values.put(OPTIONS, options);
		synchronized (this.keys) {


@@ 484,7 479,7 @@ public class Account extends AbstractEntity {
		values.put(PORT, port);
		values.put(STATUS, presenceStatus.toShowString());
		values.put(STATUS_MESSAGE, presenceStatusMessage);
		values.put(RESOURCE,jid.getResourcepart());
		values.put(RESOURCE,jid.getResource());
		return values;
	}



@@ 589,7 584,7 @@ public class Account extends AbstractEntity {

	public Bookmark getBookmark(final Jid jid) {
		for(final Bookmark bookmark : this.bookmarks) {
			if (bookmark.getJid() != null && jid.toBareJid().equals(bookmark.getJid().toBareJid())) {
			if (bookmark.getJid() != null && jid.asBareJid().equals(bookmark.getJid().asBareJid())) {
				return bookmark;
			}
		}


@@ 623,7 618,7 @@ public class Account extends AbstractEntity {

	public String getShareableUri() {
		List<XmppUri.Fingerprint> fingerprints = this.getFingerprints();
		String uri = "xmpp:"+this.getJid().toBareJid().toString();
		String uri = "xmpp:"+this.getJid().asBareJid().toString();
		if (fingerprints.size() > 0) {
			return XmppUri.getFingerprintUri(uri,fingerprints,';');
		} else {


@@ 633,7 628,7 @@ public class Account extends AbstractEntity {

	public String getShareableLink() {
		List<XmppUri.Fingerprint> fingerprints = this.getFingerprints();
		String uri = "https://conversations.im/i/"+this.getJid().toBareJid().toString();
		String uri = "https://conversations.im/i/"+this.getJid().asBareJid().toString();
		if (fingerprints.size() > 0) {
			return XmppUri.getFingerprintUri(uri,fingerprints,'&');
		} else {


@@ 657,11 652,11 @@ public class Account extends AbstractEntity {

	public boolean isBlocked(final ListItem contact) {
		final Jid jid = contact.getJid();
		return jid != null && (blocklist.contains(jid.toBareJid()) || blocklist.contains(jid.toDomainJid()));
		return jid != null && (blocklist.contains(jid.asBareJid()) || blocklist.contains(Jid.ofDomain(jid.getDomain())));
	}

	public boolean isBlocked(final Jid jid) {
		return jid != null && blocklist.contains(jid.toBareJid());
		return jid != null && blocklist.contains(jid.asBareJid());
	}

	public Collection<Jid> getBlocklist() {

M src/main/java/eu/siacs/conversations/entities/Blockable.java => src/main/java/eu/siacs/conversations/entities/Blockable.java +1 -1
@@ 1,6 1,6 @@
package eu.siacs.conversations.entities;

import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public interface Blockable {
	boolean isBlocked();

M src/main/java/eu/siacs/conversations/entities/Bookmark.java => src/main/java/eu/siacs/conversations/entities/Bookmark.java +2 -2
@@ 9,7 9,7 @@ import java.util.Locale;

import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class Bookmark extends Element implements ListItem {



@@ 58,7 58,7 @@ public class Bookmark extends Element implements ListItem {
			return getBookmarkName().trim();
		} else {
			Jid jid = this.getJid();
			String name = jid != null ? jid.getLocalpart() : getAttribute("jid");
			String name = jid != null ? jid.getLocal() : getAttribute("jid");
			return name != null ? name : "";
		}
	}

M src/main/java/eu/siacs/conversations/entities/Contact.java => src/main/java/eu/siacs/conversations/entities/Contact.java +10 -11
@@ 18,9 18,8 @@ import eu.siacs.conversations.Config;
import eu.siacs.conversations.utils.JidHelper;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar;
import rocks.xmpp.addr.Jid;

public class Contact implements ListItem, Blockable {
	public static final String TABLENAME = "contacts";


@@ 93,8 92,8 @@ public class Contact implements ListItem, Blockable {
	public static Contact fromCursor(final Cursor cursor) {
		final Jid jid;
		try {
			jid = Jid.fromString(cursor.getString(cursor.getColumnIndex(JID)), true);
		} catch (final InvalidJidException e) {
			jid = Jid.of(cursor.getString(cursor.getColumnIndex(JID)));
		} catch (final IllegalArgumentException e) {
			// TODO: Borked DB... handle this somehow?
			return null;
		}


@@ 121,10 120,10 @@ public class Contact implements ListItem, Blockable {
			return this.serverName;
		} else if (this.presenceName != null && !this.presenceName.isEmpty() && mutualPresenceSubscription() ) {
			return this.presenceName;
		} else if (jid.hasLocalpart()) {
		} else if (jid.getLocal() != null) {
			return JidHelper.localPartOrFallback(jid);
		} else {
			return jid.getDomainpart();
			return jid.getDomain();
		}
	}



@@ 197,7 196,7 @@ public class Contact implements ListItem, Blockable {
			values.put(ACCOUNT, accountUuid);
			values.put(SYSTEMNAME, systemName);
			values.put(SERVERNAME, serverName);
			values.put(JID, jid.toPreppedString());
			values.put(JID, jid.toString());
			values.put(OPTIONS, subscription);
			values.put(SYSTEMACCOUNT, systemAccount);
			values.put(PHOTOURI, photoUri);


@@ 445,7 444,7 @@ public class Contact implements ListItem, Blockable {
	}

	public Jid getServer() {
		return getJid().toDomainJid();
		return Jid.ofDomain(getJid().getDomain());
	}

	public boolean setAvatar(Avatar avatar) {


@@ 499,20 498,20 @@ public class Contact implements ListItem, Blockable {

	@Override
	public boolean isDomainBlocked() {
		return getAccount().isBlocked(this.getJid().toDomainJid());
		return getAccount().isBlocked(Jid.ofDomain(this.getJid().getDomain()));
	}

	@Override
	public Jid getBlockedJid() {
		if (isDomainBlocked()) {
			return getJid().toDomainJid();
			return Jid.ofDomain(getJid().getDomain());
		} else {
			return getJid();
		}
	}

	public boolean isSelf() {
		return account.getJid().toBareJid().equals(getJid().toBareJid());
		return account.getJid().asBareJid().equals(getJid().asBareJid());
	}

	public void setCommonName(String cn) {

M src/main/java/eu/siacs/conversations/entities/Conversation.java => src/main/java/eu/siacs/conversations/entities/Conversation.java +11 -12
@@ 21,9 21,8 @@ import eu.siacs.conversations.Config;
import eu.siacs.conversations.crypto.PgpDecryptionService;
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
import eu.siacs.conversations.xmpp.chatstate.ChatState;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.mam.MamReference;
import rocks.xmpp.addr.Jid;


public class Conversation extends AbstractEntity implements Blockable, Comparable<Conversation> {


@@ 350,7 349,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl

	public List<Jid> getAcceptedCryptoTargets() {
		if (mode == MODE_SINGLE) {
			return Collections.singletonList(getJid().toBareJid());
			return Collections.singletonList(getJid().asBareJid());
		} else {
			return getJidListAttribute(ATTRIBUTE_CRYPTO_TARGETS);
		}


@@ 482,11 481,11 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
				if (generatedName != null) {
					return generatedName;
				} else {
					return getJid().getUnescapedLocalpart();
					return getJid().getLocal();
				}
			}
		} else if (isWithStranger()) {
			return contactJid.toBareJid().toString();
			return contactJid.asBareJid().toString();
		} else {
			return this.getContact().getDisplayName();
		}


@@ 527,7 526,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
		values.put(NAME, name);
		values.put(CONTACT, contactUuid);
		values.put(ACCOUNT, accountUuid);
		values.put(CONTACTJID, contactJid.toPreppedString());
		values.put(CONTACTJID, contactJid.toString());
		values.put(CREATED, created);
		values.put(STATUS, status);
		values.put(MODE, mode);


@@ 538,8 537,8 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
	public static Conversation fromCursor(Cursor cursor) {
		Jid jid;
		try {
			jid = Jid.fromString(cursor.getString(cursor.getColumnIndex(CONTACTJID)), true);
		} catch (final InvalidJidException e) {
			jid = Jid.of(cursor.getString(cursor.getColumnIndex(CONTACTJID)));
		} catch (final IllegalArgumentException e) {
			// Borked DB..
			jid = null;
		}


@@ 739,7 738,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
	public boolean setAttribute(String key, List<Jid> jids) {
		JSONArray array = new JSONArray();
		for(Jid jid : jids) {
			array.put(jid.toBareJid().toString());
			array.put(jid.asBareJid().toString());
		}
		synchronized (this.attributes) {
			try {


@@ 769,8 768,8 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
				JSONArray array = this.attributes.getJSONArray(key);
				for (int i = 0; i < array.length(); ++i) {
					try {
						list.add(Jid.fromString(array.getString(i)));
					} catch (InvalidJidException e) {
						list.add(Jid.of(array.getString(i)));
					} catch (IllegalArgumentException e) {
						//ignored
					}
				}


@@ 906,7 905,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl

	public boolean isWithStranger() {
		return mode == MODE_SINGLE
				&& !getJid().equals(account.getJid().toDomainJid())
				&& !getJid().equals(Jid.ofDomain(account.getJid().getDomain()))
				&& !getContact().showInRoster()
				&& sentMessagesCount() == 0;
	}

M src/main/java/eu/siacs/conversations/entities/ListItem.java => src/main/java/eu/siacs/conversations/entities/ListItem.java +2 -1
@@ 4,7 4,8 @@ import android.content.Context;

import java.util.List;

import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;


public interface ListItem extends Comparable<ListItem> {
	String getDisplayName();

M src/main/java/eu/siacs/conversations/entities/Message.java => src/main/java/eu/siacs/conversations/entities/Message.java +14 -19
@@ 3,10 3,6 @@ package eu.siacs.conversations.entities;
import android.content.ContentValues;
import android.database.Cursor;
import android.text.SpannableStringBuilder;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;

import java.net.MalformedURLException;
import java.net.URL;


@@ 25,8 21,7 @@ import eu.siacs.conversations.utils.Emoticons;
import eu.siacs.conversations.utils.GeoHelper;
import eu.siacs.conversations.utils.MimeUtils;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class Message extends AbstractEntity {



@@ 118,7 113,7 @@ public class Message extends AbstractEntity {
	public Message(Conversation conversation, String body, int encryption, int status) {
		this(conversation, java.util.UUID.randomUUID().toString(),
				conversation.getUuid(),
				conversation.getJid() == null ? null : conversation.getJid().toBareJid(),
				conversation.getJid() == null ? null : conversation.getJid().asBareJid(),
				null,
				body,
				System.currentTimeMillis(),


@@ 173,11 168,11 @@ public class Message extends AbstractEntity {
		try {
			String value = cursor.getString(cursor.getColumnIndex(COUNTERPART));
			if (value != null) {
				jid = Jid.fromString(value, true);
				jid = Jid.of(value);
			} else {
				jid = null;
			}
		} catch (InvalidJidException e) {
		} catch (IllegalArgumentException e) {
			jid = null;
		} catch (IllegalStateException e) {
			return null; // message too long?


@@ 186,11 181,11 @@ public class Message extends AbstractEntity {
		try {
			String value = cursor.getString(cursor.getColumnIndex(TRUE_COUNTERPART));
			if (value != null) {
				trueCounterpart = Jid.fromString(value, true);
				trueCounterpart = Jid.of(value);
			} else {
				trueCounterpart = null;
			}
		} catch (InvalidJidException e) {
		} catch (IllegalArgumentException e) {
			trueCounterpart = null;
		}
		return new Message(conversation,


@@ 247,12 242,12 @@ public class Message extends AbstractEntity {
		if (counterpart == null) {
			values.putNull(COUNTERPART);
		} else {
			values.put(COUNTERPART, counterpart.toPreppedString());
			values.put(COUNTERPART, counterpart.toString());
		}
		if (trueCounterpart == null) {
			values.putNull(TRUE_COUNTERPART);
		} else {
			values.put(TRUE_COUNTERPART, trueCounterpart.toPreppedString());
			values.put(TRUE_COUNTERPART, trueCounterpart.toString());
		}
		values.put(BODY, body.length() > Config.MAX_STORAGE_MESSAGE_CHARS ? body.substring(0,Config.MAX_STORAGE_MESSAGE_CHARS) : body);
		values.put(TIME_SENT, timeSent);


@@ 439,7 434,7 @@ public class Message extends AbstractEntity {

	public boolean addReadByMarker(ReadByMarker readByMarker) {
		if (readByMarker.getRealJid() != null) {
			if (readByMarker.getRealJid().toBareJid().equals(trueCounterpart)) {
			if (readByMarker.getRealJid().asBareJid().equals(trueCounterpart)) {
				return false;
			}
		} else if (readByMarker.getFullJid() != null) {


@@ 569,7 564,7 @@ public class Message extends AbstractEntity {
						((this.axolotlFingerprint == null && message.axolotlFingerprint == null) || this.axolotlFingerprint.equals(message.getFingerprint())) &&
						UIHelper.sameDay(message.getTimeSent(),this.getTimeSent()) &&
						this.getReadByMarkers().equals(message.getReadByMarkers()) &&
						!this.conversation.getJid().toBareJid().toString().equals(Config.BUG_REPORTS)
						!this.conversation.getJid().asBareJid().toString().equals(Config.BUG_REPORTS)
				);
	}



@@ 651,15 646,15 @@ public class Message extends AbstractEntity {

	public boolean fixCounterpart() {
		Presences presences = conversation.getContact().getPresences();
		if (counterpart != null && presences.has(counterpart.getResourcepart())) {
		if (counterpart != null && presences.has(counterpart.getResource())) {
			return true;
		} else if (presences.size() >= 1) {
			try {
				counterpart = Jid.fromParts(conversation.getJid().getLocalpart(),
						conversation.getJid().getDomainpart(),
				counterpart = Jid.of(conversation.getJid().getLocal(),
						conversation.getJid().getDomain(),
						presences.toResourceArray()[0]);
				return true;
			} catch (InvalidJidException e) {
			} catch (IllegalArgumentException e) {
				counterpart = null;
				return false;
			}

M src/main/java/eu/siacs/conversations/entities/MucOptions.java => src/main/java/eu/siacs/conversations/entities/MucOptions.java +12 -13
@@ 15,9 15,8 @@ import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.chatstate.ChatState;
import eu.siacs.conversations.xmpp.forms.Data;
import eu.siacs.conversations.xmpp.forms.Field;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar;
import rocks.xmpp.addr.Jid;

@SuppressLint("DefaultLocale")
public class MucOptions {


@@ 179,11 178,11 @@ public class MucOptions {
		}

		public String getName() {
			return fullJid == null ? null : fullJid.getResourcepart();
			return fullJid == null ? null : fullJid.getResource();
		}

		public void setRealJid(Jid jid) {
			this.realJid = jid != null ? jid.toBareJid() : null;
			this.realJid = jid != null ? jid.asBareJid() : null;
		}

		public Role getRole() {


@@ 319,7 318,7 @@ public class MucOptions {
		}

		public boolean realJidMatchesAccount() {
			return realJid != null && realJid.equals(options.account.getJid().toBareJid());
			return realJid != null && realJid.equals(options.account.getJid().asBareJid());
		}

		@Override


@@ 448,7 447,7 @@ public class MucOptions {
						break;
					}
				}
				boolean self = user.realJid != null && user.realJid.equals(account.getJid().toBareJid());
				boolean self = user.realJid != null && user.realJid.equals(account.getJid().asBareJid());
				if (membersOnly()
						&& nonanonymous()
						&& user.affiliation.ranks(Affiliation.MEMBER)


@@ 536,7 535,7 @@ public class MucOptions {

	public User findUser(ReadByMarker readByMarker) {
		if (readByMarker.getRealJid() != null) {
			User user = findUserByRealJid(readByMarker.getRealJid().toBareJid());
			User user = findUserByRealJid(readByMarker.getRealJid().asBareJid());
			if (user == null) {
				user = new User(this,readByMarker.getFullJid());
				user.setRealJid(readByMarker.getRealJid());


@@ 550,7 549,7 @@ public class MucOptions {
	}

	public boolean isContactInRoom(Contact contact) {
		return findUserByRealJid(contact.getJid().toBareJid()) != null;
		return findUserByRealJid(contact.getJid().asBareJid()) != null;
	}

	public boolean isUserInRoom(Jid jid) {


@@ 606,7 605,7 @@ public class MucOptions {
	public List<User> getUsers(int max) {
		ArrayList<User> subset = new ArrayList<>();
		HashSet<Jid> jids = new HashSet<>();
		jids.add(account.getJid().toBareJid());
		jids.add(account.getJid().asBareJid());
		synchronized (users) {
			for(User user : users) {
				if (user.getRealJid() == null || jids.add(user.getRealJid())) {


@@ 632,7 631,7 @@ public class MucOptions {
				&& !conversation.getBookmark().getNick().trim().isEmpty()) {
			return conversation.getBookmark().getNick().trim();
		} else if (!conversation.getJid().isBareJid()) {
			return conversation.getJid().getResourcepart();
			return conversation.getJid().getResource();
		} else {
			return JidHelper.localPartOrFallback(account.getJid());
		}


@@ 756,15 755,15 @@ public class MucOptions {

	public Jid createJoinJid(String nick) {
		try {
			return Jid.fromString(this.conversation.getJid().toBareJid().toString() + "/" + nick);
		} catch (final InvalidJidException e) {
			return Jid.of(this.conversation.getJid().asBareJid().toString() + "/" + nick);
		} catch (final IllegalArgumentException e) {
			return null;
		}
	}

	public Jid getTrueCounterpart(Jid jid) {
		if (jid.equals(getSelf().getFullJid())) {
			return account.getJid().toBareJid();
			return account.getJid().asBareJid();
		}
		User user = findUserByFullJid(jid);
		return user == null ? null : user.realJid;

M src/main/java/eu/siacs/conversations/entities/ReadByMarker.java => src/main/java/eu/siacs/conversations/entities/ReadByMarker.java +9 -10
@@ 8,8 8,7 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class ReadByMarker {



@@ 52,14 51,14 @@ public class ReadByMarker {
		JSONObject jsonObject = new JSONObject();
		if (fullJid != null) {
			try {
				jsonObject.put("fullJid", fullJid.toPreppedString());
				jsonObject.put("fullJid", fullJid.toString());
			} catch (JSONException e) {
				//ignore
			}
		}
		if (realJid != null) {
			try {
				jsonObject.put("realJid", realJid.toPreppedString());
				jsonObject.put("realJid", realJid.toString());
			} catch (JSONException e) {
				//ignore
			}


@@ 82,7 81,7 @@ public class ReadByMarker {
	public static ReadByMarker from(Jid fullJid, Jid realJid) {
		final ReadByMarker marker = new ReadByMarker();
		marker.fullJid = fullJid;
		marker.realJid = realJid == null ? null : realJid.toBareJid();
		marker.realJid = realJid == null ? null : realJid.asBareJid();
		return marker;
	}



@@ 111,13 110,13 @@ public class ReadByMarker {
	public static ReadByMarker fromJson(JSONObject jsonObject) {
		ReadByMarker marker = new ReadByMarker();
		try {
			marker.fullJid = Jid.fromString(jsonObject.getString("fullJid"),true);
		} catch (JSONException | InvalidJidException e) {
			marker.fullJid = Jid.of(jsonObject.getString("fullJid"));
		} catch (JSONException | IllegalArgumentException e) {
			marker.fullJid = null;
		}
		try {
			marker.realJid = Jid.fromString(jsonObject.getString("realJid"),true);
		} catch (JSONException | InvalidJidException e) {
			marker.realJid = Jid.of(jsonObject.getString("realJid"));
		} catch (JSONException | IllegalArgumentException e) {
			marker.realJid = null;
		}
		return marker;


@@ 142,7 141,7 @@ public class ReadByMarker {
	public static boolean contains(ReadByMarker needle, Set<ReadByMarker> readByMarkers) {
		for(ReadByMarker marker : readByMarkers) {
			if (marker.realJid != null && needle.realJid != null) {
				if (marker.realJid.toBareJid().equals(needle.realJid.toBareJid())) {
				if (marker.realJid.asBareJid().equals(needle.realJid.asBareJid())) {
					return true;
				}
			} else if (marker.fullJid != null && needle.fullJid != null) {

M src/main/java/eu/siacs/conversations/entities/ReceiptRequest.java => src/main/java/eu/siacs/conversations/entities/ReceiptRequest.java +2 -2
@@ 29,7 29,7 @@

package eu.siacs.conversations.entities;

import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class ReceiptRequest {



@@ 43,7 43,7 @@ public class ReceiptRequest {
		if (jid == null) {
			throw new IllegalArgumentException("jid must not be null");
		}
		this.jid = jid.toBareJid();
		this.jid = jid.asBareJid();
		this.id = id;
	}


M src/main/java/eu/siacs/conversations/entities/Roster.java => src/main/java/eu/siacs/conversations/entities/Roster.java +8 -7
@@ 5,7 5,8 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;


public class Roster {
	final Account account;


@@ 21,7 22,7 @@ public class Roster {
			return null;
		}
		synchronized (this.contacts) {
			Contact contact = contacts.get(jid.toBareJid());
			Contact contact = contacts.get(jid.asBareJid());
			if (contact != null && contact.showInRoster()) {
				return contact;
			} else {


@@ 32,13 33,13 @@ public class Roster {

	public Contact getContact(final Jid jid) {
		synchronized (this.contacts) {
			if (!contacts.containsKey(jid.toBareJid())) {
				Contact contact = new Contact(jid.toBareJid());
			if (!contacts.containsKey(jid.asBareJid())) {
				Contact contact = new Contact(jid.asBareJid());
				contact.setAccount(account);
				contacts.put(contact.getJid().toBareJid(), contact);
				contacts.put(contact.getJid().asBareJid(), contact);
				return contact;
			}
			return contacts.get(jid.toBareJid());
			return contacts.get(jid.asBareJid());
		}
	}



@@ 78,7 79,7 @@ public class Roster {
		contact.setAccount(account);
		contact.setOption(Contact.Options.IN_ROSTER);
		synchronized (this.contacts) {
			contacts.put(contact.getJid().toBareJid(), contact);
			contacts.put(contact.getJid().asBareJid(), contact);
		}
	}


M src/main/java/eu/siacs/conversations/generator/IqGenerator.java => src/main/java/eu/siacs/conversations/generator/IqGenerator.java +8 -8
@@ 31,9 31,9 @@ import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.forms.Data;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import rocks.xmpp.addr.Jid;

public class IqGenerator extends AbstractGenerator {



@@ 284,7 284,7 @@ public class IqGenerator extends AbstractGenerator {
	public IqPacket generateSetBlockRequest(final Jid jid, boolean reportSpam) {
		final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
		final Element block = iq.addChild("block", Namespace.BLOCKING);
		final Element item = block.addChild("item").setAttribute("jid", jid.toBareJid().toString());
		final Element item = block.addChild("item").setAttribute("jid", jid.asBareJid().toString());
		if (reportSpam) {
			item.addChild("report", "urn:xmpp:reporting:0").addChild("spam");
		}


@@ 295,7 295,7 @@ public class IqGenerator extends AbstractGenerator {
	public IqPacket generateSetUnblockRequest(final Jid jid) {
		final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
		final Element block = iq.addChild("unblock", Namespace.BLOCKING);
		block.addChild("item").setAttribute("jid", jid.toBareJid().toString());
		block.addChild("item").setAttribute("jid", jid.asBareJid().toString());
		return iq;
	}



@@ 304,7 304,7 @@ public class IqGenerator extends AbstractGenerator {
		packet.setTo(account.getServer());
		final Element query = packet.addChild("query", Namespace.REGISTER);
		final Jid jid = account.getJid();
		query.addChild("username").setContent(jid.getLocalpart());
		query.addChild("username").setContent(jid.getLocal());
		query.addChild("password").setContent(newPassword);
		return packet;
	}


@@ 317,7 317,7 @@ public class IqGenerator extends AbstractGenerator {

	public IqPacket changeAffiliation(Conversation conference, List<Jid> jids, String affiliation) {
		IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
		packet.setTo(conference.getJid().toBareJid());
		packet.setTo(conference.getJid().asBareJid());
		packet.setFrom(conference.getAccount().getJid());
		Element query = packet.query("http://jabber.org/protocol/muc#admin");
		for(Jid jid : jids) {


@@ 330,7 330,7 @@ public class IqGenerator extends AbstractGenerator {

	public IqPacket changeRole(Conversation conference, String nick, String role) {
		IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
		packet.setTo(conference.getJid().toBareJid());
		packet.setTo(conference.getJid().asBareJid());
		packet.setFrom(conference.getAccount().getJid());
		Element item = packet.query("http://jabber.org/protocol/muc#admin").addChild("item");
		item.setAttribute("nick", nick);


@@ 367,7 367,7 @@ public class IqGenerator extends AbstractGenerator {

	public IqPacket generateCreateAccountWithCaptcha(Account account, String id, Data data) {
		final IqPacket register = new IqPacket(IqPacket.TYPE.SET);
		register.setFrom(account.getJid().toBareJid());
		register.setFrom(account.getJid().asBareJid());
		register.setTo(account.getServer());
		register.setId(id);
		Element query = register.query("jabber:iq:register");


@@ 406,7 406,7 @@ public class IqGenerator extends AbstractGenerator {

	public IqPacket queryAffiliation(Conversation conversation, String affiliation) {
		IqPacket packet = new IqPacket(IqPacket.TYPE.GET);
		packet.setTo(conversation.getJid().toBareJid());
		packet.setTo(conversation.getJid().asBareJid());
		packet.query("http://jabber.org/protocol/muc#admin").addChild("item").setAttribute("affiliation",affiliation);
		return packet;
	}

M src/main/java/eu/siacs/conversations/generator/MessageGenerator.java => src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +10 -10
@@ 17,8 17,8 @@ import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.chatstate.ChatState;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
import rocks.xmpp.addr.Jid;

public class MessageGenerator extends AbstractGenerator {
	private static final String OMEMO_FALLBACK_MESSAGE = "I sent you an OMEMO encrypted message but your client doesn’t seem to support that. Find more information on https://conversations.im/omemo";


@@ 47,7 47,7 @@ public class MessageGenerator extends AbstractGenerator {
				packet.addChild("request", "urn:xmpp:receipts");
			}
		} else {
			packet.setTo(message.getCounterpart().toBareJid());
			packet.setTo(message.getCounterpart().asBareJid());
			packet.setType(MessagePacket.TYPE_GROUPCHAT);
		}
		if (conversation.isSingleOrPrivateAndNonAnonymous() && message.getType() != Message.TYPE_PRIVATE) {


@@ 147,7 147,7 @@ public class MessageGenerator extends AbstractGenerator {
		final Account account = conversation.getAccount();
		MessagePacket packet = new MessagePacket();
		packet.setType(conversation.getMode() == Conversation.MODE_MULTI ? MessagePacket.TYPE_GROUPCHAT : MessagePacket.TYPE_CHAT);
		packet.setTo(conversation.getJid().toBareJid());
		packet.setTo(conversation.getJid().asBareJid());
		packet.setFrom(account.getJid());
		packet.addChild(ChatState.toElement(conversation.getOutgoingChatState()));
		packet.addChild("no-store", "urn:xmpp:hints");


@@ 158,12 158,12 @@ public class MessageGenerator extends AbstractGenerator {
	public MessagePacket confirm(final Account account, final Jid to, final String id, final Jid counterpart, final boolean groupChat) {
		MessagePacket packet = new MessagePacket();
		packet.setType(groupChat ? MessagePacket.TYPE_GROUPCHAT : MessagePacket.TYPE_CHAT);
		packet.setTo(groupChat ? to.toBareJid() : to);
		packet.setTo(groupChat ? to.asBareJid() : to);
		packet.setFrom(account.getJid());
		Element displayed = packet.addChild("displayed","urn:xmpp:chat-markers:0");
		displayed.setAttribute("id", id);
		if (groupChat && counterpart != null) {
			displayed.setAttribute("sender",counterpart.toPreppedString());
			displayed.setAttribute("sender",counterpart.toString());
		}
		packet.addChild("store", "urn:xmpp:hints");
		return packet;


@@ 172,11 172,11 @@ public class MessageGenerator extends AbstractGenerator {
	public MessagePacket conferenceSubject(Conversation conversation,String subject) {
		MessagePacket packet = new MessagePacket();
		packet.setType(MessagePacket.TYPE_GROUPCHAT);
		packet.setTo(conversation.getJid().toBareJid());
		packet.setTo(conversation.getJid().asBareJid());
		Element subjectChild = new Element("subject");
		subjectChild.setContent(subject);
		packet.addChild(subjectChild);
		packet.setFrom(conversation.getAccount().getJid().toBareJid());
		packet.setFrom(conversation.getAccount().getJid().asBareJid());
		return packet;
	}



@@ 186,7 186,7 @@ public class MessageGenerator extends AbstractGenerator {
		packet.setTo(contact);
		packet.setFrom(conversation.getAccount().getJid());
		Element x = packet.addChild("x", "jabber:x:conference");
		x.setAttribute("jid", conversation.getJid().toBareJid().toString());
		x.setAttribute("jid", conversation.getJid().asBareJid().toString());
		String password = conversation.getMucOptions().getPassword();
		if (password != null) {
			x.setAttribute("password",password);


@@ 196,12 196,12 @@ public class MessageGenerator extends AbstractGenerator {

	public MessagePacket invite(Conversation conversation, Jid contact) {
		MessagePacket packet = new MessagePacket();
		packet.setTo(conversation.getJid().toBareJid());
		packet.setTo(conversation.getJid().asBareJid());
		packet.setFrom(conversation.getAccount().getJid());
		Element x = new Element("x");
		x.setAttribute("xmlns", "http://jabber.org/protocol/muc#user");
		Element invite = new Element("invite");
		invite.setAttribute("to", contact.toBareJid().toString());
		invite.setAttribute("to", contact.asBareJid().toString());
		x.addChild(invite);
		packet.addChild(x);
		return packet;

M src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java => src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java +1 -1
@@ 18,7 18,7 @@ public class PresenceGenerator extends AbstractGenerator {
		PresencePacket packet = new PresencePacket();
		packet.setAttribute("type", type);
		packet.setTo(contact.getJid());
		packet.setFrom(contact.getAccount().getJid().toBareJid());
		packet.setFrom(contact.getAccount().getJid().asBareJid());
		return packet;
	}


M src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java => src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java +3 -3
@@ 29,8 29,8 @@ import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import rocks.xmpp.addr.Jid;

public class HttpUploadConnection implements Transferable {



@@ 121,7 121,7 @@ public class HttpUploadConnection implements Transferable {
		try {
			pair = AbstractConnectionManager.createInputStream(file, true);
		} catch (FileNotFoundException e) {
			Log.d(Config.LOGTAG, account.getJid().toBareJid()+": could not find file to upload - "+e.getMessage());
			Log.d(Config.LOGTAG, account.getJid().asBareJid()+": could not find file to upload - "+e.getMessage());
			fail(e.getMessage());
			return;
		}


@@ 220,7 220,7 @@ public class HttpUploadConnection implements Transferable {
				mXmppConnectionService.getFileBackend().updateFileParams(message, mGetUrl);
				mXmppConnectionService.getFileBackend().updateMediaScanner(file);
				message.setTransferable(null);
				message.setCounterpart(message.getConversation().getJid().toBareJid());
				message.setCounterpart(message.getConversation().getJid().asBareJid());
				mXmppConnectionService.resendMessage(message, delayed);
			} else {
				Log.d(Config.LOGTAG,"http upload failed because response code was "+code);

M src/main/java/eu/siacs/conversations/parser/AbstractParser.java => src/main/java/eu/siacs/conversations/parser/AbstractParser.java +7 -8
@@ 11,9 11,8 @@ import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
import rocks.xmpp.addr.Jid;

public abstract class AbstractParser {



@@ 39,7 38,7 @@ public abstract class AbstractParser {
		for(Element child : element.getChildren()) {
			if ("delay".equals(child.getName()) && "urn:xmpp:delay".equals(child.getNamespace())) {
				final Jid f = to == null ? null : child.getAttributeAsJid("from");
				if (f != null && (to.toBareJid().equals(f) || to.getDomainpart().equals(f.toString()))) {
				if (f != null && (to.asBareJid().equals(f) || to.getDomain().equals(f.toString()))) {
					continue;
				}
				final String stamp = child.getAttribute("stamp");


@@ 86,7 85,7 @@ public abstract class AbstractParser {

	protected void updateLastseen(final Account account, final Jid from) {
		final Contact contact = account.getRoster().getContact(from);
		contact.setLastResource(from.isBareJid() ? "" : from.getResourcepart());
		contact.setLastResource(from.isBareJid() ? "" : from.getResource());
	}

	protected String avatarData(Element items) {


@@ 102,15 101,15 @@ public abstract class AbstractParser {
	}

	public static MucOptions.User parseItem(Conversation conference, Element item, Jid fullJid) {
		final String local = conference.getJid().getLocalpart();
		final String domain = conference.getJid().getDomainpart();
		final String local = conference.getJid().getLocal();
		final String domain = conference.getJid().getDomain();
		String affiliation = item.getAttribute("affiliation");
		String role = item.getAttribute("role");
		String nick = item.getAttribute("nick");
		if (nick != null && fullJid == null) {
			try {
				fullJid = Jid.fromParts(local, domain, nick);
			} catch (InvalidJidException e) {
				fullJid = Jid.of(local, domain, nick);
			} catch (IllegalArgumentException e) {
				fullJid = null;
			}
		}

M src/main/java/eu/siacs/conversations/parser/IqParser.java => src/main/java/eu/siacs/conversations/parser/IqParser.java +2 -2
@@ 31,8 31,8 @@ import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import rocks.xmpp.addr.Jid;

public class IqParser extends AbstractParser implements OnIqPacketReceived {



@@ 70,7 70,7 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
				}
				boolean both = contact.getOption(Contact.Options.TO) && contact.getOption(Contact.Options.FROM);
				if ((both != bothPre) && both) {
					Log.d(Config.LOGTAG,account.getJid().toBareJid()+": gained mutual presence subscription with "+contact.getJid());
					Log.d(Config.LOGTAG,account.getJid().asBareJid()+": gained mutual presence subscription with "+contact.getJid());
					AxolotlService axolotlService = account.getAxolotlService();
					if (axolotlService != null) {
						axolotlService.clearErrorsInFetchStatusMap(contact.getJid());

M src/main/java/eu/siacs/conversations/parser/MessageParser.java => src/main/java/eu/siacs/conversations/parser/MessageParser.java +35 -35
@@ 32,9 32,9 @@ import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
import eu.siacs.conversations.xmpp.chatstate.ChatState;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
import rocks.xmpp.addr.Jid;

public class MessageParser extends AbstractParser implements OnMessagePacketReceived {



@@ 47,7 47,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
		if (state != null && c != null) {
			final Account account = c.getAccount();
			Jid from = packet.getFrom();
			if (from.toBareJid().equals(account.getJid().toBareJid())) {
			if (from.asBareJid().equals(account.getJid().asBareJid())) {
				c.setOutgoingChatState(state);
				if (state == ChatState.ACTIVE || state == ChatState.COMPOSING) {
					mXmppConnectionService.markRead(c);


@@ 74,9 74,9 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
		final AxolotlService service = conversation.getAccount().getAxolotlService();
		final XmppAxolotlMessage xmppAxolotlMessage;
		try {
			xmppAxolotlMessage = XmppAxolotlMessage.fromElement(axolotlMessage, from.toBareJid());
			xmppAxolotlMessage = XmppAxolotlMessage.fromElement(axolotlMessage, from.asBareJid());
		} catch (Exception e) {
			Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": invalid omemo message received " + e.getMessage());
			Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": invalid omemo message received " + e.getMessage());
			return null;
		}
		if (xmppAxolotlMessage.hasPayload()) {


@@ 88,7 88,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
				return finishedMessage;
			}
		} else {
			Log.d(Config.LOGTAG,conversation.getAccount().getJid().toBareJid()+": received OMEMO key transport message");
			Log.d(Config.LOGTAG,conversation.getAccount().getJid().asBareJid()+": received OMEMO key transport message");
			service.processReceivingKeyTransportMessage(xmppAxolotlMessage, postpone);
		}
		return null;


@@ 145,11 145,11 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
		final Jid by;
		final boolean safeToExtract;
		if (isTypeGroupChat) {
			by = conversation.getJid().toBareJid();
			by = conversation.getJid().asBareJid();
			safeToExtract = conversation.getMucOptions().hasFeature(Namespace.STANZA_IDS);
		} else {
			Account account = conversation.getAccount();
			by = account.getJid().toBareJid();
			by = account.getJid().asBareJid();
			safeToExtract = account.getXmppConnection().getFeatures().stanzaIds();
		}
		return safeToExtract ? extractStanzaId(packet, by) : null;


@@ 172,9 172,9 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
		if ("urn:xmpp:avatar:metadata".equals(node)) {
			Avatar avatar = Avatar.parseMetadata(items);
			if (avatar != null) {
				avatar.owner = from.toBareJid();
				avatar.owner = from.asBareJid();
				if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) {
					if (account.getJid().toBareJid().equals(from)) {
					if (account.getJid().asBareJid().equals(from)) {
						if (account.setAvatar(avatar.getFilename())) {
							mXmppConnectionService.databaseBackend.updateAccount(account);
						}


@@ 218,7 218,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
			Jid from = packet.getFrom();
			if (from != null) {
				Message message = mXmppConnectionService.markMessage(account,
						from.toBareJid(),
						from.asBareJid(),
						packet.getId(),
						Message.STATUS_SEND_FAILED,
						extractErrorMessage(packet));


@@ 257,7 257,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
			serverMsgId = result.getAttribute("id");
			query.incrementMessageCount();
		} else if (query != null) {
			Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": received mam result from invalid sender");
			Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received mam result from invalid sender");
			return;
		} else if (original.fromServer(account)) {
			Pair<MessagePacket, Long> f;


@@ 306,7 306,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece

		boolean isTypeGroupChat = packet.getType() == MessagePacket.TYPE_GROUPCHAT;
		if (query != null && !query.muc() && isTypeGroupChat) {
			Log.e(Config.LOGTAG,account.getJid().toBareJid()+": received groupchat ("+from+") message on regular MAM request. skipping");
			Log.e(Config.LOGTAG,account.getJid().asBareJid()+": received groupchat ("+from+") message on regular MAM request. skipping");
			return;
		}
		boolean isProperlyAddressed = (to != null) && (!to.isBareJid() || account.countPresences() == 0);


@@ 314,7 314,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
		boolean selfAddressed;
		if (packet.fromAccount(account)) {
			status = Message.STATUS_SEND;
			selfAddressed = to == null || account.getJid().toBareJid().equals(to.toBareJid());
			selfAddressed = to == null || account.getJid().asBareJid().equals(to.asBareJid());
			if (selfAddressed) {
				counterpart = from;
			} else {


@@ 332,7 332,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
		}

		if ((body != null || pgpEncrypted != null || (axolotlEncrypted != null && axolotlEncrypted.hasChild("payload")) || oobUrl != null) && !isMucStatusMessage) {
			final Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, counterpart.toBareJid(), isTypeGroupChat, false, query, false);
			final Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, counterpart.asBareJid(), isTypeGroupChat, false, query, false);
			final boolean conversationMultiMode = conversation.getMode() == Conversation.MODE_MULTI;

			if (serverMsgId == null) {


@@ 384,7 384,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
				}
				message = parseAxolotlChat(axolotlEncrypted, origin, conversation, status, query != null);
				if (message == null) {
					if (query == null &&  extractChatState(mXmppConnectionService.find(account, counterpart.toBareJid()), isTypeGroupChat, packet)) {
					if (query == null &&  extractChatState(mXmppConnectionService.find(account, counterpart.asBareJid()), isTypeGroupChat, packet)) {
						mXmppConnectionService.updateConversationUi();
					}
					if (query != null && status == Message.STATUS_SEND && remoteMsgId != null) {


@@ 392,7 392,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
						if (previouslySent != null && previouslySent.getServerMsgId() == null && serverMsgId != null) {
							previouslySent.setServerMsgId(serverMsgId);
							mXmppConnectionService.databaseBackend.updateMessage(previouslySent);
							Log.d(Config.LOGTAG,account.getJid().toBareJid()+": encountered previously sent OMEMO message without serverId. updating...");
							Log.d(Config.LOGTAG,account.getJid().asBareJid()+": encountered previously sent OMEMO message without serverId. updating...");
						}
					}
					return;


@@ 432,7 432,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
				} else {
					trueCounterpart = fallback;
				}
				if (trueCounterpart != null && trueCounterpart.toBareJid().equals(account.getJid().toBareJid())) {
				if (trueCounterpart != null && trueCounterpart.asBareJid().equals(account.getJid().asBareJid())) {
					status = isTypeGroupChat ? Message.STATUS_SEND_RECEIVED : Message.STATUS_SEND;
				}
				message.setStatus(status);


@@ 470,7 470,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
							if (replacedMessage.getStatus() == Message.STATUS_RECEIVED) {
								replacedMessage.markUnread();
							}
							extractChatState(mXmppConnectionService.find(account, counterpart.toBareJid()), isTypeGroupChat, packet);
							extractChatState(mXmppConnectionService.find(account, counterpart.asBareJid()), isTypeGroupChat, packet);
							mXmppConnectionService.updateMessage(replacedMessage, uuid);
							mXmppConnectionService.getNotificationService().updateNotification(false);
							if (mXmppConnectionService.confirmMessages()


@@ 488,14 488,14 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
						}
						return;
					} else {
						Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": received message correction but verification didn't check out");
						Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received message correction but verification didn't check out");
					}
				}
			}

			long deletionDate = mXmppConnectionService.getAutomaticMessageDeletionDate();
			if (deletionDate != 0 && message.getTimeSent() < deletionDate) {
				Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": skipping message from " + message.getCounterpart().toString() + " because it was sent prior to our deletion date");
				Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": skipping message from " + message.getCounterpart().toString() + " because it was sent prior to our deletion date");
				return;
			}



@@ 547,7 547,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
			}

			if (query == null) {
				extractChatState(mXmppConnectionService.find(account, counterpart.toBareJid()), isTypeGroupChat, packet);
				extractChatState(mXmppConnectionService.find(account, counterpart.asBareJid()), isTypeGroupChat, packet);
				mXmppConnectionService.updateConversationUi();
			}



@@ 573,7 573,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
			}
		} else if (!packet.hasChild("body")) { //no body

			final Conversation conversation = mXmppConnectionService.find(account, from.toBareJid());
			final Conversation conversation = mXmppConnectionService.find(account, from.asBareJid());
			if (axolotlEncrypted != null) {
				Jid origin;
				if (conversation != null && conversation.getMode() == Conversation.MODE_MULTI) {


@@ 589,16 589,16 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
					origin = from;
				}
				try {
					final XmppAxolotlMessage xmppAxolotlMessage = XmppAxolotlMessage.fromElement(axolotlEncrypted, origin.toBareJid());
					final XmppAxolotlMessage xmppAxolotlMessage = XmppAxolotlMessage.fromElement(axolotlEncrypted, origin.asBareJid());
					account.getAxolotlService().processReceivingKeyTransportMessage(xmppAxolotlMessage, query != null);
					Log.d(Config.LOGTAG,account.getJid().toBareJid()+": omemo key transport message received from "+origin);
					Log.d(Config.LOGTAG,account.getJid().asBareJid()+": omemo key transport message received from "+origin);
				} catch (Exception e) {
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": invalid omemo key transport message received " + e.getMessage());
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": invalid omemo key transport message received " + e.getMessage());
					return;
				}
			}

			if (query == null && extractChatState(mXmppConnectionService.find(account, counterpart.toBareJid()), isTypeGroupChat, packet)) {
			if (query == null && extractChatState(mXmppConnectionService.find(account, counterpart.asBareJid()), isTypeGroupChat, packet)) {
				mXmppConnectionService.updateConversationUi();
			}



@@ 637,7 637,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
						MucOptions.User user = AbstractParser.parseItem(conversation, child);
						Log.d(Config.LOGTAG, account.getJid() + ": changing affiliation for "
								+ user.getRealJid() + " to " + user.getAffiliation() + " in "
								+ conversation.getJid().toBareJid());
								+ conversation.getJid().asBareJid());
						if (!user.realJidMatchesAccount()) {
							boolean isNew = conversation.getMucOptions().updateUser(user);
							mXmppConnectionService.getAvatarService().clear(conversation);


@@ 648,7 648,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
								Jid jid = user.getRealJid();
								List<Jid> cryptoTargets = conversation.getAcceptedCryptoTargets();
								if (cryptoTargets.remove(user.getRealJid())) {
									Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": removed " + jid + " from crypto targets of " + conversation.getName());
									Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": removed " + jid + " from crypto targets of " + conversation.getName());
									conversation.setAcceptedCryptoTargets(cryptoTargets);
									mXmppConnectionService.updateConversation(conversation);
								}


@@ 676,7 676,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
					query.pendingReceiptRequests.remove(new ReceiptRequest(packet.getTo(),id));
				}
			} else {
				mXmppConnectionService.markMessage(account, from.toBareJid(), received.getAttribute("id"), Message.STATUS_SEND_RECEIVED);
				mXmppConnectionService.markMessage(account, from.asBareJid(), received.getAttribute("id"), Message.STATUS_SEND_RECEIVED);
			}
		}
		Element displayed = packet.findChild("displayed", "urn:xmpp:chat-markers:0");


@@ 686,13 686,13 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
			if (packet.fromAccount(account) && !selfAddressed) {
				dismissNotification(account, counterpart, query);
			} else if (isTypeGroupChat) {
				Conversation conversation = mXmppConnectionService.find(account, counterpart.toBareJid());
				Conversation conversation = mXmppConnectionService.find(account, counterpart.asBareJid());
				if (conversation != null && id != null && sender != null) {
					Message message = conversation.findMessageWithRemoteId(id, sender);
					if (message != null) {
						final Jid fallback = conversation.getMucOptions().getTrueCounterpart(counterpart);
						final Jid trueJid = getTrueCounterpart((query != null && query.safeToExtractTrueCounterpart()) ? mucUserElement : null, fallback);
						final boolean trueJidMatchesAccount = account.getJid().toBareJid().equals(trueJid == null ? null : trueJid.toBareJid());
						final boolean trueJidMatchesAccount = account.getJid().asBareJid().equals(trueJid == null ? null : trueJid.asBareJid());
						if (trueJidMatchesAccount || conversation.getMucOptions().isSelf(counterpart)) {
							if (!message.isRead() && (query == null || query.isCatchup())) { //checking if message is unread fixes race conditions with reflections
								mXmppConnectionService.markRead(conversation);


@@ 700,14 700,14 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
						} else  if (!counterpart.isBareJid() && trueJid != null){
							ReadByMarker readByMarker = ReadByMarker.from(counterpart, trueJid);
							if (message.addReadByMarker(readByMarker)) {
								Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": added read by (" + readByMarker.getRealJid() + ") to message '" + message.getBody() + "'");
								Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": added read by (" + readByMarker.getRealJid() + ") to message '" + message.getBody() + "'");
								mXmppConnectionService.updateMessage(message);
							}
						}
					}
				}
			} else {
				final Message displayedMessage = mXmppConnectionService.markMessage(account, from.toBareJid(), id, Message.STATUS_SEND_DISPLAYED);
				final Message displayedMessage = mXmppConnectionService.markMessage(account, from.asBareJid(), id, Message.STATUS_SEND_DISPLAYED);
				Message message = displayedMessage == null ? null : displayedMessage.prev();
				while (message != null
						&& message.getStatus() == Message.STATUS_SEND_RECEIVED


@@ 736,7 736,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
	}

	private void dismissNotification(Account account, Jid counterpart, MessageArchiveService.Query query) {
		Conversation conversation = mXmppConnectionService.find(account, counterpart.toBareJid());
		Conversation conversation = mXmppConnectionService.find(account, counterpart.asBareJid());
		if (conversation != null && (query == null || query.isCatchup())) {
			mXmppConnectionService.markRead(conversation); //TODO only mark messages read that are older than timestamp
		}


@@ 777,7 777,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece

	private void activateGracePeriod(Account account) {
		long duration = mXmppConnectionService.getLongPreference("grace_period_length", R.integer.grace_period) * 1000;
		Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": activating grace period till " + TIME_FORMAT.format(new Date(System.currentTimeMillis() + duration)));
		Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": activating grace period till " + TIME_FORMAT.format(new Date(System.currentTimeMillis() + duration)));
		account.activateGracePeriod(duration);
	}
}

M src/main/java/eu/siacs/conversations/parser/PresenceParser.java => src/main/java/eu/siacs/conversations/parser/PresenceParser.java +9 -9
@@ 23,9 23,9 @@ import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar;
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
import rocks.xmpp.addr.Jid;

public class PresenceParser extends AbstractParser implements
		OnPresencePacketReceived {


@@ 35,7 35,7 @@ public class PresenceParser extends AbstractParser implements
	}

	public void parseConferencePresence(PresencePacket packet, Account account) {
		final Conversation conversation = packet.getFrom() == null ? null : mXmppConnectionService.find(account, packet.getFrom().toBareJid());
		final Conversation conversation = packet.getFrom() == null ? null : mXmppConnectionService.find(account, packet.getFrom().asBareJid());
		if (conversation != null) {
			final MucOptions mucOptions = conversation.getMucOptions();
			boolean before = mucOptions.online();


@@ 89,9 89,9 @@ public class PresenceParser extends AbstractParser implements
							axolotlService.fetchDeviceIds(user.getRealJid());
						}
						if (codes.contains(MucOptions.STATUS_CODE_ROOM_CREATED) && mucOptions.autoPushConfiguration()) {
							Log.d(Config.LOGTAG,mucOptions.getAccount().getJid().toBareJid()
							Log.d(Config.LOGTAG,mucOptions.getAccount().getJid().asBareJid()
									+": room '"
									+mucOptions.getConversation().getJid().toBareJid()
									+mucOptions.getConversation().getJid().asBareJid()
									+"' created. pushing default configuration");
							mXmppConnectionService.pushConferenceConfiguration(mucOptions.getConversation(),
									IqGenerator.defaultRoomConfiguration(),


@@ 217,15 217,15 @@ public class PresenceParser extends AbstractParser implements
		final String type = packet.getAttribute("type");
		final Contact contact = account.getRoster().getContact(from);
		if (type == null) {
			final String resource = from.isBareJid() ? "" : from.getResourcepart();
			final String resource = from.isBareJid() ? "" : from.getResource();
			if (contact.setPresenceName(packet.findChildContent("nick", Namespace.NICK))) {
				mXmppConnectionService.getAvatarService().clear(contact);
			}
			Avatar avatar = Avatar.parsePresence(packet.findChild("x", "vcard-temp:x:update"));
			if (avatar != null && (!contact.isSelf() || account.getAvatar() == null)) {
				avatar.owner = from.toBareJid();
				avatar.owner = from.asBareJid();
				if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) {
					if (avatar.owner.equals(account.getJid().toBareJid())) {
					if (avatar.owner.equals(account.getJid().asBareJid())) {
						account.setAvatar(avatar.getFilename());
						mXmppConnectionService.databaseBackend.updateAccount(account);
						mXmppConnectionService.getAvatarService().clear(account);


@@ 284,7 284,7 @@ public class PresenceParser extends AbstractParser implements
			if (from.isBareJid()) {
				contact.clearPresences();
			} else {
				contact.removePresence(from.getResourcepart());
				contact.removePresence(from.getResource());
			}
			mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, false);
		} else if (type.equals("subscribe")) {


@@ 294,7 294,7 @@ public class PresenceParser extends AbstractParser implements
			} else {
				contact.setOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST);
				final Conversation conversation = mXmppConnectionService.findOrCreateConversation(
						account, contact.getJid().toBareJid(), false, false);
						account, contact.getJid().asBareJid(), false, false);
				final String statusMessage = packet.findChildContent("status");
				if (statusMessage != null
						&& !statusMessage.isEmpty()

M src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java => src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +21 -28
@@ 4,7 4,6 @@ import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteCantOpenDatabaseException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;


@@ 28,7 27,6 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;


@@ 53,9 51,8 @@ import eu.siacs.conversations.services.ShortcutService;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.MimeUtils;
import eu.siacs.conversations.utils.Resolver;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.mam.MamReference;
import rocks.xmpp.addr.Jid;

public class DatabaseBackend extends SQLiteOpenHelper {



@@ 320,7 317,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
					continue;
				}
				int ownDeviceId = Integer.valueOf(ownDeviceIdString);
				SignalProtocolAddress ownAddress = new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(), ownDeviceId);
				SignalProtocolAddress ownAddress = new SignalProtocolAddress(account.getJid().asBareJid().toString(), ownDeviceId);
				deleteSession(db, account, ownAddress);
				IdentityKeyPair identityKeyPair = loadOwnIdentityKeyPair(db, account);
				if (identityKeyPair != null) {


@@ 335,7 332,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
									+ SQLiteAxolotlStore.FINGERPRINT + " = ? ",
							selectionArgs);
				} else {
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not load own identity key pair");
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": could not load own identity key pair");
				}
			}
		}


@@ 497,10 494,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
		while (cursor.moveToNext()) {
			String newJid;
			try {
				newJid = Jid.fromString(
						cursor.getString(cursor.getColumnIndex(Conversation.CONTACTJID))
				).toPreppedString();
			} catch (InvalidJidException ignored) {
				newJid = Jid.of(cursor.getString(cursor.getColumnIndex(Conversation.CONTACTJID))).toString();
			} catch (IllegalArgumentException ignored) {
				Log.e(Config.LOGTAG, "Failed to migrate Conversation CONTACTJID "
						+ cursor.getString(cursor.getColumnIndex(Conversation.CONTACTJID))
						+ ": " + ignored + ". Skipping...");


@@ 522,10 517,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
		while (cursor.moveToNext()) {
			String newJid;
			try {
				newJid = Jid.fromString(
						cursor.getString(cursor.getColumnIndex(Contact.JID))
				).toPreppedString();
			} catch (InvalidJidException ignored) {
				newJid = Jid.of(cursor.getString(cursor.getColumnIndex(Contact.JID))).toString();
			} catch (IllegalArgumentException ignored) {
				Log.e(Config.LOGTAG, "Failed to migrate Contact JID "
						+ cursor.getString(cursor.getColumnIndex(Contact.JID))
						+ ": " + ignored + ". Skipping...");


@@ 549,12 542,12 @@ public class DatabaseBackend extends SQLiteOpenHelper {
		while (cursor.moveToNext()) {
			String newServer;
			try {
				newServer = Jid.fromParts(
				newServer = Jid.of(
						cursor.getString(cursor.getColumnIndex(Account.USERNAME)),
						cursor.getString(cursor.getColumnIndex(Account.SERVER)),
						"mobile"
				).getDomainpart();
			} catch (InvalidJidException ignored) {
						null
				).getDomain();
			} catch (IllegalArgumentException ignored) {
				Log.e(Config.LOGTAG, "Failed to migrate Account SERVER "
						+ cursor.getString(cursor.getColumnIndex(Account.SERVER))
						+ ": " + ignored + ". Skipping...");


@@ 751,8 744,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
	public Conversation findConversation(final Account account, final Jid contactJid) {
		SQLiteDatabase db = this.getReadableDatabase();
		String[] selectionArgs = {account.getUuid(),
				contactJid.toBareJid().toPreppedString() + "/%",
				contactJid.toBareJid().toPreppedString()
				contactJid.asBareJid().toString() + "/%",
				contactJid.asBareJid().toString()
		};
		Cursor cursor = db.query(Conversation.TABLENAME, null,
				Conversation.ACCOUNT + "=? AND (" + Conversation.CONTACTJID


@@ 786,7 779,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
		Cursor cursor = db.query(Account.TABLENAME,columns,null,null,null,null,null);
		try {
			while(cursor.moveToNext()) {
				jids.add(Jid.fromParts(cursor.getString(0),cursor.getString(1),null));
				jids.add(Jid.of(cursor.getString(0),cursor.getString(1),null));
			}
			return jids;
		} catch (Exception e) {


@@ 864,7 857,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
				db.insert(Contact.TABLENAME, null, contact.getContentValues());
			} else {
				String where = Contact.ACCOUNT + "=? AND " + Contact.JID + "=?";
				String[] whereArgs = {account.getUuid(), contact.getJid().toPreppedString()};
				String[] whereArgs = {account.getUuid(), contact.getJid().toString()};
				db.delete(Contact.TABLENAME, where, whereArgs);
			}
		}


@@ 1257,7 1250,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
	}

	private IdentityKeyPair loadOwnIdentityKeyPair(SQLiteDatabase db, Account account) {
		String name = account.getJid().toBareJid().toPreppedString();
		String name = account.getJid().asBareJid().toString();
		IdentityKeyPair identityKeyPair = null;
		Cursor cursor = getIdentityKeyCursor(db, account, name, true);
		if (cursor.getCount() != 0) {


@@ 1265,7 1258,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
			try {
				identityKeyPair = new IdentityKeyPair(Base64.decode(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY)), Base64.DEFAULT));
			} catch (InvalidKeyException e) {
				Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Encountered invalid IdentityKey in database for account" + account.getJid().toBareJid() + ", address: " + name);
				Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Encountered invalid IdentityKey in database for account" + account.getJid().asBareJid() + ", address: " + name);
			}
		}
		cursor.close();


@@ 1290,10 1283,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
				if (key != null) {
					identityKeys.add(new IdentityKey(Base64.decode(key, Base64.DEFAULT), 0));
				} else {
					Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Missing key (possibly preverified) in database for account" + account.getJid().toBareJid() + ", address: " + name);
					Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Missing key (possibly preverified) in database for account" + account.getJid().asBareJid() + ", address: " + name);
				}
			} catch (InvalidKeyException e) {
				Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Encountered invalid IdentityKey in database for account" + account.getJid().toBareJid() + ", address: " + name);
				Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Encountered invalid IdentityKey in database for account" + account.getJid().asBareJid() + ", address: " + name);
			}
		}
		cursor.close();


@@ 1429,7 1422,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
	}

	public void storeOwnIdentityKeyPair(Account account, IdentityKeyPair identityKeyPair) {
		storeIdentityKey(account, account.getJid().toBareJid().toPreppedString(), true, CryptoHelper.bytesToHex(identityKeyPair.getPublicKey().serialize()), Base64.encodeToString(identityKeyPair.serialize(), Base64.DEFAULT), FingerprintStatus.createActiveVerified(false));
		storeIdentityKey(account, account.getJid().asBareJid().toString(), true, CryptoHelper.bytesToHex(identityKeyPair.getPublicKey().serialize()), Base64.encodeToString(identityKeyPair.serialize(), Base64.DEFAULT), FingerprintStatus.createActiveVerified(false));
	}




@@ 1474,7 1467,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
		ArrayList<ShortcutService.FrequentContact> contacts = new ArrayList<>();
		while(cursor.moveToNext()) {
			try {
				contacts.add(new ShortcutService.FrequentContact(cursor.getString(0), Jid.fromString(cursor.getString(1))));
				contacts.add(new ShortcutService.FrequentContact(cursor.getString(0), Jid.of(cursor.getString(1))));
			} catch (Exception e) {
				Log.d(Config.LOGTAG,e.getMessage());
			}

M src/main/java/eu/siacs/conversations/services/AvatarService.java => src/main/java/eu/siacs/conversations/services/AvatarService.java +16 -16
@@ 30,7 30,7 @@ import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
import eu.siacs.conversations.xmpp.XmppConnection;
import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class AvatarService implements OnAdvancedStreamFeaturesLoaded {



@@ 68,7 68,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
			avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatar(), size);
		}
		if (avatar == null) {
            avatar = get(contact.getDisplayName(), contact.getJid().toBareJid().toString(), size, cachedOnly);
            avatar = get(contact.getDisplayName(), contact.getJid().asBareJid().toString(), size, cachedOnly);
		}
		this.mXmppConnectionService.getBitmapCache().put(KEY, avatar);
		return avatar;


@@ 115,7 115,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
			if (contact != null) {
				avatar = get(contact, size, cachedOnly);
			} else {
				String seed = user.getRealJid() != null ? user.getRealJid().toBareJid().toString() : null;
				String seed = user.getRealJid() != null ? user.getRealJid().asBareJid().toString() : null;
				avatar = get(user.getName(), seed, size, cachedOnly);
			}
		}


@@ 141,7 141,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
				this.sizes.add(size);
			}
		}
		return PREFIX_CONTACT + "_" + contact.getAccount().getJid().toBareJid() + "_"
		return PREFIX_CONTACT + "_" + contact.getAccount().getJid().asBareJid() + "_"
				+ contact.getJid() + "_" + String.valueOf(size);
	}



@@ 151,7 151,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
				this.sizes.add(size);
			}
		}
		return PREFIX_CONTACT + "_" + user.getAccount().getJid().toBareJid() + "_"
		return PREFIX_CONTACT + "_" + user.getAccount().getJid().asBareJid() + "_"
				+ user.getFullJid() + "_" + String.valueOf(size);
	}



@@ 167,11 167,11 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
			if (bookmark.getConversation() != null) {
				return get(bookmark.getConversation(), size, cachedOnly);
			} else {
				String seed = bookmark.getJid() != null ? bookmark.getJid().toBareJid().toString() : null;
				String seed = bookmark.getJid() != null ? bookmark.getJid().asBareJid().toString() : null;
				return get(bookmark.getDisplayName(), seed, size, cachedOnly);
			}
		} else {
			String seed = item.getJid() != null ? item.getJid().toBareJid().toString() : null;
			String seed = item.getJid() != null ? item.getJid().asBareJid().toString() : null;
			return get(item.getDisplayName(), seed, size, cachedOnly);
		}
	}


@@ 216,7 216,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
		final List<MucOptions.User> users = mucOptions.getUsersRelevantForNameAndAvatar();
		if (users.size() == 0) {
			Conversation c = mucOptions.getConversation();
			bitmap = getImpl(c.getName(),c.getJid().toBareJid().toString(),size);
			bitmap = getImpl(c.getName(),c.getJid().asBareJid().toString(),size);
		} else {
			bitmap = getImpl(users,size);
		}


@@ 294,9 294,9 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {

		for(MucOptions.User user : users) {
			builder.append("\0");
			builder.append(user.getRealJid() == null ? "" : user.getRealJid().toBareJid().toPreppedString());
			builder.append(user.getRealJid() == null ? "" : user.getRealJid().asBareJid().toString());
			builder.append("\0");
			builder.append(user.getFullJid() == null ? "" : user.getFullJid().toPreppedString());
			builder.append(user.getFullJid() == null ? "" : user.getFullJid().toString());
		}
		final String key = builder.toString();
		synchronized (this.conversationDependentKeys) {


@@ 324,7 324,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
		}
		avatar = mXmppConnectionService.getFileBackend().getAvatar(account.getAvatar(), size);
		if (avatar == null) {
			avatar = get(account.getJid().toBareJid().toString(), null, size,false);
			avatar = get(account.getJid().asBareJid().toString(), null, size,false);
		}
		mXmppConnectionService.getBitmapCache().put(KEY, avatar);
		return avatar;


@@ 353,7 353,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
				return get(c, size, cachedOnly);
			}
			Jid tcp = message.getTrueCounterpart();
			String seed = tcp != null ? tcp.toBareJid().toString() :null;
			String seed = tcp != null ? tcp.asBareJid().toString() :null;
			return get(UIHelper.getMessageDisplayName(message), seed, size, cachedOnly);
		} else  {
			return get(conversation.getAccount(), size, cachedOnly);


@@ 458,10 458,10 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
			}
		}
		if (contact != null) {
			String seed = contact.getJid().toBareJid().toString();
			String seed = contact.getJid().asBareJid().toString();
			drawTile(canvas, contact.getDisplayName(), seed, left, top, right, bottom);
		} else {
			String seed = user.getRealJid() == null ? null : user.getRealJid().toBareJid().toString();
			String seed = user.getRealJid() == null ? null : user.getRealJid().asBareJid().toString();
			drawTile(canvas, user.getName(), seed, left, top, right, bottom);
		}
		return true;


@@ 477,7 477,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
				}
			}
		}
		String name = account.getJid().toBareJid().toString();
		String name = account.getJid().asBareJid().toString();
		return drawTile(canvas, name, name, left, top, right, bottom);
	}



@@ 522,7 522,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
	public void onAdvancedStreamFeaturesAvailable(Account account) {
		XmppConnection.Features features = account.getXmppConnection().getFeatures();
		if (features.pep() && !features.pepPersistent()) {
			Log.d(Config.LOGTAG,account.getJid().toBareJid()+": has pep but is not persistent");
			Log.d(Config.LOGTAG,account.getJid().asBareJid()+": has pep but is not persistent");
			if (account.getAvatar() != null) {
				mXmppConnectionService.republishAvatarIfNeeded(account);
			}

M src/main/java/eu/siacs/conversations/services/BarcodeProvider.java => src/main/java/eu/siacs/conversations/services/BarcodeProvider.java +3 -3
@@ 31,7 31,7 @@ import java.util.Hashtable;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class BarcodeProvider extends ContentProvider implements ServiceConnection {



@@ 99,7 99,7 @@ public class BarcodeProvider extends ContentProvider implements ServiceConnectio
            if (connectAndWait()) {
                Log.d(Config.LOGTAG, "connected to background service");
                try {
                    Account account = mXmppConnectionService.findAccountByJid(Jid.fromString(jid));
                    Account account = mXmppConnectionService.findAccountByJid(Jid.of(jid));
                    if (account != null) {
                        String shareableUri = account.getShareableUri();
                        String hash = CryptoHelper.getFingerprint(shareableUri);


@@ 179,7 179,7 @@ public class BarcodeProvider extends ContentProvider implements ServiceConnectio

    public static Uri getUriForAccount(Context context, Account account) {
        final String packageId = context.getPackageName();
        return Uri.parse("content://" + packageId + AUTHORITY + "/" + account.getJid().toBareJid() + ".png");
        return Uri.parse("content://" + packageId + AUTHORITY + "/" + account.getJid().asBareJid() + ".png");
    }

    public static Bitmap create2dBarcodeBitmap(String input, int size) {

M src/main/java/eu/siacs/conversations/services/ExportLogsService.java => src/main/java/eu/siacs/conversations/services/ExportLogsService.java +4 -4
@@ 21,7 21,7 @@ import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class ExportLogsService extends Service {



@@ 78,7 78,7 @@ public class ExportLogsService extends Service {
		Jid accountJid = resolveAccountUuid(conversation.getAccountUuid());
		Jid contactJid = conversation.getJid();

		File dir = new File(String.format(DIRECTORY_STRING_FORMAT,accountJid.toBareJid().toString()));
		File dir = new File(String.format(DIRECTORY_STRING_FORMAT,accountJid.asBareJid().toString()));
		dir.mkdirs();

		BufferedWriter bw = null;


@@ 90,7 90,7 @@ public class ExportLogsService extends Service {
					String date = simpleDateFormat.format(new Date(message.getTimeSent()));
					if (bw == null) {
						bw = new BufferedWriter(new FileWriter(
								new File(dir, contactJid.toBareJid().toString() + ".txt")));
								new File(dir, contactJid.asBareJid().toString() + ".txt")));
					}
					String jid = null;
					switch (message.getStatus()) {


@@ 100,7 100,7 @@ public class ExportLogsService extends Service {
						case Message.STATUS_SEND:
						case Message.STATUS_SEND_RECEIVED:
						case Message.STATUS_SEND_DISPLAYED:
							jid = accountJid.toBareJid().toString();
							jid = accountJid.asBareJid().toString();
							break;
					}
					if (jid != null) {

M src/main/java/eu/siacs/conversations/services/MessageArchiveService.java => src/main/java/eu/siacs/conversations/services/MessageArchiveService.java +8 -8
@@ 17,9 17,9 @@ import eu.siacs.conversations.generator.AbstractGenerator;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.mam.MamReference;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import rocks.xmpp.addr.Jid;

public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {



@@ 164,7 164,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
	private void execute(final Query query) {
		final Account account = query.getAccount();
		if (account.getStatus() == Account.State.ONLINE) {
			Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": running mam query " + query.toString());
			Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": running mam query " + query.toString());
			IqPacket packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(query);
			this.mXmppConnectionService.sendIqPacket(account, packet, (a, p) -> {
				Element fin = p.findChild("fin", Namespace.MAM);


@@ 180,7 180,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
				} else if (p.getType() == IqPacket.TYPE.RESULT && query.isLegacy()) {
					//do nothing
				} else {
					Log.d(Config.LOGTAG, a.getJid().toBareJid().toString() + ": error executing mam: " + p.toString());
					Log.d(Config.LOGTAG, a.getJid().asBareJid().toString() + ": error executing mam: " + p.toString());
					finalizeQuery(query, true);
				}
			});


@@ 278,7 278,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
			done = done || (query.getActualMessageCount() == 0 && !query.isCatchup());
			this.finalizeQuery(query, done);

			Log.d(Config.LOGTAG, query.getAccount().getJid().toBareJid() + ": finished mam after " + query.getTotalCount() + "(" + query.getActualMessageCount() + ") messages. messages left=" + Boolean.toString(!done) + " count=" + count);
			Log.d(Config.LOGTAG, query.getAccount().getJid().asBareJid() + ": finished mam after " + query.getTotalCount() + "(" + query.getActualMessageCount() + ") messages. messages left=" + Boolean.toString(!done) + " count=" + count);
			if (query.isCatchup() && query.getActualMessageCount() > 0) {
				mXmppConnectionService.getNotificationService().finishBacklog(true, query.getAccount());
			}


@@ 313,7 313,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
	}

	private void kill(Query query) {
		Log.d(Config.LOGTAG, query.getAccount().getJid().toBareJid() + ": killing mam query prematurely");
		Log.d(Config.LOGTAG, query.getAccount().getJid().asBareJid() + ": killing mam query prematurely");
		query.callback = null;
		this.finalizeQuery(query, false);
		if (query.isCatchup() && query.getActualMessageCount() > 0) {


@@ 324,7 324,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {

	private void processPostponed(Query query) {
		query.account.getAxolotlService().processPostponed();
		Log.d(Config.LOGTAG, query.getAccount().getJid().toBareJid() + ": found " + query.pendingReceiptRequests.size() + " pending receipt requests");
		Log.d(Config.LOGTAG, query.getAccount().getJid().asBareJid() + ": found " + query.pendingReceiptRequests.size() + " pending receipt requests");
		Iterator<ReceiptRequest> iterator = query.pendingReceiptRequests.iterator();
		while (iterator.hasNext()) {
			ReceiptRequest rr = iterator.next();


@@ 441,7 441,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
		}

		public Jid getWith() {
			return conversation == null ? null : conversation.getJid().toBareJid();
			return conversation == null ? null : conversation.getJid().asBareJid();
		}

		public boolean muc() {


@@ 506,7 506,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
			if (muc()) {
				return getWith().equals(from);
			} else {
				return (from == null) || account.getJid().toBareJid().equals(from.toBareJid());
				return (from == null) || account.getJid().asBareJid().equals(from.asBareJid());
			}
		}


M src/main/java/eu/siacs/conversations/services/NotificationService.java => src/main/java/eu/siacs/conversations/services/NotificationService.java +4 -4
@@ 156,7 156,7 @@ public class NotificationService {
				}
			}
		}
		Log.d(Config.LOGTAG,account.getJid().toBareJid()+": backlog message count="+count);
		Log.d(Config.LOGTAG,account.getJid().asBareJid()+": backlog message count="+count);
		return count;
	}



@@ 190,12 190,12 @@ public class NotificationService {
	private void pushNow(final Message message) {
		mXmppConnectionService.updateUnreadCountBadge();
		if (!notify(message)) {
			Log.d(Config.LOGTAG,message.getConversation().getAccount().getJid().toBareJid()+": suppressing notification because turned off");
			Log.d(Config.LOGTAG,message.getConversation().getAccount().getJid().asBareJid()+": suppressing notification because turned off");
			return;
		}
		final boolean isScreenOn = mXmppConnectionService.isInteractive();
		if (this.mIsInForeground && isScreenOn && this.mOpenConversation == message.getConversation()) {
			Log.d(Config.LOGTAG,message.getConversation().getAccount().getJid().toBareJid()+": suppressing notification because conversation is open");
			Log.d(Config.LOGTAG,message.getConversation().getAccount().getJid().asBareJid()+": suppressing notification because conversation is open");
			return;
		}
		synchronized (notifications) {


@@ 787,7 787,7 @@ public class NotificationService {
			return;
		} else if (errors.size() == 1) {
			mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.problem_connecting_to_account));
			mBuilder.setContentText(errors.get(0).getJid().toBareJid().toString());
			mBuilder.setContentText(errors.get(0).getJid().asBareJid().toString());
		} else {
			mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.problem_connecting_to_accounts));
			mBuilder.setContentText(mXmppConnectionService.getString(R.string.touch_to_fix));

M src/main/java/eu/siacs/conversations/services/ShortcutService.java => src/main/java/eu/siacs/conversations/services/ShortcutService.java +4 -4
@@ 18,7 18,7 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.ui.StartConversationActivity;
import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor;
import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class ShortcutService {



@@ 109,14 109,14 @@ public class ShortcutService {
    }

    private static String getShortcutId(Contact contact) {
        return contact.getAccount().getJid().toBareJid().toPreppedString()+"#"+contact.getJid().toBareJid().toPreppedString();
        return contact.getAccount().getJid().asBareJid().toString()+"#"+contact.getJid().asBareJid().toString();
    }

    private Intent getShortcutIntent(Contact contact) {
        Intent intent = new Intent(xmppConnectionService, StartConversationActivity.class);
        intent.setAction(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("xmpp:"+contact.getJid().toBareJid().toString()));
        intent.putExtra("account",contact.getAccount().getJid().toBareJid().toString());
        intent.setData(Uri.parse("xmpp:"+contact.getJid().asBareJid().toString()));
        intent.putExtra("account",contact.getAccount().getJid().asBareJid().toString());
        return intent;
    }


M src/main/java/eu/siacs/conversations/services/XmppConnectionService.java => src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +85 -86
@@ 122,8 122,6 @@ import eu.siacs.conversations.xmpp.Patches;
import eu.siacs.conversations.xmpp.XmppConnection;
import eu.siacs.conversations.xmpp.chatstate.ChatState;
import eu.siacs.conversations.xmpp.forms.Data;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived;
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;


@@ 133,6 131,7 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
import me.leolin.shortcutbadger.ShortcutBadger;
import rocks.xmpp.addr.Jid;

public class XmppConnectionService extends Service {



@@ 191,7 190,7 @@ public class XmppConnectionService extends Service {
				Element error = packet.findChild("error");
				String text = error != null ? error.findChildContent("text") : null;
				if (text != null) {
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": received iq error - " + text);
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received iq error - " + text);
				}
			}
		}


@@ 278,7 277,7 @@ public class XmppConnectionService extends Service {
			synchronized (mInProgressAvatarFetches) {
				for (Iterator<String> iterator = mInProgressAvatarFetches.iterator(); iterator.hasNext(); ) {
					final String KEY = iterator.next();
					if (KEY.startsWith(account.getJid().toBareJid() + "_")) {
					if (KEY.startsWith(account.getJid().asBareJid() + "_")) {
						iterator.remove();
					}
				}


@@ 295,7 294,7 @@ public class XmppConnectionService extends Service {
			if (flexible && catchup) {
				sendIqPacket(account, mIqGenerator.purgeOfflineMessages(), (acc, packet) -> {
					if (packet.getType() == IqPacket.TYPE.RESULT) {
						Log.d(Config.LOGTAG, acc.getJid().toBareJid()+": successfully purged offline messages");
						Log.d(Config.LOGTAG, acc.getJid().asBareJid()+": successfully purged offline messages");
					}
				});
			}


@@ 317,8 316,8 @@ public class XmppConnectionService extends Service {
			}
			if (account.getStatus() == Account.State.ONLINE) {
				synchronized (mLowPingTimeoutMode) {
					if (mLowPingTimeoutMode.remove(account.getJid().toBareJid())) {
						Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": leaving low ping timeout mode");
					if (mLowPingTimeoutMode.remove(account.getJid().asBareJid())) {
						Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": leaving low ping timeout mode");
					}
				}
				if (account.setShowErrorNotification(true)) {


@@ 327,10 326,10 @@ public class XmppConnectionService extends Service {
				mMessageArchiveService.executePendingQueries(account);
				if (connection != null && connection.getFeatures().csi()) {
					if (checkListeners()) {
						Log.d(Config.LOGTAG, account.getJid().toBareJid() + " sending csi//inactive");
						Log.d(Config.LOGTAG, account.getJid().asBareJid() + " sending csi//inactive");
						connection.sendInactive();
					} else {
						Log.d(Config.LOGTAG, account.getJid().toBareJid() + " sending csi//active");
						Log.d(Config.LOGTAG, account.getJid().asBareJid() + " sending csi//active");
						connection.sendActive();
					}
				}


@@ 352,7 351,7 @@ public class XmppConnectionService extends Service {
			} else if (account.getStatus() == Account.State.OFFLINE || account.getStatus() == Account.State.DISABLED) {
				resetSendingToWaiting(account);
				if (account.isEnabled() && isInLowPingTimeoutMode(account)) {
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": went into offline state during low ping mode. reconnecting now");
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": went into offline state during low ping mode. reconnecting now");
					reconnectAccount(account, true, false);
				} else {
					int timeToReconnect = mRandom.nextInt(10) + 2;


@@ 367,11 366,11 @@ public class XmppConnectionService extends Service {
					final int next = connection.getTimeToNextAttempt();
					final boolean lowPingTimeoutMode = isInLowPingTimeoutMode(account);
					if (next <= 0) {
						Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": error connecting account. reconnecting now. lowPingTimeout=" + Boolean.toString(lowPingTimeoutMode));
						Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": error connecting account. reconnecting now. lowPingTimeout=" + Boolean.toString(lowPingTimeoutMode));
						reconnectAccount(account, true, false);
					} else {
						final int attempt = connection.getAttempt() + 1;
						Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": 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=" + Boolean.toString(lowPingTimeoutMode));
						scheduleWakeUpCall(next, account.getUuid().hashCode());
					}
				}


@@ 382,7 381,7 @@ public class XmppConnectionService extends Service {

	private boolean isInLowPingTimeoutMode(Account account) {
		synchronized (mLowPingTimeoutMode) {
			return mLowPingTimeoutMode.contains(account.getJid().toBareJid());
			return mLowPingTimeoutMode.contains(account.getJid().asBareJid());
		}
	}



@@ 406,7 405,7 @@ public class XmppConnectionService extends Service {
	public final CountDownLatch restoredFromDatabaseLatch = new CountDownLatch(1);

	private static String generateFetchKey(Account account, final Avatar avatar) {
		return account.getJid().toBareJid() + "_" + avatar.owner + "_" + avatar.sha1sum;
		return account.getJid().asBareJid() + "_" + avatar.owner + "_" + avatar.sha1sum;
	}

	public boolean areMessagesInitialized() {


@@ 499,7 498,7 @@ public class XmppConnectionService extends Service {
		if ("never".equals(compressPictures)
				|| ("auto".equals(compressPictures) && getFileBackend().useImageAsIs(uri))
				|| (mimeType != null && mimeType.endsWith("/gif"))) {
			Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": not compressing picture. sending as file");
			Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": not compressing picture. sending as file");
			attachFileToConversation(conversation, uri, mimeType, callback);
			return;
		}


@@ 683,7 682,7 @@ public class XmppConnectionService extends Service {
				for (Account account : pingCandidates) {
					final boolean lowTimeout = isInLowPingTimeoutMode(account);
					account.getXmppConnection().sendPing();
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + " send ping (action=" + action + ",lowTimeout=" + Boolean.toString(lowTimeout) + ")");
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + " send ping (action=" + action + ",lowTimeout=" + Boolean.toString(lowTimeout) + ")");
					scheduleWakeUpCall(lowTimeout ? Config.LOW_PING_TIMEOUT : Config.PING_TIMEOUT, account.getUuid().hashCode());
				}
			}


@@ 721,11 720,11 @@ public class XmppConnectionService extends Service {
						long lastSent = account.getXmppConnection().getLastPingSent();
						long pingInterval = isUiAction ? Config.PING_MIN_INTERVAL * 1000 : Config.PING_MAX_INTERVAL * 1000;
						long msToNextPing = (Math.max(lastReceived, lastSent) + pingInterval) - SystemClock.elapsedRealtime();
						int pingTimeout = mLowPingTimeoutMode.contains(account.getJid().toBareJid()) ? Config.LOW_PING_TIMEOUT * 1000 : Config.PING_TIMEOUT * 1000;
						int pingTimeout = mLowPingTimeoutMode.contains(account.getJid().asBareJid()) ? Config.LOW_PING_TIMEOUT * 1000 : Config.PING_TIMEOUT * 1000;
						long pingTimeoutIn = (lastSent + pingTimeout) - SystemClock.elapsedRealtime();
						if (lastSent > lastReceived) {
							if (pingTimeoutIn < 0) {
								Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": ping timeout");
								Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ping timeout");
								this.reconnectAccount(account, true, interactive);
							} else {
								int secs = (int) (pingTimeoutIn / 1000);


@@ 735,15 734,15 @@ public class XmppConnectionService extends Service {
							pingCandidates.add(account);
							if (isAccountPushed) {
								pingNow = true;
								if (mLowPingTimeoutMode.add(account.getJid().toBareJid())) {
									Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": entering low ping timeout mode");
								if (mLowPingTimeoutMode.add(account.getJid().asBareJid())) {
									Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": entering low ping timeout mode");
								}
							} else if (msToNextPing <= 0) {
								pingNow = true;
							} else {
								this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode());
								if (mLowPingTimeoutMode.remove(account.getJid().toBareJid())) {
									Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": leaving low ping timeout mode");
								if (mLowPingTimeoutMode.remove(account.getJid().asBareJid())) {
									Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": leaving low ping timeout mode");
								}
							}
						}


@@ 898,7 897,7 @@ public class XmppConnectionService extends Service {
	private void dismissErrorNotifications() {
		for (final Account account : this.accounts) {
			if (account.hasErrorStatus()) {
				Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": dismissing error notification");
				Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": dismissing error notification");
				if (account.setShowErrorNotification(false)) {
					databaseBackend.updateAccount(account);
				}


@@ 1318,10 1317,10 @@ public class XmppConnectionService extends Service {
	public void fetchRosterFromServer(final Account account) {
		final IqPacket iqPacket = new IqPacket(IqPacket.TYPE.GET);
		if (!"".equals(account.getRosterVersion())) {
			Log.d(Config.LOGTAG, account.getJid().toBareJid()
			Log.d(Config.LOGTAG, account.getJid().asBareJid()
					+ ": fetching roster version " + account.getRosterVersion());
		} else {
			Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": fetching roster");
			Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": fetching roster");
		}
		iqPacket.query(Namespace.ROSTER).setAttribute("ver", account.getRosterVersion());
		sendIqPacket(account, iqPacket, mIqParser);


@@ 1360,7 1359,7 @@ public class XmppConnectionService extends Service {
					}
					account.setBookmarks(new CopyOnWriteArrayList<>(bookmarks.values()));
				} else {
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not fetch bookmarks");
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": could not fetch bookmarks");
				}
			}
		};


@@ 1368,7 1367,7 @@ public class XmppConnectionService extends Service {
	}

	public void pushBookmarks(Account account) {
		Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": pushing bookmarks");
		Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": pushing bookmarks");
		IqPacket iqPacket = new IqPacket(IqPacket.TYPE.SET);
		Element query = iqPacket.query("jabber:iq:private");
		Element storage = query.addChild("storage", "storage:bookmarks");


@@ 1458,8 1457,8 @@ public class XmppConnectionService extends Service {
							for (Bundle phoneContact : phoneContacts) {
								Jid jid;
								try {
									jid = Jid.fromString(phoneContact.getString("jid"));
								} catch (final InvalidJidException e) {
									jid = Jid.of(phoneContact.getString("jid"));
								} catch (final IllegalArgumentException e) {
									continue;
								}
								final Contact contact = account.getRoster().getContact(jid);


@@ 1628,7 1627,7 @@ public class XmppConnectionService extends Service {
		}
		for (final Conversation conversation : haystack) {
			if ((account == null || conversation.getAccount() == account)
					&& (conversation.getJid().toBareJid().equals(jid.toBareJid()))) {
					&& (conversation.getJid().asBareJid().equals(jid.asBareJid()))) {
				return conversation;
			}
		}


@@ 1672,7 1671,7 @@ public class XmppConnectionService extends Service {
					conversation.setContactJid(jid);
				} else {
					conversation.setMode(Conversation.MODE_SINGLE);
					conversation.setContactJid(jid.toBareJid());
					conversation.setContactJid(jid.asBareJid());
				}
				databaseBackend.updateConversation(conversation);
				loadMessagesFromDb = conversation.messagesLoaded.compareAndSet(true, false);


@@ 1682,13 1681,13 @@ public class XmppConnectionService extends Service {
				if (contact != null) {
					conversationName = contact.getDisplayName();
				} else {
					conversationName = jid.getLocalpart();
					conversationName = jid.getLocal();
				}
				if (muc) {
					conversation = new Conversation(conversationName, account, jid,
							Conversation.MODE_MULTI);
				} else {
					conversation = new Conversation(conversationName, account, jid.toBareJid(),
					conversation = new Conversation(conversationName, account, jid.asBareJid(),
							Conversation.MODE_SINGLE);
				}
				this.databaseBackend.createConversation(conversation);


@@ 1795,7 1794,7 @@ public class XmppConnectionService extends Service {
					callback.onAccountCreated(account);
					if (Config.X509_VERIFICATION) {
						try {
							getMemorizingTrustManager().getNonInteractive(account.getJid().getDomainpart()).checkClientTrusted(chain, "RSA");
							getMemorizingTrustManager().getNonInteractive(account.getJid().getDomain()).checkClientTrusted(chain, "RSA");
						} catch (CertificateException e) {
							callback.informUser(R.string.certificate_chain_is_not_trusted);
						}


@@ 1812,16 1811,16 @@ public class XmppConnectionService extends Service {
	}

	public void updateKeyInAccount(final Account account, final String alias) {
		Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": update key in account " + alias);
		Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": update key in account " + alias);
		try {
			X509Certificate[] chain = KeyChain.getCertificateChain(XmppConnectionService.this, alias);
			Log.d(Config.LOGTAG, account.getJid().toBareJid() + " loaded certificate chain");
			Log.d(Config.LOGTAG, account.getJid().asBareJid() + " loaded certificate chain");
			Pair<Jid, String> info = CryptoHelper.extractJidAndName(chain[0]);
			if (info == null) {
				showErrorToastInUi(R.string.certificate_does_not_contain_jid);
				return;
			}
			if (account.getJid().toBareJid().equals(info.first)) {
			if (account.getJid().asBareJid().equals(info.first)) {
				account.setPrivateKeyAlias(alias);
				account.setDisplayName(info.second);
				databaseBackend.updateAccount(account);


@@ 1886,7 1885,7 @@ public class XmppConnectionService extends Service {
			}
			final Runnable runnable = () -> {
				if (!databaseBackend.deleteAccount(account)) {
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": unable to delete account");
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to delete account");
				}
			};
			mDatabaseWriterExecutor.execute(runnable);


@@ 2194,7 2193,7 @@ public class XmppConnectionService extends Service {
					Account account = conversation.getAccount();
					final MucOptions mucOptions = conversation.getMucOptions();
					final Jid joinJid = mucOptions.getSelf().getFullJid();
					Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": joining conversation " + joinJid.toString());
					Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": joining conversation " + joinJid.toString());
					PresencePacket packet = mPresenceGenerator.selfPresence(account, Presence.Status.ONLINE, mucOptions.nonanonymous() || onConferenceJoined != null);
					packet.setTo(joinJid);
					Element x = packet.addChild("x", "http://jabber.org/protocol/muc");


@@ 2286,7 2285,7 @@ public class XmppConnectionService extends Service {
					}
				} else {
					success = false;
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not request affiliation " + affiliations[i] + " in " + conversation.getJid().toBareJid());
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": could not request affiliation " + affiliations[i] + " in " + conversation.getJid().asBareJid());
				}
				++i;
				if (i >= affiliations.length) {


@@ 2298,7 2297,7 @@ public class XmppConnectionService extends Service {
							Jid jid = iterator.next();
							if (!members.contains(jid)) {
								iterator.remove();
								Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": removed " + jid + " from crypto targets of " + conversation.getName());
								Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": removed " + jid + " from crypto targets of " + conversation.getName());
								changed = true;
							}
						}


@@ 2307,7 2306,7 @@ public class XmppConnectionService extends Service {
							updateConversation(conversation);
						}
					}
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": retrieved members for " + conversation.getJid().toBareJid() + ": " + conversation.getMucOptions().getMembers());
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": retrieved members for " + conversation.getJid().asBareJid() + ": " + conversation.getMucOptions().getMembers());
					getAvatarService().clear(conversation);
					updateMucRosterUi();
					updateConversationUi();


@@ 2317,7 2316,7 @@ public class XmppConnectionService extends Service {
		for (String affiliation : affiliations) {
			sendIqPacket(account, mIqGenerator.queryAffiliation(conversation, affiliation), callback);
		}
		Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": fetching members for " + conversation.getName());
		Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": fetching members for " + conversation.getName());
	}

	public void providePasswordForMuc(Conversation conversation, String password) {


@@ 2353,8 2352,8 @@ public class XmppConnectionService extends Service {
		}

		Bookmark bookmark = conversation.getBookmark();
		if (bookmark != null && !full.getResourcepart().equals(bookmark.getNick())) {
			bookmark.setNick(full.getResourcepart());
		if (bookmark != null && !full.getResource().equals(bookmark.getNick())) {
			bookmark.setNick(full.getResource());
			pushBookmarks(bookmark.getAccount());
		}
	}


@@ 2420,7 2419,7 @@ public class XmppConnectionService extends Service {
			if (bookmark != null) {
				bookmark.setConversation(null);
			}
			Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": leaving muc " + conversation.getJid());
			Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": leaving muc " + conversation.getJid());
		} else {
			account.pendingConferenceLeaves.add(conversation);
		}


@@ 2449,7 2448,7 @@ public class XmppConnectionService extends Service {
	                                     final String subject,
	                                     final Iterable<Jid> jids,
	                                     final UiCallback<Conversation> callback) {
		Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": creating adhoc conference with " + jids.toString());
		Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": creating adhoc conference with " + jids.toString());
		if (account.getStatus() == Account.State.ONLINE) {
			try {
				String server = findConferenceServer(account);


@@ 2459,7 2458,7 @@ public class XmppConnectionService extends Service {
					}
					return false;
				}
				final Jid jid = Jid.fromParts(new BigInteger(64, getRNG()).toString(Character.MAX_RADIX), server, null);
				final Jid jid = Jid.of(new BigInteger(64, getRNG()).toString(Character.MAX_RADIX), server, null);
				final Conversation conversation = findOrCreateConversation(account, jid, true, false, true);
				joinMuc(conversation, new OnConferenceJoined() {
					@Override


@@ 2474,7 2473,7 @@ public class XmppConnectionService extends Service {
									invite(conversation, invite);
								}
								if (account.countPresences() > 1) {
									directInvite(conversation, account.getJid().toBareJid());
									directInvite(conversation, account.getJid().asBareJid());
								}
								saveConversationAsBookmark(conversation, subject);
								if (callback != null) {


@@ 2493,7 2492,7 @@ public class XmppConnectionService extends Service {
					}
				});
				return true;
			} catch (InvalidJidException e) {
			} catch (IllegalArgumentException e) {
				if (callback != null) {
					callback.error(R.string.conference_creation_failed, null);
				}


@@ 2513,7 2512,7 @@ public class XmppConnectionService extends Service {

	public void fetchConferenceConfiguration(final Conversation conversation, final OnConferenceConfigurationFetched callback) {
		IqPacket request = new IqPacket(IqPacket.TYPE.GET);
		request.setTo(conversation.getJid().toBareJid());
		request.setTo(conversation.getJid().asBareJid());
		request.query("http://jabber.org/protocol/disco#info");
		sendIqPacket(conversation.getAccount(), request, new OnIqPacketReceived() {
			@Override


@@ 2537,7 2536,7 @@ public class XmppConnectionService extends Service {
					if (callback != null) {
						callback.onConferenceConfigurationFetched(conversation);
					}
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": fetched muc configuration for " + conversation.getJid().toBareJid() + " - " + features.toString());
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": fetched muc configuration for " + conversation.getJid().asBareJid() + " - " + features.toString());
					updateConversationUi();
				} else if (packet.getType() == IqPacket.TYPE.ERROR) {
					if (callback != null) {


@@ 2549,7 2548,7 @@ public class XmppConnectionService extends Service {
	}

	public void pushNodeConfiguration(Account account, final String node, final Bundle options, final OnConfigurationPushed callback) {
		pushNodeConfiguration(account, account.getJid().toBareJid(), node, options, callback);
		pushNodeConfiguration(account, account.getJid().asBareJid(), node, options, callback);
	}

	public void pushNodeConfiguration(Account account, final Jid jid, final String node, final Bundle options, final OnConfigurationPushed callback) {


@@ 2585,7 2584,7 @@ public class XmppConnectionService extends Service {

	public void pushConferenceConfiguration(final Conversation conversation, final Bundle options, final OnConfigurationPushed callback) {
		IqPacket request = new IqPacket(IqPacket.TYPE.GET);
		request.setTo(conversation.getJid().toBareJid());
		request.setTo(conversation.getJid().asBareJid());
		request.query("http://jabber.org/protocol/muc#owner");
		sendIqPacket(conversation.getAccount(), request, new OnIqPacketReceived() {
			@Override


@@ 2594,7 2593,7 @@ public class XmppConnectionService extends Service {
					Data data = Data.parse(packet.query().findChild("x", Namespace.DATA));
					data.submit(options);
					IqPacket set = new IqPacket(IqPacket.TYPE.SET);
					set.setTo(conversation.getJid().toBareJid());
					set.setTo(conversation.getJid().asBareJid());
					set.query("http://jabber.org/protocol/muc#owner").addChild(data);
					sendIqPacket(account, set, new OnIqPacketReceived() {
						@Override


@@ 2631,7 2630,7 @@ public class XmppConnectionService extends Service {
	}

	public void changeAffiliationInConference(final Conversation conference, Jid user, final MucOptions.Affiliation affiliation, final OnAffiliationChanged callback) {
		final Jid jid = user.toBareJid();
		final Jid jid = user.asBareJid();
		IqPacket request = this.mIqGenerator.changeAffiliation(conference, jid, affiliation.toString());
		sendIqPacket(conference.getAccount(), request, new OnIqPacketReceived() {
			@Override


@@ 2784,7 2783,7 @@ public class XmppConnectionService extends Service {
									getAvatarService().clear(account);
									databaseBackend.updateAccount(account);
								}
								Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": published avatar " + (avatar.size / 1024) + "KiB");
								Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": published avatar " + (avatar.size / 1024) + "KiB");
								if (callback != null) {
									callback.success(avatar);
								}


@@ 2797,7 2796,7 @@ public class XmppConnectionService extends Service {
					});
				} else {
					Element error = result.findChild("error");
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": server rejected avatar " + (avatar.size / 1024) + "KiB " + (error != null ? error.toString() : ""));
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": server rejected avatar " + (avatar.size / 1024) + "KiB " + (error != null ? error.toString() : ""));
					if (callback != null) {
						callback.error(R.string.error_publish_avatar_server_reject, avatar);
					}


@@ 2808,7 2807,7 @@ public class XmppConnectionService extends Service {

	public void republishAvatarIfNeeded(Account account) {
		if (account.getAxolotlService().isPepBroken()) {
			Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": skipping republication of avatar because pep is broken");
			Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": skipping republication of avatar because pep is broken");
			return;
		}
		IqPacket packet = this.mIqGenerator.retrieveAvatarMetaData(null);


@@ 2839,10 2838,10 @@ public class XmppConnectionService extends Service {
					if (serverAvatar == null && account.getAvatar() != null) {
						Avatar avatar = fileBackend.getStoredPepAvatar(account.getAvatar());
						if (avatar != null) {
							Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": avatar on server was null. republishing");
							Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": avatar on server was null. republishing");
							publishAvatar(account, fileBackend.getStoredPepAvatar(account.getAvatar()), null);
						} else {
							Log.e(Config.LOGTAG, account.getJid().toBareJid() + ": error rereading avatar");
							Log.e(Config.LOGTAG, account.getJid().asBareJid() + ": error rereading avatar");
						}
					}
				}


@@ 2881,13 2880,13 @@ public class XmppConnectionService extends Service {
				synchronized (mInProgressAvatarFetches) {
					mInProgressAvatarFetches.remove(generateFetchKey(account, avatar));
				}
				final String ERROR = account.getJid().toBareJid()
				final String ERROR = account.getJid().asBareJid()
						+ ": fetching avatar for " + avatar.owner + " failed ";
				if (result.getType() == IqPacket.TYPE.RESULT) {
					avatar.image = mIqParser.avatarData(result);
					if (avatar.image != null) {
						if (getFileBackend().save(avatar)) {
							if (account.getJid().toBareJid().equals(avatar.owner)) {
							if (account.getJid().asBareJid().equals(avatar.owner)) {
								if (account.setAvatar(avatar.getFilename())) {
									databaseBackend.updateAccount(account);
								}


@@ 2905,7 2904,7 @@ public class XmppConnectionService extends Service {
							if (callback != null) {
								callback.success(avatar);
							}
							Log.d(Config.LOGTAG, account.getJid().toBareJid()
							Log.d(Config.LOGTAG, account.getJid().asBareJid()
									+ ": successfully fetched pep avatar for " + avatar.owner);
							return;
						}


@@ 2944,11 2943,11 @@ public class XmppConnectionService extends Service {
					if (image != null) {
						avatar.image = image;
						if (getFileBackend().save(avatar)) {
							Log.d(Config.LOGTAG, account.getJid().toBareJid()
							Log.d(Config.LOGTAG, account.getJid().asBareJid()
									+ ": successfully fetched vCard avatar for " + avatar.owner);
							if (avatar.owner.isBareJid()) {
								if (account.getJid().toBareJid().equals(avatar.owner) && account.getAvatar() == null) {
									Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": had no avatar. replacing with vcard");
								if (account.getJid().asBareJid().equals(avatar.owner) && account.getAvatar() == null) {
									Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": had no avatar. replacing with vcard");
									account.setAvatar(avatar.getFilename());
									databaseBackend.updateAccount(account);
									getAvatarService().clear(account);


@@ 2961,7 2960,7 @@ public class XmppConnectionService extends Service {
								}
								updateConversationUi();
							} else {
								Conversation conversation = find(account, avatar.owner.toBareJid());
								Conversation conversation = find(account, avatar.owner.asBareJid());
								if (conversation != null && conversation.getMode() == Conversation.MODE_MULTI) {
									MucOptions.User user = conversation.getMucOptions().findUserByFullJid(avatar.owner);
									if (user != null) {


@@ 2993,7 2992,7 @@ public class XmppConnectionService extends Service {
						if (items != null) {
							Avatar avatar = Avatar.parseMetadata(items);
							if (avatar != null) {
								avatar.owner = account.getJid().toBareJid();
								avatar.owner = account.getJid().asBareJid();
								if (fileBackend.isAvatarCached(avatar)) {
									if (account.setAvatar(avatar.getFilename())) {
										databaseBackend.updateAccount(account);


@@ 3079,7 3078,7 @@ public class XmppConnectionService extends Service {
	}

	public void invite(Conversation conversation, Jid contact) {
		Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": inviting " + contact + " to " + conversation.getJid().toBareJid());
		Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": inviting " + contact + " to " + conversation.getJid().asBareJid());
		MessagePacket packet = mMessageGenerator.invite(conversation, contact);
		sendMessagePacket(conversation.getAccount(), packet);
	}


@@ 3112,7 3111,7 @@ public class XmppConnectionService extends Service {
			return null;
		}
		for (Conversation conversation : getConversations()) {
			if (conversation.getJid().toBareJid().equals(recipient) && conversation.getAccount() == account) {
			if (conversation.getJid().asBareJid().equals(recipient) && conversation.getAccount() == account) {
				final Message message = conversation.findSentMessageWithUuidOrRemoteId(uuid);
				if (message != null) {
					markMessage(message, status, errorMessage);


@@ 3276,7 3275,7 @@ public class XmppConnectionService extends Service {

	public Account findAccountByJid(final Jid accountJid) {
		for (Account account : this.accounts) {
			if (account.getJid().toBareJid().equals(accountJid.toBareJid())) {
			if (account.getJid().asBareJid().equals(accountJid.asBareJid())) {
				return account;
			}
		}


@@ 3341,7 3340,7 @@ public class XmppConnectionService extends Service {
				&& markable != null
				&& (markable.trusted() || isPrivateAndNonAnonymousMuc)
				&& markable.getRemoteMsgId() != null) {
			Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": sending read marker to " + markable.getCounterpart().toString());
			Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": sending read marker to " + markable.getCounterpart().toString());
			Account account = conversation.getAccount();
			final Jid to = markable.getCounterpart();
			final boolean groupChat = conversation.getMode() == Conversation.MODE_MULTI;


@@ 3427,7 3426,7 @@ public class XmppConnectionService extends Service {
				}
				for (Bookmark bookmark : account.getBookmarks()) {
					final Jid jid = bookmark.getJid();
					final String s = jid == null ? null : jid.getDomainpart();
					final String s = jid == null ? null : jid.getDomain();
					if (s != null && !mucServers.contains(s)) {
						mucServers.add(s);
					}


@@ 3513,7 3512,7 @@ public class XmppConnectionService extends Service {
	}

	private void sendOfflinePresence(final Account account) {
		Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": sending offline presence");
		Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": sending offline presence");
		sendPresencePacket(account, mPresenceGenerator.sendOfflinePresence(account));
	}



@@ 3545,7 3544,7 @@ public class XmppConnectionService extends Service {
		ArrayList<Contact> contacts = new ArrayList<>();
		for (Account account : getAccounts()) {
			if ((account.isEnabled() || accountJid != null)
					&& (accountJid == null || accountJid.equals(account.getJid().toBareJid().toString()))) {
					&& (accountJid == null || accountJid.equals(account.getJid().asBareJid().toString()))) {
				Contact contact = account.getRoster().getContactFromRoster(jid);
				if (contact != null) {
					contacts.add(contact);


@@ 3557,7 3556,7 @@ public class XmppConnectionService extends Service {

	public Conversation findFirstMuc(Jid jid) {
		for (Conversation conversation : getConversations()) {
			if (conversation.getAccount().isEnabled() && conversation.getJid().toBareJid().equals(jid.toBareJid()) && conversation.getMode() == Conversation.MODE_MULTI) {
			if (conversation.getAccount().isEnabled() && conversation.getJid().asBareJid().equals(jid.asBareJid()) && conversation.getMode() == Conversation.MODE_MULTI) {
				return conversation;
			}
		}


@@ 3643,17 3642,17 @@ public class XmppConnectionService extends Service {
	public boolean removeBlockedConversations(final Account account, final Jid blockedJid) {
		boolean removed = false;
		synchronized (this.conversations) {
			boolean domainJid = blockedJid.isDomainJid();
			boolean domainJid = blockedJid.getLocal() == null;
			for (Conversation conversation : this.conversations) {
				boolean jidMatches = (domainJid && blockedJid.getDomainpart().equals(conversation.getJid().getDomainpart()))
						|| blockedJid.equals(conversation.getJid().toBareJid());
				boolean jidMatches = (domainJid && blockedJid.getDomain().equals(conversation.getJid().getDomain()))
						|| blockedJid.equals(conversation.getJid().asBareJid());
				if (conversation.getAccount() == account
						&& conversation.getMode() == Conversation.MODE_SINGLE
						&& jidMatches) {
					this.conversations.remove(conversation);
					markRead(conversation);
					conversation.setStatus(Conversation.STATUS_ARCHIVED);
					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": archiving conversation " + conversation.getJid().toBareJid() + " because jid was blocked");
					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": archiving conversation " + conversation.getJid().asBareJid() + " because jid was blocked");
					updateConversation(conversation);
					removed = true;
				}


@@ 3685,7 3684,7 @@ public class XmppConnectionService extends Service {
				@Override
				public void onIqPacketReceived(Account account, IqPacket packet) {
					if (packet.getType() == IqPacket.TYPE.ERROR) {
						Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not publish nick");
						Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": could not publish nick");
					}
				}
			});


@@ 3716,7 3715,7 @@ public class XmppConnectionService extends Service {
				IqPacket request = new IqPacket(IqPacket.TYPE.GET);
				request.setTo(jid);
				request.query("http://jabber.org/protocol/disco#info");
				Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": making disco request for " + key.second + " to " + jid);
				Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": making disco request for " + key.second + " to " + jid);
				sendIqPacket(account, request, new OnIqPacketReceived() {
					@Override
					public void onIqPacketReceived(Account account, IqPacket discoPacket) {


@@ 3726,7 3725,7 @@ public class XmppConnectionService extends Service {
								databaseBackend.insertDiscoveryResult(disco);
								injectServiceDiscorveryResult(account.getRoster(), presence.getHash(), presence.getVer(), disco);
							} else {
								Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": mismatch in caps for contact " + jid + " " + presence.getVer() + " vs " + disco.getVer());
								Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": mismatch in caps for contact " + jid + " " + presence.getVer() + " vs " + disco.getVer());
							}
						}
						account.inProgressDiscoFetches.remove(key);


@@ 3802,9 3801,9 @@ public class XmppConnectionService extends Service {

	public void saveConversationAsBookmark(Conversation conversation, String name) {
		Account account = conversation.getAccount();
		Bookmark bookmark = new Bookmark(account, conversation.getJid().toBareJid());
		Bookmark bookmark = new Bookmark(account, conversation.getJid().asBareJid());
		if (!conversation.getJid().isBareJid()) {
			bookmark.setNick(conversation.getJid().getResourcepart());
			bookmark.setNick(conversation.getJid().getResource());
		}
		if (name != null && !name.trim().isEmpty()) {
			bookmark.setBookmarkName(name.trim());

M src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java => src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java +4 -3
@@ 16,6 16,7 @@ import android.widget.Toast;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Blockable;
import eu.siacs.conversations.entities.Conversation;
import rocks.xmpp.addr.Jid;

public final class BlockContactDialog {
	public static void show(final XmppActivity xmppActivity, final Blockable blockable) {


@@ 32,14 33,14 @@ public final class BlockContactDialog {

		String value;
		SpannableString spannable;
		if (blockable.getJid().isDomainJid() || blockable.getAccount().isBlocked(blockable.getJid().toDomainJid())) {
		if (blockable.getJid().getLocal() == null || blockable.getAccount().isBlocked(Jid.ofDomain(blockable.getJid().getDomain()))) {
			builder.setTitle(isBlocked ? R.string.action_unblock_domain : R.string.action_block_domain);
			value = blockable.getJid().toDomainJid().toString();
			value = Jid.ofDomain(blockable.getJid().getDomain()).toString();
			spannable = new SpannableString(xmppActivity.getString(isBlocked ? R.string.unblock_domain_text : R.string.block_domain_text, value));
		} else {
			int resBlockAction = blockable instanceof Conversation && ((Conversation) blockable).isWithStranger() ? R.string.block_stranger : R.string.action_block_contact;
			builder.setTitle(isBlocked ? R.string.action_unblock_contact : resBlockAction);
			value = blockable.getJid().toBareJid().toString();
			value = blockable.getJid().asBareJid().toString();
			spannable = new SpannableString(xmppActivity.getString(isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text, value));
		}
		int start = spannable.toString().indexOf(value);

M src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java => src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java +2 -2
@@ 16,7 16,7 @@ import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class BlocklistActivity extends AbstractSearchableListItemActivity implements OnUpdateBlocklist {
	private List<String> mKnownHosts = new ArrayList<>();


@@ 87,7 87,7 @@ public class BlocklistActivity extends AbstractSearchableListItemActivity implem
		EnterJidDialog dialog = new EnterJidDialog(
				this, mKnownHosts, null,
				getString(R.string.block_jabber_id), getString(R.string.block),
				null, account.getJid().toBareJid().toString(), true
				null, account.getJid().asBareJid().toString(), true
		);

		dialog.setOnEnterJidDialogPositiveListener(new EnterJidDialog.OnEnterJidDialogPositiveListener() {

M src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java => src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java +8 -8
@@ 29,7 29,7 @@ import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.ListItem;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class ChooseContactActivity extends AbstractSearchableListItemActivity {
	private List<String> mActivatedAccounts = new ArrayList<>();


@@ 123,7 123,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity {
				data.putExtra("contact", mListItem.getJid().toString());
				String account = request.getStringExtra(EXTRA_ACCOUNT);
				if (account == null && mListItem instanceof Contact) {
					account = ((Contact) mListItem).getAccount().getJid().toBareJid().toString();
					account = ((Contact) mListItem).getAccount().getJid().asBareJid().toString();
				}
				data.putExtra(EXTRA_ACCOUNT, account);
				data.putExtra("conversation",


@@ 172,7 172,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity {
			if (account.getStatus() != Account.State.DISABLED) {
				for (final Contact contact : account.getRoster().getContacts()) {
					if (contact.showInRoster() &&
							!filterContacts.contains(contact.getJid().toBareJid().toString())
							!filterContacts.contains(contact.getJid().asBareJid().toString())
							&& contact.match(this, needle)) {
						getListItems().add(contact);
					}


@@ 241,9 241,9 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity {
		for (Account account : xmppConnectionService.getAccounts()) {
			if (account.getStatus() != Account.State.DISABLED) {
				if (Config.DOMAIN_LOCK != null) {
					this.mActivatedAccounts.add(account.getJid().getLocalpart());
					this.mActivatedAccounts.add(account.getJid().getLocal());
				} else {
					this.mActivatedAccounts.add(account.getJid().toBareJid().toString());
					this.mActivatedAccounts.add(account.getJid().asBareJid().toString());
				}
			}
		}


@@ 257,17 257,17 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity {
			for (MucOptions.User user : conversation.getMucOptions().getUsers(false)) {
				Jid jid = user.getRealJid();
				if (jid != null) {
					contacts.add(jid.toBareJid().toString());
					contacts.add(jid.asBareJid().toString());
				}
			}
		} else {
			contacts.add(conversation.getJid().toBareJid().toString());
			contacts.add(conversation.getJid().asBareJid().toString());
		}
		intent.putExtra("filter_contacts", contacts.toArray(new String[contacts.size()]));
		intent.putExtra("conversation", conversation.getUuid());
		intent.putExtra("multiple", true);
		intent.putExtra("show_enter_jid", true);
		intent.putExtra(EXTRA_ACCOUNT, conversation.getAccount().getJid().toBareJid().toString());
		intent.putExtra(EXTRA_ACCOUNT, conversation.getAccount().getJid().asBareJid().toString());
		return intent;
	}
}

M src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java => src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +10 -10
@@ 50,7 50,7 @@ import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate;
import eu.siacs.conversations.services.XmppConnectionService.OnMucRosterUpdate;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.jid.Jid;
import rocks.xmpp.addr.Jid;

public class ConferenceDetailsActivity extends XmppActivity implements OnConversationUpdate, OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged, XmppConnectionService.OnRoleChanged, XmppConnectionService.OnConfigurationPushed {
	public static final String ACTION_VIEW_MUC = "view_muc";


@@ 329,9 329,9 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
	protected String getShareableUri(boolean http) {
		if (mConversation != null) {
			if (http) {
				return "https://conversations.im/j/"+ mConversation.getJid().toBareJid();
				return "https://conversations.im/j/"+ mConversation.getJid().asBareJid();
			} else {
				return "xmpp:"+mConversation.getJid().toBareJid()+"?join";
				return "xmpp:"+mConversation.getJid().asBareJid()+"?join";
			}
		} else {
			return null;


@@ 378,7 378,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
			if (contact != null && contact.showInRoster()) {
				name = contact.getDisplayName();
			} else if (user.getRealJid() != null){
				name = user.getRealJid().toBareJid().toString();
				name = user.getRealJid().asBareJid().toString();
			} else {
				name = user.getName();
			}


@@ 502,7 502,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers

	protected void startConversation(User user) {
		if (user.getRealJid() != null) {
			Conversation conversation = xmppConnectionService.findOrCreateConversation(this.mConversation.getAccount(),user.getRealJid().toBareJid(),false,true);
			Conversation conversation = xmppConnectionService.findOrCreateConversation(this.mConversation.getAccount(),user.getRealJid().asBareJid(),false,true);
			switchToConversation(conversation);
		}
	}


@@ 544,14 544,14 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
		final User self = mucOptions.getSelf();
		String account;
		if (Config.DOMAIN_LOCK != null) {
			account = mConversation.getAccount().getJid().getLocalpart();
			account = mConversation.getAccount().getJid().getLocal();
		} else {
			account = mConversation.getAccount().getJid().toBareJid().toString();
			account = mConversation.getAccount().getJid().asBareJid().toString();
		}
		mAccountJid.setText(getString(R.string.using_account, account));
		mYourPhoto.setImageBitmap(avatarService().get(mConversation.getAccount(), getPixel(48)));
		setTitle(mConversation.getName())