/* * 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 . */ package com.juick.www; import com.juick.Message; import com.juick.Tag; import com.juick.server.MessagesQueries; import com.juick.server.TagQueries; import com.juick.server.UserQueries; import org.apache.commons.lang3.StringEscapeUtils; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.util.StringUtils; import ru.sape.Sape; import javax.servlet.http.HttpServletRequest; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * * @author Ugnich Anton */ public class PageTemplates { private static final Logger logger = Logger.getLogger(PageTemplates.class.getName()); public static Sape sape = null; protected static final SimpleDateFormat sdfSQL = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private static SimpleDateFormat sdfSimple = new SimpleDateFormat("d MMM"); private static SimpleDateFormat sdfFull = new SimpleDateFormat("d MMM yyyy"); private static String tagsHTML = null; public static void pageHead(PrintWriter out, com.juick.User visitor, String title, String headers) { out.println(""); out.print(""); out.print(""); out.println(""); out.print(""); out.print(""); if (headers != null) { out.print(headers); } out.print("" + title + ""); out.println(""); out.println(""); out.println(""); out.println(""); out.flush(); if (visitor.getUID() > 0) { out.println(""); } else { out.println(""); } } public static void pageNavigation(PrintWriter out, com.juick.User visitor, String search) { out.println("
"); out.println(" "); out.print(" "); out.print("
"); out.println("
"); if (visitor.getUID() > 0) { out.print(" "); out.print(" "); } else { out.println("

Чтобы добавлять сообщения и комментарии, представьтесь.

"); } out.println("
"); out.println("
"); } public static void pageHomeColumn(PrintWriter out, JdbcTemplate sql, com.juick.User visitor) { pageHomeColumn(out, sql, visitor, false); } public static void pageHomeColumn(PrintWriter out, JdbcTemplate sql, com.juick.User visitor, boolean showAdv) { if (tagsHTML == null) { tagsHTML = PageTemplates.formatPopularTags(sql, 80); } out.println(""); } public static String formatPopularTags(JdbcTemplate sql, int cnt) { List popularTags = TagQueries.getPopularTags(sql).stream() .map(t -> "" + StringEscapeUtils.escapeHtml4(t) + "").collect(Collectors.toList()); return StringUtils.collectionToDelimitedString(popularTags, " "); } public static void pageFooter(HttpServletRequest request, PrintWriter out, com.juick.User visitor, boolean sapeon) { out.println("
"); out.println(" "); out.print("
"); out.print("Twitter"); out.print("ВКонтакте"); out.print("Facebook"); out.println("
"); out.print("
juick.com © 2008-2016"); String queryString = request.getQueryString(); String requestURI = request.getRequestURI(); if (sapeon && sape != null && (visitor.getUID() == 0 || visitor.getUID() == 1) && queryString == null) { String links = sape.getPageLinks(requestURI, request.getCookies()).render(); if (links != null && !links.isEmpty()) { out.print("
Спонсоры: " + links); } } out.println("
"); out.println("
"); out.println(""); } public static void pageEnd(PrintWriter out) { out.println(""); } public static String formatTags(List tags) { String ret = ""; for (Tag tag : tags) { String tagName = StringEscapeUtils.escapeHtml4(tag.getName()); try { ret += " *"; } catch (UnsupportedEncodingException e) { } } return ret; } public static String formatDate(int minutes, Date fulldate) { if (minutes < 1) { return "сейчас"; } else if (minutes < 60) { String unit; int ld = minutes % 10; if ((minutes < 10 || minutes > 20) && ld == 1) { unit = "минуту"; } else if ((minutes < 10 || minutes > 20) && ld > 1 && ld < 5) { unit = "минуты"; } else { unit = "минут"; } return minutes + " " + unit + " назад"; } else if (minutes < 1440) { int hours = (minutes / 60); String unit; int ld = hours % 10; if ((hours < 10 || hours > 20) && ld == 1) { unit = "час"; } else if ((hours < 10 || hours > 20) && ld > 1 && ld < 5) { unit = "часа"; } else { unit = "часов"; } return hours + " " + unit + " назад"; } else if (minutes < 20160) { int days = (minutes / 1440); String unit; int ld = days % 10; if ((days < 10 || days > 20) && ld == 1) { unit = "день"; } else if ((days < 10 || days > 20) && ld > 1 && ld < 5) { unit = "дня"; } else { unit = "дней"; } return days + " " + unit + " назад"; } else { String ret = sdfFull.format(fulldate); synchronized (sdfSQL) { try { Calendar c = Calendar.getInstance(); int curyear = c.get(Calendar.YEAR); c.setTime(fulldate); if (c.get(Calendar.YEAR) == curyear) { ret = sdfSimple.format(fulldate); } else { ret = sdfFull.format(fulldate); } } catch (Exception e) { logger.log(Level.SEVERE, "PARSE EXCEPTION: " + fulldate); } } return ret; } } public static String formatJSLocalTime(Date ts) { return ""; } public static String formatReplies(int replies) { int ld = replies % 10; int lh = replies % 100; if ((lh < 10 || lh > 20) && ld == 1) { return replies + " ответ"; } else if ((lh < 10 || lh > 20) && ld > 1 && ld < 5) { return replies + " ответа"; } else { return replies + " ответов"; } } private static Pattern regexLinks2 = Pattern.compile("((?<=\\s)|(?<=\\A))([\\[\\{]|<)((?:ht|f)tps?://(?:www\\.)?([^\\/\\s\\\"\\)\\!]+)/?(?:[^\\]\\}](?", ">"); // http://juick.com/last?page=2 // http://juick.com/last?page=2 msg = msg.replaceAll("((?<=\\s)|(?<=\\A))((?:ht|f)tps?://(?:www\\.)?([^\\/\\s\\n\\\"]+)/?[^\\s\\n\\\"]*)", "$1$2"); // (http://juick.com/last?page=2) // (http://juick.com/last?page=2) Matcher m = regexLinks2.matcher(msg); StringBuffer sb = new StringBuffer(); while (m.find()) { String url = m.group(3).replace(" ", "%20").replaceAll("\\s+", ""); m.appendReplacement(sb, "$1$2" + url + "$5"); } m.appendTail(sb); msg = sb.toString(); return "
" + msg + "
"; } 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 // juick.com msg = msg.replaceAll("((?<=\\s)|(?<=\\A))((?:ht|f)tps?://(?:www\\.)?([^\\/\\s\\n\\\"]+)/?[^\\s\\n\\\"]*)", "$1$3"); // [link text][http://juick.com/last?page=2] // link text msg = msg.replaceAll("\\[([^\\]]+)\\]\\[((?:ht|f)tps?://[^\\]]+)\\]", "$1"); msg = msg.replaceAll("\\[([^\\]]+)\\]\\(((?:ht|f)tps?://[^\\)]+)\\)", "$1"); // #12345 // #12345 msg = msg.replaceAll("((?<=\\s)|(?<=\\A)|(?<=\\p{Punct}))#(\\d+)((?=\\s)|(?=\\Z)|(?=\\))|(?=\\.)|(?=\\,))", "$1#$2$3"); // #12345/65 // #12345/65 msg = msg.replaceAll("((?<=\\s)|(?<=\\A)|(?<=\\p{Punct}))#(\\d+)/(\\d+)((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1#$2/$3$4"); // *bold* // bold msg = msg.replaceAll("((?<=\\s)|(?<=\\A)|(?<=\\p{Punct}))\\*([^\\*\\n<>]+)\\*((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1$2$3"); // /italic/ // italic msg = msg.replaceAll("((?<=\\s)|(?<=\\A))/([^\\/\\n<>]+)/((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1$2$3"); // _underline_ // underline msg = msg.replaceAll("((?<=\\s)|(?<=\\A))_([^\\_\\n<>]+)_((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1$2$3"); // /12 // /12 msg = msg.replaceAll("((?<=\\s)|(?<=\\A))\\/(\\d+)((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1/$2$3"); // @username@jabber.org // @username@jabber.org msg = msg.replaceAll("((?<=\\s)|(?<=\\A))@([\\w\\-\\.]+@[\\w\\-\\.]+)((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1@$2$3"); // @username // @username msg = msg.replaceAll("((?<=\\s)|(?<=\\A))@([\\w\\-]{2,16})((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1@$2$3"); // (http://juick.com/last?page=2) // (juick.com) Matcher m = regexLinks2.matcher(msg); StringBuffer sb = new StringBuffer(); while (m.find()) { String url = m.group(3).replace(" ", "%20").replaceAll("\\s+", ""); m.appendReplacement(sb, "$1$2$4$5"); } m.appendTail(sb); msg = sb.toString(); // > citate msg = msg.replaceAll("(?:(?<=\\n)|(?<=\\A))> *(.*)?(\\n|(?=\\Z))", "$1"); msg = msg.replaceAll("", "\n"); msg = msg.replaceAll("\n", "
\n"); return msg; } public static void printMessages(PrintWriter out, JdbcTemplate sql, com.juick.User user, List mids, com.juick.User visitor, int YandexID, int ad_mid) { List msgs = MessagesQueries.getMessages(sql, mids); for (int i = 0; i < msgs.size(); i++) { com.juick.Message msg = msgs.get(i); if (msg.getMID() == ad_mid) { msgs.remove(i); msgs.add(0, msg); break; } } List blUIDs = new ArrayList(20); if (visitor != null) { for (Message msg : msgs) { blUIDs.add(msg.getUser().getUID()); } blUIDs = UserQueries.checkBL(sql, visitor.getUID(), blUIDs); } for (Message msg : msgs) { List tags = MessagesQueries.getMessageTags(sql, msg.getMID()); String tagsStr = formatTags(tags); if (msg.ReadOnly) { tagsStr += " *readonly"; } if (msg.Privacy < 0) { tagsStr += " *friends"; } if (msg.getMID() == ad_mid) { tagsStr += " *реклама"; } String txt; if (!msg.Tags.isEmpty() && msg.Tags.contains("code")) { txt = formatMessageCode(msg.getText()); } else { txt = formatMessage(msg.getText()); } out.println("
"); out.println(" "); out.println("
@" + msg.getUser().getUName() + ":" + tagsStr + "
"); out.println("
"); if (msg.AttachmentType != null) { String fname = msg.getMID() + "." + msg.AttachmentType; out.println("

\"\"/

"); } out.println("

" + txt + "

"); if (msg.AttachmentType != null) { out.println("
"); } out.print(" "); out.print(" "); out.print("
"); } } }