package com.juick.components; 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.net.URI; import java.net.URISyntaxException; 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 implements AutoCloseable { private static final Logger logger = LoggerFactory.getLogger(XMPPFTServer.class); private ExternalComponent component; public XMPPFTServer(Environment env) { 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("{}: received {} of {}", 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), "!!!!Juick!!")); component.sendMessage(msg); } catch (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); } } @Override public void close() throws Exception { if (component != null) component.close(); logger.info("ExternalComponent on xmpp-ft destroyed"); } }