diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/java/com/juick/http/www/Home.java | 4 | ||||
-rw-r--r-- | src/java/com/juick/http/www/Main.java | 16 | ||||
-rw-r--r-- | src/java/com/juick/http/www/NewMessage.java | 211 | ||||
-rw-r--r-- | src/java/com/juick/http/www/PageTemplates.java | 23 | ||||
-rw-r--r-- | src/java/com/juick/http/www/UserThread.java | 2 | ||||
-rw-r--r-- | src/java/com/juick/http/www/Utils.java | 95 |
6 files changed, 335 insertions, 16 deletions
diff --git a/src/java/com/juick/http/www/Home.java b/src/java/com/juick/http/www/Home.java index 6d60bfaf3..3931fd24e 100644 --- a/src/java/com/juick/http/www/Home.java +++ b/src/java/com/juick/http/www/Home.java @@ -111,8 +111,8 @@ public class Home { out.println("<section id=\"newmessage\">"); out.println(" <textarea name=\"body\" placeholder=\"Новое сообщение...\" onclick=\"$('#newmessage>div').css('display','block');$('#newmessage textarea').css('min-height','70px');\" onkeypress=\"postformListener(this.form,event)\"></textarea>"); out.println(" <div>"); - out.println(" <input type=\"text\" class=\"tags\" name=\"tags\" placeholder=\"Теги (через пробел)\"/>"); - out.println(" <div class=\"attach-photo\" onclick=\"attachCommentPhoto(this)\"></div>"); + out.println(" <input type=\"text\" class=\"img\" name=\"img\" placeholder=\"Ссылка на изображение (JPG/PNG, до 10Мб)\"/> или <a href=\"#\" onclick=\"return attachMessagePhoto(this)\">загрузить</a><br/>"); + out.println(" <input type=\"text\" class=\"tags\" name=\"tags\" placeholder=\"Теги (через пробел)\"/><br/>"); out.println(" <input type=\"submit\" class=\"subm\" value=\"Отправить\"/>"); out.println(" </div>"); out.println("</section>"); diff --git a/src/java/com/juick/http/www/Main.java b/src/java/com/juick/http/www/Main.java index 2c51456e9..13506db7c 100644 --- a/src/java/com/juick/http/www/Main.java +++ b/src/java/com/juick/http/www/Main.java @@ -41,7 +41,7 @@ import ru.sape.Sape; * @author Ugnich Anton */ @WebServlet(name = "Main", urlPatterns = {"/"}) -@MultipartConfig +@MultipartConfig(fileSizeThreshold = 1024 * 1024, maxRequestSize = 1024 * 1024 * 10) public class Main extends HttpServlet implements Stream.StreamListener { Connection sql; @@ -272,7 +272,19 @@ public class Main extends HttpServlet implements Stream.StreamListener { String uri = request.getRequestURI(); if (uri.equals("/post")) { - pagesNewMessage.doPostNewMessage(sql, request, response); + com.juick.User visitor = Utils.getVisitorUser(sql, request, response); + if (visitor != null) { + pagesNewMessage.doPostMessage(sql, request, response, xmpp, visitor); + } else { + response.sendError(403); + } + } else if (uri.equals("/comment")) { + com.juick.User visitor = Utils.getVisitorUser(sql, request, response); + if (visitor != null) { + pagesNewMessage.doPostComment(sql, request, response, xmpp, visitor); + } else { + response.sendError(403); + } } else if (uri.equals("/pm/send")) { com.juick.User visitor = Utils.getVisitorUser(sql, request, response); if (visitor != null) { diff --git a/src/java/com/juick/http/www/NewMessage.java b/src/java/com/juick/http/www/NewMessage.java index 895bfe91b..79b087ebc 100644 --- a/src/java/com/juick/http/www/NewMessage.java +++ b/src/java/com/juick/http/www/NewMessage.java @@ -18,7 +18,16 @@ package com.juick.http.www; import com.juick.Tag; +import com.juick.server.MessagesQueries; +import com.juick.server.SubscriptionsQueries; import com.juick.server.TagQueries; +import com.juick.server.UserQueries; +import com.juick.xmpp.JID; +import com.juick.xmpp.Message; +import com.juick.xmpp.Stream; +import com.juick.xmpp.extensions.JuickMessage; +import com.juick.xmpp.extensions.Nickname; +import com.juick.xmpp.extensions.XOOB; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; @@ -49,7 +58,7 @@ public class NewMessage { } out.println("<section id=\"content\" class=\"pagetext\">"); - out.println("<form action=\"/post\" method=\"post\" id=\"postmsg\" enctype=\"multipart/form-data\">"); + out.println("<form action=\"/post2\" method=\"post\" id=\"postmsg\" enctype=\"multipart/form-data\">"); out.println("<p style=\"text-align: left\"><b>Место: <span id=\"location\"></span></b> <span id=\"locationclear\">— <a href=\"#\" onclick=\"clearLocation()\">Отменить</a></span></p>"); out.println("<p style=\"text-align: left\"><b>Фото:</b> <span id=\"attachmentfile\"><input type=\"file\" name=\"attach\"/> <i>(JPG, PNG, до 10Мб)</i></span></p>"); @@ -127,6 +136,204 @@ public class NewMessage { out.println("</p>"); } - protected void doPostNewMessage(Connection sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + public void doPostMessage(Connection sql, HttpServletRequest request, HttpServletResponse response, Stream xmpp, com.juick.User visitor) throws ServletException, IOException { + String body = request.getParameter("body"); + if (body == null || body.length() < 1 || body.length() > 4096) { + response.sendError(400); + return; + } + + String tagsStr = request.getParameter("tags"); + if (tagsStr == null || tagsStr.isEmpty()) { + response.sendError(400); + return; + } + String tagsArr[] = tagsStr.split("[ \\,]"); + for (int i = 0; i < tagsArr.length; i++) { + if (tagsArr[i].startsWith("*")) { + tagsArr[i] = tagsArr[i].substring(1); + } + if (tagsArr[i].length() > 64) { + tagsArr[i] = tagsArr[i].substring(0, 64); + } + } + ArrayList<com.juick.Tag> tags = TagQueries.getTags(sql, tagsArr, true); + if (tags.isEmpty()) { + response.sendError(400); + return; + } + while (tags.size() > 5) { + tags.remove(5); + } + + String attachmentFName = null; + try { + attachmentFName = Utils.receiveMultiPartFile(request, "attach"); + } catch (Exception e) { + response.sendError(400); + return; + } + + String paramImg = request.getParameter("img"); + if (attachmentFName == null && paramImg != null && paramImg.length() > 12 && paramImg.startsWith("http://") && !paramImg.equals("http://")) { + try { + attachmentFName = Utils.downloadImage(paramImg); + } catch (Exception e) { + System.out.println("DOWNLOAD ERROR: " + e.toString()); + response.sendError(500); + return; + } + } + + String attachmentType = attachmentFName != null ? attachmentFName.substring(attachmentFName.length() - 3) : null; + int mid = MessagesQueries.createMessage(sql, visitor.UID, body, attachmentType, tags); + SubscriptionsQueries.subscribeMessage(sql, mid, visitor.UID); + + Message xmsg = new Message(); + xmsg.from = new JID("juick", "juick.com", null); + xmsg.type = Message.Type.chat; + xmsg.thread = "juick-" + mid; + + JuickMessage jmsg = new JuickMessage(MessagesQueries.getMessage(sql, mid)); + xmsg.addChild(jmsg); + + Nickname nick = new Nickname(); + nick.Nickname = "@" + jmsg.User.UName; + xmsg.addChild(nick); + + if (attachmentFName != null) { + String fname = mid + "." + attachmentType; + String attachmentURL = "http://i.juick.com/photos-1024/" + fname; + + Runtime.getRuntime().exec("/var/www/juick.com/cgi/p-convert.sh /var/www/juick.com/i/tmp/" + attachmentFName + " " + fname); + + body = attachmentURL + "\n" + body; + XOOB xoob = new XOOB(); + xoob.URL = attachmentURL; + xmsg.addChild(xoob); + } + + String tagsStr2 = ""; + for (int i = 0; i < tagsArr.length; i++) { + tagsStr2 += " *" + tagsArr[i]; + } + xmsg.body = "@" + jmsg.User.UName + ":" + tagsStr2 + "\n" + body + "\n\n#" + mid + " http://juick.com/" + mid; + + xmsg.to = new JID("juick", "s2s.juick.com", null); + xmpp.send(xmsg); + + xmsg.to.Host = "ws.juick.com"; + xmpp.send(xmsg); + + xmsg.to.Host = "push.juick.com"; + xmpp.send(xmsg); + + xmsg.to.Host = "crosspost.juick.com"; + xmsg.to.Username = "twitter"; + xmpp.send(xmsg); + xmsg.to.Username = "fb"; + xmpp.send(xmsg); + + xmsg.to.Host = "nologin.ru"; + xmsg.to.Username = "jubo"; + xmpp.send(xmsg); + + Utils.sendTemporaryRedirect(response, "/" + visitor.UName + "/" + mid); + } + + public void doPostComment(Connection sql, HttpServletRequest request, HttpServletResponse response, Stream xmpp, com.juick.User visitor) throws ServletException, IOException { + int mid = Utils.parseInt(request.getParameter("mid"), 0); + if (mid == 0) { + response.sendError(400); + return; + } + com.juick.Message msg = MessagesQueries.getMessage(sql, mid); + if (msg == null) { + response.sendError(404); + return; + } + + int rid = Utils.parseInt(request.getParameter("rid"), 0); + com.juick.Message reply = null; + if (rid > 0) { + reply = MessagesQueries.getReply(sql, mid, rid); + if (reply == null) { + response.sendError(404); + return; + } + } + + String body = request.getParameter("body"); + if (body == null || body.length() < 1 || body.length() > 4096) { + response.sendError(400); + return; + } + + if ((msg.ReadOnly && msg.User.UID != visitor.UID) || UserQueries.isInBLAny(sql, msg.User.UID, visitor.UID) || (reply != null && UserQueries.isInBLAny(sql, reply.User.UID, visitor.UID))) { + response.sendError(403); + return; + } + + String attachmentFName = null; + try { + attachmentFName = Utils.receiveMultiPartFile(request, "attach"); + } catch (Exception e) { + response.sendError(400); + return; + } + + String paramImg = request.getParameter("img"); + if (attachmentFName == null && paramImg != null && paramImg.length() > 12 && paramImg.startsWith("http://") && !paramImg.equals("http://")) { + try { + attachmentFName = Utils.downloadImage(paramImg); + } catch (Exception e) { + System.out.println("DOWNLOAD ERROR: " + e.toString()); + response.sendError(500); + return; + } + } + + String attachmentType = attachmentFName != null ? attachmentFName.substring(attachmentFName.length() - 3) : null; + int ridnew = MessagesQueries.createReply(sql, mid, rid, visitor.UID, body, attachmentType); + SubscriptionsQueries.subscribeMessage(sql, mid, visitor.UID); + + Message xmsg = new Message(); + xmsg.from = new JID("juick", "juick.com", null); + xmsg.type = Message.Type.chat; + xmsg.thread = "juick-" + mid; + + JuickMessage jmsg = new JuickMessage(MessagesQueries.getReply(sql, mid, ridnew)); + xmsg.addChild(jmsg); + + String quote = reply != null ? reply.Text : msg.Text; + if (quote.length() >= 50) { + quote = quote.substring(0, 47) + "..."; + } + + Nickname nick = new Nickname(); + nick.Nickname = "@" + jmsg.User.UName; + xmsg.addChild(nick); + + if (attachmentFName != null) { + String fname = mid + "-" + ridnew + "." + attachmentType; + String attachmentURL = "http://i.juick.com/photos-1024/" + fname; + + Runtime.getRuntime().exec("/var/www/juick.com/cgi/p-convert.sh /var/www/juick.com/i/tmp/" + attachmentFName + " " + fname); + + body = attachmentURL + "\n" + body; + XOOB xoob = new XOOB(); + xoob.URL = attachmentURL; + xmsg.addChild(xoob); + } + + xmsg.body = "Reply by @" + jmsg.User.UName + ":\n>" + quote + "\n" + body + "\n\n#" + mid + "/" + ridnew + " http://juick.com/" + mid + "#" + ridnew; + + xmsg.to = new JID("juick", "s2s.juick.com", null); + xmpp.send(xmsg); + + xmsg.to.Host = "ws.juick.com"; + xmpp.send(xmsg); + + Utils.sendTemporaryRedirect(response, "/" + msg.User.UName + "/" + mid + "#" + ridnew); } } diff --git a/src/java/com/juick/http/www/PageTemplates.java b/src/java/com/juick/http/www/PageTemplates.java index 6581fbd7d..cfdc2b0a8 100644 --- a/src/java/com/juick/http/www/PageTemplates.java +++ b/src/java/com/juick/http/www/PageTemplates.java @@ -52,9 +52,9 @@ public class PageTemplates { out.println("<!DOCTYPE html>"); out.print("<html>"); out.print("<head>"); - out.print("<link rel=\"stylesheet\" href=\"/style.2014032100.css\"/>"); + out.print("<link rel=\"stylesheet\" href=\"/style.2014041701.css\"/>"); out.print("<script type=\"text/javascript\" src=\"//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js\"></script>"); - out.print("<script type=\"text/javascript\" src=\"/scripts.2014031801.js\"></script>"); + out.print("<script type=\"text/javascript\" src=\"/scripts.2014041701.js\"></script>"); if (headers != null) { out.print(headers); } @@ -138,9 +138,9 @@ public class PageTemplates { out.println("<aside id=\"column\">"); out.println(" <p class=\"tags\">" + tagsHTML + "</p>"); - if (visitor != null) { - printContestRating(out, sql); - } +// if (visitor != null) { +// printContestRating(out, sql); +// } out.println("</aside>"); } @@ -229,8 +229,8 @@ public class PageTemplates { out.println("<div id=\"footer\">"); out.println(" <div id=\"footer-right\"><a href=\"/settings\" rel=\"nofollow\">Настройки</a> · <a href=\"/help/ru/contacts\" rel=\"nofollow\">Контакты</a> · <a href=\"/help/\" rel=\"nofollow\">Справка</a> · <a href=\"/help/ru/adv\" rel=\"nofollow\">Реклама</a></div>"); out.print(" <div id=\"footer-social\">"); - out.print("<a href=\"https://twitter.com/JuickCom\" rel=\"nofollow\" class=\"ico32-twi\">Twitter</a>"); - out.print("<a href=\"https://vk.com/juickcom\" rel=\"nofollow\" class=\"ico32-vk\">ВКонтакте</a>"); + out.print("<a href=\"https://twitter.com/Juick\" rel=\"nofollow\" class=\"ico32-twi\">Twitter</a>"); + out.print("<a href=\"https://vk.com/juick\" rel=\"nofollow\" class=\"ico32-vk\">ВКонтакте</a>"); out.print("<a href=\"https://www.facebook.com/JuickCom\" rel=\"nofollow\" class=\"ico32-fb\">Facebook</a>"); out.println("</div>"); out.print(" <div id=\"footer-left\">juick.com © 2008-2014"); @@ -481,13 +481,18 @@ public class PageTemplates { for (int i = 0; i < msgs.size(); i++) { - if (i == 1 && YandexID > 0 && ad_mid == 0) { + if (i == 0 && YandexID > 0 && ad_mid == 0) { pageYandexAd728(out, YandexID); } com.juick.Message msg = msgs.get(i); - String tags = msg.Tags.isEmpty() ? "" : formatTags(msg.Tags, msg.User); + String tags; + if (user == null) { + tags = msg.Tags.isEmpty() ? "" : formatTags(msg.Tags, null); + } else { + tags = msg.Tags.isEmpty() ? "" : formatTags(msg.Tags, msg.User); + } if (msg.ReadOnly) { tags += " *readonly"; } diff --git a/src/java/com/juick/http/www/UserThread.java b/src/java/com/juick/http/www/UserThread.java index 6b42d4a17..93a793c5c 100644 --- a/src/java/com/juick/http/www/UserThread.java +++ b/src/java/com/juick/http/www/UserThread.java @@ -148,7 +148,7 @@ public class UserThread { } if (msg.VisitorCanComment) { - out.println(" <form action=\"/post\" method=\"POST\" enctype=\"multipart/form-data\"><input type=\"hidden\" name=\"mid\" value=\"" + msg.MID + "\"/>"); + out.println(" <form action=\"/comment\" method=\"POST\" enctype=\"multipart/form-data\"><input type=\"hidden\" name=\"mid\" value=\"" + msg.MID + "\"/>"); out.println(" <div class=\"msg-comment\"><div class=\"ta-wrapper\"><textarea name=\"body\" rows=\"1\" class=\"reply\" placeholder=\"Написать комментарий\" onkeypress=\"postformListener(this.form,event)\"></textarea></div></div>"); out.println(" </form>"); } diff --git a/src/java/com/juick/http/www/Utils.java b/src/java/com/juick/http/www/Utils.java index 66450acd0..7a8abecbd 100644 --- a/src/java/com/juick/http/www/Utils.java +++ b/src/java/com/juick/http/www/Utils.java @@ -18,6 +18,8 @@ package com.juick.http.www; import java.io.BufferedReader; +import java.io.FileOutputStream; +import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; @@ -26,9 +28,11 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; +import java.util.UUID; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.Part; /** * @@ -48,6 +52,27 @@ public class Utils { return null; } + public static String receiveMultiPartFile(HttpServletRequest request, String name) throws Exception { + String attachmentFName = null; + + Part filePart = request.getPart("attach"); + if (filePart != null) { + String partname = Utils.getPartFilename(filePart); + String attachmentType = partname.substring(partname.length() - 3); + if (attachmentType.equals("jpg") || attachmentType.equals("peg") || attachmentType.equals("png")) { + if (attachmentType.equals("peg")) { + attachmentType = "jpg"; + } + attachmentFName = UUID.randomUUID().toString() + "." + attachmentType; + filePart.write("/var/www/juick.com/i/tmp/" + attachmentFName); + } else { + throw new Exception("Wrong file type"); + } + } + + return attachmentFName; + } + public static com.juick.User getVisitorUser(Connection sql, HttpServletRequest request, HttpServletResponse response) { String hash = getCookie(request, "hash"); if (hash != null) { @@ -76,6 +101,16 @@ public class Utils { response.setHeader("Location", location); } + public static String getPartFilename(Part part) { + for (String cd : part.getHeader("content-disposition").split(";")) { + if (cd.trim().startsWith("filename")) { + String filename = cd.substring(cd.indexOf('=') + 1).trim().replace("\"", ""); + return filename.substring(filename.lastIndexOf('/') + 1).substring(filename.lastIndexOf('\\') + 1); // MSIE fix. + } + } + return null; + } + public static void finishSQL(ResultSet rs, Statement stmt) { if (rs != null) { try { @@ -110,6 +145,17 @@ public class Utils { return str.replaceAll("@", "\\\\@"); } + public static int parseInt(String str, int def) { + int ret = def; + if (str != null) { + try { + ret = Integer.parseInt(str); + } catch (Exception e) { + } + } + return ret; + } + public static String fetchURL(String url) { try { URLConnection c = new URL(url).openConnection(); @@ -125,4 +171,53 @@ public class Utils { return null; } } + + public static String downloadImage(String url) throws Exception { + String attachmentFName = null; + Exception ex = null; + + InputStream is = null; + FileOutputStream fos = null; + try { + URLConnection urlConn = new URL(url).openConnection(); + is = urlConn.getInputStream(); + String mime = urlConn.getContentType(); + + String attachmentType; + if (mime != null && mime.equals("image/jpeg")) { + attachmentType = "jpg"; + } else if (mime != null && mime.equals("image/png")) { + attachmentType = "png"; + } else { + throw new Exception("Wrong file type"); + } + + attachmentFName = UUID.randomUUID().toString() + "." + attachmentType; + fos = new FileOutputStream("/var/www/juick.com/i/tmp/" + attachmentFName); + byte[] buffer = new byte[10240]; + int len; + while ((len = is.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + } catch (Exception e) { + ex = e; + attachmentFName = null; + } finally { + try { + if (is != null) { + is.close(); + } + } finally { + if (fos != null) { + fos.close(); + } + } + } + + if (ex != null) { + throw ex; + } else { + return attachmentFName; + } + } } |