From 7414f1034d32c249294a081f1e176a9266fc92ac Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Thu, 8 Feb 2018 22:06:08 +0300 Subject: reorganize project structure --- .../src/main/java/com/juick/server/api/Post.java | 281 +++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 juick-server/src/main/java/com/juick/server/api/Post.java (limited to 'juick-server/src/main/java/com/juick/server/api/Post.java') diff --git a/juick-server/src/main/java/com/juick/server/api/Post.java b/juick-server/src/main/java/com/juick/server/api/Post.java new file mode 100644 index 00000000..7f014d9e --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/api/Post.java @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2008-2017, Juick + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.juick.server.api; + +import com.juick.User; +import com.juick.server.ServerManager; +import com.juick.server.EmailManager; +import com.juick.server.util.*; +import com.juick.service.MessagesService; +import com.juick.service.SubscriptionService; +import com.juick.service.UserService; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.mail.util.MimeMessageParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import rocks.xmpp.addr.Jid; +import rocks.xmpp.core.stanza.model.Message; +import rocks.xmpp.extensions.nick.model.Nickname; +import rocks.xmpp.extensions.oob.model.x.OobX; + +import javax.inject.Inject; +import javax.mail.Session; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; +import java.util.Properties; +import java.util.Scanner; +import java.util.UUID; + +/** + * Created by vt on 24/11/2016. + */ +@RestController +public class Post { + private static Logger logger = LoggerFactory.getLogger(ServerManager.class); + + @Inject + private UserService userService; + @Inject + private ServerManager serverManager; + @Inject + private MessagesService messagesService; + @Inject + private SubscriptionService subscriptionService; + @Value("${upload_tmp_dir:/var/www/juick.com/i/tmp/}") + private String tmpDir; + @Value("${img_path:/var/www/juick.com/i/}") + private String imgDir; + + @RequestMapping(value = "/post", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @ResponseStatus(value = HttpStatus.OK) + public void doPostMessage( + @RequestParam String body, + @RequestParam(required = false) String img, + @RequestParam(required = false) MultipartFile attach) throws IOException { + User visitor = UserUtils.getCurrentUser(); + + if (visitor.isAnonymous()) + throw new HttpForbiddenException(); + + if (body == null || body.length() < 1 || body.length() > 4096) { + throw new HttpBadRequestException(); + } + body = body.replace("\r", StringUtils.EMPTY); + + String attachmentFName = HttpUtils.receiveMultiPartFile(attach, tmpDir); + + if (StringUtils.isBlank(attachmentFName) && img != null && img.length() > 10) { + try { + URL imgUrl = new URL(img); + attachmentFName = HttpUtils.downloadImage(imgUrl, tmpDir); + } catch (Exception e) { + logger.error("DOWNLOAD ERROR", e); + throw new HttpBadRequestException(); + } + } + serverManager.processMessage(visitor, body, attachmentFName); + } + + @RequestMapping(value = "/comment", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public com.juick.Message doPostComment( + @RequestParam(defaultValue = "0") int mid, + @RequestParam(defaultValue = "0") int rid, + @RequestParam String body, + @RequestParam(required = false) String img, + @RequestParam(required = false) MultipartFile attach) + throws IOException { + User visitor = UserUtils.getCurrentUser(); + int vuid = visitor.getUid(); + if (vuid == 0) { + throw new HttpForbiddenException(); + } + if (mid == 0) { + throw new HttpBadRequestException(); + } + com.juick.Message msg = messagesService.getMessage(mid); + if (msg == null) { + throw new HttpNotFoundException(); + } + + com.juick.Message reply = null; + if (rid > 0) { + reply = messagesService.getReply(mid, rid); + if (reply == null) { + throw new HttpNotFoundException(); + } + } + + if (body == null || body.length() < 1 || body.length() > 4096) { + throw new HttpBadRequestException(); + } + body = body.replace("\r", StringUtils.EMPTY); + + if ((msg.ReadOnly && msg.getUser().getUid() != vuid) || userService.isInBLAny(msg.getUser().getUid(), vuid) + || (reply != null && userService.isInBLAny(reply.getUser().getUid(), vuid))) { + throw new HttpForbiddenException(); + } + + String attachmentFName = HttpUtils.receiveMultiPartFile(attach, tmpDir); + + if (StringUtils.isBlank(attachmentFName) && img != null && img.length() > 10) { + try { + attachmentFName = HttpUtils.downloadImage(new URL(img), tmpDir); + } catch (Exception e) { + logger.error("DOWNLOAD ERROR", e); + throw new HttpBadRequestException(); + } + } + + String attachmentType = StringUtils.isNotEmpty(attachmentFName) ? attachmentFName.substring(attachmentFName.length() - 3) : null; + int ridnew = messagesService.createReply(mid, rid, vuid, body, attachmentType); + subscriptionService.subscribeMessage(mid, vuid); + + com.juick.Message jmsg = messagesService.getReply(mid, ridnew); + + Message xmsg = new Message(); + xmsg.setFrom(Jid.of("juick@juick.com")); + xmsg.setType(Message.Type.CHAT); + xmsg.setThread("juick-" + mid); + xmsg.addExtension(jmsg); + + String quote = reply != null ? StringUtils.defaultString(reply.getText()) : StringUtils.defaultString(msg.getText()); + if (quote.length() >= 50) { + quote = quote.substring(0, 47) + "..."; + } + + xmsg.addExtension(new Nickname("@" + jmsg.getUser().getName())); + + if (StringUtils.isNotEmpty(attachmentFName)) { + String fname = mid + "-" + ridnew + "." + attachmentType; + String attachmentURL = "http://i.juick.com/photos-1024/" + fname; + + ImageUtils.saveImageWithPreviews(attachmentFName, fname, tmpDir, imgDir); + + body = attachmentURL + "\n" + body; + try { + xmsg.addExtension(new OobX(new URI(attachmentURL))); + } catch (URISyntaxException e) { + logger.error("invalid uri: {}, exception {}", attachmentURL, e); + } + } + + xmsg.setBody("Reply by @" + jmsg.getUser().getName() + ":\n>" + quote + "\n" + body + "\n\n#" + + mid + "/" + ridnew + " http://juick.com/" + mid + "#" + ridnew); + + xmsg.setTo(Jid.of("juick@s2s.juick.com")); + serverManager.sendMessage(xmsg); + + xmsg.setTo(Jid.of("juick@ws.juick.com")); + serverManager.sendMessage(xmsg); + + xmsg.setTo(Jid.of("juick@push.juick.com")); + serverManager.sendMessage(xmsg); + return jmsg; + } + + Session session = Session.getDefaultInstance(new Properties()); + + @PostMapping("/mail") + @ResponseStatus(value = HttpStatus.OK) + public void processMail(InputStream data) throws Exception { + MimeMessage msg = new MimeMessage(session, data); + String from = msg.getFrom().length > 1 ? ((InternetAddress) msg.getSender()).getAddress() + : ((InternetAddress) msg.getFrom()[0]).getAddress(); + logger.info("got msg from {}", from); + + User visitor = userService.getUserByEmail(from); + if (!visitor.isAnonymous()) { + MimeMessageParser parser = new MimeMessageParser(msg); + parser.parse(); + final String[] body = {parser.getPlainContent()}; + if (body[0] == null) { + parser.getAttachmentList().stream() + .filter(a -> a.getContentType().equals("text/plain")).findFirst() + .ifPresent(a -> { + try { + body[0] = IOUtils.toString(a.getInputStream(), StandardCharsets.UTF_8); + logger.info("got text: {}", body[0]); + } catch (IOException e) { + logger.info("attachment error: {}", e); + } + }); + } + final String[] attachmentFName = new String[1]; + parser.getAttachmentList().stream().filter(a -> + a.getContentType().equals("image/jpeg") || a.getContentType().equals("image/png")) + .findFirst().ifPresent(a -> { + logger.info("got attachment: {}", a.getContentType()); + String attachmentType; + if (a.getContentType().equals("image/jpeg")) { + attachmentType = "jpg"; + } else { + attachmentType = "png"; + } + attachmentFName[0] = DigestUtils.md5Hex(UUID.randomUUID().toString()) + "." + attachmentType; + try { + logger.info("got inputstream: {}", a.getInputStream()); + FileOutputStream fos = new FileOutputStream(Paths.get(tmpDir, attachmentFName[0]).toString()); + IOUtils.copy(a.getInputStream(), fos); + fos.close(); + } catch (IOException e) { + logger.info("attachment error: {}", e); + } + }); + String[] inReplyToHeaders = msg.getHeader("In-Reply-To"); + if (inReplyToHeaders != null && inReplyToHeaders.length > 0) { + Scanner inReplyToScanner = new Scanner(inReplyToHeaders[0].trim()).useDelimiter(EmailManager.MSGID_PATTERN); + int mid = Integer.parseInt(inReplyToScanner.next()); + int rid = Integer.parseInt(inReplyToScanner.next()); + logger.info("Message is reply to #{}/{}", mid, rid); + body[0] = rid > 0 ? String.format("#%d/%d %s", mid, rid, body[0]) + : String.format("#%d %s", mid, body[0]); + } + rocks.xmpp.core.stanza.model.Message xmsg = new rocks.xmpp.core.stanza.model.Message(); + xmsg.setType(rocks.xmpp.core.stanza.model.Message.Type.CHAT); + xmsg.setFrom(Jid.of(String.valueOf(visitor.getUid()), "uid.juick.com", "mail")); + xmsg.setTo(Jid.of("juick@juick.com/Juick")); + xmsg.setBody(body[0]); + try { + if (StringUtils.isNotEmpty(attachmentFName[0])) { + String attachmentUrl = String.format("juick://%s", attachmentFName[0]); + xmsg.addExtension(new OobX(new URI(attachmentUrl), "!!!!Juick!!")); + } + serverManager.sendMessage(xmsg); + } catch (URISyntaxException e1) { + logger.warn("attachment error", e1); + } + } else { + logger.info("not registered: {}", from); + } + } +} -- cgit v1.2.3