Merge branch 'feature/http_upload' into development
This commit is contained in:
		
						commit
						ed88b634fc
					
				| @ -32,6 +32,8 @@ public final class Config { | |||||||
| 	public static final boolean EXTENDED_SM_LOGGING = true; // log stanza counts | 	public static final boolean EXTENDED_SM_LOGGING = true; // log stanza counts | ||||||
| 	public static final boolean RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE = true; //setting to true might increase power consumption | 	public static final boolean RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE = true; //setting to true might increase power consumption | ||||||
| 
 | 
 | ||||||
|  | 	public static final boolean ENCRYPT_ON_HTTP_UPLOADED = false; | ||||||
|  | 
 | ||||||
| 	public static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000; | 	public static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000; | ||||||
| 	public static final long MAM_MAX_CATCHUP =  MILLISECONDS_IN_DAY / 2; | 	public static final long MAM_MAX_CATCHUP =  MILLISECONDS_IN_DAY / 2; | ||||||
| 	public static final int MAM_MAX_MESSAGES = 500; | 	public static final int MAM_MAX_MESSAGES = 500; | ||||||
|  | |||||||
| @ -59,7 +59,7 @@ public class PgpEngine { | |||||||
| 								message.setEncryption(Message.ENCRYPTION_DECRYPTED); | 								message.setEncryption(Message.ENCRYPTION_DECRYPTED); | ||||||
| 								final HttpConnectionManager manager = mXmppConnectionService.getHttpConnectionManager(); | 								final HttpConnectionManager manager = mXmppConnectionService.getHttpConnectionManager(); | ||||||
| 								if (message.trusted() | 								if (message.trusted() | ||||||
| 										&& message.bodyContainsDownloadable() | 										&& message.treatAsDownloadable() == Message.Decision.YES | ||||||
| 										&& manager.getAutoAcceptFileSize() > 0) { | 										&& manager.getAutoAcceptFileSize() > 0) { | ||||||
| 									manager.createNewConnection(message); | 									manager.createNewConnection(message); | ||||||
| 								} | 								} | ||||||
| @ -98,7 +98,7 @@ public class PgpEngine { | |||||||
| 						switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, | 						switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, | ||||||
| 								OpenPgpApi.RESULT_CODE_ERROR)) { | 								OpenPgpApi.RESULT_CODE_ERROR)) { | ||||||
| 						case OpenPgpApi.RESULT_CODE_SUCCESS: | 						case OpenPgpApi.RESULT_CODE_SUCCESS: | ||||||
| 							URL url = message.getImageParams().url; | 							URL url = message.getFileParams().url; | ||||||
| 							mXmppConnectionService.getFileBackend().updateFileParams(message,url); | 							mXmppConnectionService.getFileBackend().updateFileParams(message,url); | ||||||
| 							message.setEncryption(Message.ENCRYPTION_DECRYPTED); | 							message.setEncryption(Message.ENCRYPTION_DECRYPTED); | ||||||
| 							PgpEngine.this.mXmppConnectionService | 							PgpEngine.this.mXmppConnectionService | ||||||
| @ -143,11 +143,15 @@ public class PgpEngine { | |||||||
| 		params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, message | 		params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, message | ||||||
| 				.getConversation().getAccount().getJid().toBareJid().toString()); | 				.getConversation().getAccount().getJid().toBareJid().toString()); | ||||||
| 
 | 
 | ||||||
| 		if (message.getType() == Message.TYPE_TEXT) { | 		if (!message.needsUploading()) { | ||||||
| 			params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); | 			params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); | ||||||
| 
 | 			String body; | ||||||
| 			InputStream is = new ByteArrayInputStream(message.getBody() | 			if (message.hasFileOnRemoteHost()) { | ||||||
| 					.getBytes()); | 				body = message.getFileParams().url.toString(); | ||||||
|  | 			} else { | ||||||
|  | 				body = message.getBody(); | ||||||
|  | 			} | ||||||
|  | 			InputStream is = new ByteArrayInputStream(body.getBytes()); | ||||||
| 			final OutputStream os = new ByteArrayOutputStream(); | 			final OutputStream os = new ByteArrayOutputStream(); | ||||||
| 			api.executeApiAsync(params, is, os, new IOpenPgpCallback() { | 			api.executeApiAsync(params, is, os, new IOpenPgpCallback() { | ||||||
| 
 | 
 | ||||||
| @ -184,7 +188,7 @@ public class PgpEngine { | |||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			}); | 			}); | ||||||
| 		} else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) { | 		} else { | ||||||
| 			try { | 			try { | ||||||
| 				DownloadableFile inputFile = this.mXmppConnectionService | 				DownloadableFile inputFile = this.mXmppConnectionService | ||||||
| 						.getFileBackend().getFile(message, true); | 						.getFileBackend().getFile(message, true); | ||||||
|  | |||||||
| @ -44,6 +44,10 @@ public class Account extends AbstractEntity { | |||||||
| 	public static final int OPTION_REGISTER = 2; | 	public static final int OPTION_REGISTER = 2; | ||||||
| 	public static final int OPTION_USECOMPRESSION = 3; | 	public static final int OPTION_USECOMPRESSION = 3; | ||||||
| 
 | 
 | ||||||
|  | 	public boolean httpUploadAvailable() { | ||||||
|  | 		return xmppConnection != null && xmppConnection.getFeatures().httpUpload(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public static enum State { | 	public static enum State { | ||||||
| 		DISABLED, | 		DISABLED, | ||||||
| 		OFFLINE, | 		OFFLINE, | ||||||
|  | |||||||
| @ -2,27 +2,25 @@ package eu.siacs.conversations.entities; | |||||||
| 
 | 
 | ||||||
| public interface Downloadable { | public interface Downloadable { | ||||||
| 
 | 
 | ||||||
| 	public final String[] VALID_IMAGE_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; | 	String[] VALID_IMAGE_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; | ||||||
| 	public final String[] VALID_CRYPTO_EXTENSIONS = {"pgp", "gpg", "otr"}; | 	String[] VALID_CRYPTO_EXTENSIONS = {"pgp", "gpg", "otr"}; | ||||||
| 
 | 
 | ||||||
| 	public static final int STATUS_UNKNOWN = 0x200; | 	int STATUS_UNKNOWN = 0x200; | ||||||
| 	public static final int STATUS_CHECKING = 0x201; | 	int STATUS_CHECKING = 0x201; | ||||||
| 	public static final int STATUS_FAILED = 0x202; | 	int STATUS_FAILED = 0x202; | ||||||
| 	public static final int STATUS_OFFER = 0x203; | 	int STATUS_OFFER = 0x203; | ||||||
| 	public static final int STATUS_DOWNLOADING = 0x204; | 	int STATUS_DOWNLOADING = 0x204; | ||||||
| 	public static final int STATUS_DELETED = 0x205; | 	int STATUS_DELETED = 0x205; | ||||||
| 	public static final int STATUS_OFFER_CHECK_FILESIZE = 0x206; | 	int STATUS_OFFER_CHECK_FILESIZE = 0x206; | ||||||
| 	public static final int STATUS_UPLOADING = 0x207; | 	int STATUS_UPLOADING = 0x207; | ||||||
| 
 | 
 | ||||||
| 	public boolean start(); | 	boolean start(); | ||||||
| 
 | 
 | ||||||
| 	public int getStatus(); | 	int getStatus(); | ||||||
| 
 | 
 | ||||||
| 	public long getFileSize(); | 	long getFileSize(); | ||||||
| 
 | 
 | ||||||
| 	public int getProgress(); | 	int getProgress(); | ||||||
| 
 | 
 | ||||||
| 	public String getMimeType(); | 	void cancel(); | ||||||
| 
 |  | ||||||
| 	public void cancel(); |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -27,11 +27,6 @@ public class DownloadablePlaceholder implements Downloadable { | |||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override |  | ||||||
| 	public String getMimeType() { |  | ||||||
| 		return ""; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public void cancel() { | 	public void cancel() { | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -375,8 +375,8 @@ public class Message extends AbstractEntity { | |||||||
| 						(message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) && | 						(message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) && | ||||||
| 						!GeoHelper.isGeoUri(message.getBody()) && | 						!GeoHelper.isGeoUri(message.getBody()) && | ||||||
| 						!GeoHelper.isGeoUri(this.body) && | 						!GeoHelper.isGeoUri(this.body) && | ||||||
| 						!message.bodyContainsDownloadable() && | 						message.treatAsDownloadable() == Decision.NO && | ||||||
| 						!this.bodyContainsDownloadable() && | 						this.treatAsDownloadable() == Decision.NO && | ||||||
| 						!message.getBody().startsWith(ME_COMMAND) && | 						!message.getBody().startsWith(ME_COMMAND) && | ||||||
| 						!this.getBody().startsWith(ME_COMMAND) && | 						!this.getBody().startsWith(ME_COMMAND) && | ||||||
| 						!this.bodyIsHeart() && | 						!this.bodyIsHeart() && | ||||||
| @ -434,48 +434,50 @@ public class Message extends AbstractEntity { | |||||||
| 		return (status > STATUS_RECEIVED || (contact != null && contact.trusted())); | 		return (status > STATUS_RECEIVED || (contact != null && contact.trusted())); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public boolean bodyContainsDownloadable() { | 	public enum Decision { | ||||||
| 		/** | 		YES, | ||||||
| 		 * there are a few cases where spaces result in an unwanted behavior, e.g. | 		NO, | ||||||
| 		 * "http://example.com/image.jpg text that will not be shown /abc.png" | 		ASK | ||||||
| 		 * or more than one image link in one message. | 	} | ||||||
| 		 */ | 
 | ||||||
|  | 	public Decision treatAsDownloadable() { | ||||||
| 		if (body.trim().contains(" ")) { | 		if (body.trim().contains(" ")) { | ||||||
| 			return false; | 			return Decision.NO; | ||||||
| 		} | 		} | ||||||
| 		try { | 		try { | ||||||
| 			URL url = new URL(body); | 			URL url = new URL(body); | ||||||
| 			if (!url.getProtocol().equalsIgnoreCase("http") | 			if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) { | ||||||
| 					&& !url.getProtocol().equalsIgnoreCase("https")) { | 				return Decision.NO; | ||||||
| 				return false; | 			} | ||||||
|  | 			String path = url.getPath(); | ||||||
|  | 			if (path == null || path.isEmpty()) { | ||||||
|  | 				return Decision.NO; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			String sUrlPath = url.getPath(); | 			String filename = path.substring(path.lastIndexOf('/') + 1).toLowerCase(); | ||||||
| 			if (sUrlPath == null || sUrlPath.isEmpty()) { | 			String[] extensionParts = filename.split("\\."); | ||||||
| 				return false; | 			String extension; | ||||||
| 			} | 			String ref = url.getRef(); | ||||||
| 
 | 			if (extensionParts.length == 2) { | ||||||
| 			int iSlashIndex = sUrlPath.lastIndexOf('/') + 1; | 				extension = extensionParts[extensionParts.length - 1]; | ||||||
| 
 | 			} else if (extensionParts.length == 3 && Arrays | ||||||
| 			String sLastUrlPath = sUrlPath.substring(iSlashIndex).toLowerCase(); |  | ||||||
| 
 |  | ||||||
| 			String[] extensionParts = sLastUrlPath.split("\\."); |  | ||||||
| 			if (extensionParts.length == 2 |  | ||||||
| 					&& Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains( |  | ||||||
| 					extensionParts[extensionParts.length - 1])) { |  | ||||||
| 				return true; |  | ||||||
| 			} else if (extensionParts.length == 3 |  | ||||||
| 					&& Arrays |  | ||||||
| 					.asList(Downloadable.VALID_CRYPTO_EXTENSIONS) | 					.asList(Downloadable.VALID_CRYPTO_EXTENSIONS) | ||||||
| 					.contains(extensionParts[extensionParts.length - 1]) | 					.contains(extensionParts[extensionParts.length - 1])) { | ||||||
| 					&& Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains( | 				extension = extensionParts[extensionParts.length -2]; | ||||||
| 					extensionParts[extensionParts.length - 2])) { |  | ||||||
| 				return true; |  | ||||||
| 			} else { | 			} else { | ||||||
| 				return false; | 				return Decision.NO; | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
|  | 			if (Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains(extension)) { | ||||||
|  | 				return Decision.YES; | ||||||
|  | 			} else if (ref != null && ref.matches("([A-Fa-f0-9]{2}){48}")) { | ||||||
|  | 				return Decision.ASK; | ||||||
|  | 			} else { | ||||||
|  | 				return Decision.NO; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 		} catch (MalformedURLException e) { | 		} catch (MalformedURLException e) { | ||||||
| 			return false; | 			return Decision.NO; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -483,12 +485,12 @@ public class Message extends AbstractEntity { | |||||||
| 		return body != null && UIHelper.HEARTS.contains(body.trim()); | 		return body != null && UIHelper.HEARTS.contains(body.trim()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public ImageParams getImageParams() { | 	public FileParams getFileParams() { | ||||||
| 		ImageParams params = getLegacyImageParams(); | 		FileParams params = getLegacyFileParams(); | ||||||
| 		if (params != null) { | 		if (params != null) { | ||||||
| 			return params; | 			return params; | ||||||
| 		} | 		} | ||||||
| 		params = new ImageParams(); | 		params = new FileParams(); | ||||||
| 		if (this.downloadable != null) { | 		if (this.downloadable != null) { | ||||||
| 			params.size = this.downloadable.getFileSize(); | 			params.size = this.downloadable.getFileSize(); | ||||||
| 		} | 		} | ||||||
| @ -496,18 +498,42 @@ public class Message extends AbstractEntity { | |||||||
| 			return params; | 			return params; | ||||||
| 		} | 		} | ||||||
| 		String parts[] = body.split("\\|"); | 		String parts[] = body.split("\\|"); | ||||||
| 		if (parts.length == 1) { | 		switch (parts.length) { | ||||||
|  | 			case 1: | ||||||
| 				try { | 				try { | ||||||
| 					params.size = Long.parseLong(parts[0]); | 					params.size = Long.parseLong(parts[0]); | ||||||
| 				} catch (NumberFormatException e) { | 				} catch (NumberFormatException e) { | ||||||
| 				params.origin = parts[0]; |  | ||||||
| 					try { | 					try { | ||||||
| 						params.url = new URL(parts[0]); | 						params.url = new URL(parts[0]); | ||||||
| 					} catch (MalformedURLException e1) { | 					} catch (MalformedURLException e1) { | ||||||
| 						params.url = null; | 						params.url = null; | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 		} else if (parts.length == 3) { | 				break; | ||||||
|  | 			case 2: | ||||||
|  | 			case 4: | ||||||
|  | 				try { | ||||||
|  | 					params.url = new URL(parts[0]); | ||||||
|  | 				} catch (MalformedURLException e1) { | ||||||
|  | 					params.url = null; | ||||||
|  | 				} | ||||||
|  | 				try { | ||||||
|  | 					params.size = Long.parseLong(parts[1]); | ||||||
|  | 				} catch (NumberFormatException e) { | ||||||
|  | 					params.size = 0; | ||||||
|  | 				} | ||||||
|  | 				try { | ||||||
|  | 					params.width = Integer.parseInt(parts[2]); | ||||||
|  | 				} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { | ||||||
|  | 					params.width = 0; | ||||||
|  | 				} | ||||||
|  | 				try { | ||||||
|  | 					params.height = Integer.parseInt(parts[3]); | ||||||
|  | 				} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { | ||||||
|  | 					params.height = 0; | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 			case 3: | ||||||
| 				try { | 				try { | ||||||
| 					params.size = Long.parseLong(parts[0]); | 					params.size = Long.parseLong(parts[0]); | ||||||
| 				} catch (NumberFormatException e) { | 				} catch (NumberFormatException e) { | ||||||
| @ -523,34 +549,13 @@ public class Message extends AbstractEntity { | |||||||
| 				} catch (NumberFormatException e) { | 				} catch (NumberFormatException e) { | ||||||
| 					params.height = 0; | 					params.height = 0; | ||||||
| 				} | 				} | ||||||
| 		} else if (parts.length == 4) { | 				break; | ||||||
| 			params.origin = parts[0]; |  | ||||||
| 			try { |  | ||||||
| 				params.url = new URL(parts[0]); |  | ||||||
| 			} catch (MalformedURLException e1) { |  | ||||||
| 				params.url = null; |  | ||||||
| 			} |  | ||||||
| 			try { |  | ||||||
| 				params.size = Long.parseLong(parts[1]); |  | ||||||
| 			} catch (NumberFormatException e) { |  | ||||||
| 				params.size = 0; |  | ||||||
| 			} |  | ||||||
| 			try { |  | ||||||
| 				params.width = Integer.parseInt(parts[2]); |  | ||||||
| 			} catch (NumberFormatException e) { |  | ||||||
| 				params.width = 0; |  | ||||||
| 			} |  | ||||||
| 			try { |  | ||||||
| 				params.height = Integer.parseInt(parts[3]); |  | ||||||
| 			} catch (NumberFormatException e) { |  | ||||||
| 				params.height = 0; |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		return params; | 		return params; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public ImageParams getLegacyImageParams() { | 	public FileParams getLegacyFileParams() { | ||||||
| 		ImageParams params = new ImageParams(); | 		FileParams params = new FileParams(); | ||||||
| 		if (body == null) { | 		if (body == null) { | ||||||
| 			return params; | 			return params; | ||||||
| 		} | 		} | ||||||
| @ -586,11 +591,18 @@ public class Message extends AbstractEntity { | |||||||
| 		return type == TYPE_FILE || type == TYPE_IMAGE; | 		return type == TYPE_FILE || type == TYPE_IMAGE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public class ImageParams { | 	public boolean hasFileOnRemoteHost() { | ||||||
|  | 		return isFileOrImage() && getFileParams().url != null; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public boolean needsUploading() { | ||||||
|  | 		return isFileOrImage() && getFileParams().url == null; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public class FileParams { | ||||||
| 		public URL url; | 		public URL url; | ||||||
| 		public long size = 0; | 		public long size = 0; | ||||||
| 		public int width = 0; | 		public int width = 0; | ||||||
| 		public int height = 0; | 		public int height = 0; | ||||||
| 		public String origin; |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ import java.util.List; | |||||||
| 
 | 
 | ||||||
| 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.entities.DownloadableFile; | ||||||
| import eu.siacs.conversations.services.MessageArchiveService; | import eu.siacs.conversations.services.MessageArchiveService; | ||||||
| import eu.siacs.conversations.services.XmppConnectionService; | import eu.siacs.conversations.services.XmppConnectionService; | ||||||
| import eu.siacs.conversations.utils.PhoneHelper; | import eu.siacs.conversations.utils.PhoneHelper; | ||||||
| @ -194,4 +195,13 @@ public class IqGenerator extends AbstractGenerator { | |||||||
| 		item.setAttribute("role", role); | 		item.setAttribute("role", role); | ||||||
| 		return packet; | 		return packet; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	public IqPacket requestHttpUploadSlot(Jid host, DownloadableFile file) { | ||||||
|  | 		IqPacket packet = new IqPacket(IqPacket.TYPE.GET); | ||||||
|  | 		packet.setTo(host); | ||||||
|  | 		Element request = packet.addChild("request",Xmlns.HTTP_UPLOAD); | ||||||
|  | 		request.addChild("filename").setContent(file.getName()); | ||||||
|  | 		request.addChild("size").setContent(String.valueOf(file.getExpectedSize())); | ||||||
|  | 		return packet; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -73,7 +73,13 @@ public class MessageGenerator extends AbstractGenerator { | |||||||
| 		packet.addChild("no-copy", "urn:xmpp:hints"); | 		packet.addChild("no-copy", "urn:xmpp:hints"); | ||||||
| 		packet.addChild("no-permanent-store", "urn:xmpp:hints"); | 		packet.addChild("no-permanent-store", "urn:xmpp:hints"); | ||||||
| 		try { | 		try { | ||||||
| 			packet.setBody(otrSession.transformSending(message.getBody())[0]); | 			String content; | ||||||
|  | 			if (message.hasFileOnRemoteHost()) { | ||||||
|  | 				content = message.getFileParams().url.toString(); | ||||||
|  | 			} else { | ||||||
|  | 				content = message.getBody(); | ||||||
|  | 			} | ||||||
|  | 			packet.setBody(otrSession.transformSending(content)[0]); | ||||||
| 			return packet; | 			return packet; | ||||||
| 		} catch (OtrException e) { | 		} catch (OtrException e) { | ||||||
| 			return null; | 			return null; | ||||||
| @ -86,7 +92,11 @@ public class MessageGenerator extends AbstractGenerator { | |||||||
| 
 | 
 | ||||||
| 	public MessagePacket generateChat(Message message, boolean addDelay) { | 	public MessagePacket generateChat(Message message, boolean addDelay) { | ||||||
| 		MessagePacket packet = preparePacket(message, addDelay); | 		MessagePacket packet = preparePacket(message, addDelay); | ||||||
|  | 		if (message.hasFileOnRemoteHost()) { | ||||||
|  | 			packet.setBody(message.getFileParams().url.toString()); | ||||||
|  | 		} else { | ||||||
| 			packet.setBody(message.getBody()); | 			packet.setBody(message.getBody()); | ||||||
|  | 		} | ||||||
| 		return packet; | 		return packet; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -96,13 +106,11 @@ public class MessageGenerator extends AbstractGenerator { | |||||||
| 
 | 
 | ||||||
| 	public MessagePacket generatePgpChat(Message message, boolean addDelay) { | 	public MessagePacket generatePgpChat(Message message, boolean addDelay) { | ||||||
| 		MessagePacket packet = preparePacket(message, addDelay); | 		MessagePacket packet = preparePacket(message, addDelay); | ||||||
| 		packet.setBody("This is an XEP-0027 encryted message"); | 		packet.setBody("This is an XEP-0027 encrypted message"); | ||||||
| 		if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { | 		if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { | ||||||
| 			packet.addChild("x", "jabber:x:encrypted").setContent( | 			packet.addChild("x", "jabber:x:encrypted").setContent(message.getEncryptedBody()); | ||||||
| 					message.getEncryptedBody()); |  | ||||||
| 		} else if (message.getEncryption() == Message.ENCRYPTION_PGP) { | 		} else if (message.getEncryption() == Message.ENCRYPTION_PGP) { | ||||||
| 			packet.addChild("x", "jabber:x:encrypted").setContent( | 			packet.addChild("x", "jabber:x:encrypted").setContent(message.getBody()); | ||||||
| 					message.getBody()); |  | ||||||
| 		} | 		} | ||||||
| 		return packet; | 		return packet; | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -269,7 +269,7 @@ public class HttpConnection implements Downloadable { | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		private void updateImageBounds() { | 		private void updateImageBounds() { | ||||||
| 			message.setType(Message.TYPE_IMAGE); | 			message.setType(Message.TYPE_FILE); | ||||||
| 			mXmppConnectionService.getFileBackend().updateFileParams(message, mUrl); | 			mXmppConnectionService.getFileBackend().updateFileParams(message, mUrl); | ||||||
| 			mXmppConnectionService.updateMessage(message); | 			mXmppConnectionService.updateMessage(message); | ||||||
| 		} | 		} | ||||||
| @ -302,9 +302,4 @@ public class HttpConnection implements Downloadable { | |||||||
| 	public int getProgress() { | 	public int getProgress() { | ||||||
| 		return this.mProgress; | 		return this.mProgress; | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public String getMimeType() { |  | ||||||
| 		return ""; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -13,7 +13,8 @@ public class HttpConnectionManager extends AbstractConnectionManager { | |||||||
| 		super(service); | 		super(service); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private List<HttpConnection> connections = new CopyOnWriteArrayList<HttpConnection>(); | 	private List<HttpConnection> connections = new CopyOnWriteArrayList<>(); | ||||||
|  | 	private List<HttpUploadConnection> uploadConnections = new CopyOnWriteArrayList<>(); | ||||||
| 
 | 
 | ||||||
| 	public HttpConnection createNewConnection(Message message) { | 	public HttpConnection createNewConnection(Message message) { | ||||||
| 		HttpConnection connection = new HttpConnection(this); | 		HttpConnection connection = new HttpConnection(this); | ||||||
| @ -22,7 +23,18 @@ public class HttpConnectionManager extends AbstractConnectionManager { | |||||||
| 		return connection; | 		return connection; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	public HttpUploadConnection createNewUploadConnection(Message message) { | ||||||
|  | 		HttpUploadConnection connection = new HttpUploadConnection(this); | ||||||
|  | 		connection.init(message); | ||||||
|  | 		this.uploadConnections.add(connection); | ||||||
|  | 		return connection; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public void finishConnection(HttpConnection connection) { | 	public void finishConnection(HttpConnection connection) { | ||||||
| 		this.connections.remove(connection); | 		this.connections.remove(connection); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	public void finishUploadConnection(HttpUploadConnection httpUploadConnection) { | ||||||
|  | 		this.uploadConnections.remove(httpUploadConnection); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,199 @@ | |||||||
|  | package eu.siacs.conversations.http; | ||||||
|  | 
 | ||||||
|  | import android.app.PendingIntent; | ||||||
|  | import android.util.Log; | ||||||
|  | 
 | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.io.OutputStream; | ||||||
|  | import java.net.HttpURLConnection; | ||||||
|  | import java.net.MalformedURLException; | ||||||
|  | import java.net.URL; | ||||||
|  | 
 | ||||||
|  | import eu.siacs.conversations.Config; | ||||||
|  | import eu.siacs.conversations.entities.Account; | ||||||
|  | import eu.siacs.conversations.entities.Downloadable; | ||||||
|  | import eu.siacs.conversations.entities.DownloadableFile; | ||||||
|  | import eu.siacs.conversations.entities.Message; | ||||||
|  | import eu.siacs.conversations.persistance.FileBackend; | ||||||
|  | import eu.siacs.conversations.services.XmppConnectionService; | ||||||
|  | import eu.siacs.conversations.ui.UiCallback; | ||||||
|  | import eu.siacs.conversations.utils.CryptoHelper; | ||||||
|  | import eu.siacs.conversations.utils.Xmlns; | ||||||
|  | import eu.siacs.conversations.xml.Element; | ||||||
|  | import eu.siacs.conversations.xmpp.OnIqPacketReceived; | ||||||
|  | import eu.siacs.conversations.xmpp.jid.Jid; | ||||||
|  | import eu.siacs.conversations.xmpp.stanzas.IqPacket; | ||||||
|  | 
 | ||||||
|  | public class HttpUploadConnection implements Downloadable { | ||||||
|  | 
 | ||||||
|  | 	private HttpConnectionManager mHttpConnectionManager; | ||||||
|  | 	private XmppConnectionService mXmppConnectionService; | ||||||
|  | 
 | ||||||
|  | 	private boolean canceled = false; | ||||||
|  | 	private Account account; | ||||||
|  | 	private DownloadableFile file; | ||||||
|  | 	private Message message; | ||||||
|  | 	private URL mGetUrl; | ||||||
|  | 	private URL mPutUrl; | ||||||
|  | 
 | ||||||
|  | 	private byte[] key = null; | ||||||
|  | 
 | ||||||
|  | 	private long transmitted = 0; | ||||||
|  | 	private long expected = 1; | ||||||
|  | 
 | ||||||
|  | 	public HttpUploadConnection(HttpConnectionManager httpConnectionManager) { | ||||||
|  | 		this.mHttpConnectionManager = httpConnectionManager; | ||||||
|  | 		this.mXmppConnectionService = httpConnectionManager.getXmppConnectionService(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public boolean start() { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public int getStatus() { | ||||||
|  | 		return STATUS_UPLOADING; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public long getFileSize() { | ||||||
|  | 		return this.file.getExpectedSize(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public int getProgress() { | ||||||
|  | 		return (int) ((((double) transmitted) / expected) * 100); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void cancel() { | ||||||
|  | 		this.canceled = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private void fail() { | ||||||
|  | 		mHttpConnectionManager.finishUploadConnection(this); | ||||||
|  | 		message.setDownloadable(null); | ||||||
|  | 		mXmppConnectionService.markMessage(message,Message.STATUS_SEND_FAILED); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void init(Message message) { | ||||||
|  | 		this.message = message; | ||||||
|  | 		message.setDownloadable(this); | ||||||
|  | 		mXmppConnectionService.markMessage(message,Message.STATUS_UNSEND); | ||||||
|  | 		this.account = message.getConversation().getAccount(); | ||||||
|  | 		this.file = mXmppConnectionService.getFileBackend().getFile(message, false); | ||||||
|  | 		this.file.setExpectedSize(this.file.getSize()); | ||||||
|  | 
 | ||||||
|  | 		if (Config.ENCRYPT_ON_HTTP_UPLOADED) { | ||||||
|  | 			this.key = new byte[48]; | ||||||
|  | 			mXmppConnectionService.getRNG().nextBytes(this.key); | ||||||
|  | 			this.file.setKey(this.key); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		Jid host = account.getXmppConnection().findDiscoItemByFeature(Xmlns.HTTP_UPLOAD); | ||||||
|  | 		IqPacket request = mXmppConnectionService.getIqGenerator().requestHttpUploadSlot(host,file); | ||||||
|  | 		mXmppConnectionService.sendIqPacket(account, request, new OnIqPacketReceived() { | ||||||
|  | 			@Override | ||||||
|  | 			public void onIqPacketReceived(Account account, IqPacket packet) { | ||||||
|  | 				if (packet.getType() == IqPacket.TYPE.RESULT) { | ||||||
|  | 					Element slot = packet.findChild("slot",Xmlns.HTTP_UPLOAD); | ||||||
|  | 					if (slot != null) { | ||||||
|  | 						try { | ||||||
|  | 							mGetUrl = new URL(slot.findChildContent("get")); | ||||||
|  | 							mPutUrl = new URL(slot.findChildContent("put")); | ||||||
|  | 							if (!canceled) { | ||||||
|  | 								new Thread(new FileUploader()).start(); | ||||||
|  | 							} | ||||||
|  | 						} catch (MalformedURLException e) { | ||||||
|  | 							fail(); | ||||||
|  | 						} | ||||||
|  | 					} else { | ||||||
|  | 						fail(); | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					fail(); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private class FileUploader implements Runnable { | ||||||
|  | 
 | ||||||
|  | 		@Override | ||||||
|  | 		public void run() { | ||||||
|  | 			this.upload(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		private void upload() { | ||||||
|  | 			OutputStream os = null; | ||||||
|  | 			InputStream is = null; | ||||||
|  | 			HttpURLConnection connection = null; | ||||||
|  | 			try { | ||||||
|  | 				Log.d(Config.LOGTAG, "uploading to " + mPutUrl.toString()); | ||||||
|  | 				connection = (HttpURLConnection) mPutUrl.openConnection(); | ||||||
|  | 				connection.setRequestMethod("PUT"); | ||||||
|  | 				connection.setFixedLengthStreamingMode((int) file.getExpectedSize()); | ||||||
|  | 				connection.setDoOutput(true); | ||||||
|  | 				connection.connect(); | ||||||
|  | 				os = connection.getOutputStream(); | ||||||
|  | 				is = file.createInputStream(); | ||||||
|  | 				transmitted = 0; | ||||||
|  | 				expected = file.getExpectedSize(); | ||||||
|  | 				int count = -1; | ||||||
|  | 				byte[] buffer = new byte[4096]; | ||||||
|  | 				while (((count = is.read(buffer)) != -1) && !canceled) { | ||||||
|  | 					transmitted += count; | ||||||
|  | 					os.write(buffer, 0, count); | ||||||
|  | 					mXmppConnectionService.updateConversationUi(); | ||||||
|  | 				} | ||||||
|  | 				os.flush(); | ||||||
|  | 				os.close(); | ||||||
|  | 				is.close(); | ||||||
|  | 				int code = connection.getResponseCode(); | ||||||
|  | 				if (code == 200) { | ||||||
|  | 					Log.d(Config.LOGTAG, "finished uploading file"); | ||||||
|  | 					Message.FileParams params = message.getFileParams(); | ||||||
|  | 					if (key != null) { | ||||||
|  | 						mGetUrl = new URL(mGetUrl.toString() + "#" + CryptoHelper.bytesToHex(key)); | ||||||
|  | 					} | ||||||
|  | 					mXmppConnectionService.getFileBackend().updateFileParams(message, mGetUrl); | ||||||
|  | 					message.setDownloadable(null); | ||||||
|  | 					message.setCounterpart(message.getConversation().getJid().toBareJid()); | ||||||
|  | 					if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { | ||||||
|  | 						mXmppConnectionService.getPgpEngine().encrypt(message, new UiCallback<Message>() { | ||||||
|  | 							@Override | ||||||
|  | 							public void success(Message message) { | ||||||
|  | 								mXmppConnectionService.resendMessage(message); | ||||||
|  | 							} | ||||||
|  | 
 | ||||||
|  | 							@Override | ||||||
|  | 							public void error(int errorCode, Message object) { | ||||||
|  | 								fail(); | ||||||
|  | 							} | ||||||
|  | 
 | ||||||
|  | 							@Override | ||||||
|  | 							public void userInputRequried(PendingIntent pi, Message object) { | ||||||
|  | 								fail(); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} else { | ||||||
|  | 						mXmppConnectionService.resendMessage(message); | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					fail(); | ||||||
|  | 				} | ||||||
|  | 			} catch (IOException e) { | ||||||
|  | 				Log.d(Config.LOGTAG, e.getMessage()); | ||||||
|  | 				fail(); | ||||||
|  | 			} finally { | ||||||
|  | 				FileBackend.close(is); | ||||||
|  | 				FileBackend.close(os); | ||||||
|  | 				if (connection != null) { | ||||||
|  | 					connection.disconnect(); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -360,7 +360,7 @@ public class MessageParser extends AbstractParser implements | |||||||
| 				mXmppConnectionService.databaseBackend.createMessage(message); | 				mXmppConnectionService.databaseBackend.createMessage(message); | ||||||
| 			} | 			} | ||||||
| 			final HttpConnectionManager manager = this.mXmppConnectionService.getHttpConnectionManager(); | 			final HttpConnectionManager manager = this.mXmppConnectionService.getHttpConnectionManager(); | ||||||
| 			if (message.trusted() && message.bodyContainsDownloadable() && manager.getAutoAcceptFileSize() > 0) { | 			if (message.trusted() && message.treatAsDownloadable() == Message.Decision.YES && manager.getAutoAcceptFileSize() > 0) { | ||||||
| 				manager.createNewConnection(message); | 				manager.createNewConnection(message); | ||||||
| 			} else if (!message.isRead()) { | 			} else if (!message.isRead()) { | ||||||
| 				mXmppConnectionService.getNotificationService().push(message); | 				mXmppConnectionService.getNotificationService().push(message); | ||||||
|  | |||||||
| @ -13,6 +13,7 @@ import java.security.DigestOutputStream; | |||||||
| import java.security.MessageDigest; | import java.security.MessageDigest; | ||||||
| import java.security.NoSuchAlgorithmException; | import java.security.NoSuchAlgorithmException; | ||||||
| import java.text.SimpleDateFormat; | import java.text.SimpleDateFormat; | ||||||
|  | import java.util.Arrays; | ||||||
| import java.util.Date; | import java.util.Date; | ||||||
| import java.util.Locale; | import java.util.Locale; | ||||||
| 
 | 
 | ||||||
| @ -32,6 +33,7 @@ import android.webkit.MimeTypeMap; | |||||||
| 
 | 
 | ||||||
| import eu.siacs.conversations.Config; | import eu.siacs.conversations.Config; | ||||||
| import eu.siacs.conversations.R; | import eu.siacs.conversations.R; | ||||||
|  | import eu.siacs.conversations.entities.Downloadable; | ||||||
| import eu.siacs.conversations.entities.DownloadableFile; | import eu.siacs.conversations.entities.DownloadableFile; | ||||||
| import eu.siacs.conversations.entities.Message; | import eu.siacs.conversations.entities.Message; | ||||||
| import eu.siacs.conversations.services.XmppConnectionService; | import eu.siacs.conversations.services.XmppConnectionService; | ||||||
| @ -78,7 +80,7 @@ public class FileBackend { | |||||||
| 			if (path.startsWith("/")) { | 			if (path.startsWith("/")) { | ||||||
| 				return new DownloadableFile(path); | 				return new DownloadableFile(path); | ||||||
| 			} else { | 			} else { | ||||||
| 				if (message.getType() == Message.TYPE_FILE) { | 				if (Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains(extension)) { | ||||||
| 					return new DownloadableFile(getConversationsFileDirectory() + path); | 					return new DownloadableFile(getConversationsFileDirectory() + path); | ||||||
| 				} else { | 				} else { | ||||||
| 					return new DownloadableFile(getConversationsImageDirectory() + path); | 					return new DownloadableFile(getConversationsImageDirectory() + path); | ||||||
| @ -217,7 +219,7 @@ public class FileBackend { | |||||||
| 			long size = file.getSize(); | 			long size = file.getSize(); | ||||||
| 			int width = scaledBitmap.getWidth(); | 			int width = scaledBitmap.getWidth(); | ||||||
| 			int height = scaledBitmap.getHeight(); | 			int height = scaledBitmap.getHeight(); | ||||||
| 			message.setBody(Long.toString(size) + ',' + width + ',' + height); | 			message.setBody(Long.toString(size) + '|' + width + '|' + height); | ||||||
| 			return file; | 			return file; | ||||||
| 		} catch (FileNotFoundException e) { | 		} catch (FileNotFoundException e) { | ||||||
| 			throw new FileCopyException(R.string.error_file_not_found); | 			throw new FileCopyException(R.string.error_file_not_found); | ||||||
| @ -496,9 +498,13 @@ public class FileBackend { | |||||||
| 			} else { | 			} else { | ||||||
| 				message.setBody(url.toString()+"|"+Long.toString(file.getSize()) + '|' + imageWidth + '|' + imageHeight); | 				message.setBody(url.toString()+"|"+Long.toString(file.getSize()) + '|' + imageWidth + '|' + imageHeight); | ||||||
| 			} | 			} | ||||||
|  | 		} else { | ||||||
|  | 			if (url != null) { | ||||||
|  | 				message.setBody(url.toString()+"|"+Long.toString(file.getSize())); | ||||||
| 			} else { | 			} else { | ||||||
| 				message.setBody(Long.toString(file.getSize())); | 				message.setBody(Long.toString(file.getSize())); | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -671,6 +671,17 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	private void sendFileMessage(final Message message) { | ||||||
|  | 		Log.d(Config.LOGTAG, "send file message"); | ||||||
|  | 		final Account account = message.getConversation().getAccount(); | ||||||
|  | 		final XmppConnection connection = account.getXmppConnection(); | ||||||
|  | 		if (connection != null && connection.getFeatures().httpUpload()) { | ||||||
|  | 			mHttpConnectionManager.createNewUploadConnection(message); | ||||||
|  | 		} else { | ||||||
|  | 			mJingleConnectionManager.createNewConnection(message); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public void sendMessage(final Message message) { | 	public void sendMessage(final Message message) { | ||||||
| 		final Account account = message.getConversation().getAccount(); | 		final Account account = message.getConversation().getAccount(); | ||||||
| 		account.deactivateGracePeriod(); | 		account.deactivateGracePeriod(); | ||||||
| @ -680,19 +691,19 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa | |||||||
| 		boolean send = false; | 		boolean send = false; | ||||||
| 		if (account.getStatus() == Account.State.ONLINE | 		if (account.getStatus() == Account.State.ONLINE | ||||||
| 				&& account.getXmppConnection() != null) { | 				&& account.getXmppConnection() != null) { | ||||||
| 			if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) { | 			if (message.needsUploading()) { | ||||||
| 				if (message.getCounterpart() != null) { | 				if (message.getCounterpart() != null || account.httpUploadAvailable()) { | ||||||
| 					if (message.getEncryption() == Message.ENCRYPTION_OTR) { | 					if (message.getEncryption() == Message.ENCRYPTION_OTR) { | ||||||
| 						if (!conv.hasValidOtrSession()) { | 						if (!conv.hasValidOtrSession()) { | ||||||
| 							conv.startOtrSession(message.getCounterpart().getResourcepart(),true); | 							conv.startOtrSession(message.getCounterpart().getResourcepart(),true); | ||||||
| 							message.setStatus(Message.STATUS_WAITING); | 							message.setStatus(Message.STATUS_WAITING); | ||||||
| 						} else if (conv.hasValidOtrSession() | 						} else if (conv.hasValidOtrSession() | ||||||
| 								&& conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) { | 								&& conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) { | ||||||
| 							mJingleConnectionManager | 							mJingleConnectionManager.createNewConnection(message); | ||||||
| 								.createNewConnection(message); |  | ||||||
| 						} | 						} | ||||||
| 					} else { | 					} else { | ||||||
| 						mJingleConnectionManager.createNewConnection(message); | 						this.sendFileMessage(message); | ||||||
|  | 
 | ||||||
| 					} | 					} | ||||||
| 				} else { | 				} else { | ||||||
| 					if (message.getEncryption() == Message.ENCRYPTION_OTR) { | 					if (message.getEncryption() == Message.ENCRYPTION_OTR) { | ||||||
| @ -791,12 +802,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa | |||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private void resendMessage(final Message message) { | 	public void resendMessage(final Message message) { | ||||||
| 		Account account = message.getConversation().getAccount(); | 		Account account = message.getConversation().getAccount(); | ||||||
| 		MessagePacket packet = null; | 		MessagePacket packet = null; | ||||||
| 		if (message.getEncryption() == Message.ENCRYPTION_OTR) { | 		if (message.getEncryption() == Message.ENCRYPTION_OTR) { | ||||||
| 			Presences presences = message.getConversation().getContact() | 			Presences presences = message.getConversation().getContact().getPresences(); | ||||||
| 				.getPresences(); |  | ||||||
| 			if (!message.getConversation().hasValidOtrSession()) { | 			if (!message.getConversation().hasValidOtrSession()) { | ||||||
| 				if ((message.getCounterpart() != null) | 				if ((message.getCounterpart() != null) | ||||||
| 						&& (presences.has(message.getCounterpart().getResourcepart()))) { | 						&& (presences.has(message.getCounterpart().getResourcepart()))) { | ||||||
| @ -808,34 +818,24 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa | |||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				if (message.getConversation().getOtrSession() | 				if (message.getConversation().getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) { | ||||||
| 						.getSessionStatus() == SessionStatus.ENCRYPTED) { |  | ||||||
| 					try { | 					try { | ||||||
| 						message.setCounterpart(Jid.fromSessionID(message.getConversation().getOtrSession().getSessionID())); | 						message.setCounterpart(Jid.fromSessionID(message.getConversation().getOtrSession().getSessionID())); | ||||||
| 						if (message.getType() == Message.TYPE_TEXT) { | 						if (message.needsUploading()) { | ||||||
| 							packet = mMessageGenerator.generateOtrChat(message, |  | ||||||
| 									true); |  | ||||||
| 						} else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) { |  | ||||||
| 							mJingleConnectionManager.createNewConnection(message); | 							mJingleConnectionManager.createNewConnection(message); | ||||||
|  | 						} else { | ||||||
|  | 							packet = mMessageGenerator.generateOtrChat(message, true); | ||||||
| 						} | 						} | ||||||
| 					} catch (final InvalidJidException ignored) { | 					} catch (final InvalidJidException ignored) { | ||||||
| 
 | 
 | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} else if (message.getType() == Message.TYPE_TEXT) { | 		} else if (message.needsUploading()) { | ||||||
| 			if (message.getEncryption() == Message.ENCRYPTION_NONE) { |  | ||||||
| 				packet = mMessageGenerator.generateChat(message, true); |  | ||||||
| 			} else if ((message.getEncryption() == Message.ENCRYPTION_DECRYPTED) |  | ||||||
| 					|| (message.getEncryption() == Message.ENCRYPTION_PGP)) { |  | ||||||
| 				packet = mMessageGenerator.generatePgpChat(message, true); |  | ||||||
| 					} |  | ||||||
| 		} else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) { |  | ||||||
| 			Contact contact = message.getConversation().getContact(); | 			Contact contact = message.getConversation().getContact(); | ||||||
| 			Presences presences = contact.getPresences(); | 			Presences presences = contact.getPresences(); | ||||||
| 			if ((message.getCounterpart() != null) | 			if (account.httpUploadAvailable() || (message.getCounterpart() != null && presences.has(message.getCounterpart().getResourcepart()))) { | ||||||
| 					&& (presences.has(message.getCounterpart().getResourcepart()))) { | 				this.sendFileMessage(message); | ||||||
| 				mJingleConnectionManager.createNewConnection(message); |  | ||||||
| 			} else { | 			} else { | ||||||
| 				if (presences.size() == 1) { | 				if (presences.size() == 1) { | ||||||
| 					String presence = presences.asStringArray()[0]; | 					String presence = presences.asStringArray()[0]; | ||||||
| @ -844,9 +844,16 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa | |||||||
| 					} catch (InvalidJidException e) { | 					} catch (InvalidJidException e) { | ||||||
| 						return; | 						return; | ||||||
| 					} | 					} | ||||||
| 					mJingleConnectionManager.createNewConnection(message); | 					this.sendFileMessage(message); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 		} else { | ||||||
|  | 			if (message.getEncryption() == Message.ENCRYPTION_NONE) { | ||||||
|  | 				packet = mMessageGenerator.generateChat(message, true); | ||||||
|  | 			} else if ((message.getEncryption() == Message.ENCRYPTION_DECRYPTED) | ||||||
|  | 					|| (message.getEncryption() == Message.ENCRYPTION_PGP)) { | ||||||
|  | 				packet = mMessageGenerator.generatePgpChat(message, true); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		if (packet != null) { | 		if (packet != null) { | ||||||
| 			if (!account.getXmppConnection().getFeatures().sm() | 			if (!account.getXmppConnection().getFeatures().sm() | ||||||
| @ -1809,15 +1816,15 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa | |||||||
| 				} catch (InvalidJidException e) { | 				} catch (InvalidJidException e) { | ||||||
| 					return; | 					return; | ||||||
| 				} | 				} | ||||||
| 				if (message.getType() == Message.TYPE_TEXT) { | 				if (message.needsUploading()) { | ||||||
|  | 					mJingleConnectionManager.createNewConnection(message); | ||||||
|  | 				} else { | ||||||
| 					MessagePacket outPacket = mMessageGenerator.generateOtrChat(message, true); | 					MessagePacket outPacket = mMessageGenerator.generateOtrChat(message, true); | ||||||
| 					if (outPacket != null) { | 					if (outPacket != null) { | ||||||
| 						message.setStatus(Message.STATUS_SEND); | 						message.setStatus(Message.STATUS_SEND); | ||||||
| 						databaseBackend.updateMessage(message); | 						databaseBackend.updateMessage(message); | ||||||
| 						sendMessagePacket(account, outPacket); | 						sendMessagePacket(account, outPacket); | ||||||
| 					} | 					} | ||||||
| 				} else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) { |  | ||||||
| 					mJingleConnectionManager.createNewConnection(message); |  | ||||||
| 				} | 				} | ||||||
| 				updateConversationUi(); | 				updateConversationUi(); | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -35,6 +35,7 @@ import java.util.Iterator; | |||||||
| import java.util.List; | 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.Blockable; | import eu.siacs.conversations.entities.Blockable; | ||||||
| import eu.siacs.conversations.entities.Contact; | import eu.siacs.conversations.entities.Contact; | ||||||
| import eu.siacs.conversations.entities.Conversation; | import eu.siacs.conversations.entities.Conversation; | ||||||
| @ -382,7 +383,7 @@ public class ConversationActivity extends XmppActivity | |||||||
| 				} | 				} | ||||||
| 				if (this.getSelectedConversation().getMode() == Conversation.MODE_MULTI) { | 				if (this.getSelectedConversation().getMode() == Conversation.MODE_MULTI) { | ||||||
| 					menuContactDetails.setVisible(false); | 					menuContactDetails.setVisible(false); | ||||||
| 					menuAttach.setVisible(false); | 					menuAttach.setVisible(getSelectedConversation().getAccount().httpUploadAvailable()); | ||||||
| 					menuInviteContact.setVisible(getSelectedConversation().getMucOptions().canInvite()); | 					menuInviteContact.setVisible(getSelectedConversation().getMucOptions().canInvite()); | ||||||
| 				} else { | 				} else { | ||||||
| 					menuMucDetails.setVisible(false); | 					menuMucDetails.setVisible(false); | ||||||
| @ -398,6 +399,8 @@ public class ConversationActivity extends XmppActivity | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private void selectPresenceToAttachFile(final int attachmentChoice, final int encryption) { | 	private void selectPresenceToAttachFile(final int attachmentChoice, final int encryption) { | ||||||
|  | 		final Conversation conversation = getSelectedConversation(); | ||||||
|  | 		final Account account = conversation.getAccount(); | ||||||
| 		final OnPresenceSelected callback = new OnPresenceSelected() { | 		final OnPresenceSelected callback = new OnPresenceSelected() { | ||||||
| 
 | 
 | ||||||
| 			@Override | 			@Override | ||||||
| @ -449,11 +452,11 @@ public class ConversationActivity extends XmppActivity | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		}; | 		}; | ||||||
| 		if (attachmentChoice == ATTACHMENT_CHOICE_LOCATION && encryption != Message.ENCRYPTION_OTR) { | 		if ((account.httpUploadAvailable() || attachmentChoice == ATTACHMENT_CHOICE_LOCATION) && encryption != Message.ENCRYPTION_OTR) { | ||||||
| 			getSelectedConversation().setNextCounterpart(null); | 			conversation.setNextCounterpart(null); | ||||||
| 			callback.onPresenceSelected(); | 			callback.onPresenceSelected(); | ||||||
| 		} else { | 		} else { | ||||||
| 			selectPresence(getSelectedConversation(),callback); | 			selectPresence(conversation,callback); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -452,13 +452,12 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa | |||||||
| 			if (m.getStatus() != Message.STATUS_SEND_FAILED) { | 			if (m.getStatus() != Message.STATUS_SEND_FAILED) { | ||||||
| 				sendAgain.setVisible(false); | 				sendAgain.setVisible(false); | ||||||
| 			} | 			} | ||||||
| 			if (((m.getType() != Message.TYPE_IMAGE && m.getDownloadable() == null) | 			if (!m.hasFileOnRemoteHost() && !GeoHelper.isGeoUri(m.getBody())) { | ||||||
| 					|| m.getImageParams().url == null) && !GeoHelper.isGeoUri(m.getBody())) { |  | ||||||
| 				copyUrl.setVisible(false); | 				copyUrl.setVisible(false); | ||||||
| 			} | 			} | ||||||
| 			if (m.getType() != Message.TYPE_TEXT | 			if (m.getType() != Message.TYPE_TEXT | ||||||
| 					|| m.getDownloadable() != null | 					|| m.getDownloadable() != null | ||||||
| 					|| !m.bodyContainsDownloadable()) { | 					|| m.treatAsDownloadable() == Message.Decision.NO) { | ||||||
| 				downloadImage.setVisible(false); | 				downloadImage.setVisible(false); | ||||||
| 			} | 			} | ||||||
| 			if (!((m.getDownloadable() != null && !(m.getDownloadable() instanceof DownloadablePlaceholder)) | 			if (!((m.getDownloadable() != null && !(m.getDownloadable() instanceof DownloadablePlaceholder)) | ||||||
| @ -544,7 +543,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa | |||||||
| 			url = message.getBody(); | 			url = message.getBody(); | ||||||
| 		} else { | 		} else { | ||||||
| 			resId = R.string.image_url; | 			resId = R.string.image_url; | ||||||
| 			url = message.getImageParams().url.toString(); | 			url = message.getFileParams().url.toString(); | ||||||
| 		} | 		} | ||||||
| 		if (activity.copyTextToClipboard(url, resId)) { | 		if (activity.copyTextToClipboard(url, resId)) { | ||||||
| 			Toast.makeText(activity, R.string.url_copied_to_clipboard, | 			Toast.makeText(activity, R.string.url_copied_to_clipboard, | ||||||
| @ -912,7 +911,8 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa | |||||||
| 		final SendButtonAction action; | 		final SendButtonAction action; | ||||||
| 		final int status; | 		final int status; | ||||||
| 		final boolean empty = this.mEditMessage == null || this.mEditMessage.getText().length() == 0; | 		final boolean empty = this.mEditMessage == null || this.mEditMessage.getText().length() == 0; | ||||||
| 		if (c.getMode() == Conversation.MODE_MULTI) { | 		final boolean conference = c.getMode() == Conversation.MODE_MULTI; | ||||||
|  | 		if (conference && !c.getAccount().httpUploadAvailable()) { | ||||||
| 			if (empty && c.getNextCounterpart() != null) { | 			if (empty && c.getNextCounterpart() != null) { | ||||||
| 				action = SendButtonAction.CANCEL; | 				action = SendButtonAction.CANCEL; | ||||||
| 			} else { | 			} else { | ||||||
| @ -920,6 +920,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa | |||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			if (empty) { | 			if (empty) { | ||||||
|  | 				if (conference && c.getNextCounterpart() != null) { | ||||||
|  | 					action = SendButtonAction.CANCEL; | ||||||
|  | 				} else { | ||||||
| 					String setting = activity.getPreferences().getString("quick_action", "recent"); | 					String setting = activity.getPreferences().getString("quick_action", "recent"); | ||||||
| 					if (!setting.equals("none") && UIHelper.receivedLocationQuestion(conversation.getLatestMessage())) { | 					if (!setting.equals("none") && UIHelper.receivedLocationQuestion(conversation.getLatestMessage())) { | ||||||
| 						setting = "location"; | 						setting = "location"; | ||||||
| @ -943,6 +946,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa | |||||||
| 							action = SendButtonAction.TEXT; | 							action = SendButtonAction.TEXT; | ||||||
| 							break; | 							break; | ||||||
| 					} | 					} | ||||||
|  | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				action = SendButtonAction.TEXT; | 				action = SendButtonAction.TEXT; | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ package eu.siacs.conversations.ui.adapter; | |||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.content.res.Resources; | import android.content.res.Resources; | ||||||
| import android.graphics.Bitmap; | import android.graphics.Bitmap; | ||||||
| import android.graphics.Color; |  | ||||||
| import android.graphics.Typeface; | import android.graphics.Typeface; | ||||||
| import android.graphics.drawable.BitmapDrawable; | import android.graphics.drawable.BitmapDrawable; | ||||||
| import android.graphics.drawable.Drawable; | import android.graphics.drawable.Drawable; | ||||||
| @ -69,7 +68,7 @@ public class ConversationAdapter extends ArrayAdapter<Conversation> { | |||||||
| 			convName.setTypeface(null, Typeface.NORMAL); | 			convName.setTypeface(null, Typeface.NORMAL); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (message.getImageParams().width > 0 | 		if (message.getFileParams().width > 0 | ||||||
| 				&& (message.getDownloadable() == null | 				&& (message.getDownloadable() == null | ||||||
| 				|| message.getDownloadable().getStatus() != Downloadable.STATUS_DELETED)) { | 				|| message.getDownloadable().getStatus() != Downloadable.STATUS_DELETED)) { | ||||||
| 			mLastMessage.setVisibility(View.GONE); | 			mLastMessage.setVisibility(View.GONE); | ||||||
|  | |||||||
| @ -32,7 +32,7 @@ import eu.siacs.conversations.entities.Conversation; | |||||||
| import eu.siacs.conversations.entities.Downloadable; | import eu.siacs.conversations.entities.Downloadable; | ||||||
| import eu.siacs.conversations.entities.DownloadableFile; | import eu.siacs.conversations.entities.DownloadableFile; | ||||||
| import eu.siacs.conversations.entities.Message; | import eu.siacs.conversations.entities.Message; | ||||||
| import eu.siacs.conversations.entities.Message.ImageParams; | import eu.siacs.conversations.entities.Message.FileParams; | ||||||
| import eu.siacs.conversations.ui.ConversationActivity; | import eu.siacs.conversations.ui.ConversationActivity; | ||||||
| import eu.siacs.conversations.utils.GeoHelper; | import eu.siacs.conversations.utils.GeoHelper; | ||||||
| import eu.siacs.conversations.utils.UIHelper; | import eu.siacs.conversations.utils.UIHelper; | ||||||
| @ -100,7 +100,7 @@ public class MessageAdapter extends ArrayAdapter<Message> { | |||||||
| 		boolean multiReceived = message.getConversation().getMode() == Conversation.MODE_MULTI | 		boolean multiReceived = message.getConversation().getMode() == Conversation.MODE_MULTI | ||||||
| 			&& message.getMergedStatus() <= Message.STATUS_RECEIVED; | 			&& message.getMergedStatus() <= Message.STATUS_RECEIVED; | ||||||
| 		if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE || message.getDownloadable() != null) { | 		if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE || message.getDownloadable() != null) { | ||||||
| 			ImageParams params = message.getImageParams(); | 			FileParams params = message.getFileParams(); | ||||||
| 			if (params.size > (1.5 * 1024 * 1024)) { | 			if (params.size > (1.5 * 1024 * 1024)) { | ||||||
| 				filesize = params.size / (1024 * 1024)+ " MiB"; | 				filesize = params.size / (1024 * 1024)+ " MiB"; | ||||||
| 			} else if (params.size > 0) { | 			} else if (params.size > 0) { | ||||||
| @ -339,7 +339,7 @@ public class MessageAdapter extends ArrayAdapter<Message> { | |||||||
| 		} | 		} | ||||||
| 		viewHolder.messageBody.setVisibility(View.GONE); | 		viewHolder.messageBody.setVisibility(View.GONE); | ||||||
| 		viewHolder.image.setVisibility(View.VISIBLE); | 		viewHolder.image.setVisibility(View.VISIBLE); | ||||||
| 		ImageParams params = message.getImageParams(); | 		FileParams params = message.getFileParams(); | ||||||
| 		double target = metrics.density * 288; | 		double target = metrics.density * 288; | ||||||
| 		int scalledW; | 		int scalledW; | ||||||
| 		int scalledH; | 		int scalledH; | ||||||
| @ -494,7 +494,7 @@ public class MessageAdapter extends ArrayAdapter<Message> { | |||||||
| 		} else if (message.getType() == Message.TYPE_IMAGE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) { | 		} else if (message.getType() == Message.TYPE_IMAGE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) { | ||||||
| 			displayImageMessage(viewHolder, message); | 			displayImageMessage(viewHolder, message); | ||||||
| 		} else if (message.getType() == Message.TYPE_FILE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) { | 		} else if (message.getType() == Message.TYPE_FILE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) { | ||||||
| 			if (message.getImageParams().width > 0) { | 			if (message.getFileParams().width > 0) { | ||||||
| 				displayImageMessage(viewHolder,message); | 				displayImageMessage(viewHolder,message); | ||||||
| 			} else { | 			} else { | ||||||
| 				displayOpenableMessage(viewHolder, message); | 				displayOpenableMessage(viewHolder, message); | ||||||
|  | |||||||
| @ -5,4 +5,5 @@ public final class Xmlns { | |||||||
| 	public static final String ROSTER = "jabber:iq:roster"; | 	public static final String ROSTER = "jabber:iq:roster"; | ||||||
| 	public static final String REGISTER = "jabber:iq:register"; | 	public static final String REGISTER = "jabber:iq:register"; | ||||||
| 	public static final String BYTE_STREAMS = "http://jabber.org/protocol/bytestreams"; | 	public static final String BYTE_STREAMS = "http://jabber.org/protocol/bytestreams"; | ||||||
|  | 	public static final String HTTP_UPLOAD = "eu:siacs:conversations:http:upload"; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1025,18 +1025,18 @@ public class XmppConnection implements Runnable { | |||||||
| 		this.streamId = null; | 		this.streamId = null; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public List<String> findDiscoItemsByFeature(final String feature) { | 	public List<Jid> findDiscoItemsByFeature(final String feature) { | ||||||
| 		final List<String> items = new ArrayList<>(); | 		final List<Jid> items = new ArrayList<>(); | ||||||
| 		for (final Entry<Jid, Info> cursor : disco.entrySet()) { | 		for (final Entry<Jid, Info> cursor : disco.entrySet()) { | ||||||
| 			if (cursor.getValue().features.contains(feature)) { | 			if (cursor.getValue().features.contains(feature)) { | ||||||
| 				items.add(cursor.getKey().toString()); | 				items.add(cursor.getKey()); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return items; | 		return items; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public String findDiscoItemByFeature(final String feature) { | 	public Jid findDiscoItemByFeature(final String feature) { | ||||||
| 		final List<String> items = findDiscoItemsByFeature(feature); | 		final List<Jid> items = findDiscoItemsByFeature(feature); | ||||||
| 		if (items.size() >= 1) { | 		if (items.size() >= 1) { | ||||||
| 			return items.get(0); | 			return items.get(0); | ||||||
| 		} | 		} | ||||||
| @ -1191,6 +1191,10 @@ public class XmppConnection implements Runnable { | |||||||
| 		public void setBlockListRequested(boolean value) { | 		public void setBlockListRequested(boolean value) { | ||||||
| 			this.blockListRequested = value; | 			this.blockListRequested = value; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		public boolean httpUpload() { | ||||||
|  | 			return findDiscoItemsByFeature(Xmlns.HTTP_UPLOAD).size() > 0; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private IqGenerator getIqGenerator() { | 	private IqGenerator getIqGenerator() { | ||||||
|  | |||||||
| @ -954,24 +954,4 @@ public class JingleConnection implements Downloadable { | |||||||
| 	public int getProgress() { | 	public int getProgress() { | ||||||
| 		return this.mProgress; | 		return this.mProgress; | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public String getMimeType() { |  | ||||||
| 		if (this.message.getType() == Message.TYPE_FILE) { |  | ||||||
| 			String mime = null; |  | ||||||
| 			String path = this.message.getRelativeFilePath(); |  | ||||||
| 			if (path != null && !this.message.getRelativeFilePath().isEmpty()) { |  | ||||||
| 				mime = URLConnection.guessContentTypeFromName(this.message.getRelativeFilePath()); |  | ||||||
| 				if (mime!=null) { |  | ||||||
| 					return  mime; |  | ||||||
| 				} else { |  | ||||||
| 					return ""; |  | ||||||
| 				} |  | ||||||
| 			} else { |  | ||||||
| 				return ""; |  | ||||||
| 			} |  | ||||||
| 		} else { |  | ||||||
| 			return "image/webp"; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -87,10 +87,10 @@ public class JingleConnectionManager extends AbstractConnectionManager { | |||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		if (!this.primaryCandidates.containsKey(account.getJid().toBareJid())) { | 		if (!this.primaryCandidates.containsKey(account.getJid().toBareJid())) { | ||||||
| 			final String proxy = account.getXmppConnection().findDiscoItemByFeature(Xmlns.BYTE_STREAMS); | 			final Jid proxy = account.getXmppConnection().findDiscoItemByFeature(Xmlns.BYTE_STREAMS); | ||||||
| 			if (proxy != null) { | 			if (proxy != null) { | ||||||
| 				IqPacket iq = new IqPacket(IqPacket.TYPE.GET); | 				IqPacket iq = new IqPacket(IqPacket.TYPE.GET); | ||||||
| 				iq.setAttribute("to", proxy); | 				iq.setTo(proxy); | ||||||
| 				iq.query(Xmlns.BYTE_STREAMS); | 				iq.query(Xmlns.BYTE_STREAMS); | ||||||
| 				account.getXmppConnection().sendIqPacket(iq,new OnIqPacketReceived() { | 				account.getXmppConnection().sendIqPacket(iq,new OnIqPacketReceived() { | ||||||
| 
 | 
 | ||||||
| @ -105,11 +105,11 @@ public class JingleConnectionManager extends AbstractConnectionManager { | |||||||
| 								candidate.setHost(host); | 								candidate.setHost(host); | ||||||
| 								candidate.setPort(Integer.parseInt(port)); | 								candidate.setPort(Integer.parseInt(port)); | ||||||
| 								candidate.setType(JingleCandidate.TYPE_PROXY); | 								candidate.setType(JingleCandidate.TYPE_PROXY); | ||||||
| 								candidate.setJid(Jid.fromString(proxy)); | 								candidate.setJid(proxy); | ||||||
| 								candidate.setPriority(655360 + 65535); | 								candidate.setPriority(655360 + 65535); | ||||||
| 								primaryCandidates.put(account.getJid().toBareJid(),candidate); | 								primaryCandidates.put(account.getJid().toBareJid(),candidate); | ||||||
| 								listener.onPrimaryCandidateFound(true,candidate); | 								listener.onPrimaryCandidateFound(true,candidate); | ||||||
| 							} catch (final NumberFormatException | InvalidJidException e) { | 							} catch (final NumberFormatException e) { | ||||||
| 								listener.onPrimaryCandidateFound(false,null); | 								listener.onPrimaryCandidateFound(false,null); | ||||||
| 								return; | 								return; | ||||||
| 							} | 							} | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Daniel Gultsch
						Daniel Gultsch