support new http upload namespace
This commit is contained in:
		
							parent
							
								
									4541ac8b7b
								
							
						
					
					
						commit
						e48788e821
					
				|  | @ -342,11 +342,9 @@ public class IqGenerator extends AbstractGenerator { | |||
| 		IqPacket packet = new IqPacket(IqPacket.TYPE.GET); | ||||
| 		packet.setTo(host); | ||||
| 		Element request = packet.addChild("request", Namespace.HTTP_UPLOAD); | ||||
| 		request.addChild("filename").setContent(convertFilename(file.getName())); | ||||
| 		request.addChild("size").setContent(String.valueOf(file.getExpectedSize())); | ||||
| 		if (mime != null) { | ||||
| 			request.addChild("content-type").setContent(mime); | ||||
| 		} | ||||
| 		request.setAttribute("filename",convertFilename(file.getName())); | ||||
| 		request.setAttribute("size",file.getExpectedSize()); | ||||
| 		request.setAttribute("content-type",mime); | ||||
| 		return packet; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ import java.io.OutputStream; | |||
| import java.net.HttpURLConnection; | ||||
| import java.net.MalformedURLException; | ||||
| import java.net.URL; | ||||
| import java.util.HashMap; | ||||
| 
 | ||||
| import javax.net.ssl.HttpsURLConnection; | ||||
| 
 | ||||
|  | @ -26,7 +27,6 @@ import eu.siacs.conversations.services.XmppConnectionService; | |||
| import eu.siacs.conversations.utils.CryptoHelper; | ||||
| import eu.siacs.conversations.xml.Namespace; | ||||
| import eu.siacs.conversations.xml.Element; | ||||
| import eu.siacs.conversations.xmpp.OnIqPacketReceived; | ||||
| import eu.siacs.conversations.xmpp.jid.Jid; | ||||
| import eu.siacs.conversations.xmpp.stanzas.IqPacket; | ||||
| 
 | ||||
|  | @ -43,6 +43,7 @@ public class HttpUploadConnection implements Transferable { | |||
| 	private String mime; | ||||
| 	private URL mGetUrl; | ||||
| 	private URL mPutUrl; | ||||
| 	private HashMap<String,String> mPutHeaders; | ||||
| 	private boolean mUseTor = false; | ||||
| 
 | ||||
| 	private byte[] key = null; | ||||
|  | @ -122,103 +123,113 @@ public class HttpUploadConnection implements Transferable { | |||
| 		this.mFileInputStream = pair.first; | ||||
| 		Jid host = account.getXmppConnection().findDiscoItemByFeature(Namespace.HTTP_UPLOAD); | ||||
| 		IqPacket request = mXmppConnectionService.getIqGenerator().requestHttpUploadSlot(host,file,mime); | ||||
| 		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", Namespace.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(); | ||||
| 		mXmppConnectionService.sendIqPacket(account, request, (account, packet) -> { | ||||
| 			if (packet.getType() == IqPacket.TYPE.RESULT) { | ||||
| 				Element slot = packet.findChild("slot", Namespace.HTTP_UPLOAD); | ||||
| 				if (slot != null) { | ||||
| 					try { | ||||
| 						final Element put = slot.findChild("put"); | ||||
| 						final Element get = slot.findChild("get"); | ||||
| 						final String putUrl = put == null ? null : put.getAttribute("url"); | ||||
| 						final String getUrl = get == null ? null : get.getAttribute("url"); | ||||
| 						if (getUrl != null && putUrl != null) { | ||||
| 							this.mGetUrl = new URL(getUrl); | ||||
| 							this.mPutUrl = new URL(putUrl); | ||||
| 							this.mPutHeaders = new HashMap<>(); | ||||
| 							for(Element child : put.getChildren()) { | ||||
| 								if ("header".equals(child.getName())) { | ||||
| 									String name = child.getAttribute("name"); | ||||
| 									String value = child.getContent(); | ||||
| 									if (name != null && value != null && !name.trim().contains("\n") && !value.trim().contains("\n")) { | ||||
| 										this.mPutHeaders.put(name.trim(),value.trim()); | ||||
| 									} | ||||
| 								} | ||||
| 							} | ||||
| 							return; | ||||
| 						} catch (MalformedURLException e) { | ||||
| 							//fall through | ||||
| 						} | ||||
| 						if (!canceled) { | ||||
| 							new Thread(this::upload).start(); | ||||
| 						} | ||||
| 						return; | ||||
| 					} catch (MalformedURLException e) { | ||||
| 						//fall through | ||||
| 					} | ||||
| 				} | ||||
| 				Log.d(Config.LOGTAG,account.getJid().toString()+": invalid response to slot request "+packet); | ||||
| 				fail(IqParser.extractErrorMessage(packet)); | ||||
| 			} | ||||
| 			Log.d(Config.LOGTAG,account.getJid().toString()+": invalid response to slot request "+packet); | ||||
| 			fail(IqParser.extractErrorMessage(packet)); | ||||
| 		}); | ||||
| 		message.setTransferable(this); | ||||
| 		mXmppConnectionService.markMessage(message, Message.STATUS_UNSEND); | ||||
| 	} | ||||
| 
 | ||||
| 	private class FileUploader implements Runnable { | ||||
| 
 | ||||
| 		@Override | ||||
| 		public void run() { | ||||
| 			this.upload(); | ||||
| 		} | ||||
| 
 | ||||
| 		private void upload() { | ||||
| 			OutputStream os = null; | ||||
| 			HttpURLConnection connection = null; | ||||
| 			PowerManager.WakeLock wakeLock = mHttpConnectionManager.createWakeLock("http_upload_"+message.getUuid()); | ||||
| 			try { | ||||
| 				wakeLock.acquire(); | ||||
| 				final int expectedFileSize = (int) file.getExpectedSize(); | ||||
| 				final int readTimeout = (expectedFileSize / 2048) + Config.SOCKET_TIMEOUT; //assuming a minimum transfer speed of 16kbit/s | ||||
| 				Log.d(Config.LOGTAG, "uploading to " + mPutUrl.toString()+ " w/ read timeout of "+readTimeout+"s"); | ||||
| 				if (mUseTor) { | ||||
| 					connection = (HttpURLConnection) mPutUrl.openConnection(mHttpConnectionManager.getProxy()); | ||||
| 				} else { | ||||
| 					connection = (HttpURLConnection) mPutUrl.openConnection(); | ||||
| 				} | ||||
| 				if (connection instanceof HttpsURLConnection) { | ||||
| 					mHttpConnectionManager.setupTrustManager((HttpsURLConnection) connection, true); | ||||
| 				} | ||||
| 				connection.setRequestMethod("PUT"); | ||||
| 				connection.setFixedLengthStreamingMode(expectedFileSize); | ||||
| 				connection.setRequestProperty("Content-Type", mime == null ? "application/octet-stream" : mime); | ||||
| 				connection.setRequestProperty("User-Agent",mXmppConnectionService.getIqGenerator().getIdentityName()); | ||||
| 				connection.setDoOutput(true); | ||||
| 				connection.setConnectTimeout(Config.SOCKET_TIMEOUT * 1000); | ||||
| 				connection.setReadTimeout(readTimeout * 1000); | ||||
| 				connection.connect(); | ||||
| 				os = connection.getOutputStream(); | ||||
| 				transmitted = 0; | ||||
| 				int count; | ||||
| 				byte[] buffer = new byte[4096]; | ||||
| 				while (((count = mFileInputStream.read(buffer)) != -1) && !canceled) { | ||||
| 					transmitted += count; | ||||
| 					os.write(buffer, 0, count); | ||||
| 					mHttpConnectionManager.updateConversationUi(false); | ||||
| 				} | ||||
| 				os.flush(); | ||||
| 				os.close(); | ||||
| 				mFileInputStream.close(); | ||||
| 				int code = connection.getResponseCode(); | ||||
| 				if (code == 200 || code == 201) { | ||||
| 					Log.d(Config.LOGTAG, "finished uploading file"); | ||||
| 					if (key != null) { | ||||
| 						mGetUrl = CryptoHelper.toAesGcmUrl(new URL(mGetUrl.toString() + "#" + CryptoHelper.bytesToHex(key))); | ||||
| 					} | ||||
| 					mXmppConnectionService.getFileBackend().updateFileParams(message, mGetUrl); | ||||
| 					mXmppConnectionService.getFileBackend().updateMediaScanner(file); | ||||
| 					message.setTransferable(null); | ||||
| 					message.setCounterpart(message.getConversation().getJid().toBareJid()); | ||||
| 					mXmppConnectionService.resendMessage(message, delayed); | ||||
| 				} else { | ||||
| 					Log.d(Config.LOGTAG,"http upload failed because response code was "+code); | ||||
| 					fail("http upload failed because response code was "+code); | ||||
| 				} | ||||
| 			} catch (IOException e) { | ||||
| 				e.printStackTrace(); | ||||
| 				Log.d(Config.LOGTAG,"http upload failed "+e.getMessage()); | ||||
| 				fail(e.getMessage()); | ||||
| 			} finally { | ||||
| 				FileBackend.close(mFileInputStream); | ||||
| 				FileBackend.close(os); | ||||
| 				if (connection != null) { | ||||
| 					connection.disconnect(); | ||||
| 				} | ||||
| 				wakeLock.release(); | ||||
| 	private void upload() { | ||||
| 		OutputStream os = null; | ||||
| 		HttpURLConnection connection = null; | ||||
| 		PowerManager.WakeLock wakeLock = mHttpConnectionManager.createWakeLock("http_upload_"+message.getUuid()); | ||||
| 		try { | ||||
| 			final int expectedFileSize = (int) file.getExpectedSize(); | ||||
| 			final int readTimeout = (expectedFileSize / 2048) + Config.SOCKET_TIMEOUT; //assuming a minimum transfer speed of 16kbit/s | ||||
| 			wakeLock.acquire(readTimeout); | ||||
| 			Log.d(Config.LOGTAG, "uploading to " + mPutUrl.toString()+ " w/ read timeout of "+readTimeout+"s"); | ||||
| 			if (mUseTor) { | ||||
| 				connection = (HttpURLConnection) mPutUrl.openConnection(mHttpConnectionManager.getProxy()); | ||||
| 			} else { | ||||
| 				connection = (HttpURLConnection) mPutUrl.openConnection(); | ||||
| 			} | ||||
| 			if (connection instanceof HttpsURLConnection) { | ||||
| 				mHttpConnectionManager.setupTrustManager((HttpsURLConnection) connection, true); | ||||
| 			} | ||||
| 			connection.setRequestMethod("PUT"); | ||||
| 			connection.setFixedLengthStreamingMode(expectedFileSize); | ||||
| 			connection.setRequestProperty("Content-Type", mime == null ? "application/octet-stream" : mime); | ||||
| 			connection.setRequestProperty("User-Agent",mXmppConnectionService.getIqGenerator().getIdentityName()); | ||||
| 			if(mPutHeaders != null) { | ||||
| 				for(HashMap.Entry<String,String> entry : mPutHeaders.entrySet()) { | ||||
| 					connection.setRequestProperty(entry.getKey(),entry.getValue()); | ||||
| 				} | ||||
| 			} | ||||
| 			connection.setDoOutput(true); | ||||
| 			connection.setConnectTimeout(Config.SOCKET_TIMEOUT * 1000); | ||||
| 			connection.setReadTimeout(readTimeout * 1000); | ||||
| 			connection.connect(); | ||||
| 			os = connection.getOutputStream(); | ||||
| 			transmitted = 0; | ||||
| 			int count; | ||||
| 			byte[] buffer = new byte[4096]; | ||||
| 			while (((count = mFileInputStream.read(buffer)) != -1) && !canceled) { | ||||
| 				transmitted += count; | ||||
| 				os.write(buffer, 0, count); | ||||
| 				mHttpConnectionManager.updateConversationUi(false); | ||||
| 			} | ||||
| 			os.flush(); | ||||
| 			os.close(); | ||||
| 			mFileInputStream.close(); | ||||
| 			int code = connection.getResponseCode(); | ||||
| 			if (code == 200 || code == 201) { | ||||
| 				Log.d(Config.LOGTAG, "finished uploading file"); | ||||
| 				if (key != null) { | ||||
| 					mGetUrl = CryptoHelper.toAesGcmUrl(new URL(mGetUrl.toString() + "#" + CryptoHelper.bytesToHex(key))); | ||||
| 				} | ||||
| 				mXmppConnectionService.getFileBackend().updateFileParams(message, mGetUrl); | ||||
| 				mXmppConnectionService.getFileBackend().updateMediaScanner(file); | ||||
| 				message.setTransferable(null); | ||||
| 				message.setCounterpart(message.getConversation().getJid().toBareJid()); | ||||
| 				mXmppConnectionService.resendMessage(message, delayed); | ||||
| 			} else { | ||||
| 				Log.d(Config.LOGTAG,"http upload failed because response code was "+code); | ||||
| 				fail("http upload failed because response code was "+code); | ||||
| 			} | ||||
| 		} catch (IOException e) { | ||||
| 			e.printStackTrace(); | ||||
| 			Log.d(Config.LOGTAG,"http upload failed "+e.getMessage()); | ||||
| 			fail(e.getMessage()); | ||||
| 		} finally { | ||||
| 			FileBackend.close(mFileInputStream); | ||||
| 			FileBackend.close(os); | ||||
| 			if (connection != null) { | ||||
| 				connection.disconnect(); | ||||
| 			} | ||||
| 			wakeLock.release(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ public final class Namespace { | |||
| 	public static final String ROSTER = "jabber:iq:roster"; | ||||
| 	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"; | ||||
| 	public static final String HTTP_UPLOAD = "urn:xmpp:http:upload:0"; | ||||
| 	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"; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Daniel Gultsch
						Daniel Gultsch