@@ -351,6 +351,16 @@ public class IqGenerator extends AbstractGenerator {
return packet;
}
+ public IqPacket requestHttpUploadLegacySlot(Jid host, DownloadableFile file, String mime) {
+ IqPacket packet = new IqPacket(IqPacket.TYPE.GET);
+ packet.setTo(host);
+ Element request = packet.addChild("request", Namespace.HTTP_UPLOAD_LEGACY);
+ request.addChild("filename").setContent(convertFilename(file.getName()));
+ request.addChild("size").setContent(String.valueOf(file.getExpectedSize()));
+ request.addChild("content-type").setContent(mime);
+ return packet;
+ }
+
public IqPacket requestP1S3Slot(Jid host, String md5) {
IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
packet.setTo(host);
@@ -33,14 +33,16 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.xmpp.XmppConnection;
public enum Method {
- P1_S3, HTTP_UPLOAD;
+ P1_S3, HTTP_UPLOAD, HTTP_UPLOAD_LEGACY;
public static Method determine(Account account) {
XmppConnection.Features features = account.getXmppConnection() == null ? null : account.getXmppConnection().getFeatures();
if (features == null) {
return HTTP_UPLOAD;
}
- if (features.httpUpload(0)) {
+ if (features.useLegacyHttpUpload()) {
+ return HTTP_UPLOAD_LEGACY;
+ } else if (features.httpUpload(0)) {
return HTTP_UPLOAD;
} else if (features.p1S3FileTransfer()) {
return P1_S3;
@@ -58,11 +58,42 @@ public class SlotRequester {
if (method == Method.HTTP_UPLOAD) {
Jid host = account.getXmppConnection().findDiscoItemByFeature(Namespace.HTTP_UPLOAD);
requestHttpUpload(account, host, file, mime, callback);
+ } else if (method == Method.HTTP_UPLOAD_LEGACY) {
+ Jid host = account.getXmppConnection().findDiscoItemByFeature(Namespace.HTTP_UPLOAD_LEGACY);
+ requestHttpUploadLegacy(account, host, file, mime, callback);
} else {
requestP1S3(account, Jid.of(account.getServer()), file.getName(), md5, callback);
}
}
+ private void requestHttpUploadLegacy(Account account, Jid host, DownloadableFile file, String mime, OnSlotRequested callback) {
+ IqPacket request = service.getIqGenerator().requestHttpUploadLegacySlot(host, file, mime);
+ service.sendIqPacket(account, request, (a, packet) -> {
+ if (packet.getType() == IqPacket.TYPE.RESULT) {
+ Element slotElement = packet.findChild("slot", Namespace.HTTP_UPLOAD_LEGACY);
+ if (slotElement != null) {
+ try {
+ final String putUrl = slotElement.findChildContent("put");
+ final String getUrl = slotElement.findChildContent("get");
+ if (getUrl != null && putUrl != null) {
+ Slot slot = new Slot(new URL(putUrl));
+ slot.getUrl = new URL(getUrl);
+ slot.headers = new HashMap<>();
+ slot.headers.put("Content-Type", mime == null ? "application/octet-stream" : mime);
+ callback.success(slot);
+ return;
+ }
+ } catch (MalformedURLException e) {
+ //fall through
+ }
+ }
+ }
+ Log.d(Config.LOGTAG, account.getJid().toString() + ": invalid response to slot request " + packet);
+ callback.failure(IqParser.extractErrorMessage(packet));
+ });
+
+ }
+
private void requestHttpUpload(Account account, Jid host, DownloadableFile file, String mime, OnSlotRequested callback) {
IqPacket request = service.getIqGenerator().requestHttpUploadSlot(host, file, mime);
service.sendIqPacket(account, request, (a, packet) -> {
@@ -85,9 +116,9 @@ public class SlotRequester {
if (HttpUploadConnection.WHITE_LISTED_HEADERS.contains(name) && value != null && !value.trim().contains("\n")) {
slot.headers.put(name, value.trim());
}
- slot.headers.put("Content-Type", mime == null ? "application/octet-stream" : mime);
}
}
+ slot.headers.put("Content-Type", mime == null ? "application/octet-stream" : mime);
callback.success(slot);
return;
}
@@ -6,6 +6,7 @@ public final class Namespace {
public static final String REGISTER = "jabber:iq:register";
public static final String BYTE_STREAMS = "http://jabber.org/protocol/bytestreams";
public static final String HTTP_UPLOAD = "urn:xmpp:http:upload:0";
+ public static final String HTTP_UPLOAD_LEGACY = "urn:xmpp:http:upload";
public static final String STANZA_IDS = "urn:xmpp:sid:0";
public static final String MAM = "urn:xmpp:mam:2";
public static final String MAM_LEGACY = "urn:xmpp:mam:0";
@@ -1815,36 +1815,42 @@ public class XmppConnection implements Runnable {
if (Config.DISABLE_HTTP_UPLOAD) {
return false;
} else {
- List<Entry<Jid, ServiceDiscoveryResult>> items = findDiscoItemsByFeature(Namespace.HTTP_UPLOAD);
- if (items.size() > 0) {
- try {
- long maxsize = Long.parseLong(items.get(0).getValue().getExtendedDiscoInformation(Namespace.HTTP_UPLOAD, "max-file-size"));
- if (filesize <= maxsize) {
- return true;
- } else {
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": http upload is not available for files with size " + filesize + " (max is " + maxsize + ")");
- return false;
+ for(String namespace : new String[]{Namespace.HTTP_UPLOAD, Namespace.HTTP_UPLOAD_LEGACY}) {
+ List<Entry<Jid, ServiceDiscoveryResult>> items = findDiscoItemsByFeature(namespace);
+ if (items.size() > 0) {
+ try {
+ long maxsize = Long.parseLong(items.get(0).getValue().getExtendedDiscoInformation(namespace, "max-file-size"));
+ if (filesize <= maxsize) {
+ return true;
+ } else {
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": http upload is not available for files with size " + filesize + " (max is " + maxsize + ")");
+ return false;
+ }
+ } catch (Exception e) {
+ //ignored
}
- } catch (Exception e) {
- return true;
}
- } else {
- return false;
}
+ return false;
}
}
+ public boolean useLegacyHttpUpload() {
+ return findDiscoItemByFeature(Namespace.HTTP_UPLOAD) == null && findDiscoItemByFeature(Namespace.HTTP_UPLOAD_LEGACY) != null;
+ }
+
public long getMaxHttpUploadSize() {
- List<Entry<Jid, ServiceDiscoveryResult>> items = findDiscoItemsByFeature(Namespace.HTTP_UPLOAD);
- if (items.size() > 0) {
- try {
- return Long.parseLong(items.get(0).getValue().getExtendedDiscoInformation(Namespace.HTTP_UPLOAD, "max-file-size"));
- } catch (Exception e) {
- return -1;
+ for(String namespace : new String[]{Namespace.HTTP_UPLOAD, Namespace.HTTP_UPLOAD_LEGACY}) {
+ List<Entry<Jid, ServiceDiscoveryResult>> items = findDiscoItemsByFeature(namespace);
+ if (items.size() > 0) {
+ try {
+ return Long.parseLong(items.get(0).getValue().getExtendedDiscoInformation(namespace, "max-file-size"));
+ } catch (Exception e) {
+ //ignored
+ }
}
- } else {
- return -1;
}
+ return -1;
}
public boolean stanzaIds() {