package com.tale.utils; import com.blade.context.WebContextHolder; import com.blade.kit.*; import com.blade.mvc.http.Request; import com.blade.mvc.http.Response; import com.blade.mvc.http.wrapper.Session; import com.sun.syndication.feed.rss.Channel; import com.sun.syndication.feed.rss.Content; import com.sun.syndication.feed.rss.Item; import com.sun.syndication.io.FeedException; import com.sun.syndication.io.WireFeedOutput; import com.tale.controller.admin.AttachController; import com.tale.ext.Commons; import com.tale.ext.Theme; import com.tale.init.TaleConst; import com.tale.model.Contents; import com.tale.model.Users; import org.commonmark.Extension; import org.commonmark.ext.gfm.tables.TablesExtension; import org.commonmark.node.Node; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; import javax.imageio.ImageIO; import java.awt.*; import java.io.File; import java.io.FileInputStream; import java.io.OutputStream; import java.text.Normalizer; import java.util.*; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Tale工具类 * <p> * Created by biezhi on 2017/2/21. */ public class TaleUtils { /** * 一个月 */ private static final int one_month = 30 * 24 * 60 * 60; private static Random r = new Random(); /** * 匹配邮箱正则 */ private static final Pattern VALID_EMAIL_ADDRESS_REGEX = Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE); private static final Pattern SLUG_REGEX = Pattern.compile("^[A-Za-z0-9_-]{5,100}$", Pattern.CASE_INSENSITIVE); /** * 设置记住密码cookie * * @param response * @param uid */ public static void setCookie(Response response, Integer uid) { try { String val = Tools.enAes(uid.toString(), TaleConst.AES_SALT); boolean isSSL = Commons.site_url().startsWith("https"); response.cookie("/", TaleConst.USER_IN_COOKIE, val, one_month, isSSL); } catch (Exception e) { e.printStackTrace(); } } /** * 返回当前登录用户 * * @return */ public static Users getLoginUser() { Session session = WebContextHolder.session(); if (null == session) { return null; } Users user = session.attribute(TaleConst.LOGIN_SESSION_KEY); return user; } /** * 退出登录状态 * * @param session * @param response */ public static void logout(Session session, Response response) { session.removeAttribute(TaleConst.LOGIN_SESSION_KEY); response.removeCookie(TaleConst.USER_IN_COOKIE); response.redirect(Commons.site_url()); } /** * 获取cookie中的用户id * * @param request * @return */ public static Integer getCookieUid(Request request) { if (null != request) { String value = request.cookie(TaleConst.USER_IN_COOKIE); if (StringKit.isNotBlank(value)) { try { String uid = Tools.deAes(value, TaleConst.AES_SALT); return StringKit.isNotBlank(uid) && StringKit.isNumber(uid) ? Integer.valueOf(uid) : null; } catch (Exception e) { } } } return null; } /** * 重新拼接字符串 * * @param arr * @return */ public static String rejoin(String[] arr) { if (null == arr) { return ""; } if (arr.length == 1) { return "'" + arr[0] + "'"; } String a = StringKit.join(arr, "','"); a = a.substring(2) + "'"; return a; } /** * markdown转换为html * * @param markdown * @return */ public static String mdToHtml(String markdown) { if (StringKit.isBlank(markdown)) { return ""; } List<Extension> extensions = Arrays.asList(TablesExtension.create()); Parser parser = Parser.builder().extensions(extensions).build(); Node document = parser.parse(markdown); HtmlRenderer renderer = HtmlRenderer.builder().extensions(extensions).build(); String content = renderer.render(document); content = Commons.emoji(content); // 支持网易云音乐输出 if (TaleConst.BCONF.getBoolean("app.support_163_music", true) && content.contains("[mp3:")) { content = content.replaceAll("\\[mp3:(\\d+)\\]", "<iframe frameborder=\"no\" border=\"0\" marginwidth=\"0\" marginheight=\"0\" width=350 height=106 src=\"//music.163.com/outchain/player?type=2&id=$1&auto=0&height=88\"></iframe>"); } // 支持gist代码输出 if (TaleConst.BCONF.getBoolean("app.support_gist", true) && content.contains("https://gist.github.com/")) { content = content.replaceAll("<script src=\"https://gist.github.com/(\\w+)/(\\w+)\\.js\"></script>", "<script src=\"https://gist.github.com/$1/$2\\.js\"></script>"); } return content; } /** * 提取html中的文字 * * @param html * @return */ public static String htmlToText(String html) { if (StringKit.isNotBlank(html)) { return html.replaceAll("(?s)<[^>]*>(\\s*<[^>]*>)*", " "); } return ""; } /** * 判断文件是否是图片类型 * * @param imageFile * @return */ public static boolean isImage(File imageFile) { if (!imageFile.exists()) { return false; } try { Image img = ImageIO.read(imageFile); if (img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) { return false; } return true; } catch (Exception e) { return false; } } /** * 判断是否是邮箱 * * @param emailStr * @return */ public static boolean isEmail(String emailStr) { Matcher matcher = VALID_EMAIL_ADDRESS_REGEX.matcher(emailStr); return matcher.find(); } /** * 判断是否是合法路径 * * @param slug * @return */ public static boolean isPath(String slug) { if (StringKit.isNotBlank(slug)) { if (slug.contains("/") || slug.contains(" ") || slug.contains(".")) { return false; } Matcher matcher = SLUG_REGEX.matcher(slug); return matcher.find(); } return false; } /** * 获取RSS输出 * * @param articles * @return * @throws FeedException */ public static String getRssXml(java.util.List<Contents> articles) throws FeedException { Channel channel = new Channel("rss_2.0"); channel.setTitle(TaleConst.OPTIONS.get("site_title")); channel.setLink(Commons.site_url()); channel.setDescription(TaleConst.OPTIONS.get("site_description")); channel.setLanguage("zh-CN"); java.util.List<Item> items = new ArrayList<>(); articles.forEach(post -> { Item item = new Item(); item.setTitle(post.getTitle()); Content content = new Content(); content.setValue(Theme.article(post.getContent())); item.setContent(content); item.setLink(Theme.permalink(post.getCid(), post.getSlug())); item.setPubDate(DateKit.getDateByUnixTime(post.getCreated())); items.add(item); }); channel.setItems(items); WireFeedOutput out = new WireFeedOutput(); return out.outputString(channel); } /** * 替换HTML脚本 * * @param value * @return */ public static String cleanXSS(String value) { //You'll need to remove the spaces from the html entities below value = value.replaceAll("<", "<").replaceAll(">", ">"); value = value.replaceAll("\\(", "(").replaceAll("\\)", ")"); value = value.replaceAll("'", "'"); value = value.replaceAll("eval\\((.*)\\)", ""); value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); value = value.replaceAll("script", ""); return value; } /** * 过滤XSS注入 * * @param value * @return */ public static String filterXSS(String value) { String cleanValue = null; if (value != null) { cleanValue = Normalizer.normalize(value, Normalizer.Form.NFD); // Avoid null characters cleanValue = cleanValue.replaceAll("\0", ""); // Avoid anything between script tags Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE); cleanValue = scriptPattern.matcher(cleanValue).replaceAll(""); // Avoid anything in a src='...' type of expression scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); cleanValue = scriptPattern.matcher(cleanValue).replaceAll(""); scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); cleanValue = scriptPattern.matcher(cleanValue).replaceAll(""); // Remove any lonesome </script> tag scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE); cleanValue = scriptPattern.matcher(cleanValue).replaceAll(""); // Remove any lonesome <script ...> tag scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); cleanValue = scriptPattern.matcher(cleanValue).replaceAll(""); // Avoid eval(...) expressions scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); cleanValue = scriptPattern.matcher(cleanValue).replaceAll(""); // Avoid expression(...) expressions scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); cleanValue = scriptPattern.matcher(cleanValue).replaceAll(""); // Avoid javascript:... expressions scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE); cleanValue = scriptPattern.matcher(cleanValue).replaceAll(""); // Avoid vbscript:... expressions scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE); cleanValue = scriptPattern.matcher(cleanValue).replaceAll(""); // Avoid onload= expressions scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); cleanValue = scriptPattern.matcher(cleanValue).replaceAll(""); } return cleanValue; } public static void download(Response response, String filePath) throws Exception { response.contentType("application/octet-stream"); response.header("Content-Transfer-Encoding", "binary"); File file = new File(filePath); String fname = file.getName(); response.header("Content-Disposition", "attachment; filename=" + fname); OutputStream out = response.outputStream(); FileInputStream in = new FileInputStream(file); byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } in.close(); out.flush(); out.close(); } /** * 获取某个范围内的随机数 * * @param max 最大值 * @param len 取多少个 * @return */ public static int[] random(int max, int len) { int values[] = new int[max]; int temp1, temp2, temp3; for (int i = 0; i < values.length; i++) { values[i] = i + 1; } //随机交换values.length次 for (int i = 0; i < values.length; i++) { temp1 = Math.abs(r.nextInt()) % (values.length - 1); //随机产生一个位置 temp2 = Math.abs(r.nextInt()) % (values.length - 1); //随机产生另一个位置 if (temp1 != temp2) { temp3 = values[temp1]; values[temp1] = values[temp2]; values[temp2] = temp3; } } return Arrays.copyOf(values, len); } /** * 将list转为 (1, 2, 4) 这样的sql输出 * @param list * @param <T> * @return */ public static <T> String listToInSql(java.util.List<T> list){ StringBuffer sbuf = new StringBuffer(); list.forEach( item -> sbuf.append(',').append(item.toString())); sbuf.append(')'); return '(' + sbuf.substring(1); } public static final String upDir = AttachController.CLASSPATH.substring(0, AttachController.CLASSPATH.length() - 1); public static String getFileKey(String name){ String prefix = "/upload/" + DateKit.dateFormat(new Date(), "yyyy/MM"); String dir = upDir + prefix; if (!FileKit.exist(dir)) { new File(dir).mkdirs(); } return prefix + "/" + com.blade.kit.UUID.UU32() + "." + FileKit.getExtension(name); } }