diff options
Diffstat (limited to 'src')
27 files changed, 1971 insertions, 0 deletions
diff --git a/src/conf/MANIFEST.MF b/src/conf/MANIFEST.MF new file mode 100644 index 00000000..59499bce --- /dev/null +++ b/src/conf/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/src/java/Blogs.properties b/src/java/Blogs.properties new file mode 100644 index 00000000..3b596f77 --- /dev/null +++ b/src/java/Blogs.properties @@ -0,0 +1,14 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +Last\ messages=Last messages +Lists=Lists +Tags=Tags +Search=Search +My\ feed=My feed +Private=Private +Incoming=Incoming +Recommended=Recommended +All\ messages=All messages +Popular=Popular +With\ photos=With photos diff --git a/src/java/Blogs_ru.properties b/src/java/Blogs_ru.properties new file mode 100644 index 00000000..f5fe415f --- /dev/null +++ b/src/java/Blogs_ru.properties @@ -0,0 +1,14 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +Last\ messages=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f +Lists=\u0421\u043f\u0438\u0441\u043a\u0438 +Tags=\u0422\u0435\u0433\u0438 +Search=\u041f\u043e\u0438\u0441\u043a +My\ feed=\u041c\u043e\u044f \u043b\u0435\u043d\u0442\u0430 +Private=\u041f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 +Incoming=\u0412\u0445\u043e\u0434\u044f\u0449\u0438\u0435 +Recommended=\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043d\u043e\u0435 +All\ messages=\u0412\u0441\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f +Popular=\u041f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0435 +With\ photos=\u0421 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f\u043c\u0438 diff --git a/src/java/Chats.properties b/src/java/Chats.properties new file mode 100644 index 00000000..e5596bac --- /dev/null +++ b/src/java/Chats.properties @@ -0,0 +1,5 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +Active\ chats=Active chats +Users\ online=Users online diff --git a/src/java/Chats_ru.properties b/src/java/Chats_ru.properties new file mode 100644 index 00000000..6f144f69 --- /dev/null +++ b/src/java/Chats_ru.properties @@ -0,0 +1,5 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +Active\ chats=\u0410\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0447\u0430\u0442\u044b +Users\ online=\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043e\u043d\u043b\u0430\u0439\u043d diff --git a/src/java/Global.properties b/src/java/Global.properties new file mode 100644 index 00000000..0883bec5 --- /dev/null +++ b/src/java/Global.properties @@ -0,0 +1,17 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +Blogs=Blogs +Chats=Chats +Photos=Photos +Map=Map +Post=Post +Blog=Blog +Settings=Settings +Logout=Logout +Login=Login +Contacts=Contacts +Help=Help +Older=Older +Newer=Newer +(replies)\ by=by diff --git a/src/java/Global_ru.properties b/src/java/Global_ru.properties new file mode 100644 index 00000000..81ba9c4f --- /dev/null +++ b/src/java/Global_ru.properties @@ -0,0 +1,17 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +Blogs=\u0411\u043b\u043e\u0433\u0438 +Chats=\u0427\u0430\u0442\u044b +Photos=\u0424\u043e\u0442\u043e +Map=\u041a\u0430\u0440\u0442\u0430 +Post=\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c +Blog=\u0411\u043b\u043e\u0433 +Settings=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 +Logout=\u0412\u044b\u0439\u0442\u0438 +Login=\u0412\u043e\u0439\u0442\u0438 +Contacts=\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u044b +Help=\u0421\u043f\u0440\u0430\u0432\u043a\u0430 +Older=\u0421\u0442\u0430\u0440\u044b\u0435 +Newer=\u041d\u043e\u0432\u044b\u0435 +(replies)\ by=\u043e\u0442 diff --git a/src/java/Login.properties b/src/java/Login.properties new file mode 100644 index 00000000..820b58f3 --- /dev/null +++ b/src/java/Login.properties @@ -0,0 +1,6 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +Login=Login +Username=Username +Password=Password diff --git a/src/java/Login_ru.properties b/src/java/Login_ru.properties new file mode 100644 index 00000000..402e58eb --- /dev/null +++ b/src/java/Login_ru.properties @@ -0,0 +1,6 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +Login=\u0412\u0445\u043e\u0434 +Username=\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f +Password=\u041f\u0430\u0440\u043e\u043b\u044c diff --git a/src/java/Map.properties b/src/java/Map.properties new file mode 100644 index 00000000..004e4d13 --- /dev/null +++ b/src/java/Map.properties @@ -0,0 +1,5 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +Messages\ on\ map=Messages on map +Popular\ places=Popular places diff --git a/src/java/Map_ru.properties b/src/java/Map_ru.properties new file mode 100644 index 00000000..633a1bcc --- /dev/null +++ b/src/java/Map_ru.properties @@ -0,0 +1,5 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +Messages\ on\ map=\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043d\u0430 \u043a\u0430\u0440\u0442\u0435 +Popular\ places=\u041f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0435 \u043c\u0435\u0441\u0442\u0430 diff --git a/src/java/Photos.properties b/src/java/Photos.properties new file mode 100644 index 00000000..84624aad --- /dev/null +++ b/src/java/Photos.properties @@ -0,0 +1,4 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +Last\ photos\ and\ videos=Last photos and videos diff --git a/src/java/Photos_ru.properties b/src/java/Photos_ru.properties new file mode 100644 index 00000000..1933c3cf --- /dev/null +++ b/src/java/Photos_ru.properties @@ -0,0 +1,4 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +Last\ photos\ and\ videos=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0444\u043e\u0442\u043e \u0438 \u0432\u0438\u0434\u0435\u043e diff --git a/src/java/User.properties b/src/java/User.properties new file mode 100644 index 00000000..aa2e0bcb --- /dev/null +++ b/src/java/User.properties @@ -0,0 +1,16 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +(Stats)\ I\ read=I read +(Stats)\ My\ readers=My readers +(Stats)\ Messages=Messages +(Stats)\ Replies=Replies +(Menu)\ Messages=Messages +(Menu)\ Blog=Blog +(Menu)\ Recommendations=Recommendations +(Menu)\ Photos=Photos and videos +(Menu)\ Tags=Tags +(Menu)\ Search=Search +Expand\ all=Expand all +View\ as\ list=View as list +View\ as\ tree=View as tree diff --git a/src/java/User_ru.properties b/src/java/User_ru.properties new file mode 100644 index 00000000..a5c6f3ef --- /dev/null +++ b/src/java/User_ru.properties @@ -0,0 +1,16 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +(Stats)\ I\ read=\u042f \u0447\u0438\u0442\u0430\u044e +(Stats)\ My\ readers=\u041c\u0435\u043d\u044f \u0447\u0438\u0442\u0430\u044e\u0442 +(Stats)\ Messages=\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 +(Stats)\ Replies=\u041e\u0442\u0432\u0435\u0442\u043e\u0432 +(Menu)\ Messages=\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f +(Menu)\ Blog=\u0411\u043b\u043e\u0433 +(Menu)\ Recommendations=\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438 +(Menu)\ Photos=\u0424\u043e\u0442\u043e \u0438 \u0432\u0438\u0434\u0435\u043e +(Menu)\ Tags=\u0422\u0435\u0433\u0438 +(Menu)\ Search=\u041f\u043e\u0438\u0441\u043a +Expand\ all=\u0420\u0430\u0441\u043a\u0440\u044b\u0442\u044c \u0432\u0441\u0435 +View\ as\ list=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043a\u043e\u043c +View\ as\ tree=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u0435\u0440\u0435\u0432\u043e\u043c diff --git a/src/java/com/juick/http/www/Blogs.java b/src/java/com/juick/http/www/Blogs.java new file mode 100644 index 00000000..3b9b6882 --- /dev/null +++ b/src/java/com/juick/http/www/Blogs.java @@ -0,0 +1,217 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * 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 <http://www.gnu.org/licenses/>. + */ +package com.juick.http.www; + +import com.juick.server.MessagesQueries; +import com.juick.server.TagQueries; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; +import java.util.ResourceBundle; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Ugnich Anton + */ +public class Blogs { + + protected void doGet(Connection sql, Connection sqlSearch, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + com.juick.User visitor = Utils.getVisitorUser(sql, request); + Locale locale = request.getLocale(); + ResourceBundle rb = ResourceBundle.getBundle("Blogs", locale); + + String title; + ArrayList<Integer> mids; + + String paramShow = request.getParameter("show"); + + int paramTag = 0; + String paramTagStr = request.getParameter("tag"); + if (paramTagStr != null && paramTagStr.length() < 64) { + paramTag = TagQueries.getTagID(sql, paramTagStr, false); + } + + int paramBefore = 0; + String paramBeforeStr = request.getParameter("before"); + if (paramBeforeStr != null) { + try { + paramBefore = Integer.parseInt(paramBeforeStr); + } catch (NumberFormatException e) { + } + } + + String paramSearch = request.getParameter("search"); + if (paramSearch != null && paramSearch.length() > 64) { + paramSearch = null; + } + + if (paramShow == null) { + if (paramTag > 0) { + title = "*" + Utils.encodeHTML(paramTagStr); + mids = MessagesQueries.getTag(sql, paramTag, paramBefore); + } else if (paramSearch != null) { + title = rb.getString("Search") + ": " + Utils.encodeHTML(paramSearch); + mids = MessagesQueries.getSearch(sql, sqlSearch, Utils.encodeSphinx(paramSearch), paramBefore); + } else { + title = rb.getString("Last messages"); + mids = MessagesQueries.getAll(sql, paramBefore); + } + } else if (paramShow.equals("my")) { + title = rb.getString("My feed"); + mids = MessagesQueries.getMyFeed(sql, visitor.UID, paramBefore); + } else if (paramShow.equals("private")) { + title = rb.getString("Private"); + mids = MessagesQueries.getPrivate(sql, visitor.UID, paramBefore); + } else if (paramShow.equals("incoming")) { + title = rb.getString("Incoming"); + mids = MessagesQueries.getIncoming(sql, visitor.UID, paramBefore); + } else if (paramShow.equals("recommended")) { + title = rb.getString("Recommended"); + mids = MessagesQueries.getRecommended(sql, visitor.UID, paramBefore); + } else if (paramShow.equals("top")) { + title = rb.getString("Popular"); + mids = MessagesQueries.getPopular(sql, paramBefore); + } else if (paramShow.equals("photos")) { + title = rb.getString("With photos"); + mids = MessagesQueries.getPhotos(sql, paramBefore); + } else { + response.sendError(404); + return; + } + + response.setContentType("text/html; charset=UTF-8"); + PrintWriter out = response.getWriter(); + try { + PageTemplates.pageHead(out, title, null); + PageTemplates.pageNavigation(out, locale, visitor); + PageTemplates.pageTitle(out, title); + + out.println("<div id=\"wrapper\">"); + out.println("<div id=\"content\">"); + out.println("<ul>"); + + if (mids.size() > 0) { + PageTemplates.printMessages(out, sql, mids, locale); + } + + out.println("</ul>"); + out.println("<script type=\"text/javascript\">"); + out.println("$(\"textarea\").autoResize();"); + out.println("</script>"); + + if (mids.size() == 20) { + String nextpage = "?before=" + mids.get(mids.size() - 1); + if (paramShow != null) { + nextpage += "&show=" + paramShow; + } + if (paramTag > 0) { + nextpage += "&tag=" + URLEncoder.encode(paramTagStr, "UTF-8"); + } + out.println("<p class=\"page\"><a href=\"" + nextpage + "\">Older →</a></p>"); + } + + out.println("</div>"); + + out.println("<div id=\"column\">"); + out.println("<h2>" + rb.getString("Lists") + "</h2>"); + if (visitor != null) { + out.println("<ul>"); + out.println(" <li><a href=\"?show=my\">" + rb.getString("My feed") + "</a></li>"); + out.println(" <li><a href=\"?show=private\">" + rb.getString("Private") + "</a></li>"); + out.println(" <li><a href=\"?show=incoming\">" + rb.getString("Incoming") + "</a></li>"); + out.println(" <li><a href=\"?show=recommended\">" + rb.getString("Recommended") + "</a></li>"); + out.println("</ul>"); + } + out.println("<ul>"); + out.println(" <li><a href=\"?\">" + rb.getString("All messages") + "</a></li>"); + out.println(" <li><a href=\"?show=top\">" + rb.getString("Popular") + "</a></li>"); + out.println(" <li><a href=\"?show=photos\">" + rb.getString("With photos") + "</a></li>"); + out.println("</ul>"); + out.println("<h2>" + rb.getString("Tags") + "</h2>"); + out.println("<p style=\"text-align: justify\">" + getTags(sql, 30) + "</p>"); + out.println("<h2>" + rb.getString("Search") + "</h2>"); + out.println("<form action=\"/\" id=\"search\"><p><input type=\"text\" name=\"search\" class=\"inp\"/></p></form>"); + out.println("</div>"); + out.println("</div>"); + + PageTemplates.pageFooter(out, locale); + } finally { + out.close(); + } + } + + private String getTags(Connection sql, int cnt) { + String ret = ""; + com.juick.Tag tags[] = new com.juick.Tag[cnt]; + + int maxUsageCnt = 0; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + stmt = sql.prepareStatement("SELECT tags.name AS name,COUNT(DISTINCT messages.user_id) AS cnt FROM (messages INNER JOIN messages_tags ON (messages.ts>TIMESTAMPADD(DAY,-3,NOW()) AND messages.message_id=messages_tags.message_id)) INNER JOIN tags ON messages_tags.tag_id=tags.tag_id GROUP BY tags.tag_id ORDER BY cnt DESC LIMIT ?"); + stmt.setInt(1, cnt); + rs = stmt.executeQuery(); + rs.beforeFirst(); + cnt = 0; + while (rs.next()) { + tags[cnt] = new com.juick.Tag(); + tags[cnt].Name = rs.getString(1); + tags[cnt].UsageCnt = rs.getInt(2); + if (tags[cnt].UsageCnt > maxUsageCnt) { + maxUsageCnt = tags[cnt].UsageCnt; + } + cnt++; + } + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(rs, stmt); + } + + Arrays.sort(tags, 0, cnt); + + for (int i = 0; i < cnt; i++) { + String tag = Utils.encodeHTML(tags[i].Name); + try { + tag = "<a href=\"/?tag=" + URLEncoder.encode(tags[i].Name, "UTF-8") + "\">" + tag + "</a>"; + } catch (UnsupportedEncodingException e) { + } + + if (tags[i].UsageCnt > maxUsageCnt / 3 * 2) { + ret += "<big>" + tag + "</big> "; + } else if (tags[i].UsageCnt > maxUsageCnt / 3) { + ret += "<small>" + tag + "</small> "; + } else { + ret += tag + " "; + } + } + + return ret; + } +} diff --git a/src/java/com/juick/http/www/Chats.java b/src/java/com/juick/http/www/Chats.java new file mode 100644 index 00000000..3df37976 --- /dev/null +++ b/src/java/com/juick/http/www/Chats.java @@ -0,0 +1,77 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * 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 <http://www.gnu.org/licenses/>. + */ +package com.juick.http.www; + +import java.io.IOException; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Locale; +import java.util.ResourceBundle; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Ugnich Anton + */ +public class Chats { + + protected void doGet(Connection sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + com.juick.User visitor = Utils.getVisitorUser(sql, request); + Locale locale = request.getLocale(); + ResourceBundle rb = ResourceBundle.getBundle("Chats", locale); + + response.setContentType("text/html; charset=UTF-8"); + PrintWriter out = response.getWriter(); + try { + PageTemplates.pageHead(out, rb.getString("Active chats"), ""); + PageTemplates.pageNavigation(out, locale, visitor); + PageTemplates.pageTitle(out, rb.getString("Active chats")); + + out.println("<div id=\"wrapper\">"); + out.println("<div id=\"content\"><ul id=\"chats\">"); + + PreparedStatement stmt = null; + ResultSet rs = null; + try { + stmt = sql.prepareStatement("SELECT chats.chat_id,chats.subject,COUNT(chat_users.user_id) AS cnt FROM chats INNER JOIN chat_users USING(chat_id) GROUP BY chat_id ORDER BY cnt DESC"); + rs = stmt.executeQuery(); + rs.beforeFirst(); + while (rs.next()) { + String chatid = Integer.toString(rs.getInt(1), Character.MAX_RADIX); + out.println("<li><b>" + Utils.encodeHTML(rs.getString(2)) + "</b><br/><i>" + rb.getString("Users online") + ": " + rs.getInt(3) + "</i><br/><a href=\"xmpp:" + chatid + "@chat.juick.com?join\">" + chatid + "@chat.juick.com</a></li>"); + } + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(rs, stmt); + } + + out.println("</ul></div>"); + out.println("</div>"); + + PageTemplates.pageFooter(out, locale); + } finally { + out.close(); + } + } +} diff --git a/src/java/com/juick/http/www/Login.java b/src/java/com/juick/http/www/Login.java new file mode 100644 index 00000000..d03dd64d --- /dev/null +++ b/src/java/com/juick/http/www/Login.java @@ -0,0 +1,129 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * 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 <http://www.gnu.org/licenses/>. + */ +package com.juick.http.www; + +import java.io.IOException; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Locale; +import java.util.ResourceBundle; +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Ugnich Anton + */ +public class Login { + + protected void doGetLoginForm(Connection sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + com.juick.User visitor = Utils.getVisitorUser(sql, request); + Locale locale = request.getLocale(); + ResourceBundle rb = ResourceBundle.getBundle("Login", locale); + + response.setContentType("text/html; charset=UTF-8"); + PrintWriter out = response.getWriter(); + try { + PageTemplates.pageHead(out, rb.getString("Login"), ""); + PageTemplates.pageNavigation(out, locale, visitor); + PageTemplates.pageTitle(out, rb.getString("Login")); + + out.println("<div id=\"wrapper\">"); + out.println("<div id=\"content\">"); + out.println("<form action=\"/login\" method=\"post\">"); + out.println("<p>" + rb.getString("Username") + ": <input type=\"text\" name=\"username\"/></p>"); + out.println("<p>" + rb.getString("Password") + ": <input type=\"password\" name=\"password\"/></p>"); + out.println("<p><input type=\"submit\" value=\" OK \"/></p>"); + out.println("</form>"); + out.println("</div>"); + out.println("</div>"); + + PageTemplates.pageFooter(out, locale); + } finally { + out.close(); + } + } + + protected void doGetLogin(Connection sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + String hash = request.getQueryString(); + if (hash.length() > 32) { + response.sendError(400); + return; + } + + if (com.juick.server.UserQueries.getUIDbyHash(sql, hash) > 0) { + Cookie c = new Cookie("hash", hash); + c.setDomain(".juick.com"); + c.setMaxAge(0); + response.addCookie(c); + + response.sendRedirect("/"); + } else { + response.sendError(403); + } + } + + protected void doPostLogin(Connection sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + String username = request.getParameter("username"); + String password = request.getParameter("password"); + if (username == null || password == null || username.length() > 32) { + response.sendError(400); + return; + } + + int uid = com.juick.server.UserQueries.checkPassword(sql, username, password); + if (uid > 0) { + String hash = com.juick.server.UserQueries.getHashByUID(sql, uid); + Cookie c = new Cookie("hash", hash); + c.setDomain(".juick.com"); + c.setMaxAge(0); + response.addCookie(c); + + response.sendRedirect("/"); + } else { + response.sendError(403); + } + } + + protected void doGetLogout(Connection sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + int uid = Utils.getVisitorUID(sql, request); + if (uid > 0) { + PreparedStatement stmt = null; + try { + stmt = sql.prepareStatement("DELETE FROM logins WHERE user_id=?"); + stmt.setInt(1, uid); + stmt.executeUpdate(); + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(null, stmt); + } + } + + Cookie c = new Cookie("hash", "-"); + c.setDomain(".juick.com"); + c.setMaxAge(0); + response.addCookie(c); + + response.sendRedirect("/"); + } +} diff --git a/src/java/com/juick/http/www/Main.java b/src/java/com/juick/http/www/Main.java new file mode 100644 index 00000000..709c6588 --- /dev/null +++ b/src/java/com/juick/http/www/Main.java @@ -0,0 +1,173 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * 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 <http://www.gnu.org/licenses/>. + */ +package com.juick.http.www; + +import java.io.FileInputStream; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Ugnich Anton + */ +@WebServlet(name = "Main", urlPatterns = {"/"}) +public class Main extends HttpServlet { + + Connection sql; + Connection sqlSearch; + Blogs blogs = new Blogs(); + Chats chats = new Chats(); + Photos photos = new Photos(); + RootRedirects rootRedirects = new RootRedirects(); + Map map = new Map(); + Login login = new Login(); + User pagesUser = new User(); + UserThread pagesUserThread = new UserThread(); + NewMessage pagesNewMessage = new NewMessage(); + + @Override + public void init() throws ServletException { + super.init(); + try { + Properties conf = new Properties(); + conf.load(new FileInputStream("/etc/juick/www.conf")); + + Class.forName("com.mysql.jdbc.Driver"); + sql = DriverManager.getConnection("jdbc:mysql://localhost/juick?autoReconnect=true&user=" + conf.getProperty("mysql_username", "") + "&password=" + conf.getProperty("mysql_password", "")); + sqlSearch = DriverManager.getConnection("jdbc:mysql://127.0.0.1:9306/juick?autoReconnect=true&characterEncoding=utf8&maxAllowedPacket=512000&relaxAutoCommit=true&user=root&password="); + } catch (Exception e) { + log(null, e); + } + } + + @Override + public void destroy() { + super.destroy(); + if (sql != null) { + try { + sql.close(); + } catch (SQLException e) { + log(null, e); + } + } + } + + /** + * Handles the HTTP <code>GET</code> method. + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + if (request.getCharacterEncoding() == null) { + request.setCharacterEncoding("UTF-8"); + } + String uri = request.getRequestURI(); + if (uri.equals("/")) { + blogs.doGet(sql, sqlSearch, request, response); + } else if (uri.equals("/chats")) { + chats.doGet(sql, request, response); + } else if (uri.equals("/photos")) { + photos.doGet(sql, request, response); + } else if (uri.equals("/map")) { + map.doGet(sql, request, response); + } else if (uri.equals("/post")) { + pagesNewMessage.doGetNewMessage(sql, request, response); + } else if (uri.equals("/login")) { + if (request.getQueryString() == null) { + login.doGetLoginForm(sql, request, response); + } else { + login.doGetLogin(sql, request, response); + } + } else if (uri.equals("/logout")) { + login.doGetLogout(sql, request, response); + } else if (uri.equals("/settings")) { + //TODO settings + } else if (uri.matches("^/\\d+$")) { + rootRedirects.doGetPostID(sql, request, response); + } else if (uri.matches("^/[^/]$")) { + rootRedirects.doGetUsername(sql, request, response); + } else if (uri.matches("^/.+/.*")) { + String uriparts[] = uri.split("/"); + com.juick.User user = com.juick.server.UserQueries.getUserByNick(sql, uriparts[1]); + if (user != null && user.UName.equals(uriparts[1])) { + if (uriparts.length == 2) { // http://juick.com/username/ + pagesUser.doGetBlog(sql, sqlSearch, request, response, user); + } else if (uriparts[2].equals("info")) { + pagesUser.doGetInfo(sql, request, response, user); + } else { + int mid = 0; + try { + mid = Integer.parseInt(uriparts[2]); + } catch (NumberFormatException e) { + } + if (mid > 0) { + com.juick.User author = com.juick.server.MessagesQueries.getMessageAuthor(sql, mid); + if (author != null) { + if (!author.UName.equals(user.UName)) { + Utils.sendPermanentRedirect(response, "/" + author.UName + "/" + mid); + } else { + pagesUserThread.doGetThread(sql, request, response, user, mid); + } + } else { + response.sendError(404); + } + } else { + response.sendError(404); + } + } + } else if (user != null) { + Utils.sendPermanentRedirect(response, "/" + user.UName + "/" + (uriparts.length > 2 ? uriparts[2] : "")); + } else { + response.sendError(404); + } + } else { + response.sendError(404); + } + } + + /** + * Handles the HTTP <code>POST</code> method. + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + String uri = request.getRequestURI(); + if (uri.equals("/post")) { + pagesNewMessage.doPostNewMessage(sql, request, response); + } else if (uri.equals("/login")) { + login.doPostLogin(sql, request, response); + } else if (uri.equals("/settings")) { + } else { + response.sendError(405); + } + } +} diff --git a/src/java/com/juick/http/www/Map.java b/src/java/com/juick/http/www/Map.java new file mode 100644 index 00000000..1bc625b8 --- /dev/null +++ b/src/java/com/juick/http/www/Map.java @@ -0,0 +1,64 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * 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 <http://www.gnu.org/licenses/>. + */ +package com.juick.http.www; + +import java.io.IOException; +import java.io.PrintWriter; +import java.sql.Connection; +import java.util.Locale; +import java.util.ResourceBundle; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Ugnich Anton + */ +public class Map { + + protected void doGet(Connection sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + com.juick.User visitor = Utils.getVisitorUser(sql, request); + Locale locale = request.getLocale(); + ResourceBundle rb = ResourceBundle.getBundle("Map", locale); + + response.setContentType("text/html; charset=UTF-8"); + PrintWriter out = response.getWriter(); + try { + PageTemplates.pageHead(out, rb.getString("Messages on map"), "<script src=\"http://maps.google.com/maps?file=api&v=2&sensor=false&key=ABQIAAAAVVtPtxkw4soCEHg44FsNChRB4OFYjAXt73He16Zkp6a_0tPs2RTU6i6UlcMs4QvPBYvIY8rWvcxqOg\" type=\"text/javascript\"></script>" + + "<script src=\"http://static.juick.com/mc.js\" type=\"text/javascript\"></script>" + + "<script src=\"http://static.juick.com/map.js?2010111500\" type=\"text/javascript\"></script>"); + PageTemplates.pageNavigation(out, locale, visitor); + PageTemplates.pageTitle(out, rb.getString("Messages on map")); + + out.println("<div id=\"wrapper\">"); + out.println("<div id=\"geomap\" style=\"height: 400px; margin: 1em 0.5em\"></div>"); + out.println("<div id=\"content\"><ul id=\"messages\"></ul></div>"); + out.println("<div id=\"column\"><h2>" + rb.getString("Popular places") + "</h2><ul id=\"places\"></ul></div>"); + out.println("</div>"); + out.println("<script type=\"text/javascript\">"); + out.println("$(document).ready(mapInit);"); + out.println("$(window).unload(GUnload);"); + out.println("</script>"); + + PageTemplates.pageFooter(out, locale); + } finally { + out.close(); + } + } +} diff --git a/src/java/com/juick/http/www/NewMessage.java b/src/java/com/juick/http/www/NewMessage.java new file mode 100644 index 00000000..8a92b475 --- /dev/null +++ b/src/java/com/juick/http/www/NewMessage.java @@ -0,0 +1,37 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * 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 <http://www.gnu.org/licenses/>. + */ +package com.juick.http.www; + +import java.io.IOException; +import java.sql.Connection; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Ugnich Anton + */ +public class NewMessage { + + protected void doGetNewMessage(Connection sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + } + + protected void doPostNewMessage(Connection sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + } +} diff --git a/src/java/com/juick/http/www/PageTemplates.java b/src/java/com/juick/http/www/PageTemplates.java new file mode 100644 index 00000000..94561dfd --- /dev/null +++ b/src/java/com/juick/http/www/PageTemplates.java @@ -0,0 +1,377 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * 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 <http://www.gnu.org/licenses/>. + */ +package com.juick.http.www; + +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * + * @author Ugnich Anton + */ +public class PageTemplates { + + public static void pageHead(PrintWriter out, String title, String headers) { + out.println("<!DOCTYPE html>"); + out.println("<html>"); + out.println("<head>"); + out.println(" <meta charset=\"utf-8\"/>"); + out.println(" <title>" + title + "</title>"); + out.println(" <link rel=\"stylesheet\" href=\"http://static.juick.com/style3.css\"/>"); + out.println(" <link rel=\"icon\" type=\"image/png\" href=\"http://static.juick.com/favicon.png\"/>"); + out.println(" <script type=\"text/javascript\" src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js\"></script>"); + out.println(" <script type=\"text/javascript\" src=\"https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js\"></script>"); + out.println(" <script type=\"text/javascript\" src=\"https://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js\"></script>"); + out.println(" <script type=\"text/javascript\" src=\"http://static.juick.com/scripts3.js\"></script>"); + out.println(" <script type=\"text/javascript\" src=\"http://static.juick.com/js/jquery.autoresize.js\"></script>"); + if (headers != null) { + out.println(headers); + } + out.println("</head>"); + out.println(); + out.println("<body>"); + } + + public static void pageNavigation(PrintWriter out, Locale loc, com.juick.User user) { + ResourceBundle rb = ResourceBundle.getBundle("Global", loc); + out.println("<div id=\"header\">"); + out.println("<div id=\"logo\"><a href=\"/?show=my\"><img src=\"http://static.juick.com/logo3.png\" width=\"120\" height=\"40\" alt=\"Juick\" border=\"0\"/></a></div>"); + out.println(" <ul id=\"nav\">"); + out.println(" <li><a href=\"/\">" + rb.getString("Blogs") + "</a></li>"); + out.println(" <li><a href=\"/chats\">" + rb.getString("Chats") + "</a></li>"); + out.println(" <li><a href=\"/photos\">" + rb.getString("Photos") + "</a></li>"); + out.println(" <li><a href=\"/map\">" + rb.getString("Map") + "</a></li>"); + out.println(" </ul>"); + out.println(" <ul id=\"nav-right\">"); + if (user != null) { + out.println(" <li><a href=\"/post\">" + rb.getString("Post") + "</a></li>"); + out.println(" <li><a href=\"#\" onclick=\"$('#nav-menu').toggle('blind'); return false\"><img src=\"http://i.juick.com/as/" + user.UID + ".png\" alt=\"@\"/>" + user.UName + "</a><ul id=\"nav-menu\">"); + out.println(" <li><a href=\"/" + user.UName + "/\">" + rb.getString("Blog") + "</a></li>"); + out.println(" <li><a href=\"/settings\">" + rb.getString("Settings") + "</a></li>"); + out.println(" <li><a href=\"/logout\">" + rb.getString("Logout") + "</a></li>"); + out.println(" </ul></li>"); + } else { + out.println(" <li><a href=\"/login\">" + rb.getString("Login") + "</a></li>"); + } + out.println(" </ul>"); + out.println("</div>"); + } + + public static void pageTitle(PrintWriter out, String title) { + out.println("<div id=\"title\">"); + out.println(" <h1>" + title + "</h1>"); + out.println("</div>"); + } + + public static void pageUserTitle(PrintWriter out, Connection sql, Locale loc, com.juick.User user, com.juick.User visitor) { + ResourceBundle rb = ResourceBundle.getBundle("User", loc); + + // Full name and description + String fullname = null; + String description = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + stmt = sql.prepareStatement("SELECT fullname,descr FROM usersinfo WHERE user_id=?"); + stmt.setInt(1, user.UID); + rs = stmt.executeQuery(); + if (rs.first()) { + fullname = rs.getString(1) + " (" + user.UName + ")"; + description = rs.getString(2); + } + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(rs, stmt); + } + if (fullname == null) { + fullname = user.UName; + } + if (description == null) { + description = ""; + } + + // I read + int iread = 0; + try { + stmt = sql.prepareStatement("SELECT COUNT(*) FROM subscr_users WHERE suser_id=?"); + stmt.setInt(1, user.UID); + rs = stmt.executeQuery(); + if (rs.first()) { + iread = rs.getInt(1); + } + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(rs, stmt); + } + + // My readers + int myreaders = 0; + try { + stmt = sql.prepareStatement("SELECT COUNT(*) FROM subscr_users WHERE user_id=?"); + stmt.setInt(1, user.UID); + rs = stmt.executeQuery(); + if (rs.first()) { + myreaders = rs.getInt(1); + } + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(rs, stmt); + } + + // Messages + int messages = 0; + try { + stmt = sql.prepareStatement("SELECT COUNT(*) FROM messages WHERE user_id=?"); + stmt.setInt(1, user.UID); + rs = stmt.executeQuery(); + if (rs.first()) { + messages = rs.getInt(1); + } + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(rs, stmt); + } + + // Replies + int replies = 0; + try { + stmt = sql.prepareStatement("SELECT COUNT(*) FROM replies WHERE user_id=?"); + stmt.setInt(1, user.UID); + rs = stmt.executeQuery(); + if (rs.first()) { + replies = rs.getInt(1); + } + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(rs, stmt); + } + + out.println("<div id=\"title\"><div id=\"title-container\">"); + out.println(" <div id=\"title-av\"><a href=\"/" + user.UName + "/\"><img src=\"http://i.juick.com/a/" + user.UID + ".png\" width=\"96\" height=\"96\" alt=\"" + user.UName + "\"/></a></div>"); + out.println(" <div id=\"title-stats\"><ul>"); + out.println(" <li>" + rb.getString("(Stats) I read") + ": " + iread + "</li>"); + out.println(" <li>" + rb.getString("(Stats) My readers") + ": " + myreaders + "</li>"); + out.println(" <li>" + rb.getString("(Stats) Messages") + ": " + messages + "</li>"); + out.println(" <li>" + rb.getString("(Stats) Replies") + ": " + replies + "</li>"); + out.println(" </ul></div>"); + out.println(" <div id=\"title-username\"><h1>" + fullname + "</h1><p>" + description + "</p></div>"); + out.println("</div></div>"); + out.println(); + } + + public static void pageFooter(PrintWriter out, Locale loc) { + ResourceBundle rb = ResourceBundle.getBundle("Global", loc); + out.println("<div id=\"fwrapper\"><div id=\"footer\">"); + out.println(" <div id=\"footer-right\"><a href=\"/help/contacts\">" + rb.getString("Contacts") + "</a> · <a href=\"/help/\">" + rb.getString("Help") + "</a></div>"); + out.println(" <div id=\"footer-left\">juick.com © 2008-2011</div>"); + out.println("</div>"); + } + + public static String formatTags(String tags) { + String ret = ""; + String tagsarr[] = tags.split(" "); + for (int i = 0; i < tagsarr.length; i++) { + String tag = tagsarr[i]; + tag = tag.replaceAll("<", "<"); + tag = tag.replaceAll(">", ">"); + try { + ret += " *<a href=\"/?tag=" + URLEncoder.encode(tagsarr[i], "utf-8") + "\">" + tag + "</a>"; + } catch (UnsupportedEncodingException e) { + } + } + + return ret; + } + + public static String formatDate(int minsago, String fulldate, Locale loc) { + if (minsago < 1) { + return "now"; + } else if (minsago < 60) { + return minsago + " minute" + ((minsago % 10 == 1) ? "" : "s") + " ago"; + } else if (minsago < 1440) { + int hours = (minsago / 60); + return hours + " hour" + ((hours % 10 == 1) ? "" : "s") + " ago"; + } else if (minsago < 20160) { + int days = (minsago / 1440); + return days + " day" + ((days % 10 == 1) ? "" : "s") + " ago"; + } else { + return fulldate; + } + } + + public static String formatReplies(int replies, Locale loc) { + return replies + " repl" + (replies % 10 == 1 ? "y" : "ies"); + } + + public static String formatMessage(String msg) { + msg = msg.replaceAll("&", "&"); + msg = msg.replaceAll("<", "<"); + msg = msg.replaceAll(">", ">"); + + // -- + // — + msg = msg.replaceAll("((?<=\\s)|(?<=\\A))\\-\\-?((?=\\s)|(?=\\Z))", "$1—$2"); + + // http://juick.com/last?page=2 + // <a href="http://juick.com/last?page=2" rel="nofollow">juick.com</a> + msg = msg.replaceAll("((?<=\\s)|(?<=\\A))((?:ht|f)tps?://(?:www\\.)?([^\\/\\s\\n\\\"]+)/?[^\\s\\n\\\"]*)", "$1<a href=\"$2\" rel=\"nofollow\">$3</a>"); + + // #12345 + // <a href="http://juick.com/12345">#12345</a> + msg = msg.replaceAll("((?<=\\s)|(?<=\\A)|(?<=[[:punct:]]))#(\\d+)((?=\\s)|(?=\\Z)|(?=\\))|(?=\\.)|(?=\\,))", "$1<a href=\"http://juick.com/$2\">#$2</a>$3"); + + // #12345/65 + // <a href="http://juick.com/12345#65">#12345/65</a> + msg = msg.replaceAll("((?<=\\s)|(?<=\\A)|(?<=[[:punct:]]))#(\\d+)/(\\d+)((?=\\s)|(?=\\Z)|(?=[[:punct:]]))", "$1<a href=\"http://juick.com/$2#$3\">#$2/$3</a>$4"); + + // *bold* + // <b>bold</b> + msg = msg.replaceAll("((?<=\\s)|(?<=\\A)|(?<=[[:punct:]]))\\*([^\\*\\n<>]+)\\*((?=\\s)|(?=\\Z)|(?=[[:punct:]]))", "$1<b>$2</b>$3"); + + // /italic/ + // <i>italic</i> + msg = msg.replaceAll("((?<=\\s)|(?<=\\A))/([^\\/\\n<>]+)/((?=\\s)|(?=\\Z)|(?=[[:punct:]]))", "$1<i>$2</i>$3"); + + // _underline_ + // <span class="u">underline</span> + msg = msg.replaceAll("((?<=\\s)|(?<=\\A))_([^\\_\\n<>]+)_((?=\\s)|(?=\\Z)|(?=[[:punct:]]))", "$1<span class=\"u\">$2</span>$3"); + + // /12 + // <a href="#12">/12</a> + msg = msg.replaceAll("((?<=\\s)|(?<=\\A))\\/(\\d+)((?=\\s)|(?=\\Z)|(?=[[:punct:]]))", "$1<a href=\"#$2\">/$2</a>$3"); + + // @username@jabber.org + // <a href="http://juick.com/username@jabber.org/">@username@jabber.org</a> + msg = msg.replaceAll("((?<=\\s)|(?<=\\A))@([\\w\\-\\|\\.]+@[\\w\\-\\.]+)((?=\\s)|(?=\\Z)|(?=[[:punct:]]))", "$1<a href=\"http://juick.com/$2/\">@$2</a>$3"); + + // @username + // <a href="http://juick.com/username@jabber.org/">@username@jabber.org</a> + msg = msg.replaceAll("((?<=\\s)|(?<=\\A))@([\\w\\-]+)((?=\\s)|(?=\\Z)|(?=[[:punct:]]))", "$1<a href=\"http://juick.com/$2/\">@$2</a>$3"); + + // (http://juick.com/last?page=2) + // (<a href="http://juick.com/last?page=2" rel="nofollow">juick.com</a>) + msg = msg.replaceAll("((?<=\\s)|(?<=\\A))([\\(\\[\\{]|<)((?:ht|f)tps?://(?:www\\.)?([^\\/\\s\\n\\\"\\)\\!]+)/?[^\\s]*)([\\)\\]\\}]|>)", "$1$2<a href=\"$3\" rel=\"nofollow\">$4</a>$5"); + + // > citate + msg = msg.replaceAll("(?:(?<=\\n)|(?<=\\A))>\\s(.*)(\\n|(?=\\Z))", "<blockquote>$1</blockquote>"); + msg = msg.replaceAll("</blockquote><blockquote>", "\n"); + + msg = msg.replaceAll("\n", "<br/>\n"); + return msg; + } + + public static void printMessages(PrintWriter out, Connection sql, ArrayList<Integer> mids, Locale locale) { + ResourceBundle rb = ResourceBundle.getBundle("Global", locale); + + PreparedStatement stmt = null; + ResultSet rs = null; + try { + stmt = sql.prepareStatement("SELECT STRAIGHT_JOIN messages.message_id,messages.user_id,users.nick,messages_txt.tags,messages.readonly,messages.privacy,messages_txt.txt,TIMESTAMPDIFF(MINUTE,messages.ts,NOW()),messages.ts,messages.replies,messages_txt.repliesby,messages.attach,messages.place_id,places.name,messages.lat,messages.lon FROM ((messages INNER JOIN messages_txt ON messages.message_id=messages_txt.message_id) INNER JOIN users ON messages.user_id=users.id) LEFT JOIN places ON messages.place_id=places.place_id WHERE messages.message_id IN (" + Utils.convertArray2String(mids) + ") ORDER BY messages.message_id DESC"); + rs = stmt.executeQuery(); + rs.beforeFirst(); + while (rs.next()) { + int mid = rs.getInt(1); + int uid = rs.getInt(2); + String uname = rs.getString(3); + String tags = rs.getString(4); + String txt = rs.getString(7); + // timediff + // timestamp + // replies + // 11 repliesby + // attach + // pid + // pname + // lat + // lon + + tags = (tags != null) ? formatTags(tags) : ""; + if (rs.getInt(5) == 1) { + tags += " *readonly"; + } + switch (rs.getInt(6)) { + case 2: + tags += " *public"; + break; + case -1: + tags += " *friends"; + break; + case -2: + tags += " *private"; + break; + } + + txt = formatMessage(txt); + + if (mid == mids.get(0)) { + out.println(" <li class=\"msg\" style=\"border: 0\">"); + } else { + out.println(" <li class=\"msg\">"); + } + + if (rs.getString(12) != null) { + if (rs.getString(12).equals("jpg")) { + out.println(" <div class=\"msg-media\"><img src=\"http://i.juick.com/photos-512/" + mid + ".jpg\" alt=\"\"/></div>"); + } else { + out.println(" <div class=\"msg-media\"><div id=\"video-" + mid + "\"><b>Attachment: <a href=\"http://i.juick.com/video/" + mid + ".mp4\">Video</a></b></div></div>"); + out.println(" <script type=\"text/javascript\">"); + out.println(" inlinevideo(" + mid + ");"); + out.println(" </script>"); + } + } + + out.println(" <div class=\"msg-avatar\"><a href=\"/" + uname + "/\"><img src=\"http://i.juick.com/a/" + uid + ".png\"></a></div>"); + out.println(" <div class=\"msg-ts\"><a href=\"/" + uname + "/" + mid + "\">" + formatDate(rs.getInt(8), rs.getString(9), locale) + "</a><div class=\"msg-menu\"><a href=\"#\" onclick=\"$('#msg-menu-" + mid + "').toggle('blind'); return false\"><img src=\"http://static.juick.com/message-menu-icon.png\"></a><ul id=\"msg-menu-" + mid + "\">"); + out.println(" <li><a href=\"#\" onclick=\"return false\">Under construction</a></li>"); + out.println(" </ul></div></div>"); + out.println(" <div class=\"msg-header\"><a href=\"/" + uname + "/\">@" + uname + "</a>:" + tags + "</div>"); + out.println(" <div class=\"msg-txt\">" + txt + "</div>"); + + if (rs.getInt(10) > 0) { + String repliesby = rs.getString(11); + if (repliesby == null) { + repliesby = "..."; + } + out.println(" <div class=\"msg-comments\"><a href=\"/" + uname + "/" + mid + "\">" + formatReplies(rs.getInt(10), locale) + "</a> " + rb.getString("(replies) by") + " " + repliesby + "</div>"); + } else { + out.println(" <form action=\"/post\" method=\"POST\" enctype=\"multipart/form-data\"><input type=\"hidden\" name=\"mid\" value=\"" + mid + "\"/>"); + out.println(" <div class=\"msg-comment\"><textarea name=\"body\" rows=\"1\" placeholder=\"Add a comment...\" onkeypress=\"postformListener(this.form,event)\"></textarea></div>"); + out.println(" </form>"); + } + out.println(" </li>"); + } + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(rs, stmt); + } + } +} diff --git a/src/java/com/juick/http/www/Photos.java b/src/java/com/juick/http/www/Photos.java new file mode 100644 index 00000000..7a202625 --- /dev/null +++ b/src/java/com/juick/http/www/Photos.java @@ -0,0 +1,100 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * 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 <http://www.gnu.org/licenses/>. + */ +package com.juick.http.www; + +import java.io.IOException; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Locale; +import java.util.ResourceBundle; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Ugnich Anton + */ +public class Photos { + + protected void doGet(Connection sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + com.juick.User visitor = Utils.getVisitorUser(sql, request); + Locale locale = request.getLocale(); + ResourceBundle rb = ResourceBundle.getBundle("Photos", locale); + + response.setContentType("text/html; charset=UTF-8"); + PrintWriter out = response.getWriter(); + try { + PageTemplates.pageHead(out, rb.getString("Last photos and videos"), "<script type=\"text/javascript\" src=\"http://static.juick.com/js/jquery.onImagesLoad.min.js\"></script>" + + "<script type=\"text/javascript\" src=\"http://static.juick.com/js/gallery.js\"></script>" + + "<script type=\"text/javascript\" src=\"http://static.juick.com/js/jquery.fancybox-1.3.4.js\"></script>" + + "<link rel=\"stylesheet\" href=\"http://static.juick.com/fancybox/jquery.fancybox-1.3.4.css\"/>"); + PageTemplates.pageNavigation(out, locale, visitor); + PageTemplates.pageTitle(out, rb.getString("Last photos and videos")); + + out.println("<div id=\"wrapper\">"); + out.println("<div id=\"spinner\" style=\"text-align: center\">Loading...</div>"); + out.println("<ul id=\"gallery\" style=\"display: none\">"); + + PreparedStatement stmt = null; + ResultSet rs = null; + try { + stmt = sql.prepareStatement("SELECT messages.message_id,messages.attach,users.nick FROM messages INNER JOIN users ON messages.user_id=users.id WHERE messages.attach IS NOT NULL ORDER BY message_id DESC LIMIT 20"); + rs = stmt.executeQuery(); + rs.beforeFirst(); + while (rs.next()) { + if (rs.getString(2).equals("jpg")) { + out.println("<li class=\"galleryitem\"><a href=\"/" + rs.getString(3) + "/" + rs.getInt(1) + "\" title=\"@" + rs.getString(3) + "\"><img src=\"http://i.juick.com/photos-512/" + rs.getInt(1) + ".jpg\" alt=\"\"></a></li>"); + } else { + out.println("<li class=\"galleryitem\"><a href=\"/" + rs.getString(3) + "/" + rs.getInt(1) + "\" title=\"@" + rs.getString(3) + "\"><img src=\"http://i.juick.com/thumbs/" + rs.getInt(1) + ".jpg\" alt=\"\"></a></li>"); + } + } + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(rs, stmt); + } + + out.println("</ul>"); + out.println("</div>"); + out.println("<script type=\"text/javascript\">"); + out.println("$('#gallery').onImagesLoad({selectorCallback: galleryResize});"); + out.println("$('.galleryitem a').click(function() {"); + out.println(" $.fancybox({"); + out.println(" 'href': $(this).children('img').attr('src'),"); + out.println(" 'link': this.href,"); + out.println(" 'title': this.title,"); + out.println(" 'orig': this,"); + out.println(" 'transitionIn': 'elastic',"); + out.println(" 'transitionOut': 'none',"); + out.println(" 'easingIn': 'easeOutBack',"); + out.println(" 'easingOut': 'easeInBack'"); + out.println(" });"); + out.println(" return false;"); + out.println("});"); + out.println("</script>"); + + PageTemplates.pageFooter(out, locale); + } finally { + out.close(); + } + } +} diff --git a/src/java/com/juick/http/www/RootRedirects.java b/src/java/com/juick/http/www/RootRedirects.java new file mode 100644 index 00000000..d4e17972 --- /dev/null +++ b/src/java/com/juick/http/www/RootRedirects.java @@ -0,0 +1,53 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * 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 <http://www.gnu.org/licenses/>. + */ +package com.juick.http.www; + +import java.io.IOException; +import java.sql.Connection; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Ugnich Anton + */ +public class RootRedirects { + + protected void doGetPostID(Connection sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + String strID = request.getRequestURI().substring(1); + int mid = Integer.parseInt(strID); + if (mid > 0) { + com.juick.User author = com.juick.server.MessagesQueries.getMessageAuthor(sql, mid); + if (author != null) { + Utils.sendPermanentRedirect(response, "/" + author.UName + "/" + mid); + return; + } + } + response.sendError(404); + } + + protected void doGetUsername(Connection sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + com.juick.User user = com.juick.server.UserQueries.getUserByNick(sql, request.getRequestURI().substring(1)); + if (user != null) { + Utils.sendPermanentRedirect(response, "/" + user.UName + "/"); + } else { + response.sendError(404); + } + } +} diff --git a/src/java/com/juick/http/www/User.java b/src/java/com/juick/http/www/User.java new file mode 100644 index 00000000..fefe1174 --- /dev/null +++ b/src/java/com/juick/http/www/User.java @@ -0,0 +1,198 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * 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 <http://www.gnu.org/licenses/>. + */ +package com.juick.http.www; + +import com.juick.server.MessagesQueries; +import com.juick.server.TagQueries; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; +import java.util.ResourceBundle; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Ugnich Anton + */ +public class User { + + protected void doGetBlog(Connection sql, Connection sqlSearch, HttpServletRequest request, HttpServletResponse response, com.juick.User user) throws ServletException, IOException { + com.juick.User visitor = Utils.getVisitorUser(sql, request); + Locale locale = request.getLocale(); + ResourceBundle rb = ResourceBundle.getBundle("User", locale); + + String title = "@" + user.UName + " - "; + ArrayList<Integer> mids; + + String paramShow = request.getParameter("show"); + + int paramTag = 0; + String paramTagStr = request.getParameter("tag"); + if (paramTagStr != null && paramTagStr.length() < 64) { + paramTag = TagQueries.getTagID(sql, paramTagStr, false); + } + + int paramBefore = 0; + String paramBeforeStr = request.getParameter("before"); + if (paramBeforeStr != null) { + try { + paramBefore = Integer.parseInt(paramBeforeStr); + } catch (NumberFormatException e) { + } + } + + String paramSearch = request.getParameter("search"); + if (paramSearch != null && paramSearch.length() > 64) { + paramSearch = null; + } + + if (paramShow == null) { + if (paramTag > 0) { + title += "*" + Utils.encodeHTML(paramTagStr); + mids = MessagesQueries.getUserTag(sql, user.UID, paramTag, paramBefore); + } else if (paramSearch != null) { + title += rb.getString("(Menu) Search") + ": " + Utils.encodeHTML(paramSearch); + mids = MessagesQueries.getUserSearch(sql, sqlSearch, user.UID, Utils.encodeSphinx(paramSearch), paramBefore); + } else { + title += rb.getString("(Menu) Blog"); + mids = MessagesQueries.getUserBlog(sql, user.UID, paramBefore); + } + } else if (paramShow.equals("recomm")) { + title += rb.getString("(Menu) Recommendations"); + mids = MessagesQueries.getUserRecommendations(sql, user.UID, paramBefore); + } else if (paramShow.equals("photos")) { + title += rb.getString("(Menu) Photos"); + mids = MessagesQueries.getUserPhotos(sql, user.UID, paramBefore); + } else { + response.sendError(404); + return; + } + + response.setContentType("text/html; charset=UTF-8"); + PrintWriter out = response.getWriter(); + try { + PageTemplates.pageHead(out, title, null); + PageTemplates.pageNavigation(out, locale, visitor); + PageTemplates.pageUserTitle(out, sql, locale, user, visitor); + + out.println("<div id=\"wrapper\">"); + out.println("<div id=\"content\">"); + out.println("<ul>"); + + if (mids.size() > 0) { + PageTemplates.printMessages(out, sql, mids, locale); + } + + out.println("</ul>"); + out.println("<script type=\"text/javascript\">"); + out.println("$(\"textarea\").autoResize();"); + out.println("</script>"); + + if (mids.size() == 20) { + String nextpage = "?before=" + mids.get(19); + if (paramShow != null) { + nextpage += "&show=" + paramShow; + } + if (paramTag > 0) { + nextpage += "&tag=" + URLEncoder.encode(paramTagStr, "UTF-8"); + } + out.println("<p class=\"page\"><a href=\"" + nextpage + "\">Older →</a></p>"); + } + + out.println("</div>"); + + out.println("<div id=\"column\">"); + out.println("<h2>" + rb.getString("(Menu) Messages") + "</h2>"); + out.println("<ul>"); + out.println(" <li><a href=\"?\">" + rb.getString("(Menu) Blog") + "</a></li>"); + out.println(" <li><a href=\"?show=recomm\">" + rb.getString("(Menu) Recommendations") + "</a></li>"); + out.println(" <li><a href=\"?show=photos\">" + rb.getString("(Menu) Photos") + "</a></li>"); + out.println("</ul>"); + out.println("<h2>" + rb.getString("(Menu) Tags") + "</h2>"); + pageUserTags(out, sql, user, visitor, 15); + out.println("<h2>" + rb.getString("(Menu) Search") + "</h2>"); + out.println("<form action=\"./\" id=\"search\"><p><input type=\"text\" name=\"search\" class=\"inp\"/></p></form>"); + out.println("</div>"); + out.println("</div>"); + + PageTemplates.pageFooter(out, locale); + } finally { + out.close(); + } + } + + protected void doGetInfo(Connection sql, HttpServletRequest request, HttpServletResponse response, com.juick.User user) throws ServletException, IOException { + } + + public static void pageUserTags(PrintWriter out, Connection sql, com.juick.User user, com.juick.User visitor, int cnt) { + com.juick.Tag tags[] = new com.juick.Tag[cnt]; + + int maxUsageCnt = 0; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + stmt = sql.prepareStatement("SELECT tags.name AS name,COUNT(DISTINCT messages_tags.message_id) AS cnt FROM (messages INNER JOIN messages_tags ON (messages.message_id=messages_tags.message_id)) INNER JOIN tags ON messages_tags.tag_id=tags.tag_id WHERE messages.user_id=? GROUP BY messages_tags.tag_id ORDER BY cnt DESC LIMIT ?"); + stmt.setInt(1, user.UID); + stmt.setInt(2, cnt); + rs = stmt.executeQuery(); + rs.beforeFirst(); + cnt = 0; + while (rs.next()) { + tags[cnt] = new com.juick.Tag(); + tags[cnt].Name = rs.getString(1); + tags[cnt].UsageCnt = rs.getInt(2); + if (tags[cnt].UsageCnt > maxUsageCnt) { + maxUsageCnt = tags[cnt].UsageCnt; + } + cnt++; + } + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(rs, stmt); + } + + Arrays.sort(tags, 0, cnt); + + for (int i = 0; i < cnt; i++) { + String tag = Utils.encodeHTML(tags[i].Name); + try { + tag = "<a href=\"?tag=" + URLEncoder.encode(tags[i].Name, "UTF-8") + "\" title=\"" + tags[i].UsageCnt + "\">" + tag + "</a>"; + } catch (UnsupportedEncodingException e) { + } + + if (tags[i].UsageCnt > maxUsageCnt / 3 * 2) { + out.print("<big>" + tag + "</big> "); + } else if (tags[i].UsageCnt > maxUsageCnt / 3) { + out.print("<small>" + tag + "</small> "); + } else { + out.print(tag + " "); + } + } + } +} diff --git a/src/java/com/juick/http/www/UserThread.java b/src/java/com/juick/http/www/UserThread.java new file mode 100644 index 00000000..6688e964 --- /dev/null +++ b/src/java/com/juick/http/www/UserThread.java @@ -0,0 +1,298 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * 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 <http://www.gnu.org/licenses/>. + */ +package com.juick.http.www; + +import com.juick.server.UserQueries; +import java.io.IOException; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Locale; +import java.util.ResourceBundle; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Ugnich Anton + */ +public class UserThread { + + protected void doGetThread(Connection sql, HttpServletRequest request, HttpServletResponse response, com.juick.User user, int MID) throws ServletException, IOException { + com.juick.User visitor = Utils.getVisitorUser(sql, request); + Locale locale = request.getLocale(); + ResourceBundle rb = ResourceBundle.getBundle("User", locale); + + boolean listview = false; + String paramView = request.getParameter("view"); + if (paramView != null) { + if (paramView.equals("list")) { + listview = true; + if (visitor != null) { + UserQueries.setUserOptionInt(sql, visitor.UID, "repliesview", 1); + } + } else if (paramView.equals("tree") && visitor != null) { + UserQueries.setUserOptionInt(sql, visitor.UID, "repliesview", 0); + } + } else if (visitor != null && UserQueries.getUserOptionInt(sql, visitor.UID, "repliesview", 0) == 1) { + listview = true; + } + + String title = "@" + user.UName + " - #" + MID; + + response.setContentType("text/html; charset=UTF-8"); + PrintWriter out = response.getWriter(); + try { + PageTemplates.pageHead(out, title, null); + PageTemplates.pageNavigation(out, locale, visitor); + PageTemplates.pageUserTitle(out, sql, locale, user, visitor); + + out.println("<div id=\"wrapper\">"); + out.println("<div id=\"content\" style=\"margin-left: 0; width: 100%\">"); + + out.println("<ul>"); + printMessage(out, sql, MID, locale); + out.println("</ul>"); + + out.println("<div class=\"title2\">"); + out.print(" <div class=\"title2-right\">"); + if (listview) { + out.print("<a href=\"?view=tree\">" + rb.getString("View as tree") + "</a>"); + } else { + out.print("<a href=\"#\" onclick=\"$('#replies>li').show(); $('#replies .msg-comments').hide(); return false\">" + rb.getString("Expand all") + "</a> · <a href=\"?view=list\">" + rb.getString("View as list") + "</a>"); + } + out.print("</div>"); + out.println(" <h2>Replies</h2>"); + out.println("</div>"); + + out.println("<ul id=\"replies\">"); + printReplies(out, sql, MID, locale, listview); + out.println("</ul>"); + + out.println("<script type=\"text/javascript\">"); + out.println("$(\"textarea\").autoResize();"); + out.println("</script>"); + + out.println("</div>"); + + out.println("</div>"); + + PageTemplates.pageFooter(out, locale); + } finally { + out.close(); + } + } + + public static void printMessage(PrintWriter out, Connection sql, int mid, Locale locale) { + ResourceBundle rb = ResourceBundle.getBundle("Global", locale); + + PreparedStatement stmt = null; + ResultSet rs = null; + try { + stmt = sql.prepareStatement("SELECT STRAIGHT_JOIN messages.message_id,messages.user_id,users.nick,messages_txt.tags,messages.readonly,messages.privacy,messages_txt.txt,TIMESTAMPDIFF(MINUTE,messages.ts,NOW()),messages.ts,messages.replies,messages.attach,messages.place_id,places.name,messages.lat,messages.lon FROM ((messages INNER JOIN messages_txt ON messages.message_id=messages_txt.message_id) INNER JOIN users ON messages.user_id=users.id) LEFT JOIN places ON messages.place_id=places.place_id WHERE messages.message_id=?"); + stmt.setInt(1, mid); + rs = stmt.executeQuery(); + if (rs.first()) { + int uid = rs.getInt(2); + String uname = rs.getString(3); + String tags = rs.getString(4); + String txt = rs.getString(7); + // timediff + // timestamp + // replies + // attach + // pid + // pname + // lat + // lon + + tags = (tags != null) ? PageTemplates.formatTags(tags) : ""; + if (rs.getInt(5) == 1) { + tags += " *readonly"; + } + switch (rs.getInt(6)) { + case 2: + tags += " *public"; + break; + case -1: + tags += " *friends"; + break; + case -2: + tags += " *private"; + break; + } + + txt = PageTemplates.formatMessage(txt); + + out.println(" <li class=\"msg\" style=\"border: 0\">"); + + if (rs.getString(11) != null) { + if (rs.getString(11).equals("jpg")) { + out.println(" <div class=\"msg-media\"><img src=\"http://i.juick.com/photos-512/" + mid + ".jpg\" alt=\"\"/></div>"); + } else { + out.println(" <div class=\"msg-media\"><div id=\"video-" + mid + "\"><b>Attachment: <a href=\"http://i.juick.com/video/" + mid + ".mp4\">Video</a></b></div></div>"); + out.println(" <script type=\"text/javascript\">"); + out.println(" inlinevideo(" + mid + ");"); + out.println(" </script>"); + } + } + + out.println(" <div class=\"msg-avatar\"><a href=\"/" + uname + "/\"><img src=\"http://i.juick.com/a/" + uid + ".png\"></a></div>"); + out.println(" <div class=\"msg-ts\"><a href=\"/" + uname + "/" + mid + "\">" + PageTemplates.formatDate(rs.getInt(8), rs.getString(9), locale) + "</a><div class=\"msg-menu\"><a href=\"#\" onclick=\"$('#msg-menu-" + mid + "').toggle('blind'); return false\"><img src=\"http://static.juick.com/message-menu-icon.png\"></a><ul id=\"msg-menu-" + mid + "\">"); + out.println(" <li><a href=\"#\" onclick=\"return false\">Under construction</a></li>"); + out.println(" </ul></div></div>"); + out.println(" <div class=\"msg-header\"><a href=\"/" + uname + "/\">@" + uname + "</a>:" + tags + "</div>"); + out.println(" <div class=\"msg-txt\">" + txt + "</div>"); + out.println(" </li>"); + } + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(rs, stmt); + } + + } + + public static void printReplies(PrintWriter out, Connection sql, int mid, Locale locale, boolean listview) { + ArrayList<com.juick.Message> replies = new ArrayList<com.juick.Message>(); + + PreparedStatement stmt = null; + ResultSet rs = null; + try { + stmt = sql.prepareStatement("SELECT replies.reply_id,replies.replyto,replies.user_id,users.nick,replies.txt,TIMESTAMPDIFF(MINUTE,replies.ts,NOW()),replies.ts,replies.attach FROM replies INNER JOIN users ON replies.user_id=users.id WHERE replies.message_id=? ORDER BY replies.reply_id ASC"); + stmt.setInt(1, mid); + rs = stmt.executeQuery(); + rs.beforeFirst(); + while (rs.next()) { + com.juick.Message msg = new com.juick.Message(); + msg.MID = mid; + msg.RID = rs.getInt(1); + msg.ReplyTo = rs.getInt(2); + msg.User = new com.juick.User(); + msg.User.UID = rs.getInt(3); + msg.User.UName = rs.getString(4); + msg.Text = PageTemplates.formatMessage(rs.getString(5)); + msg.MinutesAgo = rs.getInt(6); + msg.TimestampString = rs.getString(7); + msg.AttachmentType = rs.getString(8); + + replies.add(msg); + + if (msg.ReplyTo > 0) { + boolean added = false; + for (int i = 0; i < replies.size(); i++) { + if (replies.get(i).RID == msg.ReplyTo) { + replies.get(i).childs.add(msg); + added = true; + break; + } + } + if (!added) { + msg.ReplyTo = 0; + } + } + } + } catch (SQLException e) { + System.err.println(e); + } finally { + Utils.finishSQL(rs, stmt); + } + + if (listview) { + printList(out, replies, locale); + } else { + printTree(out, replies, 0, 0, locale); + } + + for (int i = 0; i < replies.size(); i++) { + replies.get(i).cleanupChilds(); + } + replies.clear(); + } + + public static void printTree(PrintWriter out, ArrayList<com.juick.Message> replies, int ReplyTo, int margin, Locale locale) { + for (int i = 0; i < replies.size(); i++) { + com.juick.Message msg = replies.get(i); + if (msg.ReplyTo == ReplyTo) { + + out.print(" <li id=\"" + msg.RID + "\" class=\"msg\" style=\""); + if (i == 0) { + out.print("border: 0;"); + } + if (margin > 0) { + out.print("margin-left: " + margin + "px;display:none;"); + } + out.println("\">"); + if (msg.AttachmentType != null) { + if (msg.AttachmentType.equals("jpg")) { + out.println(" <div class=\"msg-media\"><img src=\"http://i.juick.com/photos-512/" + msg.MID + "-" + msg.RID + ".jpg\" alt=\"\"/></div>"); + } else { + out.println(" <div class=\"msg-media\"><div id=\"video-" + msg.MID + "-" + msg.RID + "\"><b>Attachment: <a href=\"http://i.juick.com/video/" + msg.MID + "-" + msg.RID + ".mp4\">Video</a></b></div></div>"); + out.println(" <script type=\"text/javascript\">"); + out.println(" inlinevideo('" + msg.MID + "-" + msg.RID + "');"); + out.println(" </script>"); + } + } + out.println(" <div class=\"msg-avatar\"><a href=\"/" + msg.User.UName + "/\"><img src=\"http://i.juick.com/a/" + msg.User.UID + ".png\"></a></div>"); + out.println(" <div class=\"msg-ts\"><a href=\"/" + msg.User.UName + "/" + msg.MID + "#" + msg.RID + "\">" + PageTemplates.formatDate(msg.MinutesAgo, msg.TimestampString, locale) + "</a><div class=\"msg-menu\"><a href=\"#\" onclick=\"return msgMenu(" + msg.MID + ")\"><img src=\"http://static.juick.com/message-menu-icon.png\"></a><ul id=\"msg-menu-" + msg.MID + "\">"); + out.println(" <li><a href=\"#\" onclick=\"return false\">Under construction</a></li>"); + out.println(" </ul></div></div>"); + out.println(" <div class=\"msg-header\"><a href=\"/" + msg.User.UName + "/\">@" + msg.User.UName + "</a>:</div>"); + out.println(" <div class=\"msg-txt\">" + msg.Text + "</div>"); + if (ReplyTo == 0) { + int childs = msg.getChildsCount() - 1; + if (childs > 0) { + out.println(" <div class=\"msg-comments\"><a href=\"#\" onclick=\"return showMoreReplies(" + msg.RID + ")\">" + PageTemplates.formatReplies(childs, locale) + " more</a></div>"); + } + } + out.println(" </li>"); + + printTree(out, replies, msg.RID, margin + 20, locale); + } + } + } + + public static void printList(PrintWriter out, ArrayList<com.juick.Message> replies, Locale locale) { + for (int i = 0; i < replies.size(); i++) { + com.juick.Message msg = replies.get(i); + + out.print(" <li id=\"" + msg.RID + "\" class=\"msg\"" + (i == 0 ? " style=\"border: 0\"" : "") + ">"); + if (msg.AttachmentType != null) { + if (msg.AttachmentType.equals("jpg")) { + out.println(" <div class=\"msg-media\"><img src=\"http://i.juick.com/photos-512/" + msg.MID + "-" + msg.RID + ".jpg\" alt=\"\"/></div>"); + } else { + out.println(" <div class=\"msg-media\"><div id=\"video-" + msg.MID + "-" + msg.RID + "\"><b>Attachment: <a href=\"http://i.juick.com/video/" + msg.MID + "-" + msg.RID + ".mp4\">Video</a></b></div></div>"); + out.println(" <script type=\"text/javascript\">"); + out.println(" inlinevideo('" + msg.MID + "-" + msg.RID + "');"); + out.println(" </script>"); + } + } + out.println(" <div class=\"msg-avatar\"><a href=\"/" + msg.User.UName + "/\"><img src=\"http://i.juick.com/a/" + msg.User.UID + ".png\"></a></div>"); + out.println(" <div class=\"msg-ts\"><a href=\"/" + msg.User.UName + "/" + msg.MID + "#" + msg.RID + "\">" + PageTemplates.formatDate(msg.MinutesAgo, msg.TimestampString, locale) + "</a><div class=\"msg-menu\"><a href=\"#\" onclick=\"return msgMenu(" + msg.MID + ")\"><img src=\"http://static.juick.com/message-menu-icon.png\"></a><ul id=\"msg-menu-" + msg.MID + "\">"); + out.println(" <li><a href=\"#\" onclick=\"return false\">Under construction</a></li>"); + out.println(" </ul></div></div>"); + out.println(" <div class=\"msg-header\"><a href=\"/" + msg.User.UName + "/\">@" + msg.User.UName + "</a>:</div>"); + out.println(" <div class=\"msg-txt\">" + msg.Text + "</div>"); + out.println(" </li>"); + } + } +} diff --git a/src/java/com/juick/http/www/Utils.java b/src/java/com/juick/http/www/Utils.java new file mode 100644 index 00000000..cfa4484d --- /dev/null +++ b/src/java/com/juick/http/www/Utils.java @@ -0,0 +1,112 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * 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 <http://www.gnu.org/licenses/>. + */ +package com.juick.http.www; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Ugnich Anton + */ +public class Utils { + + public static String getCookie(HttpServletRequest request, String name) { + Cookie cookies[] = request.getCookies(); + if (cookies != null) { + for (int i = 0; i < cookies.length; i++) { + if (cookies[i].getName().equals(name)) { + return cookies[i].getValue(); + } + } + } + return null; + } + + public static com.juick.User getVisitorUser(Connection sql, HttpServletRequest request) { + String hash = getCookie(request, "hash"); + if (hash != null) { + return com.juick.server.UserQueries.getUserByHash(sql, hash); + } else { + return null; + } + } + + public static int getVisitorUID(Connection sql, HttpServletRequest request) { + Cookie cookies[] = request.getCookies(); + if (cookies != null) { + for (int i = 0; i < cookies.length; i++) { + if (cookies[i].getName().equals("hash")) { + String hash = cookies[i].getValue(); + return com.juick.server.UserQueries.getUIDbyHash(sql, hash); + } + } + } + return 0; + } + + public static void sendPermanentRedirect(HttpServletResponse response, String location) { + response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); + response.setHeader("Location", location); + } + + public static void finishSQL(ResultSet rs, Statement stmt) { + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + } + } + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException e) { + } + } + } + + public static String convertArray2String(ArrayList<Integer> mids) { + String q = ""; + for (int i = 0; i < mids.size(); i++) { + if (i > 0) { + q += ","; + } + q += mids.get(i); + } + return q; + } + + public static String encodeHTML(String str) { + String ret = str; + ret = ret.replaceAll("<", "<"); + ret = ret.replaceAll(">", ">"); + return str; + } + + public static String encodeSphinx(String str) { + String ret = str; + ret = ret.replaceAll("@", "\\\\@"); + return ret; + } +} |