From 29a8f0ae0fdc27a03b723c7a9ad3be7f35db7b23 Mon Sep 17 00:00:00 2001 From: Ugnich Anton Date: Thu, 17 Apr 2014 15:40:27 +0700 Subject: NewMessage complete rewrite --- src/java/com/juick/http/www/Home.java | 4 +- src/java/com/juick/http/www/Main.java | 16 +- src/java/com/juick/http/www/NewMessage.java | 211 ++++++++++++++++++++++++- src/java/com/juick/http/www/PageTemplates.java | 23 +-- src/java/com/juick/http/www/UserThread.java | 2 +- src/java/com/juick/http/www/Utils.java | 95 +++++++++++ web/scripts3.js | 19 ++- web/style3.css | 14 +- 8 files changed, 359 insertions(+), 25 deletions(-) diff --git a/src/java/com/juick/http/www/Home.java b/src/java/com/juick/http/www/Home.java index 6d60bfaf..3931fd24 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("
"); out.println(" "); out.println("
"); - out.println(" "); - out.println("
"); + out.println(" или загрузить
"); + out.println("
"); out.println(" "); out.println("
"); out.println("
"); diff --git a/src/java/com/juick/http/www/Main.java b/src/java/com/juick/http/www/Main.java index 2c51456e..13506db7 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 895bfe91..79b087eb 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("
"); - out.println("
"); + out.println(""); out.println("

Место: Отменить

"); out.println("

Фото: (JPG, PNG, до 10Мб)

"); @@ -127,6 +136,204 @@ public class NewMessage { out.println("

"); } - 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 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 6581fbd7..cfdc2b0a 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(""); out.print(""); out.print(""); - out.print(""); + out.print(""); out.print(""); - out.print(""); + out.print(""); if (headers != null) { out.print(headers); } @@ -138,9 +138,9 @@ public class PageTemplates { out.println(""); } @@ -229,8 +229,8 @@ public class PageTemplates { out.println("
"); out.println(" "); out.print("
"); - out.print("Twitter"); - out.print("ВКонтакте"); + out.print("Twitter"); + out.print("ВКонтакте"); out.print("Facebook"); out.println("
"); out.print("
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 6b42d4a1..93a793c5 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(" "); + out.println(" "); out.println("
"); out.println(" "); } diff --git a/src/java/com/juick/http/www/Utils.java b/src/java/com/juick/http/www/Utils.java index 66450acd..7a8abecb 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; + } + } } diff --git a/web/scripts3.js b/web/scripts3.js index ca111020..c5fb472c 100644 --- a/web/scripts3.js +++ b/web/scripts3.js @@ -93,7 +93,7 @@ function showMoreReplies(id) { function showCommentForm(mid,rid) { if($('#replies #'+rid+' textarea').length==0) { var c=$('#replies #'+rid+' .msg-comment'); - c.wrap('
'); + c.wrap(''); c.before(''); c.append('
'); } @@ -110,7 +110,7 @@ function showCommentForm(mid,rid) { function showCommentFooter(e) { var a=$(e).closest("article"); if(a.find("footer.comm").length==0) { - a.append('
'); + a.append('
'); a.find('textarea').autoResize({ extraSpace: 0, minHeight: 1 @@ -134,6 +134,21 @@ function attachCommentPhoto(div) { } } +function attachMessagePhoto(div) { + var f=$(div).closest('form'); + if(f.find('input:file').length===0) { + var inp=$(''); + inp.on('change',function() { + $(div).text("загрузить (✓)"); + }); + f.append(inp); + inp.trigger('click'); + } else { + f.find('input:file').remove(); + $(div).text("загрузить"); + } +} + function unfoldReply() { if((0+window.location.hash.substring(1))>0) { var el=$(window.location.hash); diff --git a/web/style3.css b/web/style3.css index b8903e47..9c6eb890 100644 --- a/web/style3.css +++ b/web/style3.css @@ -38,13 +38,13 @@ body>header p { color: #000; font-size: 13pt; margin: 12px 0; text-align: center #content>p, #content>h1, #content>h2 { margin: 1em 0; } -#newmessage { background: #E5E5E0; padding: 15px; margin-bottom: 20px; text-align: right; } -#newmessage textarea { border: 1px solid #CCC; padding: 4px; width: 688px; resize: vertical; min-height: 14pt; height: 14pt; } -#newmessage>div { display: none; margin-top: 8px; } -#newmessage input { border: 1px solid #CCC; padding: 2px 4px; } -#newmessage .tags { width: 400px; float: left; } -#newmessage .attach-photo, #newmessage .attach-photo-active { margin-right: 10px; } -#newmessage .subm { width: 120px; background: #EEEEE5; } +#newmessage { background: #E5E5E0; padding: 15px; margin-bottom: 20px; } +#newmessage textarea { border: 1px solid #CCC; padding: 4px; width: 688px; resize: vertical; min-height: 14pt; height: 14pt; margin: 0 0 5px 0; } +#newmessage input { border: 1px solid #CCC; padding: 2px 4px; margin: 5px 0; } +#newmessage>div { display: none; } +#newmessage .img { width: 500px; } +#newmessage .tags { width: 500px; } +#newmessage .subm { width: 150px; background: #EEEEE5; } article { margin: 10px 0 20px 58px; background: #FFF; padding: 12px 13px; } article>aside { margin: -12px 0 0 -71px; width: 48px; height: 48px; float: left; } -- cgit v1.2.3