package com.juick.components; import com.juick.components.url.JuickURLStreamHandlerFactory; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; import rocks.xmpp.addr.Jid; import rocks.xmpp.core.XmppException; import rocks.xmpp.core.stanza.model.Message; import rocks.xmpp.extensions.component.accept.ExternalComponent; import rocks.xmpp.extensions.filetransfer.FileTransfer; import rocks.xmpp.extensions.filetransfer.FileTransferManager; import rocks.xmpp.extensions.oob.model.x.OobX; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.*; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; /** * Created by vitalyster on 11.11.2016. */ public class XMPPFTServer { private static final Logger logger = LoggerFactory.getLogger(XMPPFTServer.class); public XMPPFTServer(Environment env) { try { Class tomcathfc = Class.forName("org.apache.catalina.webresources.TomcatURLStreamHandlerFactory"); if (tomcathfc != null) { try { Method m = tomcathfc.getMethod("getInstance"); Object tomcathfo = m.invoke(null); m = tomcathfo.getClass().getMethod("addUserFactory", URLStreamHandlerFactory.class); m.invoke(tomcathfo, new JuickURLStreamHandlerFactory()); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { logger.error("init error", e); } } } catch (ClassNotFoundException e) { URL.setURLStreamHandlerFactory(new JuickURLStreamHandlerFactory()); } ExternalComponent component = ExternalComponent.create(env.getProperty("component_name", "files"), env.getProperty("component_password", "secret"), env.getProperty("component_host", "localhost"), NumberUtils.toInt(env.getProperty("component_port", "5347"), 5347)); String tmpDir = env.getProperty("upload_tmp_dir", "/tmp"); String juickJid = env.getProperty("xmppbot_jid", "juick@juick.com/Juick"); FileTransferManager fileTransferManager = component.getManager(FileTransferManager.class); fileTransferManager.addFileTransferOfferListener(e -> { try { List allowedTypes = new ArrayList() {{ add("png"); add("jpg"); }}; String attachmentExtension = FilenameUtils.getExtension(e.getName()).toLowerCase(); String targetFilename = String.format("%s.%s", DigestUtils.md5Hex(String.format("%s-%s", e.getInitiator().toString(), e.getSessionId()).getBytes()), attachmentExtension); if (allowedTypes.contains(attachmentExtension)) { Path filePath = Paths.get(tmpDir, targetFilename); FileTransfer ft = e.accept(filePath).get(); ft.addFileTransferStatusListener(st -> { logger.debug(String.format("%s: received %d of %d", e.getName(), st.getBytesTransferred(), e.getSize())); if (ft.isDone()) { logger.info("transfer completed"); Message msg = new Message(); msg.setType(Message.Type.CHAT); msg.setFrom(e.getInitiator()); msg.setTo(Jid.of(juickJid)); msg.setBody(e.getDescription()); try { String attachmentUrl = String.format("juick://%s", targetFilename); msg.addExtension(new OobX(new URI(attachmentUrl).toURL(), "!!!!Juick!!")); component.sendMessage(msg); } catch (MalformedURLException | URISyntaxException e1) { logger.warn("attachment error", e1); } } }); ft.transfer(); logger.info("transfer started"); } else { e.reject(); logger.info("transfer rejected"); } } catch (IOException | InterruptedException | ExecutionException e1) { logger.error("ft error", e1); } }); try { component.connect(); } catch (XmppException e) { logger.error("ft initialization error", e); } } }