Merge tag '2.8.4' into develop
This commit is contained in:
commit
c3f392445f
|
@ -1,5 +1,10 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
### Version 2.8.4
|
||||||
|
|
||||||
|
* Rework Login with certificate UI
|
||||||
|
* Add ability to pin chats on top (add to favorites)
|
||||||
|
|
||||||
### Version 2.8.3
|
### Version 2.8.3
|
||||||
|
|
||||||
* Move call icon to the left in order to keep other toolbar icons in a consistent place
|
* Move call icon to the left in order to keep other toolbar icons in a consistent place
|
||||||
|
|
|
@ -67,7 +67,7 @@ dependencies {
|
||||||
implementation 'com.makeramen:roundedimageview:2.3.0'
|
implementation 'com.makeramen:roundedimageview:2.3.0'
|
||||||
implementation "com.wefika:flowlayout:0.4.1"
|
implementation "com.wefika:flowlayout:0.4.1"
|
||||||
implementation 'net.ypresto.androidtranscoder:android-transcoder:0.3.0'
|
implementation 'net.ypresto.androidtranscoder:android-transcoder:0.3.0'
|
||||||
implementation project(':libs:xmpp-addr')
|
implementation 'org.jxmpp:jxmpp-jid:0.6.4'
|
||||||
implementation 'org.osmdroid:osmdroid-android:6.1.5'
|
implementation 'org.osmdroid:osmdroid-android:6.1.5'
|
||||||
implementation 'org.hsluv:hsluv:0.2'
|
implementation 'org.hsluv:hsluv:0.2'
|
||||||
implementation 'org.conscrypt:conscrypt-android:2.2.1'
|
implementation 'org.conscrypt:conscrypt-android:2.2.1'
|
||||||
|
@ -96,8 +96,8 @@ android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 25
|
targetSdkVersion 25
|
||||||
versionCode 383
|
versionCode 387
|
||||||
versionName "2.8.3"
|
versionName "2.8.4"
|
||||||
archivesBaseName += "-$versionName"
|
archivesBaseName += "-$versionName"
|
||||||
applicationId "eu.sum7.conversations"
|
applicationId "eu.sum7.conversations"
|
||||||
resValue "string", "applicationId", applicationId
|
resValue "string", "applicationId", applicationId
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
/build
|
|
|
@ -1,14 +0,0 @@
|
||||||
apply plugin: 'java-library'
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
jcenter()
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation 'rocks.xmpp:precis:1.0.0'
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceCompatibility = "8"
|
|
||||||
targetCompatibility = "8"
|
|
|
@ -1,179 +0,0 @@
|
||||||
/*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2017 Christian Schudt
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package rocks.xmpp.addr;
|
|
||||||
|
|
||||||
import java.text.Collator;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract Jid implementation for both full and bare JIDs.
|
|
||||||
*
|
|
||||||
* @author Christian Schudt
|
|
||||||
*/
|
|
||||||
abstract class AbstractJid implements Jid {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the JID is a full JID.
|
|
||||||
* <blockquote>
|
|
||||||
* <p>The term "full JID" refers to an XMPP address of the form <localpart@domainpart/resourcepart> (for a particular authorized client or device associated with an account) or of the form <domainpart/resourcepart> (for a particular resource or script associated with a server).</p>
|
|
||||||
* </blockquote>
|
|
||||||
*
|
|
||||||
* @return True, if the JID is a full JID; otherwise false.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final boolean isFullJid() {
|
|
||||||
return getResource() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the JID is a bare JID.
|
|
||||||
* <blockquote>
|
|
||||||
* <p>The term "bare JID" refers to an XMPP address of the form <localpart@domainpart> (for an account at a server) or of the form <domainpart> (for a server).</p>
|
|
||||||
* </blockquote>
|
|
||||||
*
|
|
||||||
* @return True, if the JID is a bare JID; otherwise false.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final boolean isBareJid() {
|
|
||||||
return getResource() == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean isDomainJid() {
|
|
||||||
return getLocal() == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean equals(Object o) {
|
|
||||||
if (o == this) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!(o instanceof Jid)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Jid other = (Jid) o;
|
|
||||||
|
|
||||||
return (getLocal() == other.getLocal() || getLocal() != null && getLocal().equals(other.getLocal()))
|
|
||||||
&& (getDomain() == other.getDomain() || getDomain() != null && getDomain().equals(other.getDomain()))
|
|
||||||
&& (getResource() == other.getResource() || getResource() != null && getResource().equals(other.getResource()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final int hashCode() {
|
|
||||||
return Arrays.hashCode(new String[]{getLocal(), getDomain(), getResource()});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares this JID with another JID. First domain parts are compared. If these are equal, local parts are compared
|
|
||||||
* and if these are equal, too, resource parts are compared.
|
|
||||||
*
|
|
||||||
* @param o The other JID.
|
|
||||||
* @return The comparison result.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final int compareTo(Jid o) {
|
|
||||||
|
|
||||||
if (this == o) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o != null) {
|
|
||||||
final Collator collator = Collator.getInstance();
|
|
||||||
int result;
|
|
||||||
// First compare domain parts.
|
|
||||||
if (getDomain() != null) {
|
|
||||||
result = o.getDomain() != null ? collator.compare(getDomain(), o.getDomain()) : -1;
|
|
||||||
} else {
|
|
||||||
result = o.getDomain() != null ? 1 : 0;
|
|
||||||
}
|
|
||||||
// If the domains are equal, compare local parts.
|
|
||||||
if (result == 0) {
|
|
||||||
if (getLocal() != null) {
|
|
||||||
// If this local part is not null, but the other is null, move this down (1).
|
|
||||||
result = o.getLocal() != null ? collator.compare(getLocal(), o.getLocal()) : 1;
|
|
||||||
} else {
|
|
||||||
// If this local part is null, but the other is not, move this up (-1).
|
|
||||||
result = o.getLocal() != null ? -1 : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the local parts are equal, compare resource parts.
|
|
||||||
if (result == 0) {
|
|
||||||
if (getResource() != null) {
|
|
||||||
// If this resource part is not null, but the other is null, move this down (1).
|
|
||||||
return o.getResource() != null ? collator.compare(getResource(), o.getResource()) : 1;
|
|
||||||
} else {
|
|
||||||
// If this resource part is null, but the other is not, move this up (-1).
|
|
||||||
return o.getResource() != null ? -1 : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final int length() {
|
|
||||||
return toString().length();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final char charAt(int index) {
|
|
||||||
return toString().charAt(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final CharSequence subSequence(int start, int end) {
|
|
||||||
return toString().subSequence(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the JID in its string representation, i.e. [ localpart "@" ] domainpart [ "/" resourcepart ].
|
|
||||||
*
|
|
||||||
* @return The JID.
|
|
||||||
* @see #toEscapedString()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final String toString() {
|
|
||||||
return toString(getLocal(), getDomain(), getResource());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String toEscapedString() {
|
|
||||||
return toString(getEscapedLocal(), getDomain(), getResource());
|
|
||||||
}
|
|
||||||
|
|
||||||
static String toString(String local, String domain, String resource) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
if (local != null) {
|
|
||||||
sb.append(local).append('@');
|
|
||||||
}
|
|
||||||
sb.append(domain);
|
|
||||||
if (resource != null) {
|
|
||||||
sb.append('/').append(resource);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,498 +0,0 @@
|
||||||
/*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2017 Christian Schudt
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package rocks.xmpp.addr;
|
|
||||||
|
|
||||||
import rocks.xmpp.precis.PrecisProfile;
|
|
||||||
import rocks.xmpp.precis.PrecisProfiles;
|
|
||||||
import rocks.xmpp.util.cache.LruCache;
|
|
||||||
|
|
||||||
import java.net.IDN;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.text.Normalizer;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The implementation of the JID as described in <a href="https://tools.ietf.org/html/rfc7622">Extensible Messaging and Presence Protocol (XMPP): Address Format</a>.
|
|
||||||
* <p>
|
|
||||||
* This class is thread-safe and immutable.
|
|
||||||
*
|
|
||||||
* @author Christian Schudt
|
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc7622">RFC 7622 - Extensible Messaging and Presence Protocol (XMPP): Address Format</a>
|
|
||||||
*/
|
|
||||||
final class FullJid extends AbstractJid {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Escapes all disallowed characters and also backslash, when followed by a defined hex code for escaping. See 4. Business Rules.
|
|
||||||
*/
|
|
||||||
private static final Pattern ESCAPE_PATTERN = Pattern.compile("[ \"&'/:<>@]|\\\\(?=20|22|26|27|2f|3a|3c|3e|40|5c)");
|
|
||||||
|
|
||||||
private static final Pattern UNESCAPE_PATTERN = Pattern.compile("\\\\(20|22|26|27|2f|3a|3c|3e|40|5c)");
|
|
||||||
|
|
||||||
private static final Pattern JID = Pattern.compile("^((.*?)@)?([^/@]+)(/(.*))?$");
|
|
||||||
|
|
||||||
private static final IDNProfile IDN_PROFILE = new IDNProfile();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whenever dots are used as label separators, the following characters MUST be recognized as dots: U+002E (full stop), U+3002 (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61 (halfwidth ideographic full stop).
|
|
||||||
*/
|
|
||||||
private static final String DOTS = "[.\u3002\uFF0E\uFF61]";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Label separators for domain labels, which should be mapped to "." (dot): IDEOGRAPHIC FULL STOP character (U+3002)
|
|
||||||
*/
|
|
||||||
private static final Pattern LABEL_SEPARATOR = Pattern.compile(DOTS);
|
|
||||||
|
|
||||||
private static final Pattern LABEL_SEPARATOR_FINAL = Pattern.compile(DOTS + "$");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Caches the escaped JIDs.
|
|
||||||
*/
|
|
||||||
private static final Map<CharSequence, Jid> ESCAPED_CACHE = new LruCache<>(5000);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Caches the unescaped JIDs.
|
|
||||||
*/
|
|
||||||
private static final Map<CharSequence, Jid> UNESCAPED_CACHE = new LruCache<>(5000);
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -3824234106101731424L;
|
|
||||||
|
|
||||||
private final String escapedLocal;
|
|
||||||
|
|
||||||
private final String local;
|
|
||||||
|
|
||||||
private final String domain;
|
|
||||||
|
|
||||||
private final String resource;
|
|
||||||
|
|
||||||
private final Jid bareJid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a full JID with local, domain and resource part.
|
|
||||||
*
|
|
||||||
* @param local The local part.
|
|
||||||
* @param domain The domain part.
|
|
||||||
* @param resource The resource part.
|
|
||||||
*/
|
|
||||||
FullJid(CharSequence local, CharSequence domain, CharSequence resource) {
|
|
||||||
this(local, domain, resource, false, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private FullJid(final CharSequence local, final CharSequence domain, final CharSequence resource, final boolean doUnescape, Jid bareJid) {
|
|
||||||
final String enforcedLocalPart;
|
|
||||||
final String enforcedDomainPart;
|
|
||||||
final String enforcedResource;
|
|
||||||
|
|
||||||
final String unescapedLocalPart;
|
|
||||||
|
|
||||||
if (domain == null) {
|
|
||||||
throw new NullPointerException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doUnescape) {
|
|
||||||
unescapedLocalPart = unescape(local);
|
|
||||||
} else {
|
|
||||||
unescapedLocalPart = local != null ? local.toString() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escape the local part, so that disallowed characters like the space characters pass the UsernameCaseMapped profile.
|
|
||||||
final String escapedLocalPart = escape(unescapedLocalPart);
|
|
||||||
|
|
||||||
// If the domainpart includes a final character considered to be a label
|
|
||||||
// separator (dot) by [RFC1034], this character MUST be stripped from
|
|
||||||
// the domainpart before the JID of which it is a part is used for the
|
|
||||||
// purpose of routing an XML stanza, comparing against another JID, or
|
|
||||||
// constructing an XMPP URI or IRI [RFC5122]. In particular, such a
|
|
||||||
// character MUST be stripped before any other canonicalization steps
|
|
||||||
// are taken.
|
|
||||||
// Also validate, that the domain name can be converted to ASCII, i.e. validate the domain name (e.g. must not start with "_").
|
|
||||||
final String strDomain = IDN.toASCII(LABEL_SEPARATOR_FINAL.matcher(domain).replaceAll(""), IDN.USE_STD3_ASCII_RULES);
|
|
||||||
enforcedLocalPart = escapedLocalPart != null ? PrecisProfiles.USERNAME_CASE_MAPPED.enforce(escapedLocalPart) : null;
|
|
||||||
enforcedResource = resource != null ? PrecisProfiles.OPAQUE_STRING.enforce(resource) : null;
|
|
||||||
// See https://tools.ietf.org/html/rfc5895#section-2
|
|
||||||
enforcedDomainPart = IDN_PROFILE.enforce(strDomain);
|
|
||||||
|
|
||||||
validateLength(enforcedLocalPart, "local");
|
|
||||||
validateLength(enforcedResource, "resource");
|
|
||||||
validateDomain(strDomain);
|
|
||||||
|
|
||||||
this.local = unescape(enforcedLocalPart);
|
|
||||||
this.escapedLocal = enforcedLocalPart;
|
|
||||||
this.domain = enforcedDomainPart;
|
|
||||||
this.resource = enforcedResource;
|
|
||||||
if (bareJid != null) {
|
|
||||||
this.bareJid = bareJid;
|
|
||||||
} else {
|
|
||||||
this.bareJid = isBareJid() ? this : new AbstractJid() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Jid asBareJid() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Jid withLocal(CharSequence local) {
|
|
||||||
if (local == this.getLocal() || local != null && local.equals(this.getLocal())) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
return new FullJid(local, getDomain(), getResource(), false, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Jid withResource(CharSequence resource) {
|
|
||||||
if (resource == this.getResource() || resource != null && resource.equals(this.getResource())) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
return new FullJid(getLocal(), getDomain(), resource, false, asBareJid());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Jid atSubdomain(CharSequence subdomain) {
|
|
||||||
if (subdomain == null) {
|
|
||||||
throw new NullPointerException();
|
|
||||||
}
|
|
||||||
return new FullJid(getLocal(), subdomain + "." + getDomain(), getResource(), false, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getLocal() {
|
|
||||||
return FullJid.this.getLocal();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getEscapedLocal() {
|
|
||||||
return FullJid.this.getEscapedLocal();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDomain() {
|
|
||||||
return FullJid.this.getDomain();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getResource() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a JID from a string. The format must be
|
|
||||||
* <blockquote><p>[ localpart "@" ] domainpart [ "/" resourcepart ]</p></blockquote>
|
|
||||||
*
|
|
||||||
* @param jid The JID.
|
|
||||||
* @param doUnescape If the jid parameter will be unescaped.
|
|
||||||
* @return The JID.
|
|
||||||
* @throws NullPointerException If the jid is null.
|
|
||||||
* @throws IllegalArgumentException If the jid could not be parsed or is not valid.
|
|
||||||
* @see <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>
|
|
||||||
*/
|
|
||||||
static Jid of(String jid, final boolean doUnescape) {
|
|
||||||
if (jid == null) {
|
|
||||||
throw new NullPointerException("jid must not be null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
jid = jid.trim();
|
|
||||||
|
|
||||||
if (jid.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("jid must not be empty.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Jid result;
|
|
||||||
if (doUnescape) {
|
|
||||||
result = UNESCAPED_CACHE.get(jid);
|
|
||||||
} else {
|
|
||||||
result = ESCAPED_CACHE.get(jid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matcher matcher = JID.matcher(jid);
|
|
||||||
if (matcher.matches()) {
|
|
||||||
Jid jidValue = new FullJid(matcher.group(2), matcher.group(3), matcher.group(5), doUnescape, null);
|
|
||||||
if (doUnescape) {
|
|
||||||
UNESCAPED_CACHE.put(jid, jidValue);
|
|
||||||
} else {
|
|
||||||
ESCAPED_CACHE.put(jid, jidValue);
|
|
||||||
}
|
|
||||||
return jidValue;
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Could not parse JID: " + jid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Escapes a local part. The characters {@code "&'/:<>@} (+ whitespace) are replaced with their respective escape characters.
|
|
||||||
*
|
|
||||||
* @param localPart The local part.
|
|
||||||
* @return The escaped local part or null.
|
|
||||||
* @see <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>
|
|
||||||
*/
|
|
||||||
private static String escape(final CharSequence localPart) {
|
|
||||||
if (localPart != null) {
|
|
||||||
final Matcher matcher = ESCAPE_PATTERN.matcher(localPart);
|
|
||||||
final StringBuffer sb = new StringBuffer();
|
|
||||||
while (matcher.find()) {
|
|
||||||
matcher.appendReplacement(sb, "\\\\" + Integer.toHexString(matcher.group().charAt(0)));
|
|
||||||
}
|
|
||||||
matcher.appendTail(sb);
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String unescape(final CharSequence localPart) {
|
|
||||||
if (localPart != null) {
|
|
||||||
final Matcher matcher = UNESCAPE_PATTERN.matcher(localPart);
|
|
||||||
final StringBuffer sb = new StringBuffer();
|
|
||||||
while (matcher.find()) {
|
|
||||||
final char c = (char) Integer.parseInt(matcher.group(1), 16);
|
|
||||||
if (c == '\\') {
|
|
||||||
matcher.appendReplacement(sb, "\\\\");
|
|
||||||
} else {
|
|
||||||
matcher.appendReplacement(sb, String.valueOf(c));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
matcher.appendTail(sb);
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void validateDomain(String domain) {
|
|
||||||
if (domain == null) {
|
|
||||||
throw new NullPointerException("domain must not be null.");
|
|
||||||
}
|
|
||||||
if (domain.contains("@")) {
|
|
||||||
// Prevent misuse of API.
|
|
||||||
throw new IllegalArgumentException("domain must not contain a '@' sign");
|
|
||||||
}
|
|
||||||
validateLength(domain, "domain");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates that the length of a local, domain or resource part is not longer than 1023 characters.
|
|
||||||
*
|
|
||||||
* @param value The value.
|
|
||||||
* @param part The part, only used to produce an exception message.
|
|
||||||
*/
|
|
||||||
private static void validateLength(CharSequence value, CharSequence part) {
|
|
||||||
if (value != null) {
|
|
||||||
if (value.length() == 0) {
|
|
||||||
throw new IllegalArgumentException(part + " must not be empty.");
|
|
||||||
}
|
|
||||||
if (value.toString().getBytes(Charset.forName("UTF-8")).length > 1023) {
|
|
||||||
throw new IllegalArgumentException(part + " must not be greater than 1023 bytes.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts this JID into a bare JID, i.e. removes the resource part.
|
|
||||||
* <blockquote>
|
|
||||||
* <p>The term "bare JID" refers to an XMPP address of the form <localpart@domainpart> (for an account at a server) or of the form <domainpart> (for a server).</p>
|
|
||||||
* </blockquote>
|
|
||||||
*
|
|
||||||
* @return The bare JID.
|
|
||||||
* @see #withResource(CharSequence)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final Jid asBareJid() {
|
|
||||||
return bareJid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the local part of the JID, also known as the name or node.
|
|
||||||
* <blockquote>
|
|
||||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.3">3.3. Localpart</a></cite></p>
|
|
||||||
* <p>The localpart of a JID is an optional identifier placed before the
|
|
||||||
* domainpart and separated from the latter by the '@' character.
|
|
||||||
* Typically, a localpart uniquely identifies the entity requesting and
|
|
||||||
* using network access provided by a server (i.e., a local account),
|
|
||||||
* although it can also represent other kinds of entities (e.g., a
|
|
||||||
* chatroom associated with a multi-user chat service [XEP-0045]). The
|
|
||||||
* entity represented by an XMPP localpart is addressed within the
|
|
||||||
* context of a specific domain (i.e., <localpart@domainpart>).</p>
|
|
||||||
* </blockquote>
|
|
||||||
*
|
|
||||||
* @return The local part or null.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final String getLocal() {
|
|
||||||
return local;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String getEscapedLocal() {
|
|
||||||
return escapedLocal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the domain part.
|
|
||||||
* <blockquote>
|
|
||||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.2">3.2. Domainpart</a></cite></p>
|
|
||||||
* <p>The domainpart is the primary identifier and is the only REQUIRED
|
|
||||||
* element of a JID (a mere domainpart is a valid JID). Typically,
|
|
||||||
* a domainpart identifies the "home" server to which clients connect
|
|
||||||
* for XML routing and data management functionality.</p>
|
|
||||||
* </blockquote>
|
|
||||||
*
|
|
||||||
* @return The domain part.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final String getDomain() {
|
|
||||||
return domain;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the resource part.
|
|
||||||
* <blockquote>
|
|
||||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.4">3.4. Resourcepart</a></cite></p>
|
|
||||||
* <p>The resourcepart of a JID is an optional identifier placed after the
|
|
||||||
* domainpart and separated from the latter by the '/' character. A
|
|
||||||
* resourcepart can modify either a <localpart@domainpart> address or a
|
|
||||||
* mere <domainpart> address. Typically, a resourcepart uniquely
|
|
||||||
* identifies a specific connection (e.g., a device or location) or
|
|
||||||
* object (e.g., an occupant in a multi-user chatroom [XEP-0045])
|
|
||||||
* belonging to the entity associated with an XMPP localpart at a domain
|
|
||||||
* (i.e., <localpart@domainpart/resourcepart>).</p>
|
|
||||||
* </blockquote>
|
|
||||||
*
|
|
||||||
* @return The resource part or null.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final String getResource() {
|
|
||||||
return resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new JID with a new local part and the same domain and resource part of the current JID.
|
|
||||||
*
|
|
||||||
* @param local The local part.
|
|
||||||
* @return The JID with a new local part.
|
|
||||||
* @throws IllegalArgumentException If the local is not a valid local part.
|
|
||||||
* @see #withResource(CharSequence)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final Jid withLocal(CharSequence local) {
|
|
||||||
if (local == this.getLocal() || local != null && local.equals(this.getLocal())) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
return new FullJid(local, getDomain(), getResource(), false, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new full JID with a resource and the same local and domain part of the current JID.
|
|
||||||
*
|
|
||||||
* @param resource The resource.
|
|
||||||
* @return The full JID with a resource.
|
|
||||||
* @throws IllegalArgumentException If the resource is not a valid resource part.
|
|
||||||
* @see #asBareJid()
|
|
||||||
* @see #withLocal(CharSequence)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final Jid withResource(CharSequence resource) {
|
|
||||||
if (resource == this.getResource() || resource != null && resource.equals(this.getResource())) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
return new FullJid(getLocal(), getDomain(), resource, false, asBareJid());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new JID at a subdomain and at the same domain as this JID.
|
|
||||||
*
|
|
||||||
* @param subdomain The subdomain.
|
|
||||||
* @return The JID at a subdomain.
|
|
||||||
* @throws NullPointerException If subdomain is null.
|
|
||||||
* @throws IllegalArgumentException If subdomain is not a valid subdomain name.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final Jid atSubdomain(CharSequence subdomain) {
|
|
||||||
if (subdomain != null) {
|
|
||||||
throw new NullPointerException();
|
|
||||||
}
|
|
||||||
return new FullJid(getLocal(), subdomain + "." + getDomain(), getResource(), false, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A profile for applying the rules for IDN as in RFC 5895. Although IDN doesn't use Precis, it's still very similar so that we can use the base class.
|
|
||||||
*
|
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc5895#section-2">RFC 5895</a>
|
|
||||||
*/
|
|
||||||
private static final class IDNProfile extends PrecisProfile {
|
|
||||||
|
|
||||||
private IDNProfile() {
|
|
||||||
super(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String prepare(CharSequence input) {
|
|
||||||
return IDN.toUnicode(input.toString(), IDN.USE_STD3_ASCII_RULES);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String enforce(CharSequence input) {
|
|
||||||
// 4. Map IDEOGRAPHIC FULL STOP character (U+3002) to dot.
|
|
||||||
return applyAdditionalMappingRule(
|
|
||||||
// 3. All characters are mapped using Unicode Normalization Form C (NFC).
|
|
||||||
applyNormalizationRule(
|
|
||||||
// 2. Fullwidth and halfwidth characters (those defined with
|
|
||||||
// Decomposition Types <wide> and <narrow>) are mapped to their
|
|
||||||
// decomposition mappings
|
|
||||||
applyWidthMappingRule(
|
|
||||||
// 1. Uppercase characters are mapped to their lowercase equivalents
|
|
||||||
applyCaseMappingRule(prepare(input))))).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected CharSequence applyWidthMappingRule(CharSequence charSequence) {
|
|
||||||
return widthMap(charSequence);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected CharSequence applyAdditionalMappingRule(CharSequence charSequence) {
|
|
||||||
return LABEL_SEPARATOR.matcher(charSequence).replaceAll(".");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected CharSequence applyCaseMappingRule(CharSequence charSequence) {
|
|
||||||
return charSequence.toString().toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected CharSequence applyNormalizationRule(CharSequence charSequence) {
|
|
||||||
return Normalizer.normalize(charSequence, Normalizer.Form.NFC);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected CharSequence applyDirectionalityRule(CharSequence charSequence) {
|
|
||||||
return charSequence;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,313 +0,0 @@
|
||||||
/*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2017 Christian Schudt
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package rocks.xmpp.addr;
|
|
||||||
|
|
||||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the JID as described in <a href="https://tools.ietf.org/html/rfc7622">Extensible Messaging and Presence Protocol (XMPP): Address Format</a>.
|
|
||||||
* <p>
|
|
||||||
* A JID consists of three parts:
|
|
||||||
* <p>
|
|
||||||
* [ localpart "@" ] domainpart [ "/" resourcepart ]
|
|
||||||
* </p>
|
|
||||||
* The easiest way to create a JID is to use the {@link #of(CharSequence)} method:
|
|
||||||
* ```java
|
|
||||||
* Jid jid = Jid.of("juliet@capulet.lit/balcony");
|
|
||||||
* ```
|
|
||||||
* You can then get the parts from it via the respective methods:
|
|
||||||
* ```java
|
|
||||||
* String local = jid.getLocal(); // juliet
|
|
||||||
* String domain = jid.getDomain(); // capulet.lit
|
|
||||||
* String resource = jid.getResource(); // balcony
|
|
||||||
* ```
|
|
||||||
* Implementations of this interface should override <code>equals()</code> and <code>hashCode()</code>, so that different instances with the same value are equal:
|
|
||||||
* ```java
|
|
||||||
* Jid.of("romeo@capulet.lit/balcony").equals(Jid.of("romeo@capulet.lit/balcony")); // true
|
|
||||||
* ```
|
|
||||||
* The default implementation of this class also supports <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>, i.e.
|
|
||||||
* ```java
|
|
||||||
* Jid.of("d'artagnan@musketeers.lit")
|
|
||||||
* ```
|
|
||||||
* is escaped as <code>d\\27artagnan@musketeers.lit</code>.
|
|
||||||
* <p>
|
|
||||||
* Implementations of this interface should be thread-safe and immutable.
|
|
||||||
*
|
|
||||||
* @author Christian Schudt
|
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc7622">RFC 7622 - Extensible Messaging and Presence Protocol (XMPP): Address Format</a>
|
|
||||||
*/
|
|
||||||
public interface Jid extends Comparable<Jid>, Serializable, CharSequence {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximal length of a full JID, which is 3071.
|
|
||||||
* <blockquote>
|
|
||||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.1">3.1. Fundamentals</a></cite></p>
|
|
||||||
* <p>Each allowable portion of a JID (localpart, domainpart, and
|
|
||||||
* resourcepart) is 1 to 1023 octets in length, resulting in a maximum
|
|
||||||
* total size (including the '@' and '/' separators) of 3071 octets.
|
|
||||||
* </p>
|
|
||||||
* </blockquote>
|
|
||||||
* Note that the length is based on bytes, not characters.
|
|
||||||
*
|
|
||||||
* @see #MAX_BARE_JID_LENGTH
|
|
||||||
*/
|
|
||||||
int MAX_FULL_JID_LENGTH = 3071;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximal length of a bare JID, which is 2047 (1023 + 1 + 1023).
|
|
||||||
* Note that the length is based on bytes, not characters.
|
|
||||||
*
|
|
||||||
* @see #MAX_FULL_JID_LENGTH
|
|
||||||
*/
|
|
||||||
int MAX_BARE_JID_LENGTH = 2047;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The service discovery feature used for determining support of JID escaping (<code>jid\20escaping</code>).
|
|
||||||
*/
|
|
||||||
String ESCAPING_FEATURE = "jid\\20escaping";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a full JID with a domain and resource part, e.g. <code>capulet.com/balcony</code>
|
|
||||||
*
|
|
||||||
* @param local The local part.
|
|
||||||
* @param domain The domain.
|
|
||||||
* @param resource The resource part.
|
|
||||||
* @return The JID.
|
|
||||||
* @throws NullPointerException If the domain is null.
|
|
||||||
* @throws IllegalArgumentException If the domain, local or resource part are not valid.
|
|
||||||
*/
|
|
||||||
static Jid of(CharSequence local, CharSequence domain, CharSequence resource) {
|
|
||||||
return new FullJid(local, domain, resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a bare JID with only the domain part, e.g. <code>capulet.com</code>
|
|
||||||
*
|
|
||||||
* @param domain The domain.
|
|
||||||
* @return The JID.
|
|
||||||
* @throws NullPointerException If the domain is null.
|
|
||||||
* @throws IllegalArgumentException If the domain or local part are not valid.
|
|
||||||
*/
|
|
||||||
static Jid ofDomain(CharSequence domain) {
|
|
||||||
return new FullJid(null, domain, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a bare JID with a local and domain part, e.g. <code>juliet@capulet.com</code>
|
|
||||||
*
|
|
||||||
* @param local The local part.
|
|
||||||
* @param domain The domain.
|
|
||||||
* @return The JID.
|
|
||||||
* @throws NullPointerException If the domain is null.
|
|
||||||
* @throws IllegalArgumentException If the domain or local part are not valid.
|
|
||||||
*/
|
|
||||||
static Jid ofLocalAndDomain(CharSequence local, CharSequence domain) {
|
|
||||||
return new FullJid(local, domain, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a full JID with a domain and resource part, e.g. <code>capulet.com/balcony</code>
|
|
||||||
*
|
|
||||||
* @param domain The domain.
|
|
||||||
* @param resource The resource part.
|
|
||||||
* @return The JID.
|
|
||||||
* @throws NullPointerException If the domain is null.
|
|
||||||
* @throws IllegalArgumentException If the domain or resource are not valid.
|
|
||||||
*/
|
|
||||||
static Jid ofDomainAndResource(CharSequence domain, CharSequence resource) {
|
|
||||||
return new FullJid(null, domain, resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a JID from an unescaped string. The format must be
|
|
||||||
* <blockquote><p>[ localpart "@" ] domainpart [ "/" resourcepart ]</p></blockquote>
|
|
||||||
* The input string will be escaped.
|
|
||||||
*
|
|
||||||
* @param jid The JID.
|
|
||||||
* @return The JID.
|
|
||||||
* @throws NullPointerException If the jid is null.
|
|
||||||
* @throws IllegalArgumentException If the jid could not be parsed or is not valid.
|
|
||||||
* @see <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>
|
|
||||||
*/
|
|
||||||
static Jid of(CharSequence jid) {
|
|
||||||
if (jid instanceof Jid) {
|
|
||||||
return (Jid) jid;
|
|
||||||
}
|
|
||||||
return FullJid.of(jid.toString(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a JID from a escaped JID string. The format must be
|
|
||||||
* <blockquote><p>[ localpart "@" ] domainpart [ "/" resourcepart ]</p></blockquote>
|
|
||||||
* This method should be used, when parsing JIDs from the XMPP stream.
|
|
||||||
*
|
|
||||||
* @param jid The JID.
|
|
||||||
* @return The JID.
|
|
||||||
* @throws NullPointerException If the jid is null.
|
|
||||||
* @throws IllegalArgumentException If the jid could not be parsed or is not valid.
|
|
||||||
* @see <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>
|
|
||||||
*/
|
|
||||||
static Jid ofEscaped(CharSequence jid) {
|
|
||||||
return FullJid.of(jid.toString(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the JID is a full JID.
|
|
||||||
* <blockquote>
|
|
||||||
* <p>The term "full JID" refers to an XMPP address of the form <localpart@domainpart/resourcepart> (for a particular authorized client or device associated with an account) or of the form <domainpart/resourcepart> (for a particular resource or script associated with a server).</p>
|
|
||||||
* </blockquote>
|
|
||||||
*
|
|
||||||
* @return True, if the JID is a full JID; otherwise false.
|
|
||||||
*/
|
|
||||||
boolean isFullJid();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the JID is a bare JID.
|
|
||||||
* <blockquote>
|
|
||||||
* <p>The term "bare JID" refers to an XMPP address of the form <localpart@domainpart> (for an account at a server) or of the form <domainpart> (for a server).</p>
|
|
||||||
* </blockquote>
|
|
||||||
*
|
|
||||||
* @return True, if the JID is a bare JID; otherwise false.
|
|
||||||
*/
|
|
||||||
boolean isBareJid();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the JID is a domain JID, i.e. if it has no local part.
|
|
||||||
*
|
|
||||||
* @return True, if the JID is a domain JID, i.e. if it has no local part.
|
|
||||||
*/
|
|
||||||
boolean isDomainJid();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the bare JID representation of this JID, i.e. removes the resource part.
|
|
||||||
* <blockquote>
|
|
||||||
* <p>The term "bare JID" refers to an XMPP address of the form <localpart@domainpart> (for an account at a server) or of the form <domainpart> (for a server).</p>
|
|
||||||
* </blockquote>
|
|
||||||
*
|
|
||||||
* @return The bare JID.
|
|
||||||
* @see #withResource(CharSequence)
|
|
||||||
*/
|
|
||||||
Jid asBareJid();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new JID with a new local part and the same domain and resource part of the current JID.
|
|
||||||
*
|
|
||||||
* @param local The local part.
|
|
||||||
* @return The JID with a new local part.
|
|
||||||
* @throws IllegalArgumentException If the local is not a valid local part.
|
|
||||||
* @see #withResource(CharSequence)
|
|
||||||
*/
|
|
||||||
Jid withLocal(CharSequence local);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new full JID with a resource and the same local and domain part of the current JID.
|
|
||||||
*
|
|
||||||
* @param resource The resource.
|
|
||||||
* @return The full JID with a resource.
|
|
||||||
* @throws IllegalArgumentException If the resource is not a valid resource part.
|
|
||||||
* @see #asBareJid()
|
|
||||||
* @see #withLocal(CharSequence)
|
|
||||||
*/
|
|
||||||
Jid withResource(CharSequence resource);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new JID at a subdomain and at the same domain as this JID.
|
|
||||||
*
|
|
||||||
* @param subdomain The subdomain.
|
|
||||||
* @return The JID at a subdomain.
|
|
||||||
* @throws NullPointerException If subdomain is null.
|
|
||||||
* @throws IllegalArgumentException If subdomain is not a valid subdomain name.
|
|
||||||
*/
|
|
||||||
Jid atSubdomain(CharSequence subdomain);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the local part of the JID, also known as the name or node.
|
|
||||||
* <blockquote>
|
|
||||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.3">3.3. Localpart</a></cite></p>
|
|
||||||
* <p>The localpart of a JID is an optional identifier placed before the
|
|
||||||
* domainpart and separated from the latter by the '@' character.
|
|
||||||
* Typically, a localpart uniquely identifies the entity requesting and
|
|
||||||
* using network access provided by a server (i.e., a local account),
|
|
||||||
* although it can also represent other kinds of entities (e.g., a
|
|
||||||
* chatroom associated with a multi-user chat service [XEP-0045]). The
|
|
||||||
* entity represented by an XMPP localpart is addressed within the
|
|
||||||
* context of a specific domain (i.e., <localpart@domainpart>).</p>
|
|
||||||
* </blockquote>
|
|
||||||
*
|
|
||||||
* @return The local part or null.
|
|
||||||
* @see #getEscapedLocal()
|
|
||||||
*/
|
|
||||||
String getLocal();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the escaped local part of the JID.
|
|
||||||
*
|
|
||||||
* @return The escaped local part or null.
|
|
||||||
* @see #getLocal()
|
|
||||||
* @since 0.8.0
|
|
||||||
*/
|
|
||||||
String getEscapedLocal();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the domain part.
|
|
||||||
* <blockquote>
|
|
||||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.2">3.2. Domainpart</a></cite></p>
|
|
||||||
* <p>The domainpart is the primary identifier and is the only REQUIRED
|
|
||||||
* element of a JID (a mere domainpart is a valid JID). Typically,
|
|
||||||
* a domainpart identifies the "home" server to which clients connect
|
|
||||||
* for XML routing and data management functionality.</p>
|
|
||||||
* </blockquote>
|
|
||||||
*
|
|
||||||
* @return The domain part.
|
|
||||||
*/
|
|
||||||
String getDomain();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the resource part.
|
|
||||||
* <blockquote>
|
|
||||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.4">3.4. Resourcepart</a></cite></p>
|
|
||||||
* <p>The resourcepart of a JID is an optional identifier placed after the
|
|
||||||
* domainpart and separated from the latter by the '/' character. A
|
|
||||||
* resourcepart can modify either a <localpart@domainpart> address or a
|
|
||||||
* mere <domainpart> address. Typically, a resourcepart uniquely
|
|
||||||
* identifies a specific connection (e.g., a device or location) or
|
|
||||||
* object (e.g., an occupant in a multi-user chatroom [XEP-0045])
|
|
||||||
* belonging to the entity associated with an XMPP localpart at a domain
|
|
||||||
* (i.e., <localpart@domainpart/resourcepart>).</p>
|
|
||||||
* </blockquote>
|
|
||||||
*
|
|
||||||
* @return The resource part or null.
|
|
||||||
*/
|
|
||||||
String getResource();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the JID in escaped form as described in <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>.
|
|
||||||
*
|
|
||||||
* @return The escaped JID.
|
|
||||||
* @see #toString()
|
|
||||||
*/
|
|
||||||
String toEscapedString();
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
/*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2017 Christian Schudt
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package rocks.xmpp.addr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a malformed JID in order to handle the <code>jid-malformed</code> error.
|
|
||||||
* <p>
|
|
||||||
* This class is not intended to be publicly instantiable, but is used for malformed JIDs during parsing automatically.
|
|
||||||
*
|
|
||||||
* @author Christian Schudt
|
|
||||||
* @see <a href="https://xmpp.org/rfcs/rfc6120.html#stanzas-error-conditions-jid-malformed">RFC 6120, 8.3.3.8. jid-malformed</a>
|
|
||||||
*/
|
|
||||||
public final class MalformedJid extends AbstractJid {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -2896737611021417985L;
|
|
||||||
|
|
||||||
private final String localPart;
|
|
||||||
|
|
||||||
private final String domainPart;
|
|
||||||
|
|
||||||
private final String resourcePart;
|
|
||||||
|
|
||||||
private final Throwable cause;
|
|
||||||
|
|
||||||
static MalformedJid of(final String jid, final Throwable cause) {
|
|
||||||
// Do some basic parsing without any further checks or validation.
|
|
||||||
final StringBuilder sb = new StringBuilder(jid);
|
|
||||||
// 1. Remove any portion from the first '/' character to the end of the
|
|
||||||
// string (if there is a '/' character present).
|
|
||||||
final int indexOfResourceDelimiter = jid.indexOf('/');
|
|
||||||
final String resourcePart;
|
|
||||||
if (indexOfResourceDelimiter > -1) {
|
|
||||||
resourcePart = sb.substring(indexOfResourceDelimiter + 1);
|
|
||||||
sb.delete(indexOfResourceDelimiter, sb.length());
|
|
||||||
} else {
|
|
||||||
resourcePart = null;
|
|
||||||
}
|
|
||||||
// 2. Remove any portion from the beginning of the string to the first
|
|
||||||
// '@' character (if there is an '@' character present).
|
|
||||||
final int indexOfAt = jid.indexOf('@');
|
|
||||||
final String localPart;
|
|
||||||
if (indexOfAt > -1) {
|
|
||||||
localPart = sb.substring(0, indexOfAt);
|
|
||||||
sb.delete(0, indexOfAt + 1);
|
|
||||||
} else {
|
|
||||||
localPart = null;
|
|
||||||
}
|
|
||||||
return new MalformedJid(localPart, sb.toString(), resourcePart, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
private MalformedJid(final String localPart, final String domainPart, final String resourcePart, final Throwable cause) {
|
|
||||||
this.localPart = localPart;
|
|
||||||
this.domainPart = domainPart;
|
|
||||||
this.resourcePart = resourcePart;
|
|
||||||
this.cause = cause;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Jid asBareJid() {
|
|
||||||
return new MalformedJid(localPart, domainPart, null, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Jid withLocal(CharSequence local) {
|
|
||||||
return new MalformedJid(local.toString(), domainPart, resourcePart, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Jid withResource(CharSequence resource) {
|
|
||||||
return new MalformedJid(localPart, domainPart, resource.toString(), cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Jid atSubdomain(CharSequence subdomain) {
|
|
||||||
if (subdomain == null) {
|
|
||||||
throw new NullPointerException();
|
|
||||||
}
|
|
||||||
return new MalformedJid(localPart, subdomain + "." + domainPart, resourcePart, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String getLocal() {
|
|
||||||
return localPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String getEscapedLocal() {
|
|
||||||
return localPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String getDomain() {
|
|
||||||
return domainPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String getResource() {
|
|
||||||
return resourcePart;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the cause why the JID is malformed.
|
|
||||||
*
|
|
||||||
* @return The cause.
|
|
||||||
*/
|
|
||||||
public final Throwable getCause() {
|
|
||||||
return cause;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2016 Christian Schudt
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides classes for the <a href="https://tools.ietf.org/html/rfc7622">XMPP Address Format</a> (JID).
|
|
||||||
*
|
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc7622">Extensible Messaging and Presence Protocol (XMPP): Address Format</a>
|
|
||||||
*/
|
|
||||||
package rocks.xmpp.addr;
|
|
||||||
|
|
|
@ -1,192 +0,0 @@
|
||||||
/*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2016 Christian Schudt
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package rocks.xmpp.util.cache;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UncheckedIOException;
|
|
||||||
import java.nio.file.FileVisitResult;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.SimpleFileVisitor;
|
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple directory based cache for caching of persistent items like avatars or entity capabilities.
|
|
||||||
*
|
|
||||||
* @author Christian Schudt
|
|
||||||
*/
|
|
||||||
public final class DirectoryCache implements Map<String, byte[]> {
|
|
||||||
|
|
||||||
private final Path cacheDirectory;
|
|
||||||
|
|
||||||
public DirectoryCache(Path cacheDirectory) {
|
|
||||||
this.cacheDirectory = cacheDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final int size() {
|
|
||||||
try (final Stream<Path> files = cacheContent()) {
|
|
||||||
return (int) Math.min(files.count(), Integer.MAX_VALUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean isEmpty() {
|
|
||||||
try (final Stream<Path> files = cacheContent()) {
|
|
||||||
return files.findAny().map(file -> Boolean.FALSE).orElse(Boolean.TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean containsKey(Object key) {
|
|
||||||
return Files.exists(cacheDirectory.resolve(key.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean containsValue(Object value) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final byte[] get(final Object key) {
|
|
||||||
return Optional.ofNullable(key).map(Object::toString).filter(((Predicate<String>) String::isEmpty).negate()).map(cacheDirectory::resolve).filter(Files::isReadable).map(file -> {
|
|
||||||
try {
|
|
||||||
return Files.readAllBytes(file);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new UncheckedIOException(e);
|
|
||||||
}
|
|
||||||
}).orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final byte[] put(String key, byte[] value) {
|
|
||||||
// Make sure the directory exists.
|
|
||||||
byte[] data = get(key);
|
|
||||||
if (!Arrays.equals(data, value))
|
|
||||||
try {
|
|
||||||
if (Files.notExists(cacheDirectory)) {
|
|
||||||
Files.createDirectories(cacheDirectory);
|
|
||||||
}
|
|
||||||
Path file = cacheDirectory.resolve(key);
|
|
||||||
Files.write(file, value);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new UncheckedIOException(e);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final byte[] remove(Object key) {
|
|
||||||
byte[] data = get(key);
|
|
||||||
try {
|
|
||||||
Files.deleteIfExists(cacheDirectory.resolve(key.toString()));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new UncheckedIOException(e);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void putAll(Map<? extends String, ? extends byte[]> m) {
|
|
||||||
m.forEach(this::put);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void clear() {
|
|
||||||
try {
|
|
||||||
Files.walkFileTree(cacheDirectory, new SimpleFileVisitor<Path>() {
|
|
||||||
@Override
|
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
|
||||||
Files.deleteIfExists(file);
|
|
||||||
return FileVisitResult.CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
|
|
||||||
// Don't delete the cache directory itself.
|
|
||||||
if (!Files.isSameFile(dir, cacheDirectory)) {
|
|
||||||
Files.deleteIfExists(dir);
|
|
||||||
}
|
|
||||||
return FileVisitResult.CONTINUE;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new UncheckedIOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Set<String> keySet() {
|
|
||||||
try (final Stream<Path> files = Files.list(cacheDirectory)) {
|
|
||||||
return Collections.unmodifiableSet(files.map(Path::getFileName).map(Path::toString).collect(Collectors.toSet()));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new UncheckedIOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Collection<byte[]> values() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Set<Entry<String, byte[]>> entrySet() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void forEach(final BiConsumer<? super String, ? super byte[]> action) {
|
|
||||||
if (Files.exists(cacheDirectory))
|
|
||||||
try (final Stream<Path> files = cacheContent().filter(Files::isReadable)) {
|
|
||||||
files.forEach(file -> {
|
|
||||||
try {
|
|
||||||
action.accept(file.getFileName().toString(), Files.readAllBytes(file));
|
|
||||||
} catch (final IOException e) {
|
|
||||||
throw new UncheckedIOException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("StreamResourceLeak")
|
|
||||||
private final Stream<Path> cacheContent() {
|
|
||||||
try {
|
|
||||||
return Files.walk(cacheDirectory).filter(Files::isRegularFile);
|
|
||||||
} catch (final IOException e) {
|
|
||||||
throw new UncheckedIOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,228 +0,0 @@
|
||||||
/*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2016 Christian Schudt
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package rocks.xmpp.util.cache;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple concurrent implementation of a least-recently-used cache.
|
|
||||||
* <p>
|
|
||||||
* This cache is keeps a maximal number of items in memory and removes the least-recently-used item, when new items are added.
|
|
||||||
*
|
|
||||||
* @param <K> The key.
|
|
||||||
* @param <V> The value.
|
|
||||||
* @author Christian Schudt
|
|
||||||
* @see <a href="http://javadecodedquestions.blogspot.de/2013/02/java-cache-static-data-loading.html">http://javadecodedquestions.blogspot.de/2013/02/java-cache-static-data-loading.html</a>
|
|
||||||
* @see <a href="http://stackoverflow.com/a/22891780">http://stackoverflow.com/a/22891780</a>
|
|
||||||
*/
|
|
||||||
public final class LruCache<K, V> implements Map<K, V> {
|
|
||||||
private final int maxEntries;
|
|
||||||
|
|
||||||
private final Map<K, V> map;
|
|
||||||
|
|
||||||
final Queue<K> queue;
|
|
||||||
|
|
||||||
public LruCache(final int maxEntries) {
|
|
||||||
this.maxEntries = maxEntries;
|
|
||||||
this.map = new ConcurrentHashMap<>(maxEntries);
|
|
||||||
// Don't use a ConcurrentLinkedQueue here.
|
|
||||||
// There's a JDK bug, leading to OutOfMemoryError and high CPU usage:
|
|
||||||
// https://bugs.openjdk.java.net/browse/JDK-8054446
|
|
||||||
this.queue = new ConcurrentLinkedDeque<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final int size() {
|
|
||||||
return map.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean isEmpty() {
|
|
||||||
return map.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean containsKey(final Object key) {
|
|
||||||
return map.containsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean containsValue(final Object value) {
|
|
||||||
return map.containsValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public final V get(final Object key) {
|
|
||||||
final V v = map.get(key);
|
|
||||||
if (v != null) {
|
|
||||||
// Remove the key from the queue and re-add it to the tail. It is now the most recently used key.
|
|
||||||
keyUsed((K) key);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final V put(final K key, final V value) {
|
|
||||||
V v = map.put(key, value);
|
|
||||||
keyUsed(key);
|
|
||||||
limit();
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final V remove(final Object key) {
|
|
||||||
queue.remove(key);
|
|
||||||
return map.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void putAll(final Map<? extends K, ? extends V> m) {
|
|
||||||
for (Map.Entry<? extends K, ? extends V> entry : m.entrySet()) {
|
|
||||||
put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void clear() {
|
|
||||||
queue.clear();
|
|
||||||
map.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Set<K> keySet() {
|
|
||||||
return map.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Collection<V> values() {
|
|
||||||
return map.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Set<Entry<K, V>> entrySet() {
|
|
||||||
return map.entrySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Default methods
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final V putIfAbsent(final K key, final V value) {
|
|
||||||
final V v = map.putIfAbsent(key, value);
|
|
||||||
if (v == null) {
|
|
||||||
keyUsed(key);
|
|
||||||
}
|
|
||||||
limit();
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean remove(final Object key, final Object value) {
|
|
||||||
final boolean removed = map.remove(key, value);
|
|
||||||
if (removed) {
|
|
||||||
queue.remove(key);
|
|
||||||
}
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean replace(final K key, final V oldValue, final V newValue) {
|
|
||||||
final boolean replaced = map.replace(key, oldValue, newValue);
|
|
||||||
if (replaced) {
|
|
||||||
keyUsed(key);
|
|
||||||
}
|
|
||||||
return replaced;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final V replace(final K key, final V value) {
|
|
||||||
final V v = map.replace(key, value);
|
|
||||||
if (v != null) {
|
|
||||||
keyUsed(key);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final V computeIfAbsent(final K key, final Function<? super K, ? extends V> mappingFunction) {
|
|
||||||
return map.computeIfAbsent(key, mappingFunction.<V>andThen(v -> {
|
|
||||||
keyUsed(key);
|
|
||||||
limit();
|
|
||||||
return v;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final V computeIfPresent(final K key, final BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
|
||||||
return map.computeIfPresent(key, remappingFunction.<V>andThen(v -> {
|
|
||||||
keyUsed(key);
|
|
||||||
limit();
|
|
||||||
return v;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final V compute(final K key, final BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
|
||||||
return map.compute(key, remappingFunction.<V>andThen(v -> {
|
|
||||||
keyUsed(key);
|
|
||||||
limit();
|
|
||||||
return v;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
|
|
||||||
return map.merge(key, value, remappingFunction.<V>andThen(v -> {
|
|
||||||
keyUsed(key);
|
|
||||||
limit();
|
|
||||||
return v;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void limit() {
|
|
||||||
while (queue.size() > maxEntries) {
|
|
||||||
final K oldestKey = queue.poll();
|
|
||||||
if (oldestKey != null) {
|
|
||||||
map.remove(oldestKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void keyUsed(final K key) {
|
|
||||||
// remove it from the queue and re-add it, to make it the most recently used key.
|
|
||||||
queue.remove(key);
|
|
||||||
queue.offer(key);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2016 Christian Schudt
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides simple cache implementations.
|
|
||||||
*/
|
|
||||||
package rocks.xmpp.util.cache;
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
• Rework Login with certificate UI
|
||||||
|
• Add ability to pin chats on top (add to favorites)
|
|
@ -1,2 +1 @@
|
||||||
include ':libs:xmpp-addr'
|
|
||||||
rootProject.name = 'Conversations'
|
rootProject.name = 'Conversations'
|
||||||
|
|
|
@ -46,7 +46,7 @@ import eu.siacs.conversations.ui.ManageAccountActivity;
|
||||||
import eu.siacs.conversations.utils.BackupFileHeader;
|
import eu.siacs.conversations.utils.BackupFileHeader;
|
||||||
import eu.siacs.conversations.utils.Compatibility;
|
import eu.siacs.conversations.utils.Compatibility;
|
||||||
import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
|
import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
import static eu.siacs.conversations.services.ExportBackupService.CIPHERMODE;
|
import static eu.siacs.conversations.services.ExportBackupService.CIPHERMODE;
|
||||||
import static eu.siacs.conversations.services.ExportBackupService.KEYTYPE;
|
import static eu.siacs.conversations.services.ExportBackupService.KEYTYPE;
|
||||||
|
@ -208,7 +208,7 @@ public class ImportBackupService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final Jid jid = backupFileHeader.getJid();
|
final Jid jid = backupFileHeader.getJid();
|
||||||
Cursor countCursor = db.rawQuery("select count(messages.uuid) from messages join conversations on conversations.uuid=messages.conversationUuid join accounts on conversations.accountUuid=accounts.uuid where accounts.username=? and accounts.server=?", new String[]{jid.getEscapedLocal(), jid.getDomain()});
|
Cursor countCursor = db.rawQuery("select count(messages.uuid) from messages join conversations on conversations.uuid=messages.conversationUuid join accounts on conversations.accountUuid=accounts.uuid where accounts.username=? and accounts.server=?", new String[]{jid.getEscapedLocal(), jid.getDomain().toEscapedString()});
|
||||||
countCursor.moveToFirst();
|
countCursor.moveToFirst();
|
||||||
int count = countCursor.getInt(0);
|
int count = countCursor.getInt(0);
|
||||||
Log.d(Config.LOGTAG, "restored " + count + " messages");
|
Log.d(Config.LOGTAG, "restored " + count + " messages");
|
||||||
|
|
|
@ -18,7 +18,7 @@ import eu.siacs.conversations.databinding.MagicCreateBinding;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.utils.InstallReferrerUtils;
|
import eu.siacs.conversations.utils.InstallReferrerUtils;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class MagicCreateActivity extends XmppActivity implements TextWatcher {
|
public class MagicCreateActivity extends XmppActivity implements TextWatcher {
|
||||||
|
|
||||||
|
@ -79,13 +79,13 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher {
|
||||||
final boolean fixedUsername;
|
final boolean fixedUsername;
|
||||||
if (this.domain != null && this.username != null) {
|
if (this.domain != null && this.username != null) {
|
||||||
fixedUsername = true;
|
fixedUsername = true;
|
||||||
jid = Jid.ofLocalAndDomain(this.username, this.domain);
|
jid = Jid.ofLocalAndDomainEscaped(this.username, this.domain);
|
||||||
} else if (this.domain != null) {
|
} else if (this.domain != null) {
|
||||||
fixedUsername = false;
|
fixedUsername = false;
|
||||||
jid = Jid.ofLocalAndDomain(username, this.domain);
|
jid = Jid.ofLocalAndDomainEscaped(username, this.domain);
|
||||||
} else {
|
} else {
|
||||||
fixedUsername = false;
|
fixedUsername = false;
|
||||||
jid = Jid.ofLocalAndDomain(username, Config.MAGIC_CREATE_DOMAIN);
|
jid = Jid.ofLocalAndDomainEscaped(username, Config.MAGIC_CREATE_DOMAIN);
|
||||||
}
|
}
|
||||||
if (!jid.getEscapedLocal().equals(jid.getLocal()) || (this.username == null && username.length() < 3)) {
|
if (!jid.getEscapedLocal().equals(jid.getLocal()) || (this.username == null && username.length() < 3)) {
|
||||||
binding.username.setError(getString(R.string.invalid_username));
|
binding.username.setError(getString(R.string.invalid_username));
|
||||||
|
@ -149,9 +149,9 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher {
|
||||||
binding.fullJid.setVisibility(View.VISIBLE);
|
binding.fullJid.setVisibility(View.VISIBLE);
|
||||||
final Jid jid;
|
final Jid jid;
|
||||||
if (this.domain == null) {
|
if (this.domain == null) {
|
||||||
jid = Jid.ofLocalAndDomain(username, Config.MAGIC_CREATE_DOMAIN);
|
jid = Jid.ofLocalAndDomainEscaped(username, Config.MAGIC_CREATE_DOMAIN);
|
||||||
} else {
|
} else {
|
||||||
jid = Jid.ofLocalAndDomain(username, this.domain);
|
jid = Jid.ofLocalAndDomainEscaped(username, this.domain);
|
||||||
}
|
}
|
||||||
binding.fullJid.setText(getString(R.string.your_full_jid_will_be, jid.toEscapedString()));
|
binding.fullJid.setText(getString(R.string.your_full_jid_will_be, jid.toEscapedString()));
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
|
|
@ -14,9 +14,7 @@ import android.view.ContextMenu.ContextMenuInfo;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.AdapterView.AdapterContextMenuInfo;
|
import android.widget.AdapterView.AdapterContextMenuInfo;
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
@ -34,7 +32,7 @@ import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
|
||||||
import eu.siacs.conversations.ui.adapter.AccountAdapter;
|
import eu.siacs.conversations.ui.adapter.AccountAdapter;
|
||||||
import eu.siacs.conversations.ui.util.MenuDoubleTabUtil;
|
import eu.siacs.conversations.ui.util.MenuDoubleTabUtil;
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
|
import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
|
||||||
import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
|
import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
|
||||||
|
@ -133,7 +131,7 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
|
||||||
menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(false);
|
menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(false);
|
||||||
menu.findItem(R.id.mgmt_account_publish_avatar).setVisible(false);
|
menu.findItem(R.id.mgmt_account_publish_avatar).setVisible(false);
|
||||||
}
|
}
|
||||||
menu.setHeaderTitle(this.selectedAccount.getJid().asBareJid().toString());
|
menu.setHeaderTitle(this.selectedAccount.getJid().asBareJid().toEscapedString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -369,7 +367,7 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteAccount(final Account account) {
|
private void deleteAccount(final Account account) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
builder.setTitle(getString(R.string.mgmt_account_are_you_sure));
|
builder.setTitle(getString(R.string.mgmt_account_are_you_sure));
|
||||||
builder.setIconAttribute(android.R.attr.alertDialogIcon);
|
builder.setIconAttribute(android.R.attr.alertDialogIcon);
|
||||||
builder.setMessage(getString(R.string.mgmt_account_delete_confirm_text));
|
builder.setMessage(getString(R.string.mgmt_account_delete_confirm_text));
|
||||||
|
@ -408,15 +406,15 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void alias(String alias) {
|
public void alias(final String alias) {
|
||||||
if (alias != null) {
|
if (alias != null) {
|
||||||
xmppConnectionService.createAccountFromKey(alias, this);
|
xmppConnectionService.createAccountFromKey(alias, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAccountCreated(Account account) {
|
public void onAccountCreated(final Account account) {
|
||||||
Intent intent = new Intent(this, EditAccountActivity.class);
|
final Intent intent = new Intent(this, EditAccountActivity.class);
|
||||||
intent.putExtra("jid", account.getJid().asBareJid().toString());
|
intent.putExtra("jid", account.getJid().asBareJid().toString());
|
||||||
intent.putExtra("init", true);
|
intent.putExtra("init", true);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
package eu.siacs.conversations.ui;
|
package eu.siacs.conversations.ui;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.ActionBar;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -14,7 +10,7 @@ import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
import eu.siacs.conversations.ui.adapter.AccountAdapter;
|
import eu.siacs.conversations.ui.adapter.AccountAdapter;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class ShareViaAccountActivity extends XmppActivity {
|
public class ShareViaAccountActivity extends XmppActivity {
|
||||||
public static final String EXTRA_CONTACT = "contact";
|
public static final String EXTRA_CONTACT = "contact";
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package eu.siacs.conversations.ui;
|
package eu.siacs.conversations.ui;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.databinding.DataBindingUtil;
|
import android.databinding.DataBindingUtil;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.security.KeyChain;
|
||||||
|
import android.security.KeyChainAliasCallback;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
|
@ -21,15 +24,16 @@ import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.databinding.ActivityWelcomeBinding;
|
import eu.siacs.conversations.databinding.ActivityWelcomeBinding;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.utils.InstallReferrerUtils;
|
import eu.siacs.conversations.utils.InstallReferrerUtils;
|
||||||
import eu.siacs.conversations.utils.SignupUtils;
|
import eu.siacs.conversations.utils.SignupUtils;
|
||||||
import eu.siacs.conversations.utils.XmppUri;
|
import eu.siacs.conversations.utils.XmppUri;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
|
import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
|
||||||
import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
|
import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
|
||||||
|
|
||||||
public class WelcomeActivity extends XmppActivity {
|
public class WelcomeActivity extends XmppActivity implements XmppConnectionService.OnAccountCreated, KeyChainAliasCallback {
|
||||||
|
|
||||||
private static final int REQUEST_IMPORT_BACKUP = 0x63fb;
|
private static final int REQUEST_IMPORT_BACKUP = 0x63fb;
|
||||||
|
|
||||||
|
@ -154,10 +158,42 @@ public class WelcomeActivity extends XmppActivity {
|
||||||
case R.id.action_scan_qr_code:
|
case R.id.action_scan_qr_code:
|
||||||
UriHandlerActivity.scan(this);
|
UriHandlerActivity.scan(this);
|
||||||
break;
|
break;
|
||||||
|
case R.id.action_add_account_with_cert:
|
||||||
|
addAccountFromKey();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addAccountFromKey() {
|
||||||
|
try {
|
||||||
|
KeyChain.choosePrivateKeyAlias(this, this, null, null, null, -1, null);
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
Toast.makeText(this, R.string.device_does_not_support_certificates, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void alias(final String alias) {
|
||||||
|
if (alias != null) {
|
||||||
|
xmppConnectionService.createAccountFromKey(alias, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAccountCreated(final Account account) {
|
||||||
|
final Intent intent = new Intent(this, EditAccountActivity.class);
|
||||||
|
intent.putExtra("jid", account.getJid().asBareJid().toString());
|
||||||
|
intent.putExtra("init", true);
|
||||||
|
addInviteUri(intent);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informUser(final int r) {
|
||||||
|
runOnUiThread(() -> Toast.makeText(this, r, Toast.LENGTH_LONG).show());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
UriHandlerActivity.onRequestPermissionResult(this, requestCode, grantResults);
|
UriHandlerActivity.onRequestPermissionResult(this, requestCode, grantResults);
|
||||||
|
|
|
@ -26,7 +26,7 @@ import eu.siacs.conversations.services.AvatarService;
|
||||||
import eu.siacs.conversations.services.ImportBackupService;
|
import eu.siacs.conversations.services.ImportBackupService;
|
||||||
import eu.siacs.conversations.utils.BackupFileHeader;
|
import eu.siacs.conversations.utils.BackupFileHeader;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class BackupFileAdapter extends RecyclerView.Adapter<BackupFileAdapter.BackupFileViewHolder> {
|
public class BackupFileAdapter extends RecyclerView.Adapter<BackupFileAdapter.BackupFileViewHolder> {
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import eu.siacs.conversations.ui.ManageAccountActivity;
|
||||||
import eu.siacs.conversations.ui.PickServerActivity;
|
import eu.siacs.conversations.ui.PickServerActivity;
|
||||||
import eu.siacs.conversations.ui.StartConversationActivity;
|
import eu.siacs.conversations.ui.StartConversationActivity;
|
||||||
import eu.siacs.conversations.ui.WelcomeActivity;
|
import eu.siacs.conversations.ui.WelcomeActivity;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class SignupUtils {
|
public class SignupUtils {
|
||||||
|
|
||||||
|
@ -24,9 +24,9 @@ public class SignupUtils {
|
||||||
public static Intent getTokenRegistrationIntent(final Activity activity, Jid jid, String preAuth) {
|
public static Intent getTokenRegistrationIntent(final Activity activity, Jid jid, String preAuth) {
|
||||||
final Intent intent = new Intent(activity, MagicCreateActivity.class);
|
final Intent intent = new Intent(activity, MagicCreateActivity.class);
|
||||||
if (jid.isDomainJid()) {
|
if (jid.isDomainJid()) {
|
||||||
intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain());
|
intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toEscapedString());
|
||||||
} else {
|
} else {
|
||||||
intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain());
|
intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toEscapedString());
|
||||||
intent.putExtra(MagicCreateActivity.EXTRA_USERNAME, jid.getEscapedLocal());
|
intent.putExtra(MagicCreateActivity.EXTRA_USERNAME, jid.getEscapedLocal());
|
||||||
}
|
}
|
||||||
intent.putExtra(MagicCreateActivity.EXTRA_PRE_AUTH, preAuth);
|
intent.putExtra(MagicCreateActivity.EXTRA_PRE_AUTH, preAuth);
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_scan_qr_code"
|
android:id="@+id/action_scan_qr_code"
|
||||||
android:title="@string/scan_qr_code"
|
android:icon="?attr/icon_scan_qr_code"
|
||||||
app:showAsAction="ifRoom"
|
|
||||||
android:orderInCategory="10"
|
android:orderInCategory="10"
|
||||||
|
android:title="@string/scan_qr_code"
|
||||||
android:visible="@bool/show_qr_code_scan"
|
android:visible="@bool/show_qr_code_scan"
|
||||||
android:icon="?attr/icon_scan_qr_code"/>
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_add_account_with_cert"
|
||||||
|
android:title="@string/action_add_account_with_certificate"
|
||||||
|
android:visible="true"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_import_backup"
|
android:id="@+id/action_import_backup"
|
||||||
app:showAsAction="never"
|
android:title="@string/restore_backup"
|
||||||
android:title="@string/restore_backup"/>
|
app:showAsAction="never" />
|
||||||
</menu>
|
</menu>
|
|
@ -3,9 +3,9 @@
|
||||||
<string name="pick_a_server">Виберіть постачальника послуг обміну повідомленнями XMPP</string>
|
<string name="pick_a_server">Виберіть постачальника послуг обміну повідомленнями XMPP</string>
|
||||||
<string name="use_chat.sum7.eu">Скористатися chat.sum7.eu</string>
|
<string name="use_chat.sum7.eu">Скористатися chat.sum7.eu</string>
|
||||||
<string name="create_new_account">Створити новий обліковий запис</string>
|
<string name="create_new_account">Створити новий обліковий запис</string>
|
||||||
<string name="do_you_have_an_account">Вже маєте обліковий запис XMPP? Можливо, користуєтеся іншою програмою XMPP або користувалися цією програмою раніше. Якщо ні, можете створити новий обліковий запис XMPP просто зараз.\nЗверніть увагу: Деякі постачальники електронної пошти водночас надають облікові записи XMPP.</string>
|
<string name="do_you_have_an_account">Вже маєте обліковий запис XMPP? Можливо, користуєтеся іншою програмою XMPP або користувалися цією програмою раніше. Якщо ні, можете створити новий обліковий запис XMPP просто зараз.\nЗверніть увагу, що деякі постачальники електронної пошти у той же час надають облікові записи XMPP.</string>
|
||||||
<string name="server_select_text">XMPP — це мережа обміну повідомленнями, незалежна від постачальників. Можете використовувати цю програму з будь-яким XMPP сервером, який оберете.\nПроте, для зручності, ми спростили створення облікового запису на chat.sum7.eu — в постачальника, який спеціально налаштований на роботу з цією програмою.</string>
|
<string name="server_select_text">XMPP — це мережа обміну повідомленнями, незалежна від постачальників. Можете використовувати цю програму з будь-яким XMPP сервером, який оберете.\nПроте, для зручності, ми спростили створення облікового запису на chat.sum7.eu — у постачальника, який спеціально налаштований на роботу з цією програмою.</string>
|
||||||
<string name="magic_create_text_on_x">Вас запросили до %1$s. Ми проведемо Вас крок за кроком, щоб створити обліковий запис.\nОбираючи %1$s в якості свого постачальника, Ви зможете спілкуватися з користувачами інших постачальників, повідомивши їм свою повну адресу XMPP.</string>
|
<string name="magic_create_text_on_x">Вас запросили до %1$s. Ми проведемо вас крок за кроком, щоб створити обліковий запис.\nОбираючи %1$s в якості свого постачальника, ви зможете спілкуватися з користувачами інших постачальників, для цього повідомте їм свою повну адресу XMPP.</string>
|
||||||
<string name="magic_create_text_fixed">Вас запросили до %1$s. Для Вас уже обрали ім\'я користувача. Ми проведемо Вас крок за кроком, щоб створити обліковий запис.\nВи зможете спілкуватися з користувачами інших постачальників, повідомивши їм свою повну адресу XMPP.</string>
|
<string name="magic_create_text_fixed">Вас запросили до %1$s. Для вас створено ім\'я користувача. Ми проведемо вас крок за кроком, щоб створити обліковий запис.\nВи зможете спілкуватися з користувачами інших постачальників, для цього повідомите їм свою повну адресу XMPP.</string>
|
||||||
<string name="your_server_invitation">Ваше запрошення до сервера</string>
|
<string name="your_server_invitation">Ваше запрошення до сервера</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public final class Config {
|
public final class Config {
|
||||||
private static final int UNENCRYPTED = 1;
|
private static final int UNENCRYPTED = 1;
|
||||||
|
|
|
@ -13,7 +13,7 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class JabberIdContact extends AbstractPhoneContact {
|
public class JabberIdContact extends AbstractPhoneContact {
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||||
import eu.siacs.conversations.xmpp.pep.PublishOptions;
|
import eu.siacs.conversations.xmpp.pep.PublishOptions;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package eu.siacs.conversations.crypto.axolotl;
|
||||||
|
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
|
||||||
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
|
@ -24,7 +23,7 @@ import javax.crypto.spec.SecretKeySpec;
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.utils.Compatibility;
|
import eu.siacs.conversations.utils.Compatibility;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class XmppAxolotlMessage {
|
public class XmppAxolotlMessage {
|
||||||
public static final String CONTAINERTAG = "encrypted";
|
public static final String CONTAINERTAG = "encrypted";
|
||||||
|
|
|
@ -24,6 +24,6 @@ public class External extends SaslMechanism {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getClientFirstMessage() {
|
public String getClientFirstMessage() {
|
||||||
return Base64.encodeToString(account.getJid().asBareJid().toString().getBytes(),Base64.NO_WRAP);
|
return Base64.encodeToString(account.getJid().asBareJid().toEscapedString().getBytes(),Base64.NO_WRAP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,7 +173,7 @@ abstract class ScramMechanism extends SaslMechanism {
|
||||||
|
|
||||||
// Map keys are "bytesToHex(JID),bytesToHex(password),bytesToHex(salt),iterations,SASL-Mechanism".
|
// Map keys are "bytesToHex(JID),bytesToHex(password),bytesToHex(salt),iterations,SASL-Mechanism".
|
||||||
final KeyPair keys = CACHE.get(
|
final KeyPair keys = CACHE.get(
|
||||||
CryptoHelper.bytesToHex(account.getJid().asBareJid().toString().getBytes()) + ","
|
CryptoHelper.bytesToHex(account.getJid().asBareJid().toEscapedString().getBytes()) + ","
|
||||||
+ CryptoHelper.bytesToHex(account.getPassword().getBytes()) + ","
|
+ CryptoHelper.bytesToHex(account.getPassword().getBytes()) + ","
|
||||||
+ CryptoHelper.bytesToHex(salt.getBytes()) + ","
|
+ CryptoHelper.bytesToHex(salt.getBytes()) + ","
|
||||||
+ String.valueOf(iterationCount) + ","
|
+ String.valueOf(iterationCount) + ","
|
||||||
|
|
|
@ -16,7 +16,6 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
|
@ -30,7 +29,7 @@ import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.utils.XmppUri;
|
import eu.siacs.conversations.utils.XmppUri;
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
|
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class Account extends AbstractEntity implements AvatarService.Avatarable {
|
public class Account extends AbstractEntity implements AvatarService.Avatarable {
|
||||||
|
|
||||||
|
@ -233,10 +232,14 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
|
||||||
return next != null && !next.equals(previousFull);
|
return next != null && !next.equals(previousFull);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getServer() {
|
public Jid getDomain() {
|
||||||
return jid.getDomain();
|
return jid.getDomain();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getServer() {
|
||||||
|
return jid.getDomain().toEscapedString();
|
||||||
|
}
|
||||||
|
|
||||||
public String getPassword() {
|
public String getPassword() {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
@ -370,7 +373,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
|
||||||
final ContentValues values = new ContentValues();
|
final ContentValues values = new ContentValues();
|
||||||
values.put(UUID, uuid);
|
values.put(UUID, uuid);
|
||||||
values.put(USERNAME, jid.getLocal());
|
values.put(USERNAME, jid.getLocal());
|
||||||
values.put(SERVER, jid.getDomain());
|
values.put(SERVER, jid.getDomain().toEscapedString());
|
||||||
values.put(PASSWORD, password);
|
values.put(PASSWORD, password);
|
||||||
values.put(OPTIONS, options);
|
values.put(OPTIONS, options);
|
||||||
synchronized (this.keys) {
|
synchronized (this.keys) {
|
||||||
|
@ -588,7 +591,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
|
||||||
|
|
||||||
public boolean isBlocked(final ListItem contact) {
|
public boolean isBlocked(final ListItem contact) {
|
||||||
final Jid jid = contact.getJid();
|
final Jid jid = contact.getJid();
|
||||||
return jid != null && (blocklist.contains(jid.asBareJid()) || blocklist.contains(Jid.ofDomain(jid.getDomain())));
|
return jid != null && (blocklist.contains(jid.asBareJid()) || blocklist.contains(jid.getDomain()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBlocked(final Jid jid) {
|
public boolean isBlocked(final Jid jid) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.siacs.conversations.entities;
|
package eu.siacs.conversations.entities;
|
||||||
|
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public interface Blockable {
|
public interface Blockable {
|
||||||
boolean isBlocked();
|
boolean isBlocked();
|
||||||
|
|
|
@ -17,7 +17,7 @@ import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xml.Namespace;
|
import eu.siacs.conversations.xml.Namespace;
|
||||||
import eu.siacs.conversations.xmpp.InvalidJid;
|
import eu.siacs.conversations.xmpp.InvalidJid;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class Bookmark extends Element implements ListItem {
|
public class Bookmark extends Element implements ListItem {
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ public class Bookmark extends Element implements ListItem {
|
||||||
public Bookmark(final Account account, final Jid jid) {
|
public Bookmark(final Account account, final Jid jid) {
|
||||||
super("conference");
|
super("conference");
|
||||||
this.jid = jid;
|
this.jid = jid;
|
||||||
this.setAttribute("jid", jid.toString());
|
this.setAttribute("jid", jid);
|
||||||
this.account = account;
|
this.account = account;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import eu.siacs.conversations.utils.JidHelper;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xmpp.pep.Avatar;
|
import eu.siacs.conversations.xmpp.pep.Avatar;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class Contact implements ListItem, Blockable {
|
public class Contact implements ListItem, Blockable {
|
||||||
public static final String TABLENAME = "contacts";
|
public static final String TABLENAME = "contacts";
|
||||||
|
@ -134,12 +134,12 @@ public class Contact implements ListItem, Blockable {
|
||||||
return this.systemName;
|
return this.systemName;
|
||||||
} else if (!TextUtils.isEmpty(this.serverName)) {
|
} else if (!TextUtils.isEmpty(this.serverName)) {
|
||||||
return this.serverName;
|
return this.serverName;
|
||||||
} else if (!TextUtils.isEmpty(this.presenceName) && ((QuickConversationsService.isQuicksy() && Config.QUICKSY_DOMAIN.equals(jid.getDomain())) ||mutualPresenceSubscription())) {
|
} else if (!TextUtils.isEmpty(this.presenceName) && ((QuickConversationsService.isQuicksy() && Config.QUICKSY_DOMAIN.equals(jid.getDomain().toEscapedString())) ||mutualPresenceSubscription())) {
|
||||||
return this.presenceName;
|
return this.presenceName;
|
||||||
} else if (jid.getLocal() != null) {
|
} else if (jid.getLocal() != null) {
|
||||||
return JidHelper.localPartOrFallback(jid);
|
return JidHelper.localPartOrFallback(jid);
|
||||||
} else {
|
} else {
|
||||||
return jid.getDomain();
|
return jid.getDomain().toEscapedString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,7 +396,7 @@ public class Contact implements ListItem, Blockable {
|
||||||
|
|
||||||
public Element asElement() {
|
public Element asElement() {
|
||||||
final Element item = new Element("item");
|
final Element item = new Element("item");
|
||||||
item.setAttribute("jid", this.jid.toString());
|
item.setAttribute("jid", this.jid);
|
||||||
if (this.serverName != null) {
|
if (this.serverName != null) {
|
||||||
item.setAttribute("name", this.serverName);
|
item.setAttribute("name", this.serverName);
|
||||||
}
|
}
|
||||||
|
@ -413,7 +413,7 @@ public class Contact implements ListItem, Blockable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getServer() {
|
public String getServer() {
|
||||||
return getJid().getDomain();
|
return getJid().getDomain().toEscapedString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setAvatar(Avatar avatar) {
|
public boolean setAvatar(Avatar avatar) {
|
||||||
|
@ -451,13 +451,13 @@ public class Contact implements ListItem, Blockable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDomainBlocked() {
|
public boolean isDomainBlocked() {
|
||||||
return getAccount().isBlocked(Jid.ofDomain(this.getJid().getDomain()));
|
return getAccount().isBlocked(this.getJid().getDomain());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Jid getBlockedJid() {
|
public Jid getBlockedJid() {
|
||||||
if (isDomainBlocked()) {
|
if (isDomainBlocked()) {
|
||||||
return Jid.ofDomain(getJid().getDomain());
|
return getJid().getDomain();
|
||||||
} else {
|
} else {
|
||||||
return getJid();
|
return getJid();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.google.common.collect.ComparisonChain;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
@ -27,7 +29,7 @@ import eu.siacs.conversations.utils.JidHelper;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
||||||
import eu.siacs.conversations.xmpp.mam.MamReference;
|
import eu.siacs.conversations.xmpp.mam.MamReference;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
import static eu.siacs.conversations.entities.Bookmark.printableValue;
|
import static eu.siacs.conversations.entities.Bookmark.printableValue;
|
||||||
|
|
||||||
|
@ -49,9 +51,9 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
||||||
|
|
||||||
public static final String ATTRIBUTE_MUTED_TILL = "muted_till";
|
public static final String ATTRIBUTE_MUTED_TILL = "muted_till";
|
||||||
public static final String ATTRIBUTE_ALWAYS_NOTIFY = "always_notify";
|
public static final String ATTRIBUTE_ALWAYS_NOTIFY = "always_notify";
|
||||||
public static final String ATTRIBUTE_PUSH_NODE = "push_node";
|
|
||||||
public static final String ATTRIBUTE_LAST_CLEAR_HISTORY = "last_clear_history";
|
public static final String ATTRIBUTE_LAST_CLEAR_HISTORY = "last_clear_history";
|
||||||
public static final String ATTRIBUTE_FORMERLY_PRIVATE_NON_ANONYMOUS = "formerly_private_non_anonymous";
|
public static final String ATTRIBUTE_FORMERLY_PRIVATE_NON_ANONYMOUS = "formerly_private_non_anonymous";
|
||||||
|
public static final String ATTRIBUTE_PINNED_ON_TOP = "pinned_on_top";
|
||||||
static final String ATTRIBUTE_MUC_PASSWORD = "muc_password";
|
static final String ATTRIBUTE_MUC_PASSWORD = "muc_password";
|
||||||
static final String ATTRIBUTE_MEMBERS_ONLY = "members_only";
|
static final String ATTRIBUTE_MEMBERS_ONLY = "members_only";
|
||||||
static final String ATTRIBUTE_MODERATED = "moderated";
|
static final String ATTRIBUTE_MODERATED = "moderated";
|
||||||
|
@ -137,7 +139,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
||||||
if (conversation.getContact().isOwnServer()) {
|
if (conversation.getContact().isOwnServer()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final String contact = conversation.getJid().getDomain();
|
final String contact = conversation.getJid().getDomain().toEscapedString();
|
||||||
final String account = conversation.getAccount().getServer();
|
final String account = conversation.getAccount().getServer();
|
||||||
if (Config.OMEMO_EXCEPTIONS.CONTACT_DOMAINS.contains(contact) || Config.OMEMO_EXCEPTIONS.ACCOUNT_DOMAINS.contains(account)) {
|
if (Config.OMEMO_EXCEPTIONS.CONTACT_DOMAINS.contains(contact) || Config.OMEMO_EXCEPTIONS.ACCOUNT_DOMAINS.contains(account)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -479,7 +481,10 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(@NonNull Conversation another) {
|
public int compareTo(@NonNull Conversation another) {
|
||||||
return Long.compare(another.getSortableTime(), getSortableTime());
|
return ComparisonChain.start()
|
||||||
|
.compareFalseFirst(another.getBooleanAttribute(ATTRIBUTE_PINNED_ON_TOP, false), getBooleanAttribute(ATTRIBUTE_PINNED_ON_TOP,false))
|
||||||
|
.compare(another.getSortableTime(), getSortableTime())
|
||||||
|
.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getSortableTime() {
|
private long getSortableTime() {
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
package eu.siacs.conversations.entities;
|
package eu.siacs.conversations.entities;
|
||||||
|
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public interface Conversational {
|
public interface Conversational {
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ import android.database.Cursor;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import eu.siacs.conversations.ui.adapter.MessageAdapter;
|
import eu.siacs.conversations.ui.adapter.MessageAdapter;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class IndividualMessage extends Message {
|
public class IndividualMessage extends Message {
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import android.content.Context;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.services.AvatarService;
|
import eu.siacs.conversations.services.AvatarService;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
|
|
||||||
public interface ListItem extends Comparable<ListItem>, AvatarService.Avatarable {
|
public interface ListItem extends Comparable<ListItem>, AvatarService.Avatarable {
|
||||||
|
|
|
@ -27,7 +27,7 @@ import eu.siacs.conversations.utils.GeoHelper;
|
||||||
import eu.siacs.conversations.utils.MessageUtils;
|
import eu.siacs.conversations.utils.MessageUtils;
|
||||||
import eu.siacs.conversations.utils.MimeUtils;
|
import eu.siacs.conversations.utils.MimeUtils;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class Message extends AbstractEntity implements AvatarService.Avatarable {
|
public class Message extends AbstractEntity implements AvatarService.Avatarable {
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,11 @@ import eu.siacs.conversations.services.AvatarService;
|
||||||
import eu.siacs.conversations.services.MessageArchiveService;
|
import eu.siacs.conversations.services.MessageArchiveService;
|
||||||
import eu.siacs.conversations.utils.JidHelper;
|
import eu.siacs.conversations.utils.JidHelper;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xml.Namespace;
|
|
||||||
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
||||||
import eu.siacs.conversations.xmpp.forms.Data;
|
import eu.siacs.conversations.xmpp.forms.Data;
|
||||||
import eu.siacs.conversations.xmpp.forms.Field;
|
import eu.siacs.conversations.xmpp.forms.Field;
|
||||||
import eu.siacs.conversations.xmpp.pep.Avatar;
|
import eu.siacs.conversations.xmpp.pep.Avatar;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class MucOptions {
|
public class MucOptions {
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class RawBlockable implements ListItem, Blockable {
|
public class RawBlockable implements ListItem, Blockable {
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,9 @@ import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class ReadByMarker {
|
public class ReadByMarker {
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
package eu.siacs.conversations.entities;
|
package eu.siacs.conversations.entities;
|
||||||
|
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class ReceiptRequest {
|
public class ReceiptRequest {
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,10 @@ import com.google.common.base.Objects;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.ComparisonChain;
|
import com.google.common.collect.ComparisonChain;
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
import eu.siacs.conversations.services.AvatarService;
|
import eu.siacs.conversations.services.AvatarService;
|
||||||
import eu.siacs.conversations.utils.LanguageUtils;
|
import eu.siacs.conversations.utils.LanguageUtils;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class Room implements AvatarService.Avatarable, Comparable<Room> {
|
public class Room implements AvatarService.Avatarable, Comparable<Room> {
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.android.AbstractPhoneContact;
|
import eu.siacs.conversations.android.AbstractPhoneContact;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
|
|
||||||
public class Roster {
|
public class Roster {
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
package eu.siacs.conversations.entities;
|
package eu.siacs.conversations.entities;
|
||||||
|
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
|
|
||||||
public class StubConversation implements Conversational {
|
public class StubConversation implements Conversational {
|
||||||
|
|
|
@ -34,7 +34,7 @@ import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xmpp.forms.Data;
|
import eu.siacs.conversations.xmpp.forms.Data;
|
||||||
import eu.siacs.conversations.xmpp.pep.Avatar;
|
import eu.siacs.conversations.xmpp.pep.Avatar;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class IqGenerator extends AbstractGenerator {
|
public class IqGenerator extends AbstractGenerator {
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ public class IqGenerator extends AbstractGenerator {
|
||||||
if (mam.muc()) {
|
if (mam.muc()) {
|
||||||
packet.setTo(mam.getWith());
|
packet.setTo(mam.getWith());
|
||||||
} else if (mam.getWith() != null) {
|
} else if (mam.getWith() != null) {
|
||||||
data.put("with", mam.getWith().toString());
|
data.put("with", mam.getWith().toEscapedString());
|
||||||
}
|
}
|
||||||
final long start = mam.getStart();
|
final long start = mam.getStart();
|
||||||
final long end = mam.getEnd();
|
final long end = mam.getEnd();
|
||||||
|
@ -334,7 +334,7 @@ public class IqGenerator extends AbstractGenerator {
|
||||||
public IqPacket generateSetBlockRequest(final Jid jid, boolean reportSpam) {
|
public IqPacket generateSetBlockRequest(final Jid jid, boolean reportSpam) {
|
||||||
final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
|
final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
|
||||||
final Element block = iq.addChild("block", Namespace.BLOCKING);
|
final Element block = iq.addChild("block", Namespace.BLOCKING);
|
||||||
final Element item = block.addChild("item").setAttribute("jid", jid.toEscapedString());
|
final Element item = block.addChild("item").setAttribute("jid", jid);
|
||||||
if (reportSpam) {
|
if (reportSpam) {
|
||||||
item.addChild("report", "urn:xmpp:reporting:0").addChild("spam");
|
item.addChild("report", "urn:xmpp:reporting:0").addChild("spam");
|
||||||
}
|
}
|
||||||
|
@ -345,13 +345,13 @@ public class IqGenerator extends AbstractGenerator {
|
||||||
public IqPacket generateSetUnblockRequest(final Jid jid) {
|
public IqPacket generateSetUnblockRequest(final Jid jid) {
|
||||||
final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
|
final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
|
||||||
final Element block = iq.addChild("unblock", Namespace.BLOCKING);
|
final Element block = iq.addChild("unblock", Namespace.BLOCKING);
|
||||||
block.addChild("item").setAttribute("jid", jid.toEscapedString());
|
block.addChild("item").setAttribute("jid", jid);
|
||||||
return iq;
|
return iq;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IqPacket generateSetPassword(final Account account, final String newPassword) {
|
public IqPacket generateSetPassword(final Account account, final String newPassword) {
|
||||||
final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
|
final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
|
||||||
packet.setTo(Jid.of(account.getServer()));
|
packet.setTo(account.getDomain());
|
||||||
final Element query = packet.addChild("query", Namespace.REGISTER);
|
final Element query = packet.addChild("query", Namespace.REGISTER);
|
||||||
final Jid jid = account.getJid();
|
final Jid jid = account.getJid();
|
||||||
query.addChild("username").setContent(jid.getLocal());
|
query.addChild("username").setContent(jid.getLocal());
|
||||||
|
@ -372,7 +372,7 @@ public class IqGenerator extends AbstractGenerator {
|
||||||
Element query = packet.query("http://jabber.org/protocol/muc#admin");
|
Element query = packet.query("http://jabber.org/protocol/muc#admin");
|
||||||
for (Jid jid : jids) {
|
for (Jid jid : jids) {
|
||||||
Element item = query.addChild("item");
|
Element item = query.addChild("item");
|
||||||
item.setAttribute("jid", jid.toEscapedString());
|
item.setAttribute("jid", jid);
|
||||||
item.setAttribute("affiliation", affiliation);
|
item.setAttribute("affiliation", affiliation);
|
||||||
}
|
}
|
||||||
return packet;
|
return packet;
|
||||||
|
@ -442,7 +442,7 @@ public class IqGenerator extends AbstractGenerator {
|
||||||
public IqPacket generateCreateAccountWithCaptcha(Account account, String id, Data data) {
|
public IqPacket generateCreateAccountWithCaptcha(Account account, String id, Data data) {
|
||||||
final IqPacket register = new IqPacket(IqPacket.TYPE.SET);
|
final IqPacket register = new IqPacket(IqPacket.TYPE.SET);
|
||||||
register.setFrom(account.getJid().asBareJid());
|
register.setFrom(account.getJid().asBareJid());
|
||||||
register.setTo(Jid.of(account.getServer()));
|
register.setTo(account.getDomain());
|
||||||
register.setId(id);
|
register.setId(id);
|
||||||
Element query = register.query(Namespace.REGISTER);
|
Element query = register.query(Namespace.REGISTER);
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
|
@ -489,7 +489,7 @@ public class IqGenerator extends AbstractGenerator {
|
||||||
public IqPacket enablePush(final Jid jid, final String node, final String secret) {
|
public IqPacket enablePush(final Jid jid, final String node, final String secret) {
|
||||||
IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
|
IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
|
||||||
Element enable = packet.addChild("enable", Namespace.PUSH);
|
Element enable = packet.addChild("enable", Namespace.PUSH);
|
||||||
enable.setAttribute("jid", jid.toString());
|
enable.setAttribute("jid", jid);
|
||||||
enable.setAttribute("node", node);
|
enable.setAttribute("node", node);
|
||||||
if (secret != null) {
|
if (secret != null) {
|
||||||
Data data = new Data();
|
Data data = new Data();
|
||||||
|
@ -504,7 +504,7 @@ public class IqGenerator extends AbstractGenerator {
|
||||||
public IqPacket disablePush(final Jid jid, final String node) {
|
public IqPacket disablePush(final Jid jid, final String node) {
|
||||||
IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
|
IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
|
||||||
Element disable = packet.addChild("disable", Namespace.PUSH);
|
Element disable = packet.addChild("disable", Namespace.PUSH);
|
||||||
disable.setAttribute("jid", jid.toEscapedString());
|
disable.setAttribute("jid", jid);
|
||||||
disable.setAttribute("node", node);
|
disable.setAttribute("node", node);
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
|
||||||
import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
|
import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
|
||||||
import eu.siacs.conversations.xmpp.jingle.Media;
|
import eu.siacs.conversations.xmpp.jingle.Media;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class MessageGenerator extends AbstractGenerator {
|
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";
|
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";
|
||||||
|
@ -198,7 +198,7 @@ public class MessageGenerator extends AbstractGenerator {
|
||||||
packet.setTo(contact);
|
packet.setTo(contact);
|
||||||
packet.setFrom(conversation.getAccount().getJid());
|
packet.setFrom(conversation.getAccount().getJid());
|
||||||
Element x = packet.addChild("x", "jabber:x:conference");
|
Element x = packet.addChild("x", "jabber:x:conference");
|
||||||
x.setAttribute("jid", conversation.getJid().asBareJid().toString());
|
x.setAttribute("jid", conversation.getJid().asBareJid());
|
||||||
String password = conversation.getMucOptions().getPassword();
|
String password = conversation.getMucOptions().getPassword();
|
||||||
if (password != null) {
|
if (password != null) {
|
||||||
x.setAttribute("password", password);
|
x.setAttribute("password", password);
|
||||||
|
|
|
@ -32,7 +32,7 @@ import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.utils.FileWriterException;
|
import eu.siacs.conversations.utils.FileWriterException;
|
||||||
import eu.siacs.conversations.utils.WakeLockHelper;
|
import eu.siacs.conversations.utils.WakeLockHelper;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class HttpDownloadConnection implements Transferable {
|
public class HttpDownloadConnection implements Transferable {
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ public class HttpDownloadConnection implements Transferable {
|
||||||
private void retrieveUrl() {
|
private void retrieveUrl() {
|
||||||
changeStatus(STATUS_CHECKING);
|
changeStatus(STATUS_CHECKING);
|
||||||
final Account account = message.getConversation().getAccount();
|
final Account account = message.getConversation().getAccount();
|
||||||
IqPacket request = mXmppConnectionService.getIqGenerator().requestP1S3Url(Jid.of(account.getJid().getDomain()), mUrl.getHost());
|
IqPacket request = mXmppConnectionService.getIqGenerator().requestP1S3Url(account.getDomain(), mUrl.getHost());
|
||||||
mXmppConnectionService.sendIqPacket(message.getConversation().getAccount(), request, (a, packet) -> {
|
mXmppConnectionService.sendIqPacket(message.getConversation().getAccount(), request, (a, packet) -> {
|
||||||
if (packet.getType() == IqPacket.TYPE.RESULT) {
|
if (packet.getType() == IqPacket.TYPE.RESULT) {
|
||||||
String download = packet.query().getAttribute("download");
|
String download = packet.query().getAttribute("download");
|
||||||
|
|
|
@ -31,7 +31,6 @@ package eu.siacs.conversations.http;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -44,7 +43,7 @@ import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xml.Namespace;
|
import eu.siacs.conversations.xml.Namespace;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class SlotRequester {
|
public class SlotRequester {
|
||||||
|
|
||||||
|
@ -62,7 +61,7 @@ public class SlotRequester {
|
||||||
Jid host = account.getXmppConnection().findDiscoItemByFeature(Namespace.HTTP_UPLOAD_LEGACY);
|
Jid host = account.getXmppConnection().findDiscoItemByFeature(Namespace.HTTP_UPLOAD_LEGACY);
|
||||||
requestHttpUploadLegacy(account, host, file, mime, callback);
|
requestHttpUploadLegacy(account, host, file, mime, callback);
|
||||||
} else {
|
} else {
|
||||||
requestP1S3(account, Jid.of(account.getServer()), file.getName(), md5, callback);
|
requestP1S3(account, account.getDomain(), file.getName(), md5, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xmpp.InvalidJid;
|
import eu.siacs.conversations.xmpp.InvalidJid;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
|
import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public abstract class AbstractParser {
|
public abstract class AbstractParser {
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ public abstract class AbstractParser {
|
||||||
|
|
||||||
public static MucOptions.User parseItem(Conversation conference, Element item, Jid fullJid) {
|
public static MucOptions.User parseItem(Conversation conference, Element item, Jid fullJid) {
|
||||||
final String local = conference.getJid().getLocal();
|
final String local = conference.getJid().getLocal();
|
||||||
final String domain = conference.getJid().getDomain();
|
final String domain = conference.getJid().getDomain().toEscapedString();
|
||||||
String affiliation = item.getAttribute("affiliation");
|
String affiliation = item.getAttribute("affiliation");
|
||||||
String role = item.getAttribute("role");
|
String role = item.getAttribute("role");
|
||||||
String nick = item.getAttribute("nick");
|
String nick = item.getAttribute("nick");
|
||||||
|
|
|
@ -39,7 +39,7 @@ import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||||
import eu.siacs.conversations.xmpp.forms.Data;
|
import eu.siacs.conversations.xmpp.forms.Data;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class IqParser extends AbstractParser implements OnIqPacketReceived {
|
public class IqParser extends AbstractParser implements OnIqPacketReceived {
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
|
||||||
import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
|
import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
|
||||||
import eu.siacs.conversations.xmpp.pep.Avatar;
|
import eu.siacs.conversations.xmpp.pep.Avatar;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class MessageParser extends AbstractParser implements OnMessagePacketReceived {
|
public class MessageParser extends AbstractParser implements OnMessagePacketReceived {
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import eu.siacs.conversations.xmpp.InvalidJid;
|
||||||
import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
|
import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
|
||||||
import eu.siacs.conversations.xmpp.pep.Avatar;
|
import eu.siacs.conversations.xmpp.pep.Avatar;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class PresenceParser extends AbstractParser implements
|
public class PresenceParser extends AbstractParser implements
|
||||||
OnPresencePacketReceived {
|
OnPresencePacketReceived {
|
||||||
|
|
|
@ -58,7 +58,7 @@ import eu.siacs.conversations.utils.MimeUtils;
|
||||||
import eu.siacs.conversations.utils.Resolver;
|
import eu.siacs.conversations.utils.Resolver;
|
||||||
import eu.siacs.conversations.xmpp.InvalidJid;
|
import eu.siacs.conversations.xmpp.InvalidJid;
|
||||||
import eu.siacs.conversations.xmpp.mam.MamReference;
|
import eu.siacs.conversations.xmpp.mam.MamReference;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class DatabaseBackend extends SQLiteOpenHelper {
|
public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
|
|
||||||
|
@ -621,7 +621,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
cursor.getString(cursor.getColumnIndex(Account.USERNAME)),
|
cursor.getString(cursor.getColumnIndex(Account.USERNAME)),
|
||||||
cursor.getString(cursor.getColumnIndex(Account.SERVER)),
|
cursor.getString(cursor.getColumnIndex(Account.SERVER)),
|
||||||
null
|
null
|
||||||
).getDomain();
|
).getDomain().toEscapedString();
|
||||||
} catch (IllegalArgumentException ignored) {
|
} catch (IllegalArgumentException ignored) {
|
||||||
Log.e(Config.LOGTAG, "Failed to migrate Account SERVER "
|
Log.e(Config.LOGTAG, "Failed to migrate Account SERVER "
|
||||||
+ cursor.getString(cursor.getColumnIndex(Account.SERVER))
|
+ cursor.getString(cursor.getColumnIndex(Account.SERVER))
|
||||||
|
@ -858,7 +858,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
public List<FilePath> getRelativeFilePaths(String account, Jid jid, int limit) {
|
public List<FilePath> getRelativeFilePaths(String account, Jid jid, int limit) {
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
SQLiteDatabase db = this.getReadableDatabase();
|
||||||
final String SQL = "select uuid,relativeFilePath from messages where type in (1,2,5) and deleted=0 and "+Message.RELATIVE_FILE_PATH+" is not null and conversationUuid=(select uuid from conversations where accountUuid=? and (contactJid=? or contactJid like ?)) order by timeSent desc";
|
final String SQL = "select uuid,relativeFilePath from messages where type in (1,2,5) and deleted=0 and "+Message.RELATIVE_FILE_PATH+" is not null and conversationUuid=(select uuid from conversations where accountUuid=? and (contactJid=? or contactJid like ?)) order by timeSent desc";
|
||||||
final String[] args = {account, jid.toEscapedString(), jid.toEscapedString() + "/%"};
|
final String[] args = {account, jid.toString(), jid.toString() + "/%"};
|
||||||
Cursor cursor = db.rawQuery(SQL + (limit > 0 ? " limit " + String.valueOf(limit) : ""), args);
|
Cursor cursor = db.rawQuery(SQL + (limit > 0 ? " limit " + String.valueOf(limit) : ""), args);
|
||||||
List<FilePath> filesPaths = new ArrayList<>();
|
List<FilePath> filesPaths = new ArrayList<>();
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
|
|
|
@ -39,11 +39,10 @@ import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.entities.MucOptions;
|
import eu.siacs.conversations.entities.MucOptions;
|
||||||
import eu.siacs.conversations.entities.RawBlockable;
|
import eu.siacs.conversations.entities.RawBlockable;
|
||||||
import eu.siacs.conversations.entities.Room;
|
import eu.siacs.conversations.entities.Room;
|
||||||
import eu.siacs.conversations.http.services.MuclumbusService;
|
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
|
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
|
public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ import android.os.CancellationSignal;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.zxing.BarcodeFormat;
|
import com.google.zxing.BarcodeFormat;
|
||||||
|
@ -32,7 +31,7 @@ import java.util.Hashtable;
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class BarcodeProvider extends ContentProvider implements ServiceConnection {
|
public class BarcodeProvider extends ContentProvider implements ServiceConnection {
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
@ -23,8 +22,6 @@ import eu.siacs.conversations.entities.Room;
|
||||||
import eu.siacs.conversations.http.HttpConnectionManager;
|
import eu.siacs.conversations.http.HttpConnectionManager;
|
||||||
import eu.siacs.conversations.http.services.MuclumbusService;
|
import eu.siacs.conversations.http.services.MuclumbusService;
|
||||||
import eu.siacs.conversations.parser.IqParser;
|
import eu.siacs.conversations.parser.IqParser;
|
||||||
import eu.siacs.conversations.utils.LanguageUtils;
|
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
|
||||||
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
|
@ -35,7 +32,7 @@ import retrofit2.Callback;
|
||||||
import retrofit2.Response;
|
import retrofit2.Response;
|
||||||
import retrofit2.Retrofit;
|
import retrofit2.Retrofit;
|
||||||
import retrofit2.converter.gson.GsonConverterFactory;
|
import retrofit2.converter.gson.GsonConverterFactory;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class ChannelDiscoveryService {
|
public class ChannelDiscoveryService {
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,12 @@ import eu.siacs.conversations.entities.Conversation;
|
||||||
import eu.siacs.conversations.entities.Conversational;
|
import eu.siacs.conversations.entities.Conversational;
|
||||||
import eu.siacs.conversations.entities.ReceiptRequest;
|
import eu.siacs.conversations.entities.ReceiptRequest;
|
||||||
import eu.siacs.conversations.generator.AbstractGenerator;
|
import eu.siacs.conversations.generator.AbstractGenerator;
|
||||||
import eu.siacs.conversations.xml.Namespace;
|
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
|
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
|
||||||
import eu.siacs.conversations.xmpp.mam.MamReference;
|
import eu.siacs.conversations.xmpp.mam.MamReference;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,6 @@ import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -49,7 +48,7 @@ import eu.siacs.conversations.ui.interfaces.OnSearchResultsAvailable;
|
||||||
import eu.siacs.conversations.utils.Cancellable;
|
import eu.siacs.conversations.utils.Cancellable;
|
||||||
import eu.siacs.conversations.utils.MessageUtils;
|
import eu.siacs.conversations.utils.MessageUtils;
|
||||||
import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor;
|
import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class MessageSearchTask implements Runnable, Cancellable {
|
public class MessageSearchTask implements Runnable, Cancellable {
|
||||||
|
|
||||||
|
|
|
@ -1109,7 +1109,7 @@ public class NotificationService {
|
||||||
return;
|
return;
|
||||||
} else if (errors.size() == 1) {
|
} else if (errors.size() == 1) {
|
||||||
mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.problem_connecting_to_account));
|
mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.problem_connecting_to_account));
|
||||||
mBuilder.setContentText(errors.get(0).getJid().asBareJid().toString());
|
mBuilder.setContentText(errors.get(0).getJid().asBareJid().toEscapedString());
|
||||||
} else {
|
} else {
|
||||||
mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.problem_connecting_to_accounts));
|
mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.problem_connecting_to_accounts));
|
||||||
mBuilder.setContentText(mXmppConnectionService.getString(R.string.touch_to_fix));
|
mBuilder.setContentText(mXmppConnectionService.getString(R.string.touch_to_fix));
|
||||||
|
|
|
@ -20,7 +20,7 @@ import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Contact;
|
import eu.siacs.conversations.entities.Contact;
|
||||||
import eu.siacs.conversations.ui.StartConversationActivity;
|
import eu.siacs.conversations.ui.StartConversationActivity;
|
||||||
import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor;
|
import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class ShortcutService {
|
public class ShortcutService {
|
||||||
|
|
||||||
|
@ -116,13 +116,13 @@ public class ShortcutService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getShortcutId(Contact contact) {
|
private static String getShortcutId(Contact contact) {
|
||||||
return contact.getAccount().getJid().asBareJid().toString()+"#"+contact.getJid().asBareJid().toString();
|
return contact.getAccount().getJid().asBareJid().toEscapedString()+"#"+contact.getJid().asBareJid().toEscapedString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Intent getShortcutIntent(Contact contact) {
|
private Intent getShortcutIntent(Contact contact) {
|
||||||
Intent intent = new Intent(xmppConnectionService, StartConversationActivity.class);
|
Intent intent = new Intent(xmppConnectionService, StartConversationActivity.class);
|
||||||
intent.setAction(Intent.ACTION_VIEW);
|
intent.setAction(Intent.ACTION_VIEW);
|
||||||
intent.setData(Uri.parse("xmpp:"+contact.getJid().asBareJid().toString()));
|
intent.setData(Uri.parse("xmpp:"+contact.getJid().asBareJid().toEscapedString()));
|
||||||
intent.putExtra("account",contact.getAccount().getJid().asBareJid().toString());
|
intent.putExtra("account",contact.getAccount().getJid().asBareJid().toString());
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
return intent;
|
return intent;
|
||||||
|
|
|
@ -155,7 +155,7 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
||||||
import me.leolin.shortcutbadger.ShortcutBadger;
|
import me.leolin.shortcutbadger.ShortcutBadger;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class XmppConnectionService extends Service {
|
public class XmppConnectionService extends Service {
|
||||||
|
|
||||||
|
@ -2196,15 +2196,16 @@ public class XmppConnectionService extends Service {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (findAccountByJid(info.first) == null) {
|
if (findAccountByJid(info.first) == null) {
|
||||||
Account account = new Account(info.first, "");
|
final Account account = new Account(info.first, "");
|
||||||
account.setPrivateKeyAlias(alias);
|
account.setPrivateKeyAlias(alias);
|
||||||
account.setOption(Account.OPTION_DISABLED, true);
|
account.setOption(Account.OPTION_DISABLED, true);
|
||||||
|
account.setOption(Account.OPTION_FIXED_USERNAME, true);
|
||||||
account.setDisplayName(info.second);
|
account.setDisplayName(info.second);
|
||||||
createAccount(account);
|
createAccount(account);
|
||||||
callback.onAccountCreated(account);
|
callback.onAccountCreated(account);
|
||||||
if (Config.X509_VERIFICATION) {
|
if (Config.X509_VERIFICATION) {
|
||||||
try {
|
try {
|
||||||
getMemorizingTrustManager().getNonInteractive(account.getJid().getDomain()).checkClientTrusted(chain, "RSA");
|
getMemorizingTrustManager().getNonInteractive(account.getServer()).checkClientTrusted(chain, "RSA");
|
||||||
} catch (CertificateException e) {
|
} catch (CertificateException e) {
|
||||||
callback.informUser(R.string.certificate_chain_is_not_trusted);
|
callback.informUser(R.string.certificate_chain_is_not_trusted);
|
||||||
}
|
}
|
||||||
|
@ -2213,7 +2214,6 @@ public class XmppConnectionService extends Service {
|
||||||
callback.informUser(R.string.account_already_exists);
|
callback.informUser(R.string.account_already_exists);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
|
||||||
callback.informUser(R.string.unable_to_parse_certificate);
|
callback.informUser(R.string.unable_to_parse_certificate);
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
|
@ -2821,7 +2821,7 @@ public class XmppConnectionService extends Service {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
for (ListIterator<Jid> iterator = cryptoTargets.listIterator(); iterator.hasNext(); ) {
|
for (ListIterator<Jid> iterator = cryptoTargets.listIterator(); iterator.hasNext(); ) {
|
||||||
Jid jid = iterator.next();
|
Jid jid = iterator.next();
|
||||||
if (!members.contains(jid) && !members.contains(Jid.ofDomain(jid.getDomain()))) {
|
if (!members.contains(jid) && !members.contains(jid.getDomain())) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": 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;
|
changed = true;
|
||||||
|
@ -3751,7 +3751,7 @@ public class XmppConnectionService extends Service {
|
||||||
if (account.getStatus() == Account.State.ONLINE) {
|
if (account.getStatus() == Account.State.ONLINE) {
|
||||||
IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
|
IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
|
||||||
Element item = iq.query(Namespace.ROSTER).addChild("item");
|
Element item = iq.query(Namespace.ROSTER).addChild("item");
|
||||||
item.setAttribute("jid", contact.getJid().toString());
|
item.setAttribute("jid", contact.getJid());
|
||||||
item.setAttribute("subscription", "remove");
|
item.setAttribute("subscription", "remove");
|
||||||
account.getXmppConnection().sendIqPacket(iq, mDefaultIqHandler);
|
account.getXmppConnection().sendIqPacket(iq, mDefaultIqHandler);
|
||||||
}
|
}
|
||||||
|
@ -4160,7 +4160,7 @@ public class XmppConnectionService extends Service {
|
||||||
mucServers.addAll(account.getXmppConnection().getMucServers());
|
mucServers.addAll(account.getXmppConnection().getMucServers());
|
||||||
for (Bookmark bookmark : account.getBookmarks()) {
|
for (Bookmark bookmark : account.getBookmarks()) {
|
||||||
final Jid jid = bookmark.getJid();
|
final Jid jid = bookmark.getJid();
|
||||||
final String s = jid == null ? null : jid.getDomain();
|
final String s = jid == null ? null : jid.getDomain().toEscapedString();
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
mucServers.add(s);
|
mucServers.add(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,6 @@ package eu.siacs.conversations.ui;
|
||||||
import android.databinding.DataBindingUtil;
|
import android.databinding.DataBindingUtil;
|
||||||
import android.support.annotation.StringRes;
|
import android.support.annotation.StringRes;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.text.SpannableString;
|
|
||||||
import android.text.Spanned;
|
|
||||||
import android.text.style.TypefaceSpan;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
@ -14,7 +11,7 @@ import eu.siacs.conversations.databinding.DialogBlockContactBinding;
|
||||||
import eu.siacs.conversations.entities.Blockable;
|
import eu.siacs.conversations.entities.Blockable;
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
import eu.siacs.conversations.ui.util.JidDialog;
|
import eu.siacs.conversations.ui.util.JidDialog;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public final class BlockContactDialog {
|
public final class BlockContactDialog {
|
||||||
public static void show(final XmppActivity xmppActivity, final Blockable blockable) {
|
public static void show(final XmppActivity xmppActivity, final Blockable blockable) {
|
||||||
|
|
|
@ -11,12 +11,11 @@ import java.util.Collections;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Blockable;
|
import eu.siacs.conversations.entities.Blockable;
|
||||||
import eu.siacs.conversations.entities.Contact;
|
|
||||||
import eu.siacs.conversations.entities.ListItem;
|
import eu.siacs.conversations.entities.ListItem;
|
||||||
import eu.siacs.conversations.entities.RawBlockable;
|
import eu.siacs.conversations.entities.RawBlockable;
|
||||||
import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
|
import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
|
||||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class BlocklistActivity extends AbstractSearchableListItemActivity implements OnUpdateBlocklist {
|
public class BlocklistActivity extends AbstractSearchableListItemActivity implements OnUpdateBlocklist {
|
||||||
|
|
||||||
|
@ -80,7 +79,7 @@ public class BlocklistActivity extends AbstractSearchableListItemActivity implem
|
||||||
getString(R.string.block_jabber_id),
|
getString(R.string.block_jabber_id),
|
||||||
getString(R.string.block),
|
getString(R.string.block),
|
||||||
null,
|
null,
|
||||||
account.getJid().asBareJid().toString(),
|
account.getJid().asBareJid().toEscapedString(),
|
||||||
true,
|
true,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
|
@ -38,7 +38,7 @@ import eu.siacs.conversations.ui.util.PendingItem;
|
||||||
import eu.siacs.conversations.ui.util.SoftKeyboardUtils;
|
import eu.siacs.conversations.ui.util.SoftKeyboardUtils;
|
||||||
import eu.siacs.conversations.ui.util.StyledAttributes;
|
import eu.siacs.conversations.ui.util.StyledAttributes;
|
||||||
import eu.siacs.conversations.utils.AccountUtils;
|
import eu.siacs.conversations.utils.AccountUtils;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class ChannelDiscoveryActivity extends XmppActivity implements MenuItem.OnActionExpandListener, TextView.OnEditorActionListener, ChannelDiscoveryService.OnChannelSearchResultsFound, ChannelSearchResultAdapter.OnChannelSearchResultSelected {
|
public class ChannelDiscoveryActivity extends XmppActivity implements MenuItem.OnActionExpandListener, TextView.OnEditorActionListener, ChannelDiscoveryService.OnChannelSearchResultsFound, ChannelSearchResultAdapter.OnChannelSearchResultSelected {
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ public class ChannelDiscoveryActivity extends XmppActivity implements MenuItem.O
|
||||||
}
|
}
|
||||||
|
|
||||||
public void joinChannelSearchResult(String selectedAccount, Room result) {
|
public void joinChannelSearchResult(String selectedAccount, Room result) {
|
||||||
final Jid jid = Config.DOMAIN_LOCK == null ? Jid.of(selectedAccount) : Jid.of(selectedAccount, Config.DOMAIN_LOCK, null);
|
final Jid jid = Config.DOMAIN_LOCK == null ? Jid.ofEscaped(selectedAccount) : Jid.ofEscaped(selectedAccount, Config.DOMAIN_LOCK, null);
|
||||||
final boolean syncAutoJoin = getBooleanPreference("autojoin", R.bool.autojoin);
|
final boolean syncAutoJoin = getBooleanPreference("autojoin", R.bool.autojoin);
|
||||||
final Account account = xmppConnectionService.findAccountByJid(jid);
|
final Account account = xmppConnectionService.findAccountByJid(jid);
|
||||||
final Conversation conversation = xmppConnectionService.findOrCreateConversation(account, result.getRoom(), true, true, true);
|
final Conversation conversation = xmppConnectionService.findOrCreateConversation(account, result.getRoom(), true, true, true);
|
||||||
|
|
|
@ -3,7 +3,6 @@ package eu.siacs.conversations.ui;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.ActionBar;
|
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
@ -12,9 +11,7 @@ import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
|
||||||
import eu.siacs.conversations.ui.adapter.AccountAdapter;
|
import eu.siacs.conversations.ui.adapter.AccountAdapter;
|
||||||
import rocks.xmpp.addr.Jid;
|
|
||||||
|
|
||||||
public class ChooseAccountForProfilePictureActivity extends XmppActivity {
|
public class ChooseAccountForProfilePictureActivity extends XmppActivity {
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
|
||||||
import eu.siacs.conversations.ui.util.ActivityResult;
|
import eu.siacs.conversations.ui.util.ActivityResult;
|
||||||
import eu.siacs.conversations.ui.util.PendingItem;
|
import eu.siacs.conversations.ui.util.PendingItem;
|
||||||
import eu.siacs.conversations.utils.XmppUri;
|
import eu.siacs.conversations.utils.XmppUri;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class ChooseContactActivity extends AbstractSearchableListItemActivity implements MultiChoiceModeListener, AdapterView.OnItemClickListener {
|
public class ChooseContactActivity extends AbstractSearchableListItemActivity implements MultiChoiceModeListener, AdapterView.OnItemClickListener {
|
||||||
public static final String EXTRA_TITLE_RES_ID = "extra_title_res_id";
|
public static final String EXTRA_TITLE_RES_ID = "extra_title_res_id";
|
||||||
|
@ -361,9 +361,9 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
|
||||||
for (Account account : xmppConnectionService.getAccounts()) {
|
for (Account account : xmppConnectionService.getAccounts()) {
|
||||||
if (account.getStatus() != Account.State.DISABLED) {
|
if (account.getStatus() != Account.State.DISABLED) {
|
||||||
if (Config.DOMAIN_LOCK != null) {
|
if (Config.DOMAIN_LOCK != null) {
|
||||||
this.mActivatedAccounts.add(account.getJid().getLocal());
|
this.mActivatedAccounts.add(account.getJid().getEscapedLocal());
|
||||||
} else {
|
} else {
|
||||||
this.mActivatedAccounts.add(account.getJid().asBareJid().toString());
|
this.mActivatedAccounts.add(account.getJid().asBareJid().toEscapedString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package eu.siacs.conversations.ui;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentSender.SendIntentException;
|
|
||||||
import android.databinding.DataBindingUtil;
|
import android.databinding.DataBindingUtil;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
|
@ -23,7 +22,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.crypto.PgpEngine;
|
|
||||||
import eu.siacs.conversations.databinding.ActivityMucDetailsBinding;
|
import eu.siacs.conversations.databinding.ActivityMucDetailsBinding;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Bookmark;
|
import eu.siacs.conversations.entities.Bookmark;
|
||||||
|
@ -51,7 +49,7 @@ import eu.siacs.conversations.utils.StringUtils;
|
||||||
import eu.siacs.conversations.utils.StylingHelper;
|
import eu.siacs.conversations.utils.StylingHelper;
|
||||||
import eu.siacs.conversations.utils.XmppUri;
|
import eu.siacs.conversations.utils.XmppUri;
|
||||||
import me.drakeet.support.toast.ToastCompat;
|
import me.drakeet.support.toast.ToastCompat;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
import static eu.siacs.conversations.entities.Bookmark.printableValue;
|
import static eu.siacs.conversations.entities.Bookmark.printableValue;
|
||||||
import static eu.siacs.conversations.utils.StringUtils.changed;
|
import static eu.siacs.conversations.utils.StringUtils.changed;
|
||||||
|
@ -447,9 +445,9 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
|
||||||
final User self = mucOptions.getSelf();
|
final User self = mucOptions.getSelf();
|
||||||
String account;
|
String account;
|
||||||
if (Config.DOMAIN_LOCK != null) {
|
if (Config.DOMAIN_LOCK != null) {
|
||||||
account = mConversation.getAccount().getJid().getLocal();
|
account = mConversation.getAccount().getJid().getEscapedLocal();
|
||||||
} else {
|
} else {
|
||||||
account = mConversation.getAccount().getJid().asBareJid().toString();
|
account = mConversation.getAccount().getJid().asBareJid().toEscapedString();
|
||||||
}
|
}
|
||||||
setTitle(mucOptions.isPrivateAndNonAnonymous() ? R.string.action_muc_details : R.string.channel_details);
|
setTitle(mucOptions.isPrivateAndNonAnonymous() ? R.string.action_muc_details : R.string.channel_details);
|
||||||
this.binding.editMucNameButton.setVisibility((self.getAffiliation().ranks(MucOptions.Affiliation.OWNER) || mucOptions.canChangeSubject()) ? View.VISIBLE : View.GONE);
|
this.binding.editMucNameButton.setVisibility((self.getAffiliation().ranks(MucOptions.Affiliation.OWNER) || mucOptions.canChangeSubject()) ? View.VISIBLE : View.GONE);
|
||||||
|
@ -586,7 +584,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAffiliationChangeFailed(Jid jid, int resId) {
|
public void onAffiliationChangeFailed(Jid jid, int resId) {
|
||||||
displayToast(getString(resId, jid.asBareJid().toString()));
|
displayToast(getString(resId, jid.asBareJid().toEscapedString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -60,7 +60,7 @@ import eu.siacs.conversations.xml.Namespace;
|
||||||
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
||||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class ContactDetailsActivity extends OmemoActivity implements OnAccountUpdate, OnRosterUpdate, OnUpdateBlocklist, OnKeyStatusUpdated, OnMediaLoaded {
|
public class ContactDetailsActivity extends OmemoActivity implements OnAccountUpdate, OnRosterUpdate, OnUpdateBlocklist, OnKeyStatusUpdated, OnMediaLoaded {
|
||||||
public static final String ACTION_VIEW_CONTACT = "view_contact";
|
public static final String ACTION_VIEW_CONTACT = "view_contact";
|
||||||
|
@ -136,7 +136,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(
|
AlertDialog.Builder builder = new AlertDialog.Builder(
|
||||||
ContactDetailsActivity.this);
|
ContactDetailsActivity.this);
|
||||||
builder.setTitle(getString(R.string.action_add_phone_book));
|
builder.setTitle(getString(R.string.action_add_phone_book));
|
||||||
builder.setMessage(getString(R.string.add_phone_book_text, contact.getJid().toString()));
|
builder.setMessage(getString(R.string.add_phone_book_text, contact.getJid().toEscapedString()));
|
||||||
builder.setNegativeButton(getString(R.string.cancel), null);
|
builder.setNegativeButton(getString(R.string.cancel), null);
|
||||||
builder.setPositiveButton(getString(R.string.add), addToPhonebook);
|
builder.setPositiveButton(getString(R.string.add), addToPhonebook);
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
|
@ -411,9 +411,9 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
||||||
binding.detailsContactjid.setText(IrregularUnicodeDetector.style(this, contact.getJid()));
|
binding.detailsContactjid.setText(IrregularUnicodeDetector.style(this, contact.getJid()));
|
||||||
String account;
|
String account;
|
||||||
if (Config.DOMAIN_LOCK != null) {
|
if (Config.DOMAIN_LOCK != null) {
|
||||||
account = contact.getAccount().getJid().getLocal();
|
account = contact.getAccount().getJid().getEscapedLocal();
|
||||||
} else {
|
} else {
|
||||||
account = contact.getAccount().getJid().asBareJid().toString();
|
account = contact.getAccount().getJid().asBareJid().toEscapedString();
|
||||||
}
|
}
|
||||||
binding.detailsAccount.setText(getString(R.string.using_account, account));
|
binding.detailsAccount.setText(getString(R.string.using_account, account));
|
||||||
AvatarWorkerTask.loadAvatar(contact, binding.detailsContactBadge, R.dimen.avatar_on_details_screen_size);
|
AvatarWorkerTask.loadAvatar(contact, binding.detailsContactBadge, R.dimen.avatar_on_details_screen_size);
|
||||||
|
|
|
@ -56,6 +56,7 @@ import com.google.common.base.Optional;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -123,7 +124,7 @@ import eu.siacs.conversations.xmpp.jingle.JingleFileTransferConnection;
|
||||||
import eu.siacs.conversations.xmpp.jingle.Media;
|
import eu.siacs.conversations.xmpp.jingle.Media;
|
||||||
import eu.siacs.conversations.xmpp.jingle.OngoingRtpSession;
|
import eu.siacs.conversations.xmpp.jingle.OngoingRtpSession;
|
||||||
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
|
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
import static eu.siacs.conversations.ui.XmppActivity.EXTRA_ACCOUNT;
|
import static eu.siacs.conversations.ui.XmppActivity.EXTRA_ACCOUNT;
|
||||||
import static eu.siacs.conversations.ui.XmppActivity.REQUEST_INVITE_TO_CONVERSATION;
|
import static eu.siacs.conversations.ui.XmppActivity.REQUEST_INVITE_TO_CONVERSATION;
|
||||||
|
@ -863,13 +864,13 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
}
|
}
|
||||||
|
|
||||||
private void commitAttachments() {
|
private void commitAttachments() {
|
||||||
if (!hasPermissions(REQUEST_COMMIT_ATTACHMENTS, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
final List<Attachment> attachments = mediaPreviewAdapter.getAttachments();
|
||||||
|
if (anyNeedsExternalStoragePermission(attachments) && !hasPermissions(REQUEST_COMMIT_ATTACHMENTS, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (conversation.getNextEncryption() == Message.ENCRYPTION_AXOLOTL && trustKeysIfNeeded(REQUEST_TRUST_KEYS_ATTACHMENTS)) {
|
if (conversation.getNextEncryption() == Message.ENCRYPTION_AXOLOTL && trustKeysIfNeeded(REQUEST_TRUST_KEYS_ATTACHMENTS)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final List<Attachment> attachments = mediaPreviewAdapter.getAttachments();
|
|
||||||
final PresenceSelector.OnPresenceSelected callback = () -> {
|
final PresenceSelector.OnPresenceSelected callback = () -> {
|
||||||
for (Iterator<Attachment> i = attachments.iterator(); i.hasNext(); i.remove()) {
|
for (Iterator<Attachment> i = attachments.iterator(); i.hasNext(); i.remove()) {
|
||||||
final Attachment attachment = i.next();
|
final Attachment attachment = i.next();
|
||||||
|
@ -896,6 +897,16 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static boolean anyNeedsExternalStoragePermission(final Collection<Attachment> attachments) {
|
||||||
|
for(final Attachment attachment : attachments) {
|
||||||
|
if (attachment.getType() != Attachment.Type.LOCATION) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void toggleInputMethod() {
|
public void toggleInputMethod() {
|
||||||
boolean hasAttachments = mediaPreviewAdapter.hasAttachments();
|
boolean hasAttachments = mediaPreviewAdapter.hasAttachments();
|
||||||
binding.textinput.setVisibility(hasAttachments ? View.GONE : View.VISIBLE);
|
binding.textinput.setVisibility(hasAttachments ? View.GONE : View.VISIBLE);
|
||||||
|
@ -962,6 +973,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
final MenuItem menuCall = menu.findItem(R.id.action_call);
|
final MenuItem menuCall = menu.findItem(R.id.action_call);
|
||||||
final MenuItem menuOngoingCall = menu.findItem(R.id.action_ongoing_call);
|
final MenuItem menuOngoingCall = menu.findItem(R.id.action_ongoing_call);
|
||||||
final MenuItem menuVideoCall = menu.findItem(R.id.action_video_call);
|
final MenuItem menuVideoCall = menu.findItem(R.id.action_video_call);
|
||||||
|
final MenuItem menuTogglePinned = menu.findItem(R.id.action_toggle_pinned);
|
||||||
|
|
||||||
|
|
||||||
if (conversation != null) {
|
if (conversation != null) {
|
||||||
|
@ -994,6 +1006,11 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
}
|
}
|
||||||
ConversationMenuConfigurator.configureAttachmentMenu(conversation, menu);
|
ConversationMenuConfigurator.configureAttachmentMenu(conversation, menu);
|
||||||
ConversationMenuConfigurator.configureEncryptionMenu(conversation, menu);
|
ConversationMenuConfigurator.configureEncryptionMenu(conversation, menu);
|
||||||
|
if (conversation.getBooleanAttribute(Conversation.ATTRIBUTE_PINNED_ON_TOP, false)) {
|
||||||
|
menuTogglePinned.setTitle(R.string.remove_from_favorites);
|
||||||
|
} else {
|
||||||
|
menuTogglePinned.setTitle(R.string.add_to_favorites);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
super.onCreateOptionsMenu(menu, menuInflater);
|
super.onCreateOptionsMenu(menu, menuInflater);
|
||||||
}
|
}
|
||||||
|
@ -1261,6 +1278,9 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
case R.id.action_ongoing_call:
|
case R.id.action_ongoing_call:
|
||||||
returnToOngoingCall();
|
returnToOngoingCall();
|
||||||
break;
|
break;
|
||||||
|
case R.id.action_toggle_pinned:
|
||||||
|
togglePinned();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1289,6 +1309,12 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void togglePinned() {
|
||||||
|
final boolean pinned = conversation.getBooleanAttribute(Conversation.ATTRIBUTE_PINNED_ON_TOP, false);
|
||||||
|
conversation.setAttribute(Conversation.ATTRIBUTE_PINNED_ON_TOP, !pinned);
|
||||||
|
activity.xmppConnectionService.updateConversation(conversation);
|
||||||
|
}
|
||||||
|
|
||||||
private void checkPermissionAndTriggerAudioCall() {
|
private void checkPermissionAndTriggerAudioCall() {
|
||||||
if (activity.mUseTor || conversation.getAccount().isOnion()) {
|
if (activity.mUseTor || conversation.getAccount().isOnion()) {
|
||||||
Toast.makeText(activity, R.string.disable_tor_to_make_call, Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, R.string.disable_tor_to_make_call, Toast.LENGTH_SHORT).show();
|
||||||
|
|
|
@ -81,7 +81,7 @@ import eu.siacs.conversations.utils.ExceptionHelper;
|
||||||
import eu.siacs.conversations.utils.SignupUtils;
|
import eu.siacs.conversations.utils.SignupUtils;
|
||||||
import eu.siacs.conversations.utils.XmppUri;
|
import eu.siacs.conversations.utils.XmppUri;
|
||||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
import static eu.siacs.conversations.ui.ConversationFragment.REQUEST_DECRYPT_PGP;
|
import static eu.siacs.conversations.ui.ConversationFragment.REQUEST_DECRYPT_PGP;
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ import android.text.TextWatcher;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.Spinner;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -23,7 +22,6 @@ import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.databinding.CreateConferenceDialogBinding;
|
|
||||||
import eu.siacs.conversations.databinding.CreatePublicChannelDialogBinding;
|
import eu.siacs.conversations.databinding.CreatePublicChannelDialogBinding;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
|
@ -32,7 +30,7 @@ import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
|
||||||
import eu.siacs.conversations.ui.util.DelayedHintHelper;
|
import eu.siacs.conversations.ui.util.DelayedHintHelper;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class CreatePublicChannelDialog extends DialogFragment implements OnBackendConnected {
|
public class CreatePublicChannelDialog extends DialogFragment implements OnBackendConnected {
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection.Features;
|
import eu.siacs.conversations.xmpp.XmppConnection.Features;
|
||||||
import eu.siacs.conversations.xmpp.forms.Data;
|
import eu.siacs.conversations.xmpp.forms.Data;
|
||||||
import eu.siacs.conversations.xmpp.pep.Avatar;
|
import eu.siacs.conversations.xmpp.pep.Avatar;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class EditAccountActivity extends OmemoActivity implements OnAccountUpdate, OnUpdateBlocklist,
|
public class EditAccountActivity extends OmemoActivity implements OnAccountUpdate, OnUpdateBlocklist,
|
||||||
OnKeyStatusUpdated, OnCaptchaRequested, KeyChainAliasCallback, XmppConnectionService.OnShowErrorToast, XmppConnectionService.OnMamPreferencesFetched {
|
OnKeyStatusUpdated, OnCaptchaRequested, KeyChainAliasCallback, XmppConnectionService.OnShowErrorToast, XmppConnectionService.OnMamPreferencesFetched {
|
||||||
|
@ -201,9 +201,9 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
||||||
final Jid jid;
|
final Jid jid;
|
||||||
try {
|
try {
|
||||||
if (mUsernameMode) {
|
if (mUsernameMode) {
|
||||||
jid = Jid.of(binding.accountJid.getText().toString(), getUserModeDomain(), null);
|
jid = Jid.ofEscaped(binding.accountJid.getText().toString(), getUserModeDomain(), null);
|
||||||
} else {
|
} else {
|
||||||
jid = Jid.of(binding.accountJid.getText().toString());
|
jid = Jid.ofEscaped(binding.accountJid.getText().toString());
|
||||||
}
|
}
|
||||||
} catch (final NullPointerException | IllegalArgumentException e) {
|
} catch (final NullPointerException | IllegalArgumentException e) {
|
||||||
if (mUsernameMode) {
|
if (mUsernameMode) {
|
||||||
|
@ -577,9 +577,9 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
||||||
protected boolean jidEdited() {
|
protected boolean jidEdited() {
|
||||||
final String unmodified;
|
final String unmodified;
|
||||||
if (mUsernameMode) {
|
if (mUsernameMode) {
|
||||||
unmodified = this.mAccount.getJid().getLocal();
|
unmodified = this.mAccount.getJid().getEscapedLocal();
|
||||||
} else {
|
} else {
|
||||||
unmodified = this.mAccount.getJid().asBareJid().toString();
|
unmodified = this.mAccount.getJid().asBareJid().toEscapedString();
|
||||||
}
|
}
|
||||||
return !unmodified.equals(this.binding.accountJid.getText().toString());
|
return !unmodified.equals(this.binding.accountJid.getText().toString());
|
||||||
}
|
}
|
||||||
|
@ -784,12 +784,6 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
||||||
|
|
||||||
this.mInitMode |= this.mAccount.isOptionSet(Account.OPTION_REGISTER);
|
this.mInitMode |= this.mAccount.isOptionSet(Account.OPTION_REGISTER);
|
||||||
this.mUsernameMode |= mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) && mAccount.isOptionSet(Account.OPTION_REGISTER);
|
this.mUsernameMode |= mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) && mAccount.isOptionSet(Account.OPTION_REGISTER);
|
||||||
if (this.mAccount.getPrivateKeyAlias() != null) {
|
|
||||||
this.binding.accountPassword.setHint(R.string.authenticate_with_certificate);
|
|
||||||
if (this.mInitMode) {
|
|
||||||
this.binding.accountPassword.requestFocus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mPendingFingerprintVerificationUri != null) {
|
if (mPendingFingerprintVerificationUri != null) {
|
||||||
processFingerprintVerification(mPendingFingerprintVerificationUri, false);
|
processFingerprintVerification(mPendingFingerprintVerificationUri, false);
|
||||||
mPendingFingerprintVerificationUri = null;
|
mPendingFingerprintVerificationUri = null;
|
||||||
|
@ -822,7 +816,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
||||||
|
|
||||||
private String getUserModeDomain() {
|
private String getUserModeDomain() {
|
||||||
if (mAccount != null && mAccount.getJid().getDomain() != null) {
|
if (mAccount != null && mAccount.getJid().getDomain() != null) {
|
||||||
return mAccount.getJid().getDomain();
|
return mAccount.getServer();
|
||||||
} else {
|
} else {
|
||||||
return Config.DOMAIN_LOCK;
|
return Config.DOMAIN_LOCK;
|
||||||
}
|
}
|
||||||
|
@ -965,9 +959,9 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
||||||
if (init) {
|
if (init) {
|
||||||
this.binding.accountJid.getEditableText().clear();
|
this.binding.accountJid.getEditableText().clear();
|
||||||
if (mUsernameMode) {
|
if (mUsernameMode) {
|
||||||
this.binding.accountJid.getEditableText().append(this.mAccount.getJid().getLocal());
|
this.binding.accountJid.getEditableText().append(this.mAccount.getJid().getEscapedLocal());
|
||||||
} else {
|
} else {
|
||||||
this.binding.accountJid.getEditableText().append(this.mAccount.getJid().asBareJid().toString());
|
this.binding.accountJid.getEditableText().append(this.mAccount.getJid().asBareJid().toEscapedString());
|
||||||
}
|
}
|
||||||
this.binding.accountPassword.getEditableText().clear();
|
this.binding.accountPassword.getEditableText().clear();
|
||||||
this.binding.accountPassword.getEditableText().append(this.mAccount.getPassword());
|
this.binding.accountPassword.getEditableText().append(this.mAccount.getPassword());
|
||||||
|
|
|
@ -24,7 +24,7 @@ import eu.siacs.conversations.databinding.EnterJidDialogBinding;
|
||||||
import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
|
import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
|
||||||
import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
|
import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
|
||||||
import eu.siacs.conversations.ui.util.DelayedHintHelper;
|
import eu.siacs.conversations.ui.util.DelayedHintHelper;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class EnterJidDialog extends DialogFragment implements OnBackendConnected, TextWatcher {
|
public class EnterJidDialog extends DialogFragment implements OnBackendConnected, TextWatcher {
|
||||||
|
|
||||||
|
@ -146,16 +146,16 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (Config.DOMAIN_LOCK != null) {
|
if (Config.DOMAIN_LOCK != null) {
|
||||||
accountJid = Jid.of((String) binding.account.getSelectedItem(), Config.DOMAIN_LOCK, null);
|
accountJid = Jid.ofEscaped((String) binding.account.getSelectedItem(), Config.DOMAIN_LOCK, null);
|
||||||
} else {
|
} else {
|
||||||
accountJid = Jid.of((String) binding.account.getSelectedItem());
|
accountJid = Jid.ofEscaped((String) binding.account.getSelectedItem());
|
||||||
}
|
}
|
||||||
} catch (final IllegalArgumentException e) {
|
} catch (final IllegalArgumentException e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Jid contactJid;
|
final Jid contactJid;
|
||||||
try {
|
try {
|
||||||
contactJid = Jid.of(binding.jid.getText().toString());
|
contactJid = Jid.ofEscaped(binding.jid.getText().toString());
|
||||||
} catch (final IllegalArgumentException e) {
|
} catch (final IllegalArgumentException e) {
|
||||||
binding.jidLayout.setError(getActivity().getString(R.string.invalid_jid));
|
binding.jidLayout.setError(getActivity().getString(R.string.invalid_jid));
|
||||||
return;
|
return;
|
||||||
|
@ -168,7 +168,7 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
|
||||||
issuedWarning = true;
|
issuedWarning = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (suspiciousSubDomain(contactJid.getDomain())) {
|
if (suspiciousSubDomain(contactJid.getDomain().toEscapedString())) {
|
||||||
binding.jidLayout.setError(getActivity().getString(R.string.this_looks_like_channel));
|
binding.jidLayout.setError(getActivity().getString(R.string.this_looks_like_channel));
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add_anway);
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add_anway);
|
||||||
issuedWarning = true;
|
issuedWarning = true;
|
||||||
|
|
|
@ -18,7 +18,7 @@ import eu.siacs.conversations.ui.adapter.MediaAdapter;
|
||||||
import eu.siacs.conversations.ui.interfaces.OnMediaLoaded;
|
import eu.siacs.conversations.ui.interfaces.OnMediaLoaded;
|
||||||
import eu.siacs.conversations.ui.util.Attachment;
|
import eu.siacs.conversations.ui.util.Attachment;
|
||||||
import eu.siacs.conversations.ui.util.GridManager;
|
import eu.siacs.conversations.ui.util.GridManager;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class MediaBrowserActivity extends XmppActivity implements OnMediaLoaded {
|
public class MediaBrowserActivity extends XmppActivity implements OnMediaLoaded {
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ public class MediaBrowserActivity extends XmppActivity implements OnMediaLoaded
|
||||||
String account = intent == null ? null : intent.getStringExtra("account");
|
String account = intent == null ? null : intent.getStringExtra("account");
|
||||||
String jid = intent == null ? null : intent.getStringExtra("jid");
|
String jid = intent == null ? null : intent.getStringExtra("jid");
|
||||||
if (account != null && jid != null) {
|
if (account != null && jid != null) {
|
||||||
xmppConnectionService.getAttachments(account, Jid.of(jid), 0, this);
|
xmppConnectionService.getAttachments(account, Jid.ofEscaped(jid), 0, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ import eu.siacs.conversations.entities.MucOptions;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.ui.adapter.UserAdapter;
|
import eu.siacs.conversations.ui.adapter.UserAdapter;
|
||||||
import eu.siacs.conversations.ui.util.MucDetailsContextMenuHelper;
|
import eu.siacs.conversations.ui.util.MucDetailsContextMenuHelper;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class MucUsersActivity extends XmppActivity implements XmppConnectionService.OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged, MenuItem.OnActionExpandListener, TextWatcher {
|
public class MucUsersActivity extends XmppActivity implements XmppConnectionService.OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged, MenuItem.OnActionExpandListener, TextWatcher {
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
|
||||||
import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
|
import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
|
||||||
import eu.siacs.conversations.xmpp.jingle.Media;
|
import eu.siacs.conversations.xmpp.jingle.Media;
|
||||||
import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;
|
import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
import static eu.siacs.conversations.utils.PermissionUtils.getFirstDenied;
|
import static eu.siacs.conversations.utils.PermissionUtils.getFirstDenied;
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
@ -129,7 +129,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
|
||||||
final Intent intent = getIntent();
|
final Intent intent = getIntent();
|
||||||
final String action = intent.getAction();
|
final String action = intent.getAction();
|
||||||
final Account account = extractAccount(intent);
|
final Account account = extractAccount(intent);
|
||||||
final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
|
final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
|
||||||
final String state = intent.getStringExtra(EXTRA_LAST_REPORTED_STATE);
|
final String state = intent.getStringExtra(EXTRA_LAST_REPORTED_STATE);
|
||||||
if (!Intent.ACTION_VIEW.equals(action) || state == null || !END_CARD.contains(RtpEndUserState.valueOf(state))) {
|
if (!Intent.ACTION_VIEW.equals(action) || state == null || !END_CARD.contains(RtpEndUserState.valueOf(state))) {
|
||||||
resetIntent(account, with, RtpEndUserState.RETRACTED, actionToMedia(intent.getAction()));
|
resetIntent(account, with, RtpEndUserState.RETRACTED, actionToMedia(intent.getAction()));
|
||||||
|
@ -246,7 +246,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Account account = extractAccount(intent);
|
final Account account = extractAccount(intent);
|
||||||
final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
|
final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
|
||||||
final String sessionId = intent.getStringExtra(EXTRA_SESSION_ID);
|
final String sessionId = intent.getStringExtra(EXTRA_SESSION_ID);
|
||||||
if (sessionId != null) {
|
if (sessionId != null) {
|
||||||
Log.d(Config.LOGTAG, "reinitializing from onNewIntent()");
|
Log.d(Config.LOGTAG, "reinitializing from onNewIntent()");
|
||||||
|
@ -268,7 +268,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
|
||||||
final Intent intent = getIntent();
|
final Intent intent = getIntent();
|
||||||
final String action = intent.getAction();
|
final String action = intent.getAction();
|
||||||
final Account account = extractAccount(intent);
|
final Account account = extractAccount(intent);
|
||||||
final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
|
final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
|
||||||
final String sessionId = intent.getStringExtra(EXTRA_SESSION_ID);
|
final String sessionId = intent.getStringExtra(EXTRA_SESSION_ID);
|
||||||
if (sessionId != null) {
|
if (sessionId != null) {
|
||||||
if (initializeActivityWithRunningRtpSession(account, with, sessionId)) {
|
if (initializeActivityWithRunningRtpSession(account, with, sessionId)) {
|
||||||
|
@ -831,7 +831,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
|
||||||
Log.d(Config.LOGTAG, "attempting retry");
|
Log.d(Config.LOGTAG, "attempting retry");
|
||||||
final Intent intent = getIntent();
|
final Intent intent = getIntent();
|
||||||
final Account account = extractAccount(intent);
|
final Account account = extractAccount(intent);
|
||||||
final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
|
final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
|
||||||
final String lastAction = intent.getStringExtra(EXTRA_LAST_ACTION);
|
final String lastAction = intent.getStringExtra(EXTRA_LAST_ACTION);
|
||||||
final String action = intent.getAction();
|
final String action = intent.getAction();
|
||||||
final Set<Media> media = actionToMedia(lastAction == null ? action : lastAction);
|
final Set<Media> media = actionToMedia(lastAction == null ? action : lastAction);
|
||||||
|
|
|
@ -41,7 +41,7 @@ import eu.siacs.conversations.services.QuickConversationsService;
|
||||||
import eu.siacs.conversations.ui.util.StyledAttributes;
|
import eu.siacs.conversations.ui.util.StyledAttributes;
|
||||||
import eu.siacs.conversations.utils.GeoHelper;
|
import eu.siacs.conversations.utils.GeoHelper;
|
||||||
import eu.siacs.conversations.utils.TimeFrameUtils;
|
import eu.siacs.conversations.utils.TimeFrameUtils;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class SettingsActivity extends XmppActivity implements
|
public class SettingsActivity extends XmppActivity implements
|
||||||
OnSharedPreferenceChangeListener {
|
OnSharedPreferenceChangeListener {
|
||||||
|
|
|
@ -12,7 +12,6 @@ import android.view.MenuItem;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
|
@ -21,9 +20,7 @@ import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.ui.adapter.ConversationAdapter;
|
import eu.siacs.conversations.ui.adapter.ConversationAdapter;
|
||||||
import eu.siacs.conversations.ui.service.EmojiService;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
import eu.siacs.conversations.utils.GeoHelper;
|
|
||||||
import rocks.xmpp.addr.Jid;
|
|
||||||
|
|
||||||
public class ShareWithActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate {
|
public class ShareWithActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate {
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ import eu.siacs.conversations.utils.AccountUtils;
|
||||||
import eu.siacs.conversations.utils.XmppUri;
|
import eu.siacs.conversations.utils.XmppUri;
|
||||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class StartConversationActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate, OnRosterUpdate, OnUpdateBlocklist, CreatePrivateGroupChatDialog.CreateConferenceDialogListener, JoinConferenceDialog.JoinConferenceDialogListener, SwipeRefreshLayout.OnRefreshListener, CreatePublicChannelDialog.CreatePublicChannelDialogListener {
|
public class StartConversationActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate, OnRosterUpdate, OnUpdateBlocklist, CreatePrivateGroupChatDialog.CreateConferenceDialogListener, JoinConferenceDialog.JoinConferenceDialogListener, SwipeRefreshLayout.OnRefreshListener, CreatePublicChannelDialog.CreatePublicChannelDialogListener {
|
||||||
|
|
||||||
|
@ -577,9 +577,9 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
|
||||||
Jid jid;
|
Jid jid;
|
||||||
try {
|
try {
|
||||||
if (Config.DOMAIN_LOCK != null) {
|
if (Config.DOMAIN_LOCK != null) {
|
||||||
jid = Jid.of((String) spinner.getSelectedItem(), Config.DOMAIN_LOCK, null);
|
jid = Jid.ofEscaped((String) spinner.getSelectedItem(), Config.DOMAIN_LOCK, null);
|
||||||
} else {
|
} else {
|
||||||
jid = Jid.of((String) spinner.getSelectedItem());
|
jid = Jid.ofEscaped((String) spinner.getSelectedItem());
|
||||||
}
|
}
|
||||||
} catch (final IllegalArgumentException e) {
|
} catch (final IllegalArgumentException e) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -855,11 +855,11 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
|
||||||
switchToConversationDoNotAppend(muc, invite.getBody());
|
switchToConversationDoNotAppend(muc, invite.getBody());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
showJoinConferenceDialog(invite.getJid().asBareJid().toString());
|
showJoinConferenceDialog(invite.getJid().asBareJid().toEscapedString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (contacts.size() == 0) {
|
} else if (contacts.size() == 0) {
|
||||||
showCreateContactDialog(invite.getJid().toString(), invite);
|
showCreateContactDialog(invite.getJid().toEscapedString(), invite);
|
||||||
return false;
|
return false;
|
||||||
} else if (contacts.size() == 1) {
|
} else if (contacts.size() == 1) {
|
||||||
Contact contact = contacts.get(0);
|
Contact contact = contacts.get(0);
|
||||||
|
@ -881,10 +881,10 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
|
||||||
if (mMenuSearchView != null) {
|
if (mMenuSearchView != null) {
|
||||||
mMenuSearchView.expandActionView();
|
mMenuSearchView.expandActionView();
|
||||||
mSearchEditText.setText("");
|
mSearchEditText.setText("");
|
||||||
mSearchEditText.append(invite.getJid().toString());
|
mSearchEditText.append(invite.getJid().toEscapedString());
|
||||||
filter(invite.getJid().toString());
|
filter(invite.getJid().toEscapedString());
|
||||||
} else {
|
} else {
|
||||||
mInitialSearchValue.push(invite.getJid().toString());
|
mInitialSearchValue.push(invite.getJid().toEscapedString());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1017,7 +1017,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
|
||||||
final String input = jid.getText().toString();
|
final String input = jid.getText().toString();
|
||||||
Jid conferenceJid;
|
Jid conferenceJid;
|
||||||
try {
|
try {
|
||||||
conferenceJid = Jid.of(input);
|
conferenceJid = Jid.ofEscaped(input);
|
||||||
} catch (final IllegalArgumentException e) {
|
} catch (final IllegalArgumentException e) {
|
||||||
final XmppUri xmppUri = new XmppUri(input);
|
final XmppUri xmppUri = new XmppUri(input);
|
||||||
if (xmppUri.isValidJid() && xmppUri.isAction(XmppUri.ACTION_JOIN)) {
|
if (xmppUri.isValidJid() && xmppUri.isAction(XmppUri.ACTION_JOIN)) {
|
||||||
|
|
|
@ -38,7 +38,7 @@ import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.utils.IrregularUnicodeDetector;
|
import eu.siacs.conversations.utils.IrregularUnicodeDetector;
|
||||||
import eu.siacs.conversations.utils.XmppUri;
|
import eu.siacs.conversations.utils.XmppUri;
|
||||||
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
|
|
||||||
public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdated {
|
public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdated {
|
||||||
|
@ -213,7 +213,7 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
|
||||||
showCameraToast();
|
showCameraToast();
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.ownKeysTitle.setText(mAccount.getJid().asBareJid().toString());
|
binding.ownKeysTitle.setText(mAccount.getJid().asBareJid().toEscapedString());
|
||||||
binding.ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE);
|
binding.ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE);
|
||||||
binding.foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE);
|
binding.foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE);
|
||||||
if (hasPendingKeyFetches()) {
|
if (hasPendingKeyFetches()) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.persistance.DatabaseBackend;
|
import eu.siacs.conversations.persistance.DatabaseBackend;
|
||||||
import eu.siacs.conversations.utils.SignupUtils;
|
import eu.siacs.conversations.utils.SignupUtils;
|
||||||
import eu.siacs.conversations.utils.XmppUri;
|
import eu.siacs.conversations.utils.XmppUri;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class UriHandlerActivity extends AppCompatActivity {
|
public class UriHandlerActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ import eu.siacs.conversations.utils.ExceptionHelper;
|
||||||
import eu.siacs.conversations.utils.ThemeHelper;
|
import eu.siacs.conversations.utils.ThemeHelper;
|
||||||
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
||||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public abstract class XmppActivity extends ActionBarActivity {
|
public abstract class XmppActivity extends ActionBarActivity {
|
||||||
|
|
||||||
|
@ -870,7 +870,7 @@ public abstract class XmppActivity extends ActionBarActivity {
|
||||||
protected Account extractAccount(Intent intent) {
|
protected Account extractAccount(Intent intent) {
|
||||||
final String jid = intent != null ? intent.getStringExtra(EXTRA_ACCOUNT) : null;
|
final String jid = intent != null ? intent.getStringExtra(EXTRA_ACCOUNT) : null;
|
||||||
try {
|
try {
|
||||||
return jid != null ? xmppConnectionService.findAccountByJid(Jid.of(jid)) : null;
|
return jid != null ? xmppConnectionService.findAccountByJid(Jid.ofEscaped(jid)) : null;
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ public class AccountAdapter extends ArrayAdapter<Account> {
|
||||||
if (Config.DOMAIN_LOCK != null) {
|
if (Config.DOMAIN_LOCK != null) {
|
||||||
viewHolder.binding.accountJid.setText(account.getJid().getLocal());
|
viewHolder.binding.accountJid.setText(account.getJid().getLocal());
|
||||||
} else {
|
} else {
|
||||||
viewHolder.binding.accountJid.setText(account.getJid().asBareJid().toString());
|
viewHolder.binding.accountJid.setText(account.getJid().asBareJid().toEscapedString());
|
||||||
}
|
}
|
||||||
AvatarWorkerTask.loadAvatar(account, viewHolder.binding.accountImage, R.dimen.avatar);
|
AvatarWorkerTask.loadAvatar(account, viewHolder.binding.accountImage, R.dimen.avatar);
|
||||||
viewHolder.binding.accountStatus.setText(getContext().getString(account.getStatus().getReadableId()));
|
viewHolder.binding.accountStatus.setText(getContext().getString(account.getStatus().getReadableId()));
|
||||||
|
|
|
@ -19,7 +19,7 @@ import eu.siacs.conversations.databinding.SearchResultItemBinding;
|
||||||
import eu.siacs.conversations.entities.Room;
|
import eu.siacs.conversations.entities.Room;
|
||||||
import eu.siacs.conversations.ui.XmppActivity;
|
import eu.siacs.conversations.ui.XmppActivity;
|
||||||
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
|
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class ChannelSearchResultAdapter extends ListAdapter<Room, ChannelSearchResultAdapter.ViewHolder> implements View.OnCreateContextMenuListener {
|
public class ChannelSearchResultAdapter extends ListAdapter<Room, ChannelSearchResultAdapter.ViewHolder> implements View.OnCreateContextMenuListener {
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,8 @@ import eu.siacs.conversations.ui.util.StyledAttributes;
|
||||||
import eu.siacs.conversations.utils.EmojiWrapper;
|
import eu.siacs.conversations.utils.EmojiWrapper;
|
||||||
import eu.siacs.conversations.utils.IrregularUnicodeDetector;
|
import eu.siacs.conversations.utils.IrregularUnicodeDetector;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
|
|
||||||
import eu.siacs.conversations.xmpp.jingle.OngoingRtpSession;
|
import eu.siacs.conversations.xmpp.jingle.OngoingRtpSession;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class ConversationAdapter extends RecyclerView.Adapter<ConversationAdapter.ConversationViewHolder> {
|
public class ConversationAdapter extends RecyclerView.Adapter<ConversationAdapter.ConversationViewHolder> {
|
||||||
|
|
||||||
|
@ -202,6 +201,7 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationAdapte
|
||||||
} else {
|
} else {
|
||||||
timestamp = conversation.getLatestMessage().getTimeSent();
|
timestamp = conversation.getLatestMessage().getTimeSent();
|
||||||
}
|
}
|
||||||
|
viewHolder.binding.pinnedOnTop.setVisibility(conversation.getBooleanAttribute(Conversation.ATTRIBUTE_PINNED_ON_TOP,false) ? View.VISIBLE : View.GONE);
|
||||||
viewHolder.binding.conversationLastupdate.setText(UIHelper.readableTimeDifference(activity, timestamp));
|
viewHolder.binding.conversationLastupdate.setText(UIHelper.readableTimeDifference(activity, timestamp));
|
||||||
AvatarWorkerTask.loadAvatar(conversation, viewHolder.binding.conversationImage, R.dimen.avatar_on_conversation_overview);
|
AvatarWorkerTask.loadAvatar(conversation, viewHolder.binding.conversationImage, R.dimen.avatar_on_conversation_overview);
|
||||||
viewHolder.itemView.setOnClickListener(v -> listener.onConversationClick(v, conversation));
|
viewHolder.itemView.setOnClickListener(v -> listener.onConversationClick(v, conversation));
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
package eu.siacs.conversations.ui.adapter;
|
package eu.siacs.conversations.ui.adapter;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.databinding.DataBindingUtil;
|
import android.databinding.DataBindingUtil;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -17,9 +12,7 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import com.wefika.flowlayout.FlowLayout;
|
import com.wefika.flowlayout.FlowLayout;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
|
||||||
|
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.databinding.ContactBinding;
|
import eu.siacs.conversations.databinding.ContactBinding;
|
||||||
|
@ -30,9 +23,7 @@ import eu.siacs.conversations.ui.util.AvatarWorkerTask;
|
||||||
import eu.siacs.conversations.ui.util.StyledAttributes;
|
import eu.siacs.conversations.ui.util.StyledAttributes;
|
||||||
import eu.siacs.conversations.utils.EmojiWrapper;
|
import eu.siacs.conversations.utils.EmojiWrapper;
|
||||||
import eu.siacs.conversations.utils.IrregularUnicodeDetector;
|
import eu.siacs.conversations.utils.IrregularUnicodeDetector;
|
||||||
import eu.siacs.conversations.utils.ThemeHelper;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
|
||||||
import rocks.xmpp.addr.Jid;
|
|
||||||
|
|
||||||
public class ListItemAdapter extends ArrayAdapter<ListItem> {
|
public class ListItemAdapter extends ArrayAdapter<ListItem> {
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ import eu.siacs.conversations.utils.StylingHelper;
|
||||||
import eu.siacs.conversations.utils.TimeFrameUtils;
|
import eu.siacs.conversations.utils.TimeFrameUtils;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xmpp.mam.MamReference;
|
import eu.siacs.conversations.xmpp.mam.MamReference;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextView.CopyHandler {
|
public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextView.CopyHandler {
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ import eu.siacs.conversations.ui.ConferenceDetailsActivity;
|
||||||
import eu.siacs.conversations.ui.XmppActivity;
|
import eu.siacs.conversations.ui.XmppActivity;
|
||||||
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
|
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
|
||||||
import eu.siacs.conversations.ui.util.MucDetailsContextMenuHelper;
|
import eu.siacs.conversations.ui.util.MucDetailsContextMenuHelper;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class UserAdapter extends ListAdapter<MucOptions.User, UserAdapter.ViewHolder> implements View.OnCreateContextMenuListener {
|
public class UserAdapter extends ListAdapter<MucOptions.User, UserAdapter.ViewHolder> implements View.OnCreateContextMenuListener {
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.xmpp.forms.Field;
|
import eu.siacs.conversations.xmpp.forms.Field;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class FormJidSingleFieldWrapper extends FormTextFieldWrapper {
|
public class FormJidSingleFieldWrapper extends FormTextFieldWrapper {
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ import eu.siacs.conversations.ui.ConversationFragment;
|
||||||
import eu.siacs.conversations.ui.ConversationsActivity;
|
import eu.siacs.conversations.ui.ConversationsActivity;
|
||||||
import eu.siacs.conversations.ui.MucUsersActivity;
|
import eu.siacs.conversations.ui.MucUsersActivity;
|
||||||
import eu.siacs.conversations.ui.XmppActivity;
|
import eu.siacs.conversations.ui.XmppActivity;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
|
|
||||||
public final class MucDetailsContextMenuHelper {
|
public final class MucDetailsContextMenuHelper {
|
||||||
|
|
|
@ -43,7 +43,7 @@ import eu.siacs.conversations.entities.Contact;
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
import eu.siacs.conversations.entities.Presences;
|
import eu.siacs.conversations.entities.Presences;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class PresenceSelector {
|
public class PresenceSelector {
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ import eu.siacs.conversations.ui.ConversationsActivity;
|
||||||
import eu.siacs.conversations.ui.XmppActivity;
|
import eu.siacs.conversations.ui.XmppActivity;
|
||||||
import eu.siacs.conversations.utils.Patterns;
|
import eu.siacs.conversations.utils.Patterns;
|
||||||
import eu.siacs.conversations.utils.XmppUri;
|
import eu.siacs.conversations.utils.XmppUri;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class ShareUtil {
|
public class ShareUtil {
|
||||||
|
|
||||||
|
|
|
@ -39,9 +39,9 @@ public class AccountUtils {
|
||||||
for (Account account : service.getAccounts()) {
|
for (Account account : service.getAccounts()) {
|
||||||
if (account.getStatus() != Account.State.DISABLED) {
|
if (account.getStatus() != Account.State.DISABLED) {
|
||||||
if (Config.DOMAIN_LOCK != null) {
|
if (Config.DOMAIN_LOCK != null) {
|
||||||
accounts.add(account.getJid().getLocal());
|
accounts.add(account.getJid().toEscapedString());
|
||||||
} else {
|
} else {
|
||||||
accounts.add(account.getJid().asBareJid().toString());
|
accounts.add(account.getJid().asBareJid().toEscapedString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,8 @@ package eu.siacs.conversations.utils;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class BackupFileHeader {
|
public class BackupFileHeader {
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
|
@ -32,7 +31,7 @@ import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Message;
|
import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.http.AesGcmURLStreamHandler;
|
import eu.siacs.conversations.http.AesGcmURLStreamHandler;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public final class CryptoHelper {
|
public final class CryptoHelper {
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ import java.util.regex.Pattern;
|
||||||
|
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.ui.util.StyledAttributes;
|
import eu.siacs.conversations.ui.util.StyledAttributes;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class IrregularUnicodeDetector {
|
public class IrregularUnicodeDetector {
|
||||||
|
|
||||||
|
@ -82,14 +82,14 @@ public class IrregularUnicodeDetector {
|
||||||
private static Spannable style(Jid jid, @ColorInt int color) {
|
private static Spannable style(Jid jid, @ColorInt int color) {
|
||||||
PatternTuple patternTuple = find(jid);
|
PatternTuple patternTuple = find(jid);
|
||||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||||
if (jid.getLocal() != null && patternTuple.local != null) {
|
if (jid.getEscapedLocal() != null && patternTuple.local != null) {
|
||||||
SpannableString local = new SpannableString(jid.getLocal());
|
SpannableString local = new SpannableString(jid.getEscapedLocal());
|
||||||
colorize(local, patternTuple.local, color);
|
colorize(local, patternTuple.local, color);
|
||||||
builder.append(local);
|
builder.append(local);
|
||||||
builder.append('@');
|
builder.append('@');
|
||||||
}
|
}
|
||||||
if (jid.getDomain() != null) {
|
if (jid.getDomain() != null) {
|
||||||
String[] labels = jid.getDomain().split("\\.");
|
String[] labels = jid.getDomain().toEscapedString().split("\\.");
|
||||||
for (int i = 0; i < labels.length; ++i) {
|
for (int i = 0; i < labels.length; ++i) {
|
||||||
SpannableString spannableString = new SpannableString(labels[i]);
|
SpannableString spannableString = new SpannableString(labels[i]);
|
||||||
colorize(spannableString, patternTuple.domain.get(i), color);
|
colorize(spannableString, patternTuple.domain.get(i), color);
|
||||||
|
@ -258,12 +258,12 @@ public class IrregularUnicodeDetector {
|
||||||
|
|
||||||
private static PatternTuple of(Jid jid) {
|
private static PatternTuple of(Jid jid) {
|
||||||
final Pattern localPattern;
|
final Pattern localPattern;
|
||||||
if (jid.getLocal() != null) {
|
if (jid.getEscapedLocal() != null) {
|
||||||
localPattern = create(findIrregularCodePoints(jid.getLocal()));
|
localPattern = create(findIrregularCodePoints(jid.getEscapedLocal()));
|
||||||
} else {
|
} else {
|
||||||
localPattern = null;
|
localPattern = null;
|
||||||
}
|
}
|
||||||
String domain = jid.getDomain();
|
String domain = jid.getDomain().toEscapedString();
|
||||||
final List<Pattern> domainPatterns = new ArrayList<>();
|
final List<Pattern> domainPatterns = new ArrayList<>();
|
||||||
if (domain != null) {
|
if (domain != null) {
|
||||||
for (String label : domain.split("\\.")) {
|
for (String label : domain.split("\\.")) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import eu.siacs.conversations.xmpp.InvalidJid;
|
import eu.siacs.conversations.xmpp.InvalidJid;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class JidHelper {
|
public class JidHelper {
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ public class JidHelper {
|
||||||
|
|
||||||
public static String localPartOrFallback(Jid jid) {
|
public static String localPartOrFallback(Jid jid) {
|
||||||
if (LOCAL_PART_BLACKLIST.contains(jid.getLocal().toLowerCase(Locale.ENGLISH))) {
|
if (LOCAL_PART_BLACKLIST.contains(jid.getLocal().toLowerCase(Locale.ENGLISH))) {
|
||||||
final String domain = jid.getDomain();
|
final String domain = jid.getDomain().toEscapedString();
|
||||||
final int index = domain.indexOf('.');
|
final int index = domain.indexOf('.');
|
||||||
return index > 1 ? domain.substring(0, index) : domain;
|
return index > 1 ? domain.substring(0, index) : domain;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class NickValidityChecker {
|
public class NickValidityChecker {
|
||||||
|
|
||||||
|
|
|
@ -2,19 +2,13 @@ package eu.siacs.conversations.utils;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.ColorInt;
|
import android.support.annotation.ColorInt;
|
||||||
import android.text.SpannableString;
|
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.widget.PopupMenu;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -34,7 +28,7 @@ import eu.siacs.conversations.entities.Presence;
|
||||||
import eu.siacs.conversations.entities.RtpSessionStatus;
|
import eu.siacs.conversations.entities.RtpSessionStatus;
|
||||||
import eu.siacs.conversations.entities.Transferable;
|
import eu.siacs.conversations.entities.Transferable;
|
||||||
import eu.siacs.conversations.services.ExportBackupService;
|
import eu.siacs.conversations.services.ExportBackupService;
|
||||||
import rocks.xmpp.addr.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
|
||||||
public class UIHelper {
|
public class UIHelper {
|
||||||
|
|
||||||
|
@ -526,7 +520,7 @@ public class UIHelper {
|
||||||
return ((Conversation) conversation).getMucOptions().getSelf().getName();
|
return ((Conversation) conversation).getMucOptions().getSelf().getName();
|
||||||
} else {
|
} else {
|
||||||
final Jid jid = conversation.getAccount().getJid();
|
final Jid jid = conversation.getAccount().getJid();
|
||||||
return jid.getLocal() != null ? jid.getLocal() : Jid.ofDomain(jid.getDomain()).toString();
|
return jid.getLocal() != null ? jid.getLocal() : jid.getDomain().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue